support /proc/self/exe (needed for GDB to attach to an existing process)
This commit is contained in:
@ -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);
|
||||
|
||||
@ -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,6 +159,8 @@ 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 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);
|
||||
@ -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));
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user