From 895a8c40995eaf2e1b46c1cde5206105a30ce627 Mon Sep 17 00:00:00 2001 From: Tomoki Shirasawa Date: Wed, 22 Aug 2018 16:18:23 +0900 Subject: [PATCH] procfs: Support multiple reads of e.g. /proc/*/maps Refs: #1021 Change-Id: If36e1a0f3f41f0215868daf578e96775d96a59a3 --- executer/kernel/mcctrl/mcctrl.h | 1 + executer/kernel/mcctrl/procfs.c | 325 +++++++++++++++++++++++- kernel/host.c | 1 + kernel/include/syscall.h | 1 + kernel/procfs.c | 435 ++++++++++++++++---------------- test/issues/1021/C1021.c | 286 +++++++++++++++++++++ test/issues/1021/C1021.sh | 81 ++++++ test/issues/1021/C1021.txt | 71 ++++++ test/issues/1021/Makefile | 13 + test/issues/1021/README | 58 +++++ 10 files changed, 1042 insertions(+), 230 deletions(-) create mode 100644 test/issues/1021/C1021.c create mode 100755 test/issues/1021/C1021.sh create mode 100644 test/issues/1021/C1021.txt create mode 100644 test/issues/1021/Makefile create mode 100644 test/issues/1021/README diff --git a/executer/kernel/mcctrl/mcctrl.h b/executer/kernel/mcctrl/mcctrl.h index 06e099ac..b4ade3dc 100644 --- a/executer/kernel/mcctrl/mcctrl.h +++ b/executer/kernel/mcctrl/mcctrl.h @@ -67,6 +67,7 @@ #define SCD_MSG_PROCFS_DELETE 0x11 #define SCD_MSG_PROCFS_REQUEST 0x12 #define SCD_MSG_PROCFS_ANSWER 0x13 +#define SCD_MSG_PROCFS_RELEASE 0x15 #define SCD_MSG_DEBUG_LOG 0x20 diff --git a/executer/kernel/mcctrl/procfs.c b/executer/kernel/mcctrl/procfs.c index 4a148e7b..4afcd1c3 100644 --- a/executer/kernel/mcctrl/procfs.c +++ b/executer/kernel/mcctrl/procfs.c @@ -922,6 +922,303 @@ static const struct file_operations mckernel_forward = { .write = mckernel_procfs_write, }; +#define PA_NULL (-1L) + +struct mckernel_procfs_buffer_info { + unsigned long top_pa; + unsigned long cur_pa; + ihk_os_t os; + int pid; + char path[0]; +}; + +struct mckernel_procfs_buffer { + unsigned long next_pa; + unsigned long pos; + unsigned long size; + char buf[0]; +}; + +static int mckernel_procfs_buff_open(struct inode *inode, struct file *file) +{ + struct mckernel_procfs_buffer_info *info; + int pid; + int ret; + char *path; + char *path_buf; + char *p; + ihk_os_t os; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) + struct proc_dir_entry *dp = PDE(inode); + struct procfs_list_entry *e = dp->data; +#else + struct procfs_list_entry *e = PDE_DATA(inode); +#endif + + os = osnum_to_os(e->osnum); + if (!os) { + return -EINVAL; + } + path_buf = kmalloc(PROCFS_NAME_MAX, GFP_KERNEL); + if (!path_buf) { + return -ENOMEM; + } + path = getpath(e, path_buf, PROCFS_NAME_MAX); + p = strchr(path, '/') + 1; + ret = sscanf(p, "%d/", &pid); + if (ret != 1) { + pid = -1; + } + + info = kmalloc(sizeof(struct mckernel_procfs_buffer_info) + + strlen(path) + 1, GFP_KERNEL); + if (!info) { + kfree(path_buf); + return -ENOMEM; + } + info->top_pa = PA_NULL; + info->cur_pa = PA_NULL; + info->os = os; + info->pid = pid; + strcpy(info->path, path); + file->private_data = info; + + kfree(path_buf); + return 0; +} + +static int mckernel_procfs_buff_release(struct inode *inode, struct file *file) +{ + struct mckernel_procfs_buffer_info *info = file->private_data; + int rc = 0; + + if (!info) { + return -EIO; + } + + file->private_data = NULL; + if (info->top_pa != PA_NULL) { + int ret; + struct procfs_read *r = NULL; + struct ikc_scd_packet isp; + int do_free; + + r = kmalloc(sizeof(struct procfs_read), GFP_KERNEL); + if (r == NULL) { + rc = -ENOMEM; + goto out; + } + memset(r, '\0', sizeof(struct procfs_read)); + r->pbuf = info->top_pa; + r->ret = -EIO; /* default */ + r->fname[0] = '\0'; + isp.msg = SCD_MSG_PROCFS_RELEASE; + isp.ref = 0; + isp.arg = virt_to_phys(r); + isp.pid = 0; + + rc = -EIO; + ret = mcctrl_ikc_send_wait(info->os, 0, + &isp, 5 * HZ, NULL, &do_free, 1, r); + + if (!do_free && ret >= 0) { + ret = -EIO; + } + + if (ret < 0) { + rc = ret; + if (ret == -ETIME) { + pr_info("%s: error: timeout (1 sec)\n", + __func__); + } + else if (ret == -ERESTARTSYS) { + rc = -ERESTART; + } + if (!do_free) + r = NULL; + goto out; + } + + if (r->ret < 0) { + rc = r->ret; + goto out; + } + rc = 0; +out: + if (r) + kfree((void *)r); + } + kfree(info); + return rc; +} + +static ssize_t mckernel_procfs_buff_read(struct file *file, char __user *ubuf, + size_t nbytes, loff_t *ppos) +{ + struct mckernel_procfs_buffer_info *info = file->private_data; + unsigned long phys; + struct mckernel_procfs_buffer *buf; + int pos = *ppos; + ssize_t l = 0; + int done = 0; + ihk_os_t os; + + if (nbytes <= 0 || *ppos < 0) { + return 0; + } + + if (!info) { + return -EIO; + } + + os = info->os; + if (info->top_pa == PA_NULL) { + int ret; + int pid = info->pid; + struct procfs_read *r = NULL; + struct ikc_scd_packet isp; + struct mcctrl_usrdata *udp = NULL; + struct mcctrl_per_proc_data *ppd = NULL; + int do_free; + + udp = ihk_host_os_get_usrdata(os); + if (!udp) { + pr_err("%s: no MCCTRL data found for OS\n", + __func__); + return -EINVAL; + } + + if (pid > 0) { + ppd = mcctrl_get_per_proc_data(udp, pid); + + if (unlikely(!ppd)) { + pr_err("%s: no per-process structure for PID %d", + __func__, pid); + return -EINVAL; + } + } + + r = kmalloc(sizeof(struct procfs_read), GFP_KERNEL); + if (r == NULL) { + l = -ENOMEM; + done = 1; + goto out; + } + memset(r, '\0', sizeof(struct procfs_read)); + r->pbuf = PA_NULL; + r->ret = -EIO; /* default */ + strncpy((char *)r->fname, info->path, PROCFS_NAME_MAX); + isp.msg = SCD_MSG_PROCFS_REQUEST; + isp.ref = 0; + isp.arg = virt_to_phys(r); + isp.pid = pid; + + l = -EIO; + done = 1; + ret = mcctrl_ikc_send_wait(os, + (pid > 0) ? ppd->ikc_target_cpu : 0, + &isp, 5 * HZ, NULL, &do_free, 1, r); + + if (!do_free && ret >= 0) { + ret = -EIO; + } + + if (ret < 0) { + l = ret; + if (ret == -ETIME) { + pr_info("%s: error: timeout (1 sec)\n", + __func__); + } + else if (ret == -ERESTARTSYS) { + l = -ERESTART; + } + if (!do_free) + r = NULL; + goto out; + } + + if (r->ret < 0) { + l = r->ret; + goto out; + } + + done = 0; + l = 0; + info->top_pa = info->cur_pa = r->pbuf; + +out: + if (ppd) + mcctrl_put_per_proc_data(ppd); + if (r) + kfree((void *)r); + } + + if (info->cur_pa == PA_NULL) { + info->cur_pa = info->top_pa; + } + + while (!done && info->cur_pa != PA_NULL) { + long bpos; + long bsize; + + phys = ihk_device_map_memory(ihk_os_to_dev(os), info->cur_pa, + PAGE_SIZE); +#ifdef CONFIG_MIC + buf = ioremap_wc(phys, PAGE_SIZE); +#else + buf = ihk_device_map_virtual(ihk_os_to_dev(os), phys, + PAGE_SIZE, NULL, 0); +#endif + + if (pos < buf->pos) { + info->cur_pa = info->top_pa; + goto rep; + } + + if (pos >= buf->pos + buf->size) { + info->cur_pa = buf->next_pa; + goto rep; + } + + bpos = pos - buf->pos; + bsize = (buf->pos + buf->size) - pos; + if (bsize > (nbytes - l)) { + bsize = nbytes - l; + } + if (copy_to_user(ubuf, buf->buf + bpos, bsize)) { + done = 1; + pos = *ppos; + l = -EFAULT; + } + else { + ubuf += bsize; + pos += bsize; + l += bsize; + if (l == nbytes) { + done = 1; + } + } +rep: +#ifdef CONFIG_MIC + iounmap(buf); +#else + ihk_device_unmap_virtual(ihk_os_to_dev(os), buf, PAGE_SIZE); +#endif + ihk_device_unmap_memory(ihk_os_to_dev(os), phys, PAGE_SIZE); + }; + + *ppos = pos; + return l; +} + +static const struct file_operations mckernel_buff_io = { + .llseek = mckernel_procfs_lseek, + .read = mckernel_procfs_buff_read, + .write = NULL, + .open = mckernel_procfs_buff_open, + .release = mckernel_procfs_buff_release, +}; + static const struct procfs_entry tid_entry_stuff[] = { // PROC_REG("auxv", S_IRUSR, NULL), // PROC_REG("clear_refs", S_IWUSR, NULL), @@ -931,10 +1228,10 @@ static const struct procfs_entry tid_entry_stuff[] = { // PROC_LNK("exe", mckernel_readlink), // PROC_REG("limits", S_IRUSR|S_IWUSR, NULL), // PROC_REG("maps", S_IRUGO, NULL), - PROC_REG("mem", S_IRUSR|S_IWUSR, NULL), + PROC_REG("mem", 0600, NULL), // PROC_REG("pagemap", S_IRUGO, NULL), // PROC_REG("smaps", S_IRUGO, NULL), - PROC_REG("stat", S_IRUGO, NULL), + PROC_REG("stat", 0444, &mckernel_buff_io), // PROC_REG("statm", S_IRUGO, NULL), // PROC_REG("status", S_IRUGO, NULL), // PROC_REG("syscall", S_IRUGO, NULL), @@ -943,26 +1240,26 @@ static const struct procfs_entry tid_entry_stuff[] = { }; static const struct procfs_entry pid_entry_stuff[] = { - PROC_REG("auxv", S_IRUSR, NULL), + PROC_REG("auxv", 0400, &mckernel_buff_io), /* Support the case where McKernel process retrieves its job-id under the Fujitsu TCS suite. */ // PROC_REG("cgroup", S_IXUSR, NULL), // PROC_REG("clear_refs", S_IWUSR, NULL), - PROC_REG("cmdline", S_IRUGO, NULL), + PROC_REG("cmdline", 0444, &mckernel_buff_io), // PROC_REG("comm", S_IRUGO|S_IWUSR, NULL), // PROC_REG("coredump_filter", S_IRUGO|S_IWUSR, NULL), - PROC_REG("cpuset", S_IXUSR, NULL), +// PROC_REG("cpuset", S_IRUGO, NULL), // PROC_REG("environ", S_IRUSR, NULL), // PROC_LNK("exe", mckernel_readlink), // PROC_REG("limits", S_IRUSR|S_IWUSR, NULL), - PROC_REG("maps", S_IRUGO, NULL), - PROC_REG("mem", S_IRUSR|S_IWUSR, NULL), - PROC_REG("pagemap", S_IRUGO, NULL), - PROC_REG("smaps", S_IRUGO, NULL), -// PROC_REG("stat", S_IRUGO, NULL), + PROC_REG("maps", 0444, &mckernel_buff_io), + PROC_REG("mem", 0600, NULL), + PROC_REG("pagemap", 0444, NULL), +// PROC_REG("smaps", S_IRUGO, NULL), +// PROC_REG("stat", 0444, &mckernel_buff_io), // PROC_REG("statm", S_IRUGO, NULL), - PROC_REG("status", S_IRUGO, NULL), + PROC_REG("status", 0444, &mckernel_buff_io), // PROC_REG("syscall", S_IRUGO, NULL), - PROC_DIR("task", S_IRUGO|S_IXUGO), + PROC_DIR("task", 0555), // PROC_REG("wchan", S_IRUGO, NULL), PROC_TERM }; @@ -970,14 +1267,14 @@ static const struct procfs_entry pid_entry_stuff[] = { static const struct procfs_entry base_entry_stuff[] = { // PROC_REG("cmdline", S_IRUGO, NULL), #ifdef POSTK_DEBUG_ARCH_DEP_42 /* /proc/cpuinfo support added. */ - PROC_REG("cpuinfo", S_IRUGO, NULL), + PROC_REG("cpuinfo", 0444, &mckernel_buff_io), #else /* POSTK_DEBUG_ARCH_DEP_42 */ // PROC_REG("cpuinfo", S_IRUGO, NULL), #endif /* POSTK_DEBUG_ARCH_DEP_42 */ // PROC_REG("meminfo", S_IRUGO, NULL), // PROC_REG("pagetypeinfo",S_IRUGO, NULL), // PROC_REG("softirq", S_IRUGO, NULL), - PROC_REG("stat", S_IRUGO, NULL), + PROC_REG("stat", 0444, &mckernel_buff_io), // PROC_REG("uptime", S_IRUGO, NULL), // PROC_REG("version", S_IRUGO, NULL), // PROC_REG("vmallocinfo",S_IRUSR, NULL), diff --git a/kernel/host.c b/kernel/host.c index cfedb483..ca948ca4 100644 --- a/kernel/host.c +++ b/kernel/host.c @@ -667,6 +667,7 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c, break; case SCD_MSG_PROCFS_REQUEST: + case SCD_MSG_PROCFS_RELEASE: pckt.msg = SCD_MSG_PROCFS_ANSWER; pckt.ref = packet->ref; pckt.arg = packet->arg; diff --git a/kernel/include/syscall.h b/kernel/include/syscall.h index 8d08549a..1517f175 100644 --- a/kernel/include/syscall.h +++ b/kernel/include/syscall.h @@ -49,6 +49,7 @@ #define SCD_MSG_PROCFS_DELETE 0x11 #define SCD_MSG_PROCFS_REQUEST 0x12 #define SCD_MSG_PROCFS_ANSWER 0x13 +#define SCD_MSG_PROCFS_RELEASE 0x15 #define SCD_MSG_DEBUG_LOG 0x20 diff --git a/kernel/procfs.c b/kernel/procfs.c index 0fdea252..52300235 100644 --- a/kernel/procfs.c +++ b/kernel/procfs.c @@ -40,6 +40,78 @@ extern int sprintf(char * buf, const char *fmt, ...); extern int sscanf(const char * buf, const char * fmt, ...); extern int scnprintf(char * buf, size_t size, const char *fmt, ...); +struct mckernel_procfs_buffer { + unsigned long next_pa; + unsigned long pos; + unsigned long size; + char buf[0]; +}; + +#define PA_NULL (-1L) + +static struct mckernel_procfs_buffer *buf_alloc(unsigned long *phys, long pos) +{ + struct mckernel_procfs_buffer *buf; + + buf = ihk_mc_alloc_pages(1, IHK_MC_AP_NOWAIT); + if (!buf) + return NULL; + buf->next_pa = PA_NULL; + buf->pos = pos; + buf->size = 0; + if (phys) + *phys = virt_to_phys(buf); + return buf; +} + +static void buf_free(unsigned long phys) +{ + struct mckernel_procfs_buffer *pbuf; + unsigned long next; + + while (phys != PA_NULL) { + pbuf = phys_to_virt(phys); + next = pbuf->next_pa; + ihk_mc_free_pages(pbuf, 1); + phys = next; + } +} + +static int buf_add(struct mckernel_procfs_buffer **top, + struct mckernel_procfs_buffer **cur, void *buf, int l) +{ + int pos = 0; + int r; + int bufmax = PAGE_SIZE - sizeof(struct mckernel_procfs_buffer); + char *chr = buf; + + if (!*top) { + *top = *cur = buf_alloc(NULL, 0); + if (!*top) + return -ENOMEM; + } + while (l) { + r = bufmax - (*cur)->size; + if (!r) { + *cur = buf_alloc(&(*cur)->next_pa, (*cur)->pos + + bufmax); + if (!*cur) { + buf_free(virt_to_phys(*top)); + return -ENOMEM; + } + r = bufmax; + } + if (r > l) { + r = l; + } + memcpy((*cur)->buf + (*cur)->size, chr + pos, r); + l -= r; + pos += r; + (*cur)->size += r; + } + return 0; +} + static void procfs_thread_ctl(struct thread *thread, int msg) { @@ -85,13 +157,17 @@ int process_procfs_request(struct ikc_scd_packet *rpacket) struct procfs_read *r; int osnum = ihk_mc_get_osnum(); int rosnum, ret, pid, tid, ans = -EIO, eof = 0; - char *buf, *p; + char *buf, *p = NULL; + char *vbuf = NULL; + char *tmp = NULL; struct mcs_rwlock_node_irqsave lock; unsigned long offset; int count; int npages; int readwrite = 0; int err = -EIO; + struct mckernel_procfs_buffer *buf_top = NULL; + struct mckernel_procfs_buffer *buf_cur = NULL; dprintf("process_procfs_request: invoked.\n"); @@ -100,27 +176,55 @@ int process_procfs_request(struct ikc_scd_packet *rpacket) dprintf("parg: %x\n", parg); r = ihk_mc_map_virtual(parg, 1, PTATTR_WRITABLE | PTATTR_ACTIVE); if (r == NULL) { + ihk_mc_unmap_memory(NULL, parg, sizeof(struct procfs_read)); kprintf("ERROR: process_procfs_request: got a null procfs_read structure.\n"); - goto dataunavail; + goto err; } dprintf("r: %p\n", r); - dprintf("remote pbuf: %x\n", r->pbuf); - pbuf = ihk_mc_map_memory(NULL, r->pbuf, r->count); - dprintf("pbuf: %x\n", pbuf); - count = r->count + ((uintptr_t)pbuf & (PAGE_SIZE - 1)); - npages = (count + (PAGE_SIZE - 1)) / PAGE_SIZE; - buf = ihk_mc_map_virtual(pbuf, npages, PTATTR_WRITABLE | PTATTR_ACTIVE); - dprintf("buf: %p\n", buf); - if (buf == NULL) { - kprintf("ERROR: process_procfs_request: got a null buffer.\n"); - goto bufunavail; + if (rpacket->msg == SCD_MSG_PROCFS_RELEASE) { + struct mckernel_procfs_buffer *pbuf; + unsigned long phys; + unsigned long next; + + for (phys = r->pbuf; phys != PA_NULL; phys = next) { + pbuf = phys_to_virt(phys); + next = pbuf->next_pa; + ihk_mc_free_pages(pbuf, 1); + } + r->ret = 0; + err = 0; + goto err; } - readwrite = r->readwrite; - count = r->count; + if (r->pbuf == PA_NULL) { + tmp = ihk_mc_alloc_pages(1, IHK_MC_AP_NOWAIT); + if (!tmp) + goto err; + buf = tmp; + count = PAGE_SIZE; + } + else { + dprintf("remote pbuf: %x\n", r->pbuf); + pbuf = ihk_mc_map_memory(NULL, r->pbuf, r->count); + dprintf("pbuf: %x\n", pbuf); + count = r->count + ((uintptr_t)pbuf & (PAGE_SIZE - 1)); + npages = (count + (PAGE_SIZE - 1)) / PAGE_SIZE; + vbuf = ihk_mc_map_virtual(pbuf, npages, + PTATTR_WRITABLE|PTATTR_ACTIVE); + dprintf("buf: %p\n", vbuf); + if (vbuf == NULL) { + ihk_mc_unmap_memory(NULL, pbuf, r->count); + kprintf("ERROR: %s: got a null buffer.\n", __func__); + goto err; + } + buf = vbuf; + readwrite = r->readwrite; + count = r->count; + dprintf("fname: %s, offset: %lx, count:%d.\n", r->fname, + r->offset, r->count); + } offset = r->offset; - dprintf("fname: %s, offset: %lx, count:%d.\n", r->fname, r->offset, r->count); /* * check for "mcos%d/" @@ -200,35 +304,24 @@ int process_procfs_request(struct ikc_scd_packet *rpacket) } else if (!strcmp(p, "stat")) { /* "/proc/stat" */ extern int num_processors; /* kernel/ap.c */ - char *p; - size_t remain; int cpu; - if (offset > 0) { - ans = 0; - eof = 1; - goto end; - } - p = buf; - remain = count; for (cpu = 0; cpu < num_processors; ++cpu) { - size_t n; - - n = snprintf(p, remain, "cpu%d\n", cpu); - if (n >= remain) { - ans = -ENOSPC; - eof = 1; - goto end; - } - p += n; + snprintf(buf, count, "cpu%d\n", cpu); + if (buf_add(&buf_top, &buf_cur, buf, strlen(buf)) < 0) + goto err; } - ans = p - buf; - eof = 1; + ans = 0; goto end; } #ifdef POSTK_DEBUG_ARCH_DEP_42 /* /proc/cpuinfo support added. */ else if (!strcmp(p, "cpuinfo")) { /* "/proc/cpuinfo" */ - ans = ihk_mc_show_cpuinfo(buf, count, offset, &eof); + ans = ihk_mc_show_cpuinfo(buf, count, 0, &eof); + if (ans < 0) + goto err; + if (buf_add(&buf_top, &buf_cur, buf, strlen(buf)) < 0) + goto err; + ans = 0; goto end; } #endif /* POSTK_DEBUG_ARCH_DEP_42 */ @@ -313,110 +406,51 @@ int process_procfs_request(struct ikc_scd_packet *rpacket) */ if (strcmp(p, "maps") == 0) { struct vm_range *range; -#ifdef POSTK_DEBUG_TEMP_FIX_47 /* /proc//maps 1024 byte over read fix. */ - int left = PAGE_SIZE * 2; -#else /* POSTK_DEBUG_TEMP_FIX_47 */ - int left = r->count - 1; /* extra 1 for terminating NULL */ -#endif /* POSTK_DEBUG_TEMP_FIX_47 */ - int written = 0; - char *_buf = buf; -#ifdef POSTK_DEBUG_TEMP_FIX_47 /* /proc//maps 1024 byte over read fix. */ - int len = 0; - char *tmp = NULL; - - _buf = tmp = kmalloc(left, IHK_MC_AP_CRITICAL); - if (!tmp) { - kprintf("%s: error allocating /proc/self/maps buffer\n", - __FUNCTION__); - ans = 0; - goto end; - } -#endif /* POSTK_DEBUG_TEMP_FIX_47 */ - -#ifndef POSTK_DEBUG_TEMP_FIX_47 /* /proc//maps 1024 byte over read fix. */ - /* Starting from the middle of a proc file is not supported for maps */ - if (offset > 0) { - ans = 0; - eof = 1; - goto end; - } -#endif /* POSTK_DEBUG_TEMP_FIX_47 */ ihk_mc_spinlock_lock_noirq(&vm->memory_range_lock); range = lookup_process_memory_range(vm, 0, -1); while (range) { - int written_now; - /* format is (from man proc): * address perms offset dev inode pathname * 08048000-08056000 r-xp 00000000 03:0c 64593 /usr/sbin/gpm */ - written_now = snprintf(_buf, left, - "%012lx-%012lx %s%s%s%s %lx %lx:%lx %d\t\t\t%s\n", - range->start, range->end, - range->flag & VR_PROT_READ ? "r" : "-", - range->flag & VR_PROT_WRITE ? "w" : "-", - range->flag & VR_PROT_EXEC ? "x" : "-", - range->flag & VR_PRIVATE ? "p" : "s", - /* TODO: fill in file details! */ - 0UL, - 0UL, - 0UL, - 0, - range->memobj && range->memobj->path ? range->memobj->path : - range->start == - (unsigned long)vm->vdso_addr ? "[vdso]" : - range->start == - (unsigned long)vm->vvar_addr ? "[vsyscall]" : - range->flag & VR_STACK ? "[stack]" : - range->start >= vm->region.brk_start && - range->end <= vm->region.brk_end_allocated ? - "[heap]" : + snprintf(buf, count, + "%012lx-%012lx %s%s%s%s %lx %lx:%lx %d\t\t\t%s\n", + range->start, range->end, + range->flag & VR_PROT_READ ? "r" : "-", + range->flag & VR_PROT_WRITE ? "w" : "-", + range->flag & VR_PROT_EXEC ? "x" : "-", + range->flag & VR_PRIVATE ? "p" : "s", + /* TODO: fill in file details! */ + 0UL, + 0UL, + 0UL, + 0, + range->memobj && range->memobj->path ? + range->memobj->path : + range->start == (unsigned long)vm->vdso_addr ? + "[vdso]" : + range->start == (unsigned long)vm->vvar_addr ? + "[vsyscall]" : + range->flag & VR_STACK ? + "[stack]" : + range->start >= vm->region.brk_start && + range->end <= vm->region.brk_end_allocated ? + "[heap]" : "" - ); - - left -= written_now; - _buf += written_now; - written += written_now; + ); -#ifdef POSTK_DEBUG_TEMP_FIX_47 /* /proc//maps 1024 byte over read fix. */ - if (left == 0) { - kprintf("%s(): WARNING: buffer too small to fill proc/maps\n", - __FUNCTION__); - break; + if (buf_add(&buf_top, &buf_cur, buf, strlen(buf)) < 0) { + ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock); + goto err; } -#else /* POSTK_DEBUG_TEMP_FIX_47 */ - if (left == 1) { - kprintf("%s(): WARNING: buffer too small to fill proc/maps\n", - __FUNCTION__); - break; - } -#endif /* POSTK_DEBUG_TEMP_FIX_47 */ range = next_process_memory_range(vm, range); } ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock); -#ifdef POSTK_DEBUG_TEMP_FIX_47 /* /proc//maps 1024 byte over read fix. */ - len = strlen(tmp); - if (r->offset < len) { - if (r->offset + r->count < len) { - ans = r->count; - } else { - eof = 1; - ans = len; - } - strncpy(buf, tmp + r->offset, ans); - } else if (r->offset == len) { - ans = 0; - eof = 1; - } - kfree(tmp); -#else /* POSTK_DEBUG_TEMP_FIX_47 */ - ans = written; - eof = 1; -#endif /* POSTK_DEBUG_TEMP_FIX_47 */ + ans = 0; goto end; } @@ -465,28 +499,16 @@ int process_procfs_request(struct ikc_scd_packet *rpacket) extern int num_processors; /* kernel/ap.c */ struct vm_range *range; unsigned long lockedsize = 0; - char *tmp; char *bitmasks; int bitmasks_offset = 0; char *cpu_bitmask, *cpu_list, *numa_bitmask, *numa_list; - int len; char *state; - tmp = kmalloc(8192, IHK_MC_AP_CRITICAL); - if (!tmp) { - kprintf("%s: error allocating /proc/self/status buffer\n", - __FUNCTION__); - ans = 0; - goto end; - } - bitmasks = kmalloc(BITMASKS_BUF_SIZE, IHK_MC_AP_CRITICAL); - if (!tmp) { + if (!bitmasks) { kprintf("%s: error allocating /proc/self/status bitmaks buffer\n", __FUNCTION__); - kfree(tmp); - ans = 0; - goto end; + goto err; } ihk_mc_spinlock_lock_noirq(&proc->vm->memory_range_lock); @@ -529,37 +551,43 @@ int process_procfs_request(struct ikc_scd_packet *rpacket) state = "T (tracing stop)"; else if (proc->status == PS_EXITED) state = "Z (zombie)"; - sprintf(tmp, - "Pid:\t%d\n" - "Uid:\t%d\t%d\t%d\t%d\n" - "Gid:\t%d\t%d\t%d\t%d\n" + sprintf(buf, + "Pid:\t%d\n" + "Uid:\t%d\t%d\t%d\t%d\n" + "Gid:\t%d\t%d\t%d\t%d\n" "State:\t%s\n" - "VmLck:\t%9lu kB\n" - "Cpus_allowed:\t%s\n" - "Cpus_allowed_list:\t%s\n" - "Mems_allowed:\t%s\n" - "Mems_allowed_list:\t%s\n", - proc->pid, - proc->ruid, proc->euid, proc->suid, proc->fsuid, - proc->rgid, proc->egid, proc->sgid, proc->fsgid, + "VmLck:\t%9lu kB\n", + proc->pid, + proc->ruid, proc->euid, proc->suid, proc->fsuid, + proc->rgid, proc->egid, proc->sgid, proc->fsgid, state, - (lockedsize + 1023) >> 10, - cpu_bitmask, cpu_list, numa_bitmask, numa_list); - len = strlen(tmp); - if (r->offset < len) { - if (r->offset + r->count < len) { - ans = r->count; - } else { - eof = 1; - ans = len; - } - strncpy(buf, tmp + r->offset, ans); - } else if (r->offset == len) { - ans = 0; - eof = 1; + (lockedsize + 1023) >> 10); + if (buf_add(&buf_top, &buf_cur, buf, strlen(buf)) < 0) { + goto err; + } + + sprintf(buf, "Cpus_allowed:\t%s\n", cpu_bitmask); + if (buf_add(&buf_top, &buf_cur, buf, strlen(buf)) < 0) { + kfree(bitmasks); + goto err; + } + sprintf(buf, "Cpus_allowed_list:\t%s\n", cpu_list); + if (buf_add(&buf_top, &buf_cur, buf, strlen(buf)) < 0) { + kfree(bitmasks); + goto err; + } + sprintf(buf, "Mems_allowed:\t%s\n", numa_bitmask); + if (buf_add(&buf_top, &buf_cur, buf, strlen(buf)) < 0) { + kfree(bitmasks); + goto err; + } + sprintf(buf, "Mems_allowed_list:\t%s\n", numa_list); + if (buf_add(&buf_top, &buf_cur, buf, strlen(buf)) < 0) { + kfree(bitmasks); + goto err; } - kfree(tmp); kfree(bitmasks); + ans = 0; goto end; } @@ -568,20 +596,10 @@ int process_procfs_request(struct ikc_scd_packet *rpacket) */ if (strcmp(p, "auxv") == 0) { unsigned int limit = AUXV_LEN * sizeof(unsigned long); - unsigned int len = r->count; - if (r->offset < limit) { - if (limit < r->offset + r->count) { - len = limit - r->offset; - } - memcpy((void *)buf, ((char *) proc->saved_auxv) + r->offset, len); - ans = len; - if (r->offset + len == limit) { - eof = 1; - } - } else if (r->offset == limit) { - ans = 0; - eof = 1; - } + + if (buf_add(&buf_top, &buf_cur, proc->saved_auxv, limit) < 0) + goto err; + ans = 0; goto end; } @@ -590,27 +608,17 @@ int process_procfs_request(struct ikc_scd_packet *rpacket) */ if (strcmp(p, "cmdline") == 0) { unsigned int limit = proc->saved_cmdline_len; - unsigned int len = r->count; if(!proc->saved_cmdline){ + if (buf_add(&buf_top, &buf_cur, "", 0) < 0) + goto err; ans = 0; - eof = 1; goto end; } - if (r->offset < limit) { - if (limit < r->offset + r->count) { - len = limit - r->offset; - } - memcpy((void *)buf, ((char *) proc->saved_cmdline) + r->offset, len); - ans = len; - if (r->offset + len == limit) { - eof = 1; - } - } else if (r->offset == limit) { - ans = 0; - eof = 1; - } + if (buf_add(&buf_top, &buf_cur, proc->saved_cmdline, limit) < 0) + goto err; + ans = 0; goto end; } @@ -622,8 +630,6 @@ int process_procfs_request(struct ikc_scd_packet *rpacket) */ if (!strcmp(p, "stat")) { - char tmp[1024]; - int len; /* * pid (comm) state ppid @@ -638,7 +644,7 @@ int process_procfs_request(struct ikc_scd_packet *rpacket) * cnswap exit_signal processor rt_priority * policy delayacct_blkio_ticks guest_time cguest_time */ - ans = sprintf(tmp, + ans = sprintf(buf, "%d (%s) %c %d " // pid... "%d %d %d %d " // pgrp... "%u %lu %lu %lu " // flags... @@ -662,21 +668,10 @@ int process_procfs_request(struct ikc_scd_packet *rpacket) 0L, 0, thread->cpu_id, 0, // cnswap... 0, 0LL, 0L, 0L // policy... ); - dprintf("tmp=%s\n", tmp); - len = strlen(tmp); - if (r->offset < len) { - if (r->offset + r->count < len) { - ans = r->count; - } else { - eof = 1; - ans = len; - } - strncpy(buf, tmp + r->offset, ans); - } else if (r->offset == len) { - ans = 0; - eof = 1; - } + if (buf_add(&buf_top, &buf_cur, buf, strlen(buf)) < 0) + goto err; + ans = 0; goto end; } @@ -686,16 +681,24 @@ int process_procfs_request(struct ikc_scd_packet *rpacket) kprintf("unsupported procfs entry: %d/%s\n", pid, p); end: - ihk_mc_unmap_virtual(buf, npages); dprintf("ret: %d, eof: %d\n", ans, eof); r->ret = ans; r->eof = eof; err = 0; -bufunavail: - ihk_mc_unmap_memory(NULL, pbuf, r->count); - ihk_mc_unmap_virtual(r, 1); -dataunavail: - ihk_mc_unmap_memory(NULL, parg, sizeof(struct procfs_read)); + if (r->pbuf == PA_NULL && buf_top) + r->pbuf = virt_to_phys(buf_top); +err: + if (vbuf) { + ihk_mc_unmap_virtual(vbuf, npages); + ihk_mc_unmap_memory(NULL, pbuf, r->count); + } + if (r) { + ihk_mc_unmap_virtual(r, 1); + ihk_mc_unmap_memory(NULL, parg, sizeof(struct procfs_read)); + } + if (tmp) { + ihk_mc_free_pages(tmp, 1); + } if(proc) release_process(proc); diff --git a/test/issues/1021/C1021.c b/test/issues/1021/C1021.c new file mode 100644 index 00000000..df55bd09 --- /dev/null +++ b/test/issues/1021/C1021.c @@ -0,0 +1,286 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int id; +int okcnt; +int ngcnt; +void *area; + +void +ok(char *file, char *fmt, ...) +{ + va_list ap; + + printf("*** C1021T%02d %s ", id, file); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\n"); + okcnt++; +} + +void +ng(char *file, char *fmt, ...) +{ + va_list ap; + + printf("*** C1021T%02d %s ", id, file); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\n"); + ngcnt++; +} + +void +hex(char *bp, int len) +{ + unsigned char *buf; + long l; + long p; + long zl = 0; + long zf = 1; + long zp = 0; + + for (p = 0; p < len; p += 16) { + int i; + + buf = (unsigned char *)bp + p; + l = 16; + if (p + 16 > len) { + l = len - p; + } + if (!zf) { + int zz = 0; + + for (i = 0; i < l; i++) { + if (buf[i]) + zz = 1; + } + if (l < 16 || !zz) { + zl += 16; + continue; + } + if (zl == 16) { + printf("%016lx 00000000 00000000 00000000 " + "00000000 *................*\n", zp); + } + else if (zl) { + printf(" %08lx - %08lx ZERO\n", zp, p); + } + } + zf = 0; + printf("%08lx ", p); + for (i = 0; i < 16; i++) { + if (i % 4 == 0) + printf(" "); + printf(i < l ? "%02x" : " ", buf[i]); + if (i < l && buf[i]) + zf = 1; + } + printf(" *"); + for (i = 0; i < 16; i++) + printf(i < l ? "%c" : " ", + isprint(buf[i]) ? buf[i] : '.'); + printf("*\n"); + zl = 0; + zp = p + 16; + } +} + +void +sub(char *file, int mapsflag) +{ + int fd; + int fd2; + char buf1[65536]; + char buf2[65536]; + char buf3[65536]; + int n; + int rc; + int pos; + + id++; + fd = open(file, O_RDONLY); + if (fd == -1) { + ng(file, "open %s", strerror(errno)); + } + else { + ok(file, "open OK"); + } + + id++; + fd2 = dup(fd); + if (fd2 == -1) { + ng(file, "dup %s", strerror(errno)); + } + else { + ok(file, "dup OK"); + } + + id++; + for (n = 0; (rc = read(fd, buf1 + n, 1)) == 1; n++); + if (rc == -1) { + ng(file, "read(1) %s", strerror(errno)); + } + else if (mapsflag && n < 4096) { + ng(file, "read(1) short n=%d", n); + } + else { + ok(file, "read(1) OK n=%d", n); + } + + id++; + rc = lseek(fd, 0L, SEEK_SET); + if (rc == -1) { + ng(file, "lseek %s", strerror(errno)); + } + else { + ok(file, "lseek OK"); + } + + if (mapsflag) + munmap(area, 4096); + + id++; + pos = 0; + while ((rc = read(fd, buf2 + pos, 1024)) > 0) { + pos += rc; + } + if (rc == -1) { + ng(file, "read(1) %s\n", strerror(errno)); + } + else { + if (pos != n) { + ng(file, "read(1024) invalid size %d != %d", pos, n); + } + else if (memcmp(buf1, buf2, n) != 0) { + ng(file, "read(1024) invalid data"); + hex(buf1, n); + hex(buf2, n); + } + else { + ok(file, "read(1024) OK"); + } + } + + id++; + rc = close(fd); + if (rc == -1) { + ng(file, "close %s", strerror(errno)); + } + else { + ok(file, "close OK"); + } + + id++; + rc = read(fd2, buf3, n); + if (rc == -1) { + ng(file, "read(dup) EOF %s", strerror(errno)); + } + else if (rc == 0) { + ok(file, "read(dup) EOF OK"); + } + else { + ng(file, "read(dup) invalid position"); + } + + id++; + rc = lseek(fd2, 0L, SEEK_SET); + if (rc == -1) { + ng(file, "lseek(dup) %s", strerror(errno)); + } + else { + ok(file, "lseek(dup) OK"); + } + + + id++; + rc = read(fd2, buf3, n); + if (rc == -1) { + ng(file, "read(dup) %s", strerror(errno)); + } + else if (rc != n) { + ng(file, "read(dup) too short"); + } + else { + rc = read(fd2, buf3 + rc, n); + if (rc == -1) { + ng(file, "read(dup) %s", strerror(errno)); + } + else if (rc != 0) { + ng(file, "read(dup) too long"); + } + else if (memcmp(buf1, buf3, n) != 0) { + ng(file, "read(dup) invalid data"); + hex(buf1, n); + hex(buf3, n); + } + else { + ok(file, "read(dup) OK"); + } + } + + id++; + rc = close(fd2); + if (rc == -1) { + ng(file, "close(dup) %s", strerror(errno)); + } + else { + ok(file, "close(dup) OK"); + } +} + +int +main(int argc, char **argv) +{ + int i; + int pid = getpid(); + char file[1024]; + + for (i = 0; i < 512; i++) { + char *c; + + if (i % 2) { + c = mmap(NULL, 4096, PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + area = c; + } + else { + c = mmap(NULL, 4096, PROT_READ|PROT_WRITE, + MAP_SHARED|MAP_ANONYMOUS, -1, 0); + } + + if (c == (void *)-1) { + printf("mmap error %d\n", errno); + exit(1); + } + *c = 1; + } + sub("/proc/stat", 0); + sprintf(file, "/proc/%d/auxv", pid); + sub(file, 0); + sprintf(file, "/proc/%d/cmdline", pid); + sub(file, 0); + sprintf(file, "/proc/%d/maps", pid); + sub(file, 1); + sprintf(file, "/proc/%d/status", pid); + sub(file, 0); + sprintf(file, "/proc/%d/task/%d/stat", pid, pid); + sub(file, 0); + + if (ngcnt) { + printf("TEST FAILED OK=%d NG=%d\n", okcnt, ngcnt); + exit(1); + } + printf("TEST SUCCESS OK=%d\n", okcnt); + exit(0); +} diff --git a/test/issues/1021/C1021.sh b/test/issues/1021/C1021.sh new file mode 100755 index 00000000..f9610bf8 --- /dev/null +++ b/test/issues/1021/C1021.sh @@ -0,0 +1,81 @@ +#!/bin/sh +BIN= +SBIN= +LTP= +OSTEST= +BOOTPARAM="-c 1-7,17-23,9-15,25-31 -m 10G@0,10G@1" + +if ! sudo ls /sys/kernel/debug | grep kmemleak > /dev/null 2>&1; then + echo kmemleak: not found >&2 + exit 1 +fi + +if [ -f ../../../config.h ]; then + str=`grep "^#define BINDIR " ../../../config.h | head -1 | sed 's/^#define BINDIR /BINDIR=/'` + eval $str +fi +if [ "x$BINDIR" = x ];then + BINDIR="$BIN" +fi + +if [ -f ../../../Makefile ]; then + str=`grep ^SBINDIR ../../../Makefile | head -1 | sed 's/ //g'` + eval $str +fi +if [ "x$SBINDIR" = x ];then + SBINDIR="$SBIN" +fi + +if [ -f $HOME/ltp/testcases/bin/fork01 ]; then + LTPDIR=$HOME/ltp +fi +if [ "x$LTPDIR" = x ]; then + LTPDIR="$LTP" +fi +if [ "x$LTPDIR" != x ]; then + LTPDIR="$LTPDIR/testcases" +fi + +if [ -f $HOME/ostest/bin/test_mck ]; then + OSTESTDIR=$HOME/ostest/ +fi +if [ "x$OSTESTDIR" = x ]; then + OSTESTDIR="$OSTEST" +fi +if [ ! -x "$OSTESTDIR"/bin/test_mck ]; then + echo no ostest found $OSTEST >&2 + exit 1 +fi +TESTMCK="$OSTESTDIR/bin/test_mck" + +if [ ! -x $SBINDIR/mcstop+release.sh ]; then + echo mcstop+release: not found >&2 + exit 1 +fi +echo -n "mcstop+release.sh ... " +sudo $SBINDIR/mcstop+release.sh +echo "done" + +if [ ! -x $SBINDIR/mcreboot.sh ]; then + echo mcreboot: not found >&2 + exit 1 +fi +echo -n "mcreboot.sh $BOOTPARAM ... " +sudo $SBINDIR/mcreboot.sh $BOOTPARAM +echo "done" + +if [ ! -x $BINDIR/mcexec ]; then + echo no mcexec found >&2 + exit 1 +fi + +################################################################################ +sudo sh -c 'echo clear > /sys/kernel/debug/kmemleak' +$BINDIR/mcexec ./C1021 +sudo $SBINDIR/mcstop+release.sh +sudo sh -c 'echo scan > /sys/kernel/debug/kmemleak' +if sudo cat /sys/kernel/debug/kmemleak | tee C1021T71.kmemleak | grep 'mcctrl'; then + echo '*** C1021T61 NG (kmemleak)' +else + echo '*** C1021T61 OK (kmemleak)' +fi diff --git a/test/issues/1021/C1021.txt b/test/issues/1021/C1021.txt new file mode 100644 index 00000000..33d314b3 --- /dev/null +++ b/test/issues/1021/C1021.txt @@ -0,0 +1,71 @@ +Script started on Wed Aug 29 15:21:45 2018 +bash-4.2$ make test +sh ./C1021.sh +mcstop+release.sh ... done +mcreboot.sh -c 1-7,17-23,9-15,25-31 -m 10G@0,10G@1 ... done +*** C1021T01 /proc/stat open OK +*** C1021T02 /proc/stat dup OK +*** C1021T03 /proc/stat read(1) OK n=158 +*** C1021T04 /proc/stat lseek OK +*** C1021T05 /proc/stat read(1024) OK +*** C1021T06 /proc/stat close OK +*** C1021T07 /proc/stat read(dup) EOF OK +*** C1021T08 /proc/stat lseek(dup) OK +*** C1021T09 /proc/stat read(dup) OK +*** C1021T10 /proc/stat close(dup) OK +*** C1021T11 /proc/12455/auxv open OK +*** C1021T12 /proc/12455/auxv dup OK +*** C1021T13 /proc/12455/auxv read(1) OK n=144 +*** C1021T14 /proc/12455/auxv lseek OK +*** C1021T15 /proc/12455/auxv read(1024) OK +*** C1021T16 /proc/12455/auxv close OK +*** C1021T17 /proc/12455/auxv read(dup) EOF OK +*** C1021T18 /proc/12455/auxv lseek(dup) OK +*** C1021T19 /proc/12455/auxv read(dup) OK +*** C1021T20 /proc/12455/auxv close(dup) OK +*** C1021T21 /proc/12455/cmdline open OK +*** C1021T22 /proc/12455/cmdline dup OK +*** C1021T23 /proc/12455/cmdline read(1) OK n=8 +*** C1021T24 /proc/12455/cmdline lseek OK +*** C1021T25 /proc/12455/cmdline read(1024) OK +*** C1021T26 /proc/12455/cmdline close OK +*** C1021T27 /proc/12455/cmdline read(dup) EOF OK +*** C1021T28 /proc/12455/cmdline lseek(dup) OK +*** C1021T29 /proc/12455/cmdline read(dup) OK +*** C1021T30 /proc/12455/cmdline close(dup) OK +*** C1021T31 /proc/12455/maps open OK +*** C1021T32 /proc/12455/maps dup OK +*** C1021T33 /proc/12455/maps read(1) OK n=25401 +*** C1021T34 /proc/12455/maps lseek OK +*** C1021T35 /proc/12455/maps read(1024) OK +*** C1021T36 /proc/12455/maps close OK +*** C1021T37 /proc/12455/maps read(dup) EOF OK +*** C1021T38 /proc/12455/maps lseek(dup) OK +*** C1021T39 /proc/12455/maps read(dup) OK +*** C1021T40 /proc/12455/maps close(dup) OK +*** C1021T41 /proc/12455/status open OK +*** C1021T42 /proc/12455/status dup OK +*** C1021T43 /proc/12455/status read(1) OK n=255 +*** C1021T44 /proc/12455/status lseek OK +*** C1021T45 /proc/12455/status read(1024) OK +*** C1021T46 /proc/12455/status close OK +*** C1021T47 /proc/12455/status read(dup) EOF OK +*** C1021T48 /proc/12455/status lseek(dup) OK +*** C1021T49 /proc/12455/status read(dup) OK +*** C1021T50 /proc/12455/status close(dup) OK +*** C1021T51 /proc/12455/task/12455/stat open OK +*** C1021T52 /proc/12455/task/12455/stat dup OK +*** C1021T53 /proc/12455/task/12455/stat read(1) OK n=92 +*** C1021T54 /proc/12455/task/12455/stat lseek OK +*** C1021T55 /proc/12455/task/12455/stat read(1024) OK +*** C1021T56 /proc/12455/task/12455/stat close OK +*** C1021T57 /proc/12455/task/12455/stat read(dup) EOF OK +*** C1021T58 /proc/12455/task/12455/stat lseek(dup) OK +*** C1021T59 /proc/12455/task/12455/stat read(dup) OK +*** C1021T60 /proc/12455/task/12455/stat close(dup) OK +TEST SUCCESS OK=60 +*** C1021T61 OK (kmemleak) +bash-4.2$ exit +exit + +Script done on Wed Aug 29 15:22:55 2018 diff --git a/test/issues/1021/Makefile b/test/issues/1021/Makefile new file mode 100644 index 00000000..cfdd0e6f --- /dev/null +++ b/test/issues/1021/Makefile @@ -0,0 +1,13 @@ +CC=gcc +TARGET=C1021 + +all:: $(TARGET) + +C1021: C1021.c + $(CC) -o C1021 C1021.c -Wall -g + +test:: $(TARGET) + sh ./C1021.sh + +clean:: + rm -f *.o $(TARGET) diff --git a/test/issues/1021/README b/test/issues/1021/README new file mode 100644 index 00000000..59d76831 --- /dev/null +++ b/test/issues/1021/README @@ -0,0 +1,58 @@ +【Issue#1021 動作確認】 +□ テスト内容 +1. procfs ファイルに対するファイルオペレーションのテスト +Issue#1021 の対応において、procfs の以下のファイル処理を変更している。 + /proc/stat + /proc/pid/auxv + /proc/pid/cmdline + /proc/pid/maps + /proc/pid/status + /proc/pid/task/tid/stat + +これらのファイルに対するファイルオペレーションとして、以下をテストする。 +1) ファイルをopen(2)できること。 +2) ファイルディスクリプタをdup(2)できること。 +3) 1バイト単位にファイル終端までread(2)できること。 +4) lseek(2) できること。(※2) +5) lseek(2) 後に、1024バイト単位に read(2) できること。最初の read(2)と内容が + 一致していること。 +6) close(2) できること。 +7) dup(2) したファイルディスクリプタが EOF になっていること (5 の read(2) の + 影響)。 +8) dup(2) したファイルディスクリプタを lseek(2) できること。 +9) dup(2) したファイルディスクリプタを read(2) し、ファイル全体を 1 回の read(2) + で読み込むことができること。また、最初の read(2) と内容が一致していること。 +10) dup(2) したファイルを close(2) できること。 + +テストケースは以下の通りである。 +C1021T01-C1021T10 /proc/stat に対する上記 1) - 10) のテスト +C1021T11-C1021T20 /proc/pid/auxv に対する上記 1) - 10) のテスト +C1021T21-C1021T30 /proc/pid/cmdline に対する上記 1) - 10) のテスト +C1021T31-C1021T40 /proc/pid/maps に対する上記 1) - 10) のテスト (※1, ※2) +C1021T41-C1021T50 /proc/pid/status に対する上記 1) - 10) のテスト +C1021T51-C1021T60 /proc/pid/rask/tid/stat に対する上記 1) - 10) のテスト + +※1 /proc/pid/maps はユーザプログラムのメモリの使い方により非常に大きなファイル + になることがあるので、予め mmap を複数回行って4kB以上の read が発生するよう + にしておく。(McKernel 内のバッファが複数ページになる場合のテストを兼ねる)。 + +※2 /proc/pid/maps の読み込み中に情報が変化しても後続の read(2) に影響しない + ことを確認するため、/proc/pid/maps の lseek(2) 後に munmap(2) を行い、 + McKernel の内部情報を変化させる。(後続の read(2) では、munmap 前の情報を + 読み込む仕様)。 + +2. メモリリークが発生していないことの確認 +C1021T61 kmemleak を用いて mcctrl の procfs 処理がメモリリークを起こして + いないことを確認する。 + +□ 実行手順 +$ make test + +実行できない場合は、C1021.shの以下の行を適切に書き換えた後に実行。 +BIN= mcexec が存在するパス +SBIN= mcreboot.sh が存在するパス +LTP= LTP が存在するパス + +□ 実行結果 +C1021.txt 参照。 +全ての項目が OK となっていることを確認。