mcctrl: cleanup devobj pagers in release_handle() to avoid memory leak

This commit is contained in:
Balazs Gerofi
2017-06-11 19:10:53 +09:00
parent ab915f3331
commit b03f69783a
3 changed files with 88 additions and 13 deletions

View File

@ -969,9 +969,8 @@ void mcctrl_put_per_proc_data(struct mcctrl_per_proc_data *ppd)
} }
ihk_ikc_spinlock_unlock(&ppd->wq_list_lock, flags); ihk_ikc_spinlock_unlock(&ppd->wq_list_lock, flags);
pager_remove_process(ppd);
kfree(ppd); kfree(ppd);
pager_remove_process();
} }
@ -1464,6 +1463,9 @@ int mcexec_create_per_process_data(ihk_os_t os)
rwlock_init(&ppd->per_thread_data_hash_lock[i]); rwlock_init(&ppd->per_thread_data_hash_lock[i]);
} }
INIT_LIST_HEAD(&ppd->devobj_pager_list);
sema_init(&ppd->devobj_pager_lock, 1);
if (mcctrl_add_per_proc_data(usrdata, ppd->pid, ppd) < 0) { if (mcctrl_add_per_proc_data(usrdata, ppd->pid, ppd) < 0) {
printk("%s: error adding per process data\n", __FUNCTION__); printk("%s: error adding per process data\n", __FUNCTION__);
kfree(ppd); kfree(ppd);

View File

@ -224,6 +224,9 @@ struct mcctrl_per_proc_data {
cpumask_t cpu_set; cpumask_t cpu_set;
int ikc_target_cpu; int ikc_target_cpu;
atomic_t refcount; atomic_t refcount;
struct list_head devobj_pager_list;
struct semaphore devobj_pager_lock;
}; };
struct sysfsm_req { struct sysfsm_req {
@ -345,7 +348,7 @@ ihk_os_t osnum_to_os(int n);
/* syscall.c */ /* syscall.c */
void pager_add_process(void); void pager_add_process(void);
void pager_remove_process(void); void pager_remove_process(struct mcctrl_per_proc_data *ppd);
int __do_in_kernel_syscall(ihk_os_t os, struct ikc_scd_packet *packet); int __do_in_kernel_syscall(ihk_os_t os, struct ikc_scd_packet *packet);
int mcctrl_add_per_proc_data(struct mcctrl_usrdata *ud, int pid, int mcctrl_add_per_proc_data(struct mcctrl_usrdata *ud, int pid,

View File

@ -775,12 +775,35 @@ void pager_add_process(void)
up(&pager_sem); up(&pager_sem);
} }
void pager_remove_process(void) void pager_remove_process(struct mcctrl_per_proc_data *ppd)
{ {
int error; int error;
struct pager *pager_next, *pager; struct pager *pager_next, *pager;
error = down_interruptible(&pager_sem);
if (in_atomic() || in_interrupt()) {
printk("%s: WARNING: shouldn't be called in IRQ context..\n",
__FUNCTION__);
return;
}
/* Clean up device file mappings of this process */
error = down_interruptible(&ppd->devobj_pager_lock);
if (error) {
return;
}
list_for_each_entry_safe(pager, pager_next,
&ppd->devobj_pager_list, list) {
dprintk("%s: devobj pager 0x%lx removed\n", __FUNCTION__, pager);
list_del(&pager->list);
kfree(pager);
}
up(&ppd->devobj_pager_lock);
/* Clean up global pagers for regular file mappings if this
* was the last process */
error = down_interruptible(&pager_sem);
if (error) { if (error) {
return; return;
} }
@ -1216,8 +1239,18 @@ static int pager_req_map(ihk_os_t os, int fd, size_t len, off_t off,
struct pager *pager = NULL; struct pager *pager = NULL;
struct pager_map_result *resp; struct pager_map_result *resp;
uintptr_t phys; uintptr_t phys;
struct mcctrl_usrdata *usrdata = ihk_host_os_get_usrdata(os);
struct mcctrl_per_proc_data *ppd = NULL;
dprintk("pager_req_map(%p,%d,%lx,%lx,%lx)\n", os, fd, len, off, result_rpa); dprintk("pager_req_map(%p,%d,%lx,%lx,%lx)\n", os, fd, len, off, result_rpa);
ppd = mcctrl_get_per_proc_data(usrdata, task_tgid_vnr(current));
if (unlikely(!ppd)) {
kprintf("%s: ERROR: no per-process structure for PID %d??\n",
__FUNCTION__, task_tgid_vnr(current));
return -1;
}
pager = kzalloc(sizeof(*pager), GFP_ATOMIC); pager = kzalloc(sizeof(*pager), GFP_ATOMIC);
if (!pager) { if (!pager) {
error = -ENOMEM; error = -ENOMEM;
@ -1290,8 +1323,17 @@ static int pager_req_map(ihk_os_t os, int fd, size_t len, off_t off,
ihk_device_unmap_virtual(dev, resp, sizeof(*resp)); ihk_device_unmap_virtual(dev, resp, sizeof(*resp));
ihk_device_unmap_memory(dev, phys, sizeof(*resp)); ihk_device_unmap_memory(dev, phys, sizeof(*resp));
error = down_interruptible(&ppd->devobj_pager_lock);
if (error) {
error = -EINTR;
goto out;
}
list_add_tail(&pager->list, &ppd->devobj_pager_list);
up(&ppd->devobj_pager_lock);
pager = 0;
error = 0; error = 0;
pager = 0; /* pager should be in list? */
out: out:
if (file) { if (file) {
@ -1300,6 +1342,7 @@ out:
if (pager) { if (pager) {
kfree(pager); kfree(pager);
} }
mcctrl_put_per_proc_data(ppd);
dprintk("pager_req_map(%p,%d,%lx,%lx,%lx): %d\n", os, fd, len, off, result_rpa, error); dprintk("pager_req_map(%p,%d,%lx,%lx,%lx): %d\n", os, fd, len, off, result_rpa, error);
return error; return error;
} }
@ -1407,13 +1450,10 @@ out:
return error; return error;
} }
static int pager_req_unmap(ihk_os_t os, uintptr_t handle) static int __pager_unmap(struct pager *pager)
{ {
struct pager * const pager = (void *)handle;
int error; int error;
dprintk("pager_req_unmap(%p,%lx)\n", os, handle);
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
down_write(&current->mm->mmap_sem); down_write(&current->mm->mmap_sem);
error = do_munmap(current->mm, pager->map_uaddr, pager->map_len); error = do_munmap(current->mm, pager->map_uaddr, pager->map_len);
@ -1423,12 +1463,42 @@ static int pager_req_unmap(ihk_os_t os, uintptr_t handle)
#endif #endif
if (error) { if (error) {
printk("pager_req_unmap(%p,%lx):do_munmap failed. %d\n", os, handle, error); printk("%s: WARNING: munmap failed for pager 0x%lx: %d\n",
/* through */ __FUNCTION__, (uintptr_t)pager, error);
} }
return error;
}
static int pager_req_unmap(ihk_os_t os, uintptr_t handle)
{
struct pager * const pager = (void *)handle;
int error;
struct mcctrl_usrdata *usrdata = ihk_host_os_get_usrdata(os);
struct mcctrl_per_proc_data *ppd = NULL;
dprintk("pager_req_unmap(%p,%lx)\n", os, handle);
ppd = mcctrl_get_per_proc_data(usrdata, task_tgid_vnr(current));
if (unlikely(!ppd)) {
kprintf("%s: ERROR: no per-process structure for PID %d??\n",
__FUNCTION__, task_tgid_vnr(current));
return -1;
}
error = down_interruptible(&ppd->devobj_pager_lock);
if (error) {
error = -EINTR;
goto out;
}
list_del(&pager->list);
up(&ppd->devobj_pager_lock);
error = __pager_unmap(pager);
kfree(pager); kfree(pager);
dprintk("pager_req_unmap(%p,%lx): %d\n", os, handle, error);
out:
return error; return error;
} }