diff --git a/executer/kernel/mcctrl/control.c b/executer/kernel/mcctrl/control.c index 434f16fb..f8362e66 100644 --- a/executer/kernel/mcctrl/control.c +++ b/executer/kernel/mcctrl/control.c @@ -72,9 +72,6 @@ int (*mcctrl_sys_mount)(char *dev_name,char *dir_name, char *type, unsigned long //static DECLARE_WAIT_QUEUE_HEAD(wq_prepare); //extern struct mcctrl_channel *channels; int mcctrl_ikc_set_recv_cpu(ihk_os_t os, int cpu); -extern int procfs_create_entry(void *os, int ref, int osnum, int pid, char *name, - int mode, void *opaque); -extern void procfs_delete_entry(void *os, int osnum, char *fname); static long mcexec_prepare_image(ihk_os_t os, struct program_load_desc * __user udesc) @@ -290,12 +287,15 @@ static void release_handler(ihk_os_t os, void *param) { struct handlerinfo *info = param; struct ikc_scd_packet isp; + int os_ind = ihk_host_os_get_index(os); memset(&isp, '\0', sizeof isp); isp.msg = SCD_MSG_CLEANUP_PROCESS; isp.pid = info->pid; mcctrl_ikc_send(os, 0, &isp); + if(os_ind >= 0) + delete_pid_entry(os_ind, info->pid); kfree(param); } @@ -861,7 +861,7 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename) struct mckernel_exec_file *mcef_iter; int retval; int os_ind = ihk_host_os_get_index(os); - char *proc_name, *pathbuf, *fullpath; + char *pathbuf, *fullpath; if (os_ind < 0) { return EINVAL; @@ -872,12 +872,6 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename) return ENOMEM; } - proc_name = kmalloc(PATH_MAX, GFP_TEMPORARY); - if (!proc_name) { - retval = ENOMEM; - goto out_error_free_path; - } - file = open_exec(filename); retval = PTR_ERR(file); if (IS_ERR(file)) { @@ -896,8 +890,6 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename) goto out_put_file; } - snprintf(proc_name, 1024, "mcos%d/%d/exe", os_ind, current->tgid); - spin_lock_irq(&mckernel_exec_file_lock); /* Find previous file (if exists) and drop it */ list_for_each_entry(mcef_iter, &mckernel_exec_files, list) { @@ -906,9 +898,6 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename) fput(mcef_iter->fp); list_del(&mcef_iter->list); kfree(mcef_iter); - /* Drop old /proc/self/exe */ - procfs_delete_entry(os, os_ind, proc_name); - dprintk("%d open_exec dropped previous executable \n", (int)current->tgid); break; } } @@ -920,15 +909,12 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename) list_add_tail(&mcef->list, &mckernel_exec_files); /* Create /proc/self/exe entry */ - if (procfs_create_entry(os, 0, os_ind, current->tgid, proc_name, - S_IFLNK, fullpath) != 0) { - printk("ERROR: could not create a procfs entry for %s.\n", proc_name); - } + add_pid_entry(os_ind, current->tgid); + proc_exe_link(os_ind, current->tgid, fullpath); spin_unlock(&mckernel_exec_file_lock); dprintk("%d open_exec and holding file: %s\n", (int)current->tgid, filename); - kfree(proc_name); kfree(pathbuf); return 0; @@ -937,9 +923,6 @@ out_put_file: fput(file); out_error_free: - kfree(proc_name); - -out_error_free_path: kfree(pathbuf); return -retval; } @@ -950,7 +933,6 @@ int mcexec_close_exec(ihk_os_t os) struct mckernel_exec_file *mcef = NULL; int found = 0; int os_ind = ihk_host_os_get_index(os); - char proc_name[1024]; if (os_ind < 0) { return EINVAL; @@ -969,14 +951,6 @@ int mcexec_close_exec(ihk_os_t os) } } - /* Remove /proc/self/exe and /proc/self directory - * TODO: instead of removing directory explicitly, detect in procfs_delete_entry() - * when a directory becomes empty and remove it automatically */ - snprintf(proc_name, 1024, "mcos%d/%d/exe", os_ind, current->tgid); - procfs_delete_entry(os, os_ind, proc_name); - snprintf(proc_name, 1024, "mcos%d/%d", os_ind, current->tgid); - procfs_delete_entry(os, os_ind, proc_name); - spin_unlock(&mckernel_exec_file_lock); return (found ? 0 : EINVAL); diff --git a/executer/kernel/mcctrl/driver.c b/executer/kernel/mcctrl/driver.c index 60a545bb..81e5f572 100644 --- a/executer/kernel/mcctrl/driver.c +++ b/executer/kernel/mcctrl/driver.c @@ -82,6 +82,12 @@ static struct ihk_os_user_call mcctrl_uc[OS_MAX_MINOR]; static ihk_os_t os[OS_MAX_MINOR]; +ihk_os_t +osnum_to_os(int n) +{ + return os[n]; +} + static int __init mcctrl_init(void) { int i; diff --git a/executer/kernel/mcctrl/ikc.c b/executer/kernel/mcctrl/ikc.c index 9a7a2a4d..fe0e0721 100644 --- a/executer/kernel/mcctrl/ikc.c +++ b/executer/kernel/mcctrl/ikc.c @@ -41,9 +41,6 @@ void mcexec_prepare_ack(ihk_os_t os, unsigned long arg, int err); static void mcctrl_ikc_init(ihk_os_t os, int cpu, unsigned long rphys, struct ihk_ikc_channel_desc *c); int mcexec_syscall(struct mcctrl_channel *c, int pid, unsigned long arg); -void procfs_create(void *__os, int ref, int osnum, int pid, unsigned long arg); -void procfs_delete(void *__os, int osnum, unsigned long arg); -void procfs_answer(unsigned long arg, int err); void sig_done(unsigned long arg, int err); static int syscall_packet_handler(struct ihk_ikc_channel_desc *c, @@ -69,14 +66,6 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c, mcexec_syscall(usrdata->channels + pisp->ref, pisp->pid, pisp->arg); break; - case SCD_MSG_PROCFS_CREATE: - procfs_create(__os, pisp->ref, pisp->osnum, pisp->pid, pisp->arg); - break; - - case SCD_MSG_PROCFS_DELETE: - procfs_delete(__os, pisp->osnum, pisp->arg); - break; - case SCD_MSG_PROCFS_ANSWER: procfs_answer(pisp->arg, pisp->err); break; @@ -98,6 +87,14 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c, pisp->sysfs_arg1, pisp->sysfs_arg2); break; + case SCD_MSG_PROCFS_TID_CREATE: + add_tid_entry(ihk_host_os_get_index(__os), pisp->pid, pisp->arg); + break; + + case SCD_MSG_PROCFS_TID_DELETE: + delete_tid_entry(ihk_host_os_get_index(__os), pisp->pid, pisp->arg); + break; + default: printk(KERN_ERR "mcctrl:syscall_packet_handler:" "unknown message (%d.%d.%d.%d.%d.%#lx)\n", diff --git a/executer/kernel/mcctrl/mcctrl.h b/executer/kernel/mcctrl/mcctrl.h index abd0d1bc..0354065e 100644 --- a/executer/kernel/mcctrl/mcctrl.h +++ b/executer/kernel/mcctrl/mcctrl.h @@ -81,6 +81,8 @@ #define SCD_MSG_SYSFS_RESP_SETUP 0x41 /* #define SCD_MSG_SYSFS_REQ_CLEANUP 0x42 */ /* #define SCD_MSG_SYSFS_RESP_CLEANUP 0x43 */ +#define SCD_MSG_PROCFS_TID_CREATE 0x44 +#define SCD_MSG_PROCFS_TID_DELETE 0x45 #define DMA_PIN_SHIFT 21 @@ -226,6 +228,8 @@ int mcctrl_ikc_is_valid_thread(ihk_os_t os, int cpu); int reserve_user_space(struct mcctrl_usrdata *usrdata, unsigned long *startp, unsigned long *endp); +ihk_os_t osnum_to_os(int n); + /* syscall.c */ int init_peer_channel_registry(struct mcctrl_usrdata *ud); void destroy_peer_channel_registry(struct mcctrl_usrdata *ud); @@ -244,6 +248,7 @@ struct procfs_read { int ret; /* read bytes (answer) */ int status; /* non-zero if done (answer) */ int newcpu; /* migrated new cpu (answer) */ + int readwrite; /* 0:read, 1:write */ char fname[PROCFS_NAME_MAX]; /* procfs filename (request) */ }; @@ -253,6 +258,15 @@ struct procfs_file { char fname[PROCFS_NAME_MAX]; /* procfs filename (request) */ }; +void procfs_answer(unsigned int arg, int err); +void add_tid_entry(int osnum, int pid, int tid); +void add_pid_entry(int osnum, int pid); +void delete_tid_entry(int osnum, int pid, int tid); +void delete_pid_entry(int osnum, int pid); +void proc_exe_link(int osnum, int pid, const char *path); +void procfs_init(int osnum); +void procfs_exit(int osnum); + /* sysfs_files.c */ void setup_sysfs_files(ihk_os_t os); diff --git a/executer/kernel/mcctrl/procfs.c b/executer/kernel/mcctrl/procfs.c index c316a86a..16714b98 100644 --- a/executer/kernel/mcctrl/procfs.c +++ b/executer/kernel/mcctrl/procfs.c @@ -28,6 +28,35 @@ #define dprintk(...) #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) +typedef uid_t kuid_t; +typedef gid_t kgid_t; +#endif + +struct procfs_entry { + char *name; + mode_t mode; + const struct file_operations *fops; +}; + +#define NOD(NAME, MODE, FOP) { \ + .name = (NAME), \ + .mode = MODE, \ + .fops = FOP, \ +} +#define PROC_DIR(NAME, MODE) \ + NOD(NAME, (S_IFDIR|(MODE)), NULL) +#define PROC_REG(NAME, MODE, fops) \ + NOD(NAME, (S_IFREG|(MODE)), fops) +#define PROC_TERM \ + NOD(NULL, 0, NULL) + +static const struct procfs_entry tid_entry_stuff[]; +static const struct procfs_entry pid_entry_stuff[]; +static const struct procfs_entry base_entry_stuff[]; +static const struct file_operations mckernel_forward_ro; +static const struct file_operations mckernel_forward; + static DECLARE_WAIT_QUEUE_HEAD(procfsq); static ssize_t mckernel_procfs_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos); @@ -39,11 +68,10 @@ struct procfs_list_entry { struct list_head list; struct proc_dir_entry *entry; struct procfs_list_entry *parent; - ihk_os_t os; + struct list_head children; int osnum; - int pid; - int cpu; - char fname[PROCFS_NAME_MAX]; + char *data; + char name[0]; }; /* @@ -52,324 +80,25 @@ struct procfs_list_entry { * always nearer to the list top than its parent node * file. */ - LIST_HEAD(procfs_file_list); static ihk_spinlock_t procfs_file_list_lock; -loff_t mckernel_procfs_lseek(struct file *file, loff_t offset, int orig) +static char * +getpath(struct procfs_list_entry *e, char *buf, int bufsize) { - switch (orig) { - case 0: - file->f_pos = offset; - break; - case 1: - file->f_pos += offset; - break; - default: - return -EINVAL; + char *w = buf + bufsize - 1; + + *w = '\0'; + for(;;){ + int l = strlen(e->name); + w -= l; + memcpy(w, e->name, l); + e = e->parent; + if(!e) + return w; + w--; + *w = '/'; } - return file->f_pos; -} - -static const struct file_operations mckernel_procfs_file_operations = { - .llseek = mckernel_procfs_lseek, - .read = mckernel_procfs_read, - .write = NULL, -}; - - -/** - * \brief Return specified procfs entry. - * - * \param p a name of the procfs file - * \param osnum os number - * \param mode if zero create a directory otherwise a file or link - * \param opaque additional context dependent information - * - * return value: NULL: Something wrong has occurred. - * otherwise: address of the proc_dir_entry structure of the procfs file - * - * p should not be NULL nor terminated by "/". - * - * We create a procfs entry if there is not already one. - * This process is recursive to the root of the procfs tree. - */ -/* - * XXX: Two or more entries which have same name can be created. - * - * get_procfs_list_entry() avoids creating an entry which has already been created. - * But, it allows creating an entry which is being created by another thread. - * - * This problem occurred when two requests which created files with a common - * ancestor directory which was not explicitly created were racing. - */ - -struct procfs_list_entry *get_procfs_list_entry(char *p, int osnum, int mode, void *opaque, const struct cred *cred) -{ - char *r; - struct proc_dir_entry *pde = NULL; - struct procfs_list_entry *e, *ret = NULL, *parent = NULL; - char name[PROCFS_NAME_MAX]; - unsigned long irqflags; - - dprintk("get_procfs_list_entry: %s for osnum %d mode %o\n", p, osnum, mode); - irqflags = ihk_ikc_spinlock_lock(&procfs_file_list_lock); - list_for_each_entry(e, &procfs_file_list, list) { - if (e == NULL) { - kprintf("ERROR: The procfs_file_list has a null entry.\n"); - return NULL; - } - if (strncmp(e->fname, p, PROCFS_NAME_MAX) == 0) { - /* We found the entry */ - ret = e; - break; - } - } - ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflags); - if (ret != NULL) { - return ret; - } - r = strrchr(p, '/'); - if (r != NULL) { - /* We have non-null parent dir. */ - strncpy(name, p, r - p); - name[r - p] = '\0'; - parent = get_procfs_list_entry(name, osnum, 0, NULL, cred); - if (parent == NULL) { - /* We counld not get a parent procfs entry. Give up.*/ - return NULL; - } - } - ret = kmalloc(sizeof(struct procfs_list_entry), GFP_KERNEL); - if (ret == NULL) { - kprintf("ERROR: not enough memory to create PROCFS entry.\n"); - return NULL; - } - /* Fill the fname field of the entry */ - strncpy(ret->fname, p, PROCFS_NAME_MAX); - - if (r != NULL) { - strncpy(name, r + 1, p + PROCFS_NAME_MAX - r - 1); - } else { - strncpy(name, p, PROCFS_NAME_MAX); - } - if (mode == 0) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) - pde = proc_mkdir(name, parent ? parent->entry : NULL); -#else - pde = proc_mkdir_data(name, 0555, parent ? parent->entry : NULL, ret); -#endif - } else if (mode & S_IFLNK) { - pde = proc_symlink(name, parent->entry, (char *)opaque); - } else { -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) - pde = create_proc_entry(name, mode, parent->entry); - if (pde) - pde->proc_fops = &mckernel_procfs_file_operations; -#else - pde = proc_create_data(name, mode, parent->entry, - &mckernel_procfs_file_operations, ret); -#endif - if(pde && cred) - proc_set_user(pde, cred->uid, cred->gid); - } - if (pde == NULL) { - kprintf("ERROR: cannot create a PROCFS entry for %s.\n", p); - kfree(ret); - return NULL; - } -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) - pde->data = ret; -#endif - ret->osnum = osnum; - ret->entry = pde; - ret->parent = parent; - - irqflags = ihk_ikc_spinlock_lock(&procfs_file_list_lock); - list_add(&(ret->list), &procfs_file_list); - ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflags); - - dprintk("get_procfs_list_entry: %s done\n", p); - return ret; -} - -/** - * \brief Create procfs create (internal, can be called directly from host Linux). - * - * \param os (opaque) os variable - * \param ref cpuid of the requesting mckernel process - * \param osnum osnum of the requesting mckernel process - * \param pid pid of the requesting mckernel process - * \param name path of the file - * \param mode mode of the file (e.g., dir, link, regular, etc.) - * \param opaque context dependent additional argument - */ - -int procfs_create_entry(void *os, int ref, int osnum, int pid, char *name, - int mode, void *opaque, const struct cred *cred) -{ - struct procfs_list_entry *e; - - e = get_procfs_list_entry(name, osnum, mode, opaque, cred); - if (e == NULL) { - printk("ERROR: could not create a procfs entry for %s.\n", name); - return EINVAL; - } - - e->os = os; - e->cpu = ref; - e->pid = pid; - - return 0; -} - -/** - * \brief Create a procfs entry. - * - * \param __os (opeque) os variable - * \param ref cpuid of the requesting mckernel process - * \param osnum osnum of the requesting mckernel process - * \param pid pid of the requesting mckernel process - * \param arg sent argument - */ - -void procfs_create(void *__os, int ref, int osnum, int pid, unsigned long arg) -{ - ihk_device_t dev = ihk_os_to_dev(__os); - unsigned long parg; - struct procfs_file *f; - int mode; - char name[PROCFS_NAME_MAX]; - struct task_struct *task = NULL; - const struct cred *tcred = NULL; - - if(pid > 0){ - task = pid_task(find_vpid(pid), PIDTYPE_PID); - if(task){ - tcred = __task_cred(task); - } - } - - dprintk("procfs_create: osnum: %d, cpu: %d, pid: %d\n", osnum, ref, pid); - - parg = ihk_device_map_memory(dev, arg, sizeof(struct procfs_file)); - f = ihk_device_map_virtual(dev, parg, sizeof(struct procfs_file), NULL, 0); - - dprintk("name: %s mode: %o\n", f->fname, f->mode); - - strncpy(name, f->fname, PROCFS_NAME_MAX); - mode = f->mode; - - if (name[PROCFS_NAME_MAX - 1] != '\0') { - printk("ERROR: procfs_creat: file name not properly terminated.\n"); - goto quit; - } - - if (procfs_create_entry(__os, ref, osnum, pid, name, mode, NULL, tcred) != 0) { - printk("ERROR: could not create a procfs entry for %s.\n", name); - goto quit; - } - -quit: - f->status = 1; /* Now the peer can free the data. */ - ihk_device_unmap_virtual(dev, f, sizeof(struct procfs_file)); - ihk_device_unmap_memory(dev, parg, sizeof(struct procfs_file)); - dprintk("procfs_create: done\n"); -} - -/** - * \brief Delete a procfs entry and all of its subtree (internal). - * - * \param __os (opaque) os variable - * \param osnum os number - * - * NOTE: procfs_file_list_lock has to be held here. - */ - -void __procfs_delete_entry_recursively(struct procfs_list_entry *e) -{ - struct procfs_list_entry *le; - struct procfs_list_entry *parent = NULL; - char name[PROCFS_NAME_MAX]; - char *r; - - /* See if there are any children of this entry */ -retry: - list_for_each_entry(le, &procfs_file_list, list) { - if (le->parent != e) { - continue; - } - - __procfs_delete_entry_recursively(le); - /* List may have changed... */ - goto retry; - } - - /* No more children, remove entry */ - list_del(&e->list); -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) - e->entry->read_proc = NULL; - e->entry->data = NULL; -#endif - parent = e->parent; - r = strrchr(e->fname, '/'); - if (r == NULL) { - strncpy(name, e->fname, PROCFS_NAME_MAX); - } else { - strncpy(name, r + 1, PROCFS_NAME_MAX); - } - dprintk("found and removed %s from the list.\n", name); - remove_proc_entry(name, parent->entry); - kfree(e); -} - -/** - * \brief Delete a procfs entry (internal). - * - * \param __os (opaque) os variable - * \param osnum os number - */ - -void procfs_delete_entry(void *os, int osnum, char *fname) -{ - struct procfs_list_entry *e; - unsigned long irqflags; - - irqflags = ihk_ikc_spinlock_lock(&procfs_file_list_lock); - list_for_each_entry(e, &procfs_file_list, list) { - if ((strncmp(e->fname, fname, PROCFS_NAME_MAX) == 0) && (e->osnum == osnum)) { - __procfs_delete_entry_recursively(e); - break; - } - } - ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflags); -} - -/** - * \brief Delete a procfs entry (internal, can be called directly from host Linux). - * - * \param __os (opaque) os variable - * \param osnum os number - * \param arg sent argument - */ - -void procfs_delete(void *__os, int osnum, unsigned long arg) -{ - struct procfs_file *f; - ihk_device_t dev = ihk_os_to_dev(__os); - unsigned long parg; - - dprintk("procfs_delete: \n"); - parg = ihk_device_map_memory(dev, arg, sizeof(struct procfs_file)); - f = ihk_device_map_virtual(dev, parg, sizeof(struct procfs_file), NULL, 0); - dprintk("fname: %s.\n", f->fname); - - procfs_delete_entry(__os, osnum, f->fname); - - f->status = 1; /* Now the peer can free the data. */ - ihk_device_unmap_virtual(dev, f, sizeof(struct procfs_file)); - ihk_device_unmap_memory(dev, parg, sizeof(struct procfs_file)); - dprintk("procfs_delete: done\n"); } /** @@ -378,13 +107,390 @@ void procfs_delete(void *__os, int osnum, unsigned long arg) * \param arg sent argument * \param err error info (redundant) */ - -void procfs_answer(unsigned int arg, int err) +void +procfs_answer(unsigned int arg, int err) { dprintk("procfs: received SCD_MSG_PROCFS_ANSWER message(err = %d).\n", err); wake_up_interruptible(&procfsq); } +static struct procfs_list_entry * +find_procfs_entry(struct procfs_list_entry *parent, const char *name) +{ + struct list_head *list; + struct procfs_list_entry *e; + + if(parent == NULL) + list = &procfs_file_list; + else + list = &parent->children; + + list_for_each_entry(e, list, list) { + if(!strcmp(e->name, name)) + return e; + } + + return NULL; +} + +static void +delete_procfs_entries(struct procfs_list_entry *top) +{ + struct procfs_list_entry *e; + struct procfs_list_entry *n; + + list_del(&top->list); + + list_for_each_entry_safe(e, n, &top->children, list) { + delete_procfs_entries(e); + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + e->entry->read_proc = NULL; + e->entry->data = NULL; +#endif + remove_proc_entry(top->name, top->parent? top->parent->entry: NULL); + if(top->data) + kfree(top->data); + kfree(top); +} + +static struct procfs_list_entry * +add_procfs_entry(struct procfs_list_entry *parent, const char *name, int mode, + kuid_t uid, kgid_t gid, const void *opaque) +{ + struct procfs_list_entry *e = find_procfs_entry(parent, name); + struct proc_dir_entry *pde; + struct proc_dir_entry *parent_pde = NULL; + int f_mode = mode & 0777; + + if(e) + delete_procfs_entries(e); + + e = kmalloc(sizeof(struct procfs_list_entry) + strlen(name) + 1, + GFP_KERNEL); + if(!e){ + kprintf("ERROR: not enough memory to create PROCFS entry.\n"); + return NULL; + } + memset(e, '\0', sizeof(struct procfs_list_entry)); + INIT_LIST_HEAD(&e->children); + strcpy(e->name, name); + + if(parent) + parent_pde = parent->entry; + + if (mode & S_IFDIR) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + pde = proc_mkdir(name, parent_pde); +#else + pde = proc_mkdir_data(name, f_mode, parent_pde, e); +#endif + } + else if ((mode & S_IFLNK) == S_IFLNK) { + pde = proc_symlink(name, parent_pde, (char *)opaque); + } + else { + const struct file_operations *fop; + + if(opaque) + fop = (const struct file_operations *)opaque; + else if(mode & S_IWUSR) + fop = &mckernel_forward; + else + fop = &mckernel_forward_ro; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + pde = create_proc_entry(name, f_mode, parent_pde); + if(pde) + pde->proc_fops = fop; +#else + pde = proc_create_data(name, f_mode, parent_pde, fop, e); + if(pde) + proc_set_user(pde, uid, gid); +#endif + } + if(!pde){ + kprintf("ERROR: cannot create a PROCFS entry for %s.\n", name); + kfree(e); + return NULL; + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + pde->uid = uid; + pde->gid = gid; + pde->data = e; +#endif + + if(parent) + e->osnum = parent->osnum; + e->entry = pde; + e->parent = parent; + list_add(&(e->list), parent? &(parent->children): &procfs_file_list); + + return e; +} + +static void +add_procfs_entries(struct procfs_list_entry *parent, + const struct procfs_entry *entries, kuid_t uid, kgid_t gid) +{ + const struct procfs_entry *p; + + for(p = entries; p->name; p++){ + add_procfs_entry(parent, p->name, p->mode, uid, gid, p->fops); + } +} + +static const struct cred * +get_pid_cred(int pid) +{ + struct task_struct *task = NULL; + + if(pid > 0){ + task = pid_task(find_vpid(pid), PIDTYPE_PID); + if(task){ + return __task_cred(task); + } + } + return NULL; +} + +static struct procfs_list_entry * +find_base_entry(int osnum) +{ + char name[12]; + + sprintf(name, "mcos%d", osnum); + return find_procfs_entry(NULL, name); +} + +static struct procfs_list_entry * +find_pid_entry(int osnum, int pid) +{ + struct procfs_list_entry *e; + char name[12]; + + if(!(e = find_base_entry(osnum))) + return NULL; + sprintf(name, "%d", pid); + return find_procfs_entry(e, name); +} + +static struct procfs_list_entry * +find_tid_entry(int osnum, int pid, int tid) +{ + struct procfs_list_entry *e; + char name[12]; + + if(!(e = find_pid_entry(osnum, pid))) + return NULL; + if(!(e = find_procfs_entry(e, "task"))) + return NULL; + sprintf(name, "%d", tid); + return find_procfs_entry(e, name); +} + +static struct procfs_list_entry * +get_base_entry(int osnum) +{ + struct procfs_list_entry *e; + char name[12]; + kuid_t uid = KUIDT_INIT(0); + kgid_t gid = KGIDT_INIT(0); + + sprintf(name, "mcos%d", osnum); + e = find_procfs_entry(NULL, name); + if(!e){ + e = add_procfs_entry(NULL, name, S_IFDIR | 0555, + uid, gid, NULL); + e->osnum = osnum; + } + return e; +} + +static struct procfs_list_entry * +get_pid_entry(int osnum, int pid) +{ + struct procfs_list_entry *parent; + struct procfs_list_entry *e; + char name[12]; + kuid_t uid = KUIDT_INIT(0); + kgid_t gid = KGIDT_INIT(0); + + sprintf(name, "mcos%d", osnum); + if(!(parent = find_procfs_entry(NULL, name))) + return NULL; + sprintf(name, "%d", pid); + e = find_procfs_entry(parent, name); + if(!e) + e = add_procfs_entry(parent, name, S_IFDIR | 0555, + uid, gid, NULL); + return e; +} + +static struct procfs_list_entry * +get_tid_entry(int osnum, int pid, int tid) +{ + struct procfs_list_entry *parent; + struct procfs_list_entry *e; + char name[12]; + kuid_t uid = KUIDT_INIT(0); + kgid_t gid = KGIDT_INIT(0); + + sprintf(name, "mcos%d", osnum); + if(!(parent = find_procfs_entry(NULL, name))) + return NULL; + sprintf(name, "%d", pid); + if(!(parent = find_procfs_entry(parent, name))) + return NULL; + if(!(parent = find_procfs_entry(parent, "task"))) + return NULL; + sprintf(name, "%d", tid); + e = find_procfs_entry(parent, name); + if(!e) + e = add_procfs_entry(parent, name, S_IFDIR | 0555, + uid, gid, NULL); + return e; +} + +static void +_add_tid_entry(int osnum, int pid, int tid, const struct cred *cred) +{ + struct procfs_list_entry *parent; + struct procfs_list_entry *exe; + + parent = get_tid_entry(osnum, pid, tid); + if(parent){ + add_procfs_entries(parent, tid_entry_stuff, + cred->uid, cred->gid); + exe = find_procfs_entry(parent->parent->parent, "exe"); + if(exe){ + add_procfs_entry(parent, "exe", S_IFLNK | 0777, + cred->uid, cred->gid, exe->data); + } + + } +} + +void +add_tid_entry(int osnum, int pid, int tid) +{ + unsigned long irqflag; + const struct cred *cred = get_pid_cred(pid); + + if(!cred) + return; + irqflag = ihk_ikc_spinlock_lock(&procfs_file_list_lock); + _add_tid_entry(osnum, pid, tid, cred); + ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflag); +} + +void +add_pid_entry(int osnum, int pid) +{ + struct procfs_list_entry *parent; + unsigned long irqflag; + const struct cred *cred = get_pid_cred(pid); + + if(!cred) + return; + irqflag = ihk_ikc_spinlock_lock(&procfs_file_list_lock); + parent = get_pid_entry(osnum, pid); + add_procfs_entries(parent, pid_entry_stuff, cred->uid, cred->gid); + _add_tid_entry(osnum, pid, pid, cred); + ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflag); +} + +void +delete_tid_entry(int osnum, int pid, int tid) +{ + unsigned long irqflag; + struct procfs_list_entry *e; + + irqflag = ihk_ikc_spinlock_lock(&procfs_file_list_lock); + e = find_tid_entry(osnum, pid, tid); + if(e) + delete_procfs_entries(e); + ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflag); +} + +void +delete_pid_entry(int osnum, int pid) +{ + unsigned long irqflag; + struct procfs_list_entry *e; + + irqflag = ihk_ikc_spinlock_lock(&procfs_file_list_lock); + e = find_pid_entry(osnum, pid); + if(e) + delete_procfs_entries(e); + ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflag); +} + +void +proc_exe_link(int osnum, int pid, const char *path) +{ + struct procfs_list_entry *parent; + unsigned long irqflag; + kuid_t uid = KUIDT_INIT(0); + kgid_t gid = KGIDT_INIT(0); + + irqflag = ihk_ikc_spinlock_lock(&procfs_file_list_lock); + parent = find_pid_entry(osnum, pid); + if(parent){ + struct procfs_list_entry *task; + struct procfs_list_entry *e; + + e = add_procfs_entry(parent, "exe", S_IFLNK | 0777, uid, gid, + path); + e->data = kmalloc(strlen(path) + 1, GFP_KERNEL); + strcpy(e->data, path); + task = find_procfs_entry(parent, "task"); + list_for_each_entry(parent, &task->children, list) { + add_procfs_entry(parent, "exe", S_IFLNK | 0777, + uid, gid, path); + } + } + ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflag); +} + +/** + * \brief Initialization for procfs + * + * \param osnum os number + */ +void +procfs_init(int osnum) +{ + struct procfs_list_entry *parent; + unsigned long irqflag; + kuid_t uid = KUIDT_INIT(0); + kgid_t gid = KGIDT_INIT(0); + + irqflag = ihk_ikc_spinlock_lock(&procfs_file_list_lock); + parent = get_base_entry(osnum); + add_procfs_entries(parent, base_entry_stuff, uid, gid); + ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflag); +} + +/** + * \brief Finalization for procfs + * + * \param osnum os number + */ +void +procfs_exit(int osnum) +{ + unsigned long irqflag; + struct procfs_list_entry *e; + + irqflag = ihk_ikc_spinlock_lock(&procfs_file_list_lock); + e = find_base_entry(osnum); + if(e) + delete_procfs_entries(e); + ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflag); +} + /** * \brief The callback funciton for McKernel procfs * @@ -396,11 +502,11 @@ mckernel_procfs_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { struct inode * inode = file->f_path.dentry->d_inode; - char *kern_buffer; + char *kern_buffer = NULL; int order = 0; - volatile struct procfs_read *r; + volatile struct procfs_read *r = NULL; struct ikc_scd_packet isp; - int ret, retrycount = 0; + int ret; unsigned long pbuf; unsigned long count = nbytes; #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) @@ -410,9 +516,12 @@ mckernel_procfs_read(struct file *file, char __user *buf, size_t nbytes, struct procfs_list_entry *e = PDE_DATA(inode); #endif loff_t offset = *ppos; + char pathbuf[PROCFS_NAME_MAX]; + char *path; + path = getpath(e, pathbuf, 256); dprintk("mckernel_procfs_read: invoked for %s, offset: %lu, count: %d\n", - e->fname, offset, count); + path, offset, count); if (count <= 0 || offset < 0) { return 0; @@ -437,23 +546,22 @@ mckernel_procfs_read(struct file *file, char __user *buf, size_t nbytes, r = kmalloc(sizeof(struct procfs_read), GFP_KERNEL); if (r == NULL) { - return -ENOMEM; + ret = -ENOMEM; + goto out; } -retry: - dprintk("offset: %lx, count: %d, cpu: %d\n", offset, count, e->cpu); - r->pbuf = pbuf; r->eof = 0; r->ret = -EIO; /* default */ r->status = 0; r->offset = offset; r->count = count; - strncpy((char *)r->fname, e->fname, PROCFS_NAME_MAX); + r->readwrite = 0; + strncpy((char *)r->fname, path, PROCFS_NAME_MAX); isp.msg = SCD_MSG_PROCFS_REQUEST; - isp.ref = e->cpu; + isp.ref = 0; isp.arg = virt_to_phys(r); - ret = mcctrl_ikc_send(e->os, e->cpu, &isp); + ret = mcctrl_ikc_send(osnum_to_os(e->osnum), 0, &isp); if (ret < 0) { goto out; /* error */ @@ -471,18 +579,6 @@ retry: /* Wake up and check the result. */ dprintk("mckernel_procfs_read: woke up. ret: %d, eof: %d\n", r->ret, r->eof); - if ((r->ret == 0) && (r->eof != 1)) { - /* A miss-hit caused by migration has occurred. - * We simply retry the query with a new CPU. - */ - if (retrycount++ > 10) { - kprintf("ERROR: mckernel_procfs_read: excessive retry.\n"); - goto out; - } - e->cpu = r->newcpu; - dprintk("retry\n"); - goto retry; - } if (r->ret > 0) { if (copy_to_user(buf, kern_buffer, r->ret)) { @@ -496,75 +592,198 @@ retry: ret = r->ret; out: - free_pages((uintptr_t)kern_buffer, order); - kfree((void *)r); + if(kern_buffer) + free_pages((uintptr_t)kern_buffer, order); + if(r) + kfree((void *)r); return ret; } -/** - * \brief Initialization for procfs - * - * \param osnum os number - */ - -void procfs_init(int osnum) { -} - -/** - * \brief Finalization for procfs - * - * \param osnum os number - */ - -void procfs_exit(int osnum) { - char buf[20], *r; - int error; - mm_segment_t old_fs = get_fs(); - struct kstat stat; - struct procfs_list_entry *parent; - struct procfs_list_entry *e, *temp = NULL; - unsigned long irqflags; - - dprintk("remove remaining mckernel procfs files.\n"); - - irqflags = ihk_ikc_spinlock_lock(&procfs_file_list_lock); - list_for_each_entry_safe(e, temp, &procfs_file_list, list) { - if (e->osnum == osnum) { - dprintk("found entry for %s.\n", e->fname); - list_del(&e->list); +static ssize_t +mckernel_procfs_write(struct file *file, const char __user *buf, size_t nbytes, + loff_t *ppos) +{ + struct inode * inode = file->f_path.dentry->d_inode; + char *kern_buffer = NULL; + int order = 0; + volatile struct procfs_read *r = NULL; + struct ikc_scd_packet isp; + int ret; + unsigned long pbuf; + unsigned long count = nbytes; #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) - e->entry->read_proc = NULL; - e->entry->data = NULL; -#endif - parent = e->parent; - r = strrchr(e->fname, '/'); - if (r == NULL) { - r = e->fname; - } else { - r += 1; - } - if (parent) { - remove_proc_entry(r, parent->entry); - } - dprintk("free the entry\n"); - kfree(e); - } - dprintk("iterate it.\n"); + struct proc_dir_entry *dp = PDE(inode); + struct procfs_list_entry *e = dp->data; +#else + struct procfs_list_entry *e = PDE_DATA(inode); +#endif + loff_t offset = *ppos; + char pathbuf[PROCFS_NAME_MAX]; + char *path; + + path = getpath(e, pathbuf, 256); + dprintk("mckernel_procfs_read: invoked for %s, offset: %lu, count: %d\n", + path, offset, count); + + if (count <= 0 || offset < 0) { + return 0; } - ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflags); - - sprintf(buf, "/proc/mcos%d", osnum); - - set_fs(KERNEL_DS); - error = vfs_stat (buf, &stat); - set_fs(old_fs); - if (error != 0) { - return; + + while ((1 << order) < count) ++order; + if (order > 12) { + order -= 12; + } + else { + order = 1; } - printk("procfs_exit: We have to remove unexpectedly remaining %s.\n", buf); + /* NOTE: we need physically contigous memory to pass through IKC */ + kern_buffer = (char *)__get_free_pages(GFP_KERNEL, order); + if (!kern_buffer) { + printk("mckernel_procfs_read(): ERROR: allocating kernel buffer\n"); + return -ENOMEM; + } + if (copy_from_user(kern_buffer, buf, nbytes)) { + ret = -EFAULT; + goto out; + } + + pbuf = virt_to_phys(kern_buffer); - /* remove remnant of previous mcos%d */ - remove_proc_entry(buf + 6, NULL); + r = kmalloc(sizeof(struct procfs_read), GFP_KERNEL); + if (r == NULL) { + ret = -ENOMEM; + goto out; + } + dprintk("offset: %lx, count: %d, cpu: %d\n", offset, count, e->cpu); + + r->pbuf = pbuf; + r->eof = 0; + r->ret = -EIO; /* default */ + r->status = 0; + r->offset = offset; + r->count = count; + r->readwrite = 1; + strncpy((char *)r->fname, path, PROCFS_NAME_MAX); + isp.msg = SCD_MSG_PROCFS_REQUEST; + isp.ref = 0; + isp.arg = virt_to_phys(r); + + ret = mcctrl_ikc_send(osnum_to_os(e->osnum), 0, &isp); + + if (ret < 0) { + goto out; /* error */ + } + + /* Wait for a reply. */ + ret = -EIO; /* default exit code */ + dprintk("now wait for a relpy\n"); + + /* Wait for the status field of the procfs_read structure set ready. */ + if (wait_event_interruptible_timeout(procfsq, r->status != 0, HZ) == 0) { + kprintf("ERROR: mckernel_procfs_read: timeout (1 sec).\n"); + goto out; + } + + /* Wake up and check the result. */ + dprintk("mckernel_procfs_read: woke up. ret: %d, eof: %d\n", r->ret, r->eof); + + if (r->ret > 0) { + *ppos += r->ret; + } + ret = r->ret; + +out: + if(kern_buffer) + free_pages((uintptr_t)kern_buffer, order); + if(r) + kfree((void *)r); + + return ret; } + +static loff_t +mckernel_procfs_lseek(struct file *file, loff_t offset, int orig) +{ + switch (orig) { + case 0: + file->f_pos = offset; + break; + case 1: + file->f_pos += offset; + break; + default: + return -EINVAL; + } + return file->f_pos; +} + +static const struct file_operations mckernel_forward_ro = { + .llseek = mckernel_procfs_lseek, + .read = mckernel_procfs_read, + .write = NULL, +}; + +static const struct file_operations mckernel_forward = { + .llseek = mckernel_procfs_lseek, + .read = mckernel_procfs_read, + .write = mckernel_procfs_write, +}; + +static const struct procfs_entry tid_entry_stuff[] = { + PROC_REG("auxv", S_IRUSR, NULL), + PROC_REG("clear_refs", S_IWUSR, NULL), + PROC_REG("cmdline", S_IRUGO, NULL), + PROC_REG("comm", S_IRUGO|S_IWUSR, 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("statm", S_IRUGO, NULL), + PROC_REG("status", S_IRUGO, NULL), + PROC_REG("syscall", S_IRUGO, NULL), + PROC_REG("wchan", S_IRUGO, NULL), + PROC_TERM +}; + +static const struct procfs_entry pid_entry_stuff[] = { + PROC_REG("auxv", S_IRUSR, NULL), + PROC_REG("clear_refs", S_IWUSR, NULL), + PROC_REG("cmdline", S_IRUGO, NULL), + PROC_REG("comm", S_IRUGO|S_IWUSR, NULL), + PROC_REG("coredump_filter", S_IRUGO|S_IWUSR, 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("statm", S_IRUGO, NULL), + PROC_REG("status", S_IRUGO, NULL), + PROC_REG("syscall", S_IRUGO, NULL), + PROC_DIR("task", S_IRUGO|S_IXUGO), + PROC_REG("wchan", S_IRUGO, NULL), + PROC_TERM +}; + +static const struct procfs_entry base_entry_stuff[] = { + PROC_REG("cmdline", S_IRUGO, NULL), + PROC_REG("cpuinfo", S_IRUGO, NULL), + 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("uptime", S_IRUGO, NULL), + PROC_REG("version", S_IRUGO, NULL), + PROC_REG("vmallocinfo",S_IRUSR, NULL), + PROC_REG("vmstat", S_IRUGO, NULL), + PROC_REG("zoneinfo", S_IRUGO, NULL), + PROC_TERM +}; diff --git a/kernel/include/syscall.h b/kernel/include/syscall.h index 5c3822d2..e7c86079 100644 --- a/kernel/include/syscall.h +++ b/kernel/include/syscall.h @@ -66,6 +66,8 @@ #define SCD_MSG_SYSFS_RESP_SETUP 0x41 /* #define SCD_MSG_SYSFS_REQ_CLEANUP 0x42 */ /* #define SCD_MSG_SYSFS_RESP_CLEANUP 0x43 */ +#define SCD_MSG_PROCFS_TID_CREATE 0x44 +#define SCD_MSG_PROCFS_TID_DELETE 0x45 #define ARCH_SET_GS 0x1001 #define ARCH_SET_FS 0x1002 @@ -314,6 +316,7 @@ struct procfs_read { int ret; /* read bytes (answer) */ int status; /* non-zero if done (answer) */ int newcpu; /* migrated new cpu (answer) */ + int readwrite; /* 0:read, 1:write */ char fname[PROCFS_NAME_MAX]; /* procfs filename (request) */ }; diff --git a/kernel/init.c b/kernel/init.c index 1e651c0b..8e09d4fe 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -283,7 +283,6 @@ static void post_init(void) zero_tsc(); ap_start(); - create_os_procfs_files(); sysfs_init(); populate_sysfs(); } diff --git a/kernel/process.c b/kernel/process.c index 3b0e0a07..49a48f08 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -63,6 +63,8 @@ extern int num_processors; extern ihk_spinlock_t cpuid_head_lock; int ptrace_detach(int pid, int data); extern unsigned long do_kill(struct thread *, int pid, int tid, int sig, struct siginfo *info, int ptracecont); +extern void procfs_create_thread(struct thread *); +extern void procfs_delete_thread(struct thread *); struct list_head resource_set_list; mcs_rwlock_lock_t resource_set_lock; @@ -2166,6 +2168,7 @@ void release_thread(struct thread *thread) vm = thread->vm; + procfs_delete_thread(thread); destroy_thread(thread); release_process_vm(vm); @@ -2753,7 +2756,7 @@ void runq_add_thread(struct thread *thread, int cpu_id) __runq_add_thread(thread, cpu_id); ihk_mc_spinlock_unlock(&(v->runq_lock), irqstate); - create_proc_procfs_files(thread->proc->pid, cpu_id); + procfs_create_thread(thread); /* Kick scheduler */ if (cpu_id != ihk_mc_get_processor_id()) diff --git a/kernel/procfs.c b/kernel/procfs.c index 4cc6b2da..525d0cf1 100644 --- a/kernel/procfs.c +++ b/kernel/procfs.c @@ -38,212 +38,37 @@ extern int sscanf(const char * buf, const char * fmt, ...); extern int osnum; -void create_proc_procfs_files(int pid, int cpuid); -void delete_proc_procfs_files(int pid); -void create_os_procfs_files(void); -void delete_os_procfs_files(void); - -static void create_proc_procfs_file(int pid, char *fname, int mode, int cpuid); -static void delete_proc_procfs_file(int pid, char *fname); -static void operate_proc_procfs_file(int pid, char *fname, int msg, int mode, int cpuid); - int copy_from_user(void *dst, const void *src, size_t siz); int copy_to_user(void *dst, const void *src, size_t siz); -/** - * \brief Create all procfs files for process. - * - * \param pid pid of the process - * \param cpuid cpuid of the process - */ - -void create_proc_procfs_files(int pid, int cpuid) -{ - char fname[PROCFS_NAME_MAX]; - - dprintf("create procfs files:\n"); - - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/auxv", osnum, pid); - create_proc_procfs_file(pid, fname, 0400, cpuid); - - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/cmdline", osnum, pid); - create_proc_procfs_file(pid, fname, 0444, cpuid); - - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/mem", osnum, pid); - create_proc_procfs_file(pid, fname, 0400, cpuid); - - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/maps", osnum, pid); - create_proc_procfs_file(pid, fname, 0444, cpuid); - - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/pagemap", osnum, pid); - create_proc_procfs_file(pid, fname, 0444, cpuid); - - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/status", osnum, pid); - create_proc_procfs_file(pid, fname, 0444, cpuid); - - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/task/%d/mem", osnum, pid, pid); - create_proc_procfs_file(pid, fname, 0400, cpuid); - - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/task/%d/stat", osnum, pid, pid); - create_proc_procfs_file(pid, fname, 0444, cpuid); - - dprintf("create procfs files: done\n"); -} - -/** - * \brief Create a procfs file for process. - * - * \param pid pid of the process - * \param fname file name of the procfs file - * \param mode file mode - * \param cpuid cpuid of the process - */ - -static void create_proc_procfs_file(int pid, char *fname, int mode, int cpuid) -{ - dprintf("create procfs file: %s, mode: %o, cpuid: %d\n", fname, mode, cpuid); - operate_proc_procfs_file(pid, fname, SCD_MSG_PROCFS_CREATE, mode, cpuid); -} - -/** - * \brief Delete all procfs files for process. - * - * \param pid pid of the process - */ - -void delete_proc_procfs_files(int pid) -{ - char fname[PROCFS_NAME_MAX]; - - dprintf("delete procfs files for pid %d.\n", pid); - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/task/%d/mem", osnum, pid, pid); - delete_proc_procfs_file(pid, fname); - - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/task/%d/stat", osnum, pid, pid); - delete_proc_procfs_file(pid, fname); - - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/task/%d", osnum, pid, pid); - delete_proc_procfs_file(pid, fname); - - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/task", osnum, pid); - delete_proc_procfs_file(pid, fname); - - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/mem", osnum, pid); - delete_proc_procfs_file(pid, fname); - - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/maps", osnum, pid); - delete_proc_procfs_file(pid, fname); - - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/status", osnum, pid); - delete_proc_procfs_file(pid, fname); - - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/pagemap", osnum, pid); - delete_proc_procfs_file(pid, fname); - - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/cmdline", osnum, pid); - delete_proc_procfs_file(pid, fname); - - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/auxv", osnum, pid); - delete_proc_procfs_file(pid, fname); - - /* NOTE: Directory is removed on the host when mcexec drops the executable */ - dprintf("delete procfs files for pid %d: done\n", pid); -} - -/** - * \brief Delete a procfs file for process. - * - * \param pid pid of the process - * \param fname file name of the procfs file - */ - -static void delete_proc_procfs_file(int pid, char *fname) -{ - dprintf("delete procfs file: %s\n", fname); - operate_proc_procfs_file(pid, fname, SCD_MSG_PROCFS_DELETE, 0, 0); - dprintf("delete procfs file: %s done\n", fname); -} - -/** - * \brief create a procfs file for this operating system - * \param fname relative path name from "host:/proc". - * \param mode permissions of the file to be created - * - * Though operate_proc_procfs_file() is intended to create a process - * specific file, it is reused to create a OS specific file by - * specifying -1 as the pid parameter. - */ -static void create_os_procfs_file(char *fname, int mode) -{ - const pid_t pid = -1; - const int msg = SCD_MSG_PROCFS_CREATE; - const int cpuid = ihk_mc_get_processor_id(); /* i.e. BSP */ - - operate_proc_procfs_file(pid, fname, msg, mode, cpuid); - return; -} - -/** - * \brief create all procfs files for this operating system - */ -void create_os_procfs_files(void) -{ - char *fname = NULL; - size_t n; - - fname = kmalloc(PROCFS_NAME_MAX, IHK_MC_AP_CRITICAL); - - n = snprintf(fname, PROCFS_NAME_MAX, "mcos%d/stat", osnum); - if (n >= PROCFS_NAME_MAX) panic("/proc/stat"); - create_os_procfs_file(fname, 0444); - - return; -} - -/** - * \brief Create/delete a procfs file for process. - * - * \param pid pid of the process - * \param fname file name of the procfs file - * \param msg message (create/delete) - * \param mode file mode - * \param cpuid cpuid of the process - */ - -static void operate_proc_procfs_file(int pid, char *fname, int msg, int mode, int cpuid) +static void +procfs_thread_ctl(struct thread *thread, int msg) { struct ihk_ikc_channel_desc *syscall_channel; - struct ikc_scd_packet pckt; - struct procfs_file *f; - int ret; + struct ikc_scd_packet packet; syscall_channel = cpu_local_var(syscall_channel); + memset(&packet, '\0', sizeof packet); + packet.arg = thread->tid; + packet.msg = msg; + packet.osnum = osnum; + packet.ref = thread->cpu_id; + packet.pid = thread->proc->pid; + packet.err = 0; - f = kmalloc(sizeof(struct procfs_file), IHK_MC_AP_NOWAIT); - if (!f) { - kprintf("ERROR: not enough memory for dealing procfs file %s!", - fname); - return; - } - f->status = 0; - f->mode = mode; - strncpy(f->fname, fname, PROCFS_NAME_MAX); - pckt.arg = virt_to_phys(f); - pckt.msg = msg; - pckt.osnum = osnum; - pckt.ref = cpuid; - pckt.pid = pid; - pckt.err = 0; + ihk_ikc_send(syscall_channel, &packet, 0); +} - ret = ihk_ikc_send(syscall_channel, &pckt, 0); - if (ret < 0) { - kprintf("ERROR: sending IKC msg, ret: %d\n", ret); - } +void +procfs_create_thread(struct thread *thread) +{ + procfs_thread_ctl(thread, SCD_MSG_PROCFS_TID_CREATE); +} - while (f->status != 1) { - cpu_pause(); - } - kfree(f); +void +procfs_delete_thread(struct thread *thread) +{ + procfs_thread_ctl(thread, SCD_MSG_PROCFS_TID_DELETE); } /** @@ -251,12 +76,13 @@ static void operate_proc_procfs_file(int pid, char *fname, int msg, int mode, in * * \param rarg returned argument */ - -void process_procfs_request(unsigned long rarg) +void +process_procfs_request(unsigned long rarg) { unsigned long parg, pbuf; - struct thread *thread = cpu_local_var(current); - struct process *proc = thread->proc; + struct thread *thread = NULL; + struct process *proc = NULL; + struct process_vm *vm = NULL; struct procfs_read *r; struct ikc_scd_packet packet; int rosnum, ret, pid, tid, ans = -EIO, eof = 0; @@ -266,7 +92,8 @@ void process_procfs_request(unsigned long rarg) unsigned long offset; int count; int npages; - int is_current = 1; /* is 'proc' same as 'current'? */ + int readwrite = 0; + dprintf("process_procfs_request: invoked.\n"); @@ -296,6 +123,7 @@ void process_procfs_request(unsigned long rarg) goto bufunavail; } + readwrite = r->readwrite; count = r->count; offset = r->offset; dprintf("fname: %s, offset: %lx, count:%d.\n", r->fname, r->offset, r->count); @@ -334,32 +162,38 @@ void process_procfs_request(unsigned long rarg) */ ret = sscanf(p, "%d/", &pid); if (ret == 1) { - if (pid != cpu_local_var(current)->proc->pid) { - /* We are not located in the proper cpu for some reason. */ - - dprintf("mismatched pid. We are %d, but requested pid is %d.\n", - pid, cpu_local_var(current)->pid); - tid = pid; /* main thread */ - thread = find_thread(pid, tid, &lock); - if (!thread) { - dprintf("We cannot find the proper cpu for requested pid.\n"); - goto end; - } - else if (thread->cpu_id != ihk_mc_get_processor_id()) { - /* The target process has gone by migration. */ - r->newcpu = thread->cpu_id; - dprintf("expected cpu id is %d.\n", thread->cpu_id); - thread_unlock(thread, &lock); - ans = 0; - goto end; - } - else { - thread_unlock(thread, &lock); - /* 'proc' is not 'current' */ - is_current = 0; - } - proc = thread->proc; + proc = find_process(pid, &lock); + if(proc == NULL){ + kprintf("process_procfs_request: no such pid %d\n", pid); + goto end; } + p = strchr(p, '/') + 1; + ret = sscanf(p, "task/%d/", &tid); + if(ret == 1){ + struct mcs_rwlock_node tlock; + mcs_rwlock_reader_lock_noirq(&proc->threads_lock, &tlock); + list_for_each_entry(thread, &proc->threads_list, + siblings_list) { + if(thread->tid == tid) + break; + } + if(thread == NULL){ + mcs_rwlock_reader_unlock_noirq(&proc->threads_lock, + &tlock); + process_unlock(proc, &lock); + kprintf("process_procfs_request: no such tid %d-%d\n", pid, tid); + goto end; + } + hold_thread(thread); + mcs_rwlock_reader_unlock_noirq(&proc->threads_lock, &tlock); + p = strchr(p, '/') + 1; + p = strchr(p, '/') + 1; + } + hold_process(proc); + vm = proc->vm; + if(vm) + hold_process_vm(vm); + process_unlock(proc, &lock); } else if (!strcmp(p, "stat")) { /* "/proc/stat" */ extern int num_processors; /* kernel/ap.c */ @@ -390,10 +224,9 @@ void process_procfs_request(unsigned long rarg) goto end; } else { + kprintf("unsupported procfs entry: %s\n", p); goto end; } - dprintf("matched PID: %d.\n", pid); - p = strchr(p, '/') + 1; /* * mcos%d/PID/mem @@ -403,9 +236,8 @@ void process_procfs_request(unsigned long rarg) */ if (strcmp(p, "mem") == 0) { struct vm_range *range; - struct process_vm *vm = proc->vm; - if (!is_current) { + if (proc != cpu_local_var(current)->proc) { uint64_t reason = PF_POPULATE | PF_WRITE | PF_USER; unsigned long offset = r->offset; unsigned long left = r->count; @@ -423,8 +255,8 @@ void process_procfs_request(unsigned long rarg) if(size > left) size = left; - ret = page_fault_process_vm(proc->vm, - (void *)offset, reason); + ret = page_fault_process_vm(vm, (void *)offset, + reason); if(ret){ if(ans == 0) ans = -EIO; @@ -479,7 +311,6 @@ void process_procfs_request(unsigned long rarg) */ if (strcmp(p, "maps") == 0) { struct vm_range *range; - struct process_vm *vm = proc->vm; int left = r->count - 1; /* extra 1 for terminating NULL */ int written = 0; char *_buf = buf; @@ -537,7 +368,6 @@ void process_procfs_request(unsigned long rarg) * mcos%d/PID/pagemap */ if (strcmp(p, "pagemap") == 0) { - struct process_vm *vm = proc->vm; uint64_t *_buf = (uint64_t *)buf; uint64_t start, end; @@ -673,112 +503,72 @@ void process_procfs_request(unsigned long rarg) * The offset is treated as the beginning of the virtual address area * of the process. The count is the length of the area. */ - tid = pid; - ret = sscanf(p, "task/%d/", &tid); - if (ret == 1) { - p = strchr(p, '/') + 1; - p = strchr(p, '/') + 1; - if (!strcmp(p, "mem")){ - struct vm_range *range; - struct process_vm *vm = proc->vm; + if (!strcmp(p, "stat")) { + char tmp[1024]; + int len; - if (!is_current) { - goto end; + /* + * pid (comm) state ppid + * pgrp session tty_nr tpgid + * flags minflt cminflt majflt + * cmajflt utime stime cutime + * cstime priority nice num_threads + * itrealvalue starttime vsize rss + * rsslim startcode endcode startstack + * kstkesp kstkeip signal blocked + * sigignore sigcatch wchan nswap + * cnswap exit_signal processor rt_priority + * policy delayacct_blkio_ticks guest_time cguest_time + */ + ans = sprintf(tmp, + "%d (%s) %c %d " // pid... + "%d %d %d %d " // pgrp... + "%u %lu %lu %lu " // flags... + "%lu %lu %lu %ld " // cmajflt... + "%ld %ld %ld %ld " // cstime... + "%ld %llu %lu %ld " // itrealvalue... + "%lu %lu %lu %lu " // rsslim... + "%lu %lu %lu %lu " // kstkesp... + "%lu %lu %lu %lu " // sigignore... + "%lu %d %d %u " // cnswap... + "%u %llu %lu %ld\n", // policy... + 0, "exe", 'R', 0, // pid... + 0, 0, 0, 0, // pgrp... + 0, 0L, 0L, 0L, // flags... + 0L, 0L, 0L, 0L, // cmajflt... + 0L, 0L, 0L, 0L, // cstime... + 0L, 0LL, 0L, 0L, // itrealvalue... + 0L, 0L, 0L, 0L, // rsslim... + 0L, 0L, 0L, 0L, // kstkesp... + 0L, 0L, 0L, 0L, // sigignore... + 0L, 0, thread->cpu_id, 0, // cnswap... + 0, 0LL, 0L, 0L // policy... + ); + thread_unlock(thread, &lock); + 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; } - if (pid != tid) { - /* We are not multithreaded yet. */ - goto end; - } - list_for_each_entry(range, &vm->vm_range_list, list) { - dprintf("range: %lx - %lx\n", range->start, range->end); - if ((range->start <= r->offset) && - (r->offset < range->end)) { - unsigned int len = r->count; - if (range->end < r->offset + r->count) { - len = range->end - r->offset; - } - memcpy((void *)buf, (void *)range->start, len); - ans = len; - break; - } - } - goto end; + strncpy(buf, tmp + r->offset, ans); + } else if (r->offset == len) { + ans = 0; + eof = 1; } - - if (!strcmp(p, "stat")) { - char tmp[1024]; - int len; - - if ((thread = find_thread(pid, tid, &lock))){ - dprintf("thread found! pid=%d tid=%d\n", pid, tid); - /* - * pid (comm) state ppid - * pgrp session tty_nr tpgid - * flags minflt cminflt majflt - * cmajflt utime stime cutime - * cstime priority nice num_threads - * itrealvalue starttime vsize rss - * rsslim startcode endcode startstack - * kstkesp kstkeip signal blocked - * sigignore sigcatch wchan nswap - * cnswap exit_signal processor rt_priority - * policy delayacct_blkio_ticks guest_time cguest_time - */ - ans = sprintf(tmp, - "%d (%s) %c %d " // pid... - "%d %d %d %d " // pgrp... - "%u %lu %lu %lu " // flags... - "%lu %lu %lu %ld " // cmajflt... - "%ld %ld %ld %ld " // cstime... - "%ld %llu %lu %ld " // itrealvalue... - "%lu %lu %lu %lu " // rsslim... - "%lu %lu %lu %lu " // kstkesp... - "%lu %lu %lu %lu " // sigignore... - "%lu %d %d %u " // cnswap... - "%u %llu %lu %ld\n", // policy... - 0, "exe", 'R', 0, // pid... - 0, 0, 0, 0, // pgrp... - 0, 0L, 0L, 0L, // flags... - 0L, 0L, 0L, 0L, // cmajflt... - 0L, 0L, 0L, 0L, // cstime... - 0L, 0LL, 0L, 0L, // itrealvalue... - 0L, 0L, 0L, 0L, // rsslim... - 0L, 0L, 0L, 0L, // kstkesp... - 0L, 0L, 0L, 0L, // sigignore... - 0L, 0, thread->cpu_id, 0, // cnswap... - 0, 0LL, 0L, 0L // policy... - ); - thread_unlock(thread, &lock); - 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; - } - goto end; - } - else{ - dprintf("no thread found pid=%d tid=%d\n", pid, tid); - } - } - dprintf("could not find a matching entry for task/%d/%s.\n", tid, p); goto end; } - /* - * Processing for pattern "mcos%d/PID/xxx" files should be here. - */ - dprintf("could not find a matching entry for %s.\n", p); + if(thread) + kprintf("unsupported procfs entry: %d/task/%d/%s\n", pid, tid, p); + else + kprintf("unsupported procfs entry: %d/%s\n", pid, p); + end: ihk_mc_unmap_virtual(buf, npages, 0); dprintf("ret: %d, eof: %d\n", ans, eof); @@ -799,6 +589,12 @@ dataunavail: if (ret < 0) { kprintf("ERROR: sending IKC msg, ret: %d\n", ret); } + if(proc) + release_process(proc); + if(thread) + release_thread(thread); + if(vm) + release_process_vm(vm); return; } diff --git a/kernel/syscall.c b/kernel/syscall.c index 41e5639f..348595c9 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -632,8 +632,6 @@ terminate(int rc, int sig) list_add_tail(&mythread->siblings_list, &proc->threads_list); mcs_rwlock_writer_unlock(&proc->threads_lock, &lock); - delete_proc_procfs_files(proc->pid); - vm = proc->vm; free_all_process_memory_range(vm);