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);
pager_remove_process(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]);
}
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) {
printk("%s: error adding per process data\n", __FUNCTION__);
kfree(ppd);

View File

@ -224,6 +224,9 @@ struct mcctrl_per_proc_data {
cpumask_t cpu_set;
int ikc_target_cpu;
atomic_t refcount;
struct list_head devobj_pager_list;
struct semaphore devobj_pager_lock;
};
struct sysfsm_req {
@ -345,7 +348,7 @@ ihk_os_t osnum_to_os(int n);
/* syscall.c */
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 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);
}
void pager_remove_process(void)
void pager_remove_process(struct mcctrl_per_proc_data *ppd)
{
int error;
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) {
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_map_result *resp;
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);
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);
if (!pager) {
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_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;
pager = 0; /* pager should be in list? */
out:
if (file) {
@ -1300,6 +1342,7 @@ out:
if (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);
return error;
}
@ -1407,13 +1450,10 @@ out:
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;
dprintk("pager_req_unmap(%p,%lx)\n", os, handle);
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
down_write(&current->mm->mmap_sem);
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
if (error) {
printk("pager_req_unmap(%p,%lx):do_munmap failed. %d\n", os, handle, error);
/* through */
printk("%s: WARNING: munmap failed for pager 0x%lx: %d\n",
__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);
dprintk("pager_req_unmap(%p,%lx): %d\n", os, handle, error);
out:
return error;
}