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);
|
//static DECLARE_WAIT_QUEUE_HEAD(wq_prepare);
|
||||||
//extern struct mcctrl_channel *channels;
|
//extern struct mcctrl_channel *channels;
|
||||||
int mcctrl_ikc_set_recv_cpu(ihk_os_t os, int cpu);
|
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,
|
static long mcexec_prepare_image(ihk_os_t os,
|
||||||
struct program_load_desc * __user udesc)
|
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;
|
||||||
struct mckernel_exec_file *mcef_iter;
|
struct mckernel_exec_file *mcef_iter;
|
||||||
int retval;
|
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);
|
file = open_exec(filename);
|
||||||
retval = PTR_ERR(file);
|
retval = PTR_ERR(file);
|
||||||
@ -847,6 +856,8 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename)
|
|||||||
goto out_put_file;
|
goto out_put_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snprintf(proc_name, 1024, "mcos%d/%d/exe", os_ind, current->tgid);
|
||||||
|
|
||||||
spin_lock_irq(&mckernel_exec_file_lock);
|
spin_lock_irq(&mckernel_exec_file_lock);
|
||||||
/* Find previous file (if exists) and drop it */
|
/* Find previous file (if exists) and drop it */
|
||||||
list_for_each_entry(mcef_iter, &mckernel_exec_files, list) {
|
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);
|
fput(mcef_iter->fp);
|
||||||
list_del(&mcef_iter->list);
|
list_del(&mcef_iter->list);
|
||||||
kfree(mcef_iter);
|
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);
|
dprintk("%d open_exec dropped previous executable \n", (int)current->tgid);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -865,6 +878,12 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename)
|
|||||||
mcef->pid = current->tgid;
|
mcef->pid = current->tgid;
|
||||||
mcef->fp = file;
|
mcef->fp = file;
|
||||||
list_add_tail(&mcef->list, &mckernel_exec_files);
|
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);
|
spin_unlock(&mckernel_exec_file_lock);
|
||||||
|
|
||||||
dprintk("%d open_exec and holding file: %s\n", (int)current->tgid, filename);
|
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;
|
struct mckernel_exec_file *mcef = NULL;
|
||||||
int found = 0;
|
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);
|
spin_lock_irq(&mckernel_exec_file_lock);
|
||||||
list_for_each_entry(mcef, &mckernel_exec_files, list) {
|
list_for_each_entry(mcef, &mckernel_exec_files, list) {
|
||||||
@ -895,6 +920,15 @@ int mcexec_close_exec(ihk_os_t os)
|
|||||||
break;
|
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);
|
spin_unlock(&mckernel_exec_file_lock);
|
||||||
|
|
||||||
return (found ? 0 : EINVAL);
|
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 p a name of the procfs file
|
||||||
* \param osnum os number
|
* \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.
|
* return value: NULL: Something wrong has occurred.
|
||||||
* otherwise: address of the proc_dir_entry structure of the procfs file
|
* 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.
|
* 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;
|
char *r;
|
||||||
struct proc_dir_entry *pde = NULL;
|
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. */
|
/* We have non-null parent dir. */
|
||||||
strncpy(name, p, r - p);
|
strncpy(name, p, r - p);
|
||||||
name[r - p] = '\0';
|
name[r - p] = '\0';
|
||||||
parent = get_procfs_list_entry(name, osnum, 0);
|
parent = get_procfs_list_entry(name, osnum, 0, NULL);
|
||||||
if (parent == NULL) {
|
if (parent == NULL) {
|
||||||
/* We counld not get a parent procfs entry. Give up.*/
|
/* We counld not get a parent procfs entry. Give up.*/
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -158,6 +159,8 @@ static struct procfs_list_entry *get_procfs_list_entry(char *p, int osnum, int m
|
|||||||
#else
|
#else
|
||||||
pde = proc_mkdir_data(name, 0555, parent ? parent->entry : NULL, ret);
|
pde = proc_mkdir_data(name, 0555, parent ? parent->entry : NULL, ret);
|
||||||
#endif
|
#endif
|
||||||
|
} else if (mode & S_IFLNK) {
|
||||||
|
pde = proc_symlink(name, parent->entry, (char *)opaque);
|
||||||
} else {
|
} else {
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
|
||||||
pde = create_proc_entry(name, mode, parent->entry);
|
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;
|
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.
|
* \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)
|
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);
|
ihk_device_t dev = ihk_os_to_dev(__os);
|
||||||
unsigned long parg;
|
unsigned long parg;
|
||||||
struct procfs_file *f;
|
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");
|
printk("ERROR: procfs_creat: file name not properly terminated.\n");
|
||||||
goto quit;
|
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);
|
printk("ERROR: could not create a procfs entry for %s.\n", name);
|
||||||
goto quit;
|
goto quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
e->os = __os;
|
|
||||||
e->cpu = ref;
|
|
||||||
e->pid = pid;
|
|
||||||
|
|
||||||
quit:
|
quit:
|
||||||
f->status = 1; /* Now the peer can free the data. */
|
f->status = 1; /* Now the peer can free the data. */
|
||||||
ihk_device_unmap_virtual(dev, f, sizeof(struct procfs_file));
|
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 __os (opaque) os variable
|
||||||
* \param osnum os number
|
* \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 *e;
|
||||||
struct procfs_list_entry *parent = NULL;
|
struct procfs_list_entry *parent = NULL;
|
||||||
char name[PROCFS_NAME_MAX];
|
char name[PROCFS_NAME_MAX];
|
||||||
char *r;
|
char *r;
|
||||||
unsigned long irqflags;
|
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);
|
irqflags = ihk_ikc_spinlock_lock(&procfs_file_list_lock);
|
||||||
list_for_each_entry(e, &procfs_file_list, list) {
|
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)) {
|
(e->osnum == osnum)) {
|
||||||
list_del(&e->list);
|
list_del(&e->list);
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
|
||||||
@ -272,18 +293,41 @@ void procfs_delete(void *__os, int osnum, unsigned long arg)
|
|||||||
#endif
|
#endif
|
||||||
parent = e->parent;
|
parent = e->parent;
|
||||||
kfree(e);
|
kfree(e);
|
||||||
r = strrchr(f->fname, '/');
|
r = strrchr(fname, '/');
|
||||||
if (r == NULL) {
|
if (r == NULL) {
|
||||||
strncpy(name, f->fname, PROCFS_NAME_MAX);
|
strncpy(name, fname, PROCFS_NAME_MAX);
|
||||||
} else {
|
} else {
|
||||||
strncpy(name, r + 1, PROCFS_NAME_MAX);
|
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);
|
remove_proc_entry(name, parent->entry);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflags);
|
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. */
|
f->status = 1; /* Now the peer can free the data. */
|
||||||
ihk_device_unmap_virtual(dev, f, sizeof(struct procfs_file));
|
ihk_device_unmap_virtual(dev, f, sizeof(struct procfs_file));
|
||||||
ihk_device_unmap_memory(dev, parg, 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);
|
snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/auxv", osnum, pid);
|
||||||
delete_proc_procfs_file(pid, fname);
|
delete_proc_procfs_file(pid, fname);
|
||||||
|
|
||||||
snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d", osnum, pid);
|
/* NOTE: Directory is removed on the host when mcexec drops the executable */
|
||||||
delete_proc_procfs_file(pid, fname);
|
|
||||||
|
|
||||||
dprintf("delete procfs files for pid %d: done\n", pid);
|
dprintf("delete procfs files for pid %d: done\n", pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user