proc: always do ->release
Current two-stage scheme of removing PDE emphasizes one bug in proc: open rmmod remove_proc_entry close ->release won't be called because ->proc_fops were cleared. In simple cases it's small memory leak. For every ->open, ->release has to be done. List of openers is introduced which is traversed at remove_proc_entry() if neeeded. Discussions with Al long ago (sigh). Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:

committed by
Linus Torvalds

parent
6e644c3126
commit
881adb8535
@@ -597,6 +597,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
|
||||
ent->pde_users = 0;
|
||||
spin_lock_init(&ent->pde_unload_lock);
|
||||
ent->pde_unload_completion = NULL;
|
||||
INIT_LIST_HEAD(&ent->pde_openers);
|
||||
out:
|
||||
return ent;
|
||||
}
|
||||
@@ -789,6 +790,19 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
|
||||
spin_unlock(&de->pde_unload_lock);
|
||||
|
||||
continue_removing:
|
||||
spin_lock(&de->pde_unload_lock);
|
||||
while (!list_empty(&de->pde_openers)) {
|
||||
struct pde_opener *pdeo;
|
||||
|
||||
pdeo = list_first_entry(&de->pde_openers, struct pde_opener, lh);
|
||||
list_del(&pdeo->lh);
|
||||
spin_unlock(&de->pde_unload_lock);
|
||||
pdeo->release(pdeo->inode, pdeo->file);
|
||||
kfree(pdeo);
|
||||
spin_lock(&de->pde_unload_lock);
|
||||
}
|
||||
spin_unlock(&de->pde_unload_lock);
|
||||
|
||||
if (S_ISDIR(de->mode))
|
||||
parent->nlink--;
|
||||
de->nlink = 0;
|
||||
|
Reference in New Issue
Block a user