diff --git a/executer/kernel/mcctrl/control.c b/executer/kernel/mcctrl/control.c index 213ed097..489605d8 100644 --- a/executer/kernel/mcctrl/control.c +++ b/executer/kernel/mcctrl/control.c @@ -49,6 +49,9 @@ //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) @@ -834,6 +837,12 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename) struct mckernel_exec_file *mcef; struct mckernel_exec_file *mcef_iter; int retval; + int os_ind = ihk_host_os_get_index(os); + char proc_name[1024]; + + if (os_ind < 0) { + return EINVAL; + } file = open_exec(filename); retval = PTR_ERR(file); @@ -847,6 +856,8 @@ 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) { @@ -855,6 +866,8 @@ 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; } @@ -865,6 +878,12 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename) mcef->pid = current->tgid; mcef->fp = file; 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, filename) != 0) { + printk("ERROR: could not create a procfs entry for %s.\n", proc_name); + } spin_unlock(&mckernel_exec_file_lock); dprintk("%d open_exec and holding file: %s\n", (int)current->tgid, filename); @@ -882,6 +901,12 @@ 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; + } spin_lock_irq(&mckernel_exec_file_lock); list_for_each_entry(mcef, &mckernel_exec_files, list) { @@ -895,6 +920,15 @@ int mcexec_close_exec(ihk_os_t os) break; } } + + /* 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/procfs.c b/executer/kernel/mcctrl/procfs.c index 2d519850..2f0a5d43 100644 --- a/executer/kernel/mcctrl/procfs.c +++ b/executer/kernel/mcctrl/procfs.c @@ -83,7 +83,8 @@ static const struct file_operations mckernel_procfs_file_operations = { * * \param p a name of the procfs file * \param osnum os number - * \param mode if zero create a directory otherwise a file + * \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 @@ -103,7 +104,7 @@ static const struct file_operations mckernel_procfs_file_operations = { * ancestor directory which was not explicitly created were racing. */ -static struct procfs_list_entry *get_procfs_list_entry(char *p, int osnum, int mode) +struct procfs_list_entry *get_procfs_list_entry(char *p, int osnum, int mode, void *opaque) { char *r; struct proc_dir_entry *pde = NULL; @@ -133,7 +134,7 @@ static struct procfs_list_entry *get_procfs_list_entry(char *p, int osnum, int m /* We have non-null parent dir. */ strncpy(name, p, r - p); name[r - p] = '\0'; - parent = get_procfs_list_entry(name, osnum, 0); + parent = get_procfs_list_entry(name, osnum, 0, NULL); if (parent == NULL) { /* We counld not get a parent procfs entry. Give up.*/ return NULL; @@ -158,7 +159,9 @@ static struct procfs_list_entry *get_procfs_list_entry(char *p, int osnum, int m #else pde = proc_mkdir_data(name, 0555, parent ? parent->entry : NULL, ret); #endif - } else { + } 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) @@ -188,6 +191,36 @@ static struct procfs_list_entry *get_procfs_list_entry(char *p, int osnum, int m 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) +{ + struct procfs_list_entry *e; + + e = get_procfs_list_entry(name, osnum, mode, opaque); + 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. * @@ -200,7 +233,6 @@ static struct procfs_list_entry *get_procfs_list_entry(char *p, int osnum, int m void procfs_create(void *__os, int ref, int osnum, int pid, unsigned long arg) { - struct procfs_list_entry *e; ihk_device_t dev = ihk_os_to_dev(__os); unsigned long parg; struct procfs_file *f; @@ -221,16 +253,12 @@ void procfs_create(void *__os, int ref, int osnum, int pid, unsigned long arg) printk("ERROR: procfs_creat: file name not properly terminated.\n"); goto quit; } - e = get_procfs_list_entry(name, osnum, mode); - if (e == NULL) { + + if (procfs_create_entry(__os, ref, osnum, pid, name, mode, NULL) != 0) { printk("ERROR: could not create a procfs entry for %s.\n", name); goto quit; } - e->os = __os; - e->cpu = ref; - e->pid = pid; - quit: f->status = 1; /* Now the peer can free the data. */ ihk_device_unmap_virtual(dev, f, sizeof(struct procfs_file)); @@ -239,31 +267,24 @@ quit: } /** - * \brief Delete a procfs entry. + * \brief Delete a procfs entry (internal). * * \param __os (opaque) os variable * \param osnum os number - * \param arg sent argument */ -void procfs_delete(void *__os, int osnum, unsigned long arg) +/* TODO: detect when a directory becomes empty remove it automatically */ +void procfs_delete_entry(void *os, int osnum, char *fname) { - ihk_device_t dev = ihk_os_to_dev(__os); - unsigned long parg; - struct procfs_file *f; struct procfs_list_entry *e; struct procfs_list_entry *parent = NULL; char name[PROCFS_NAME_MAX]; char *r; unsigned long irqflags; - 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); irqflags = ihk_ikc_spinlock_lock(&procfs_file_list_lock); list_for_each_entry(e, &procfs_file_list, list) { - if ((strncmp(e->fname, f->fname, PROCFS_NAME_MAX) == 0) && + if ((strncmp(e->fname, fname, PROCFS_NAME_MAX) == 0) && (e->osnum == osnum)) { list_del(&e->list); #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) @@ -272,18 +293,41 @@ void procfs_delete(void *__os, int osnum, unsigned long arg) #endif parent = e->parent; kfree(e); - r = strrchr(f->fname, '/'); + r = strrchr(fname, '/'); if (r == NULL) { - strncpy(name, f->fname, PROCFS_NAME_MAX); + strncpy(name, fname, PROCFS_NAME_MAX); } else { strncpy(name, r + 1, PROCFS_NAME_MAX); } - dprintk("found and remove %s from the list.\n", name); + printk("found and remove %s from the list.\n", name); remove_proc_entry(name, parent->entry); 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)); diff --git a/kernel/procfs.c b/kernel/procfs.c index 321da1f6..3ba78b5f 100644 --- a/kernel/procfs.c +++ b/kernel/procfs.c @@ -146,9 +146,7 @@ void delete_proc_procfs_files(int pid) snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/auxv", osnum, pid); delete_proc_procfs_file(pid, fname); - snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d", 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); }