mcctrl: cleanup devobj pagers in release_handle() to avoid memory leak
This commit is contained in:
@ -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);
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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(¤t->mm->mmap_sem);
|
down_write(¤t->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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user