Loading fs/proc/inode.c +21 −41 Original line number Diff line number Diff line Loading @@ -133,67 +133,48 @@ enum {BIAS = -1U<<31}; static inline int use_pde(struct proc_dir_entry *pde) { int res = 1; spin_lock(&pde->pde_unload_lock); if (unlikely(pde->pde_users < 0)) res = 0; else pde->pde_users++; spin_unlock(&pde->pde_unload_lock); return res; } static void __pde_users_dec(struct proc_dir_entry *pde) { if (--pde->pde_users == BIAS) complete(pde->pde_unload_completion); return atomic_inc_unless_negative(&pde->in_use); } static void unuse_pde(struct proc_dir_entry *pde) { spin_lock(&pde->pde_unload_lock); __pde_users_dec(pde); spin_unlock(&pde->pde_unload_lock); if (atomic_dec_return(&pde->in_use) == BIAS) complete(pde->pde_unload_completion); } /* pde is locked */ static void close_pdeo(struct proc_dir_entry *pde, struct pde_opener *pdeo) { pdeo->count++; if (!mutex_trylock(&pdeo->mutex)) { if (pdeo->closing) { /* somebody else is doing that, just wait */ DECLARE_COMPLETION_ONSTACK(c); pdeo->c = &c; spin_unlock(&pde->pde_unload_lock); mutex_lock(&pdeo->mutex); wait_for_completion(&c); spin_lock(&pde->pde_unload_lock); WARN_ON(!list_empty(&pdeo->lh)); } else { struct file *file; pdeo->closing = 1; spin_unlock(&pde->pde_unload_lock); file = pdeo->file; pde->proc_fops->release(file_inode(file), file); spin_lock(&pde->pde_unload_lock); list_del_init(&pdeo->lh); } mutex_unlock(&pdeo->mutex); if (!--pdeo->count) if (pdeo->c) complete(pdeo->c); kfree(pdeo); } } void proc_entry_rundown(struct proc_dir_entry *de) { spin_lock(&de->pde_unload_lock); de->pde_users += BIAS; /* Wait until all existing callers into module are done. */ if (de->pde_users != BIAS) { DECLARE_COMPLETION_ONSTACK(c); /* Wait until all existing callers into module are done. */ de->pde_unload_completion = &c; spin_unlock(&de->pde_unload_lock); wait_for_completion(de->pde_unload_completion); if (atomic_add_return(BIAS, &de->in_use) != BIAS) wait_for_completion(&c); 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); Loading Loading @@ -356,7 +337,7 @@ static int proc_reg_open(struct inode *inode, struct file *file) * by hand in remove_proc_entry(). For this, save opener's credentials * for later. */ pdeo = kmalloc(sizeof(struct pde_opener), GFP_KERNEL); pdeo = kzalloc(sizeof(struct pde_opener), GFP_KERNEL); if (!pdeo) return -ENOMEM; Loading @@ -370,18 +351,17 @@ static int proc_reg_open(struct inode *inode, struct file *file) if (open) rv = open(inode, file); spin_lock(&pde->pde_unload_lock); if (rv == 0 && release) { /* To know what to release. */ mutex_init(&pdeo->mutex); pdeo->count = 0; pdeo->file = file; /* Strictly for "too late" ->release in proc_reg_release(). */ spin_lock(&pde->pde_unload_lock); list_add(&pdeo->lh, &pde->pde_openers); spin_unlock(&pde->pde_unload_lock); } else kfree(pdeo); __pde_users_dec(pde); spin_unlock(&pde->pde_unload_lock); unuse_pde(pde); return rv; } Loading fs/proc/internal.h +2 −2 Original line number Diff line number Diff line Loading @@ -153,8 +153,8 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent, struct pde_opener { struct file *file; struct list_head lh; int count; /* number of threads in close_pdeo() */ struct mutex mutex; int closing; struct completion *c; }; ssize_t __proc_file_read(struct file *, char __user *, size_t, loff_t *); Loading include/linux/proc_fs.h +1 −1 Original line number Diff line number Diff line Loading @@ -65,7 +65,7 @@ struct proc_dir_entry { void *data; read_proc_t *read_proc; atomic_t count; /* use count */ int pde_users; /* number of callers into module in progress; */ atomic_t in_use; /* number of callers into module in progress; */ /* negative -> it's going away RSN */ struct completion *pde_unload_completion; struct list_head pde_openers; /* who did ->open, but not ->release */ Loading Loading
fs/proc/inode.c +21 −41 Original line number Diff line number Diff line Loading @@ -133,67 +133,48 @@ enum {BIAS = -1U<<31}; static inline int use_pde(struct proc_dir_entry *pde) { int res = 1; spin_lock(&pde->pde_unload_lock); if (unlikely(pde->pde_users < 0)) res = 0; else pde->pde_users++; spin_unlock(&pde->pde_unload_lock); return res; } static void __pde_users_dec(struct proc_dir_entry *pde) { if (--pde->pde_users == BIAS) complete(pde->pde_unload_completion); return atomic_inc_unless_negative(&pde->in_use); } static void unuse_pde(struct proc_dir_entry *pde) { spin_lock(&pde->pde_unload_lock); __pde_users_dec(pde); spin_unlock(&pde->pde_unload_lock); if (atomic_dec_return(&pde->in_use) == BIAS) complete(pde->pde_unload_completion); } /* pde is locked */ static void close_pdeo(struct proc_dir_entry *pde, struct pde_opener *pdeo) { pdeo->count++; if (!mutex_trylock(&pdeo->mutex)) { if (pdeo->closing) { /* somebody else is doing that, just wait */ DECLARE_COMPLETION_ONSTACK(c); pdeo->c = &c; spin_unlock(&pde->pde_unload_lock); mutex_lock(&pdeo->mutex); wait_for_completion(&c); spin_lock(&pde->pde_unload_lock); WARN_ON(!list_empty(&pdeo->lh)); } else { struct file *file; pdeo->closing = 1; spin_unlock(&pde->pde_unload_lock); file = pdeo->file; pde->proc_fops->release(file_inode(file), file); spin_lock(&pde->pde_unload_lock); list_del_init(&pdeo->lh); } mutex_unlock(&pdeo->mutex); if (!--pdeo->count) if (pdeo->c) complete(pdeo->c); kfree(pdeo); } } void proc_entry_rundown(struct proc_dir_entry *de) { spin_lock(&de->pde_unload_lock); de->pde_users += BIAS; /* Wait until all existing callers into module are done. */ if (de->pde_users != BIAS) { DECLARE_COMPLETION_ONSTACK(c); /* Wait until all existing callers into module are done. */ de->pde_unload_completion = &c; spin_unlock(&de->pde_unload_lock); wait_for_completion(de->pde_unload_completion); if (atomic_add_return(BIAS, &de->in_use) != BIAS) wait_for_completion(&c); 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); Loading Loading @@ -356,7 +337,7 @@ static int proc_reg_open(struct inode *inode, struct file *file) * by hand in remove_proc_entry(). For this, save opener's credentials * for later. */ pdeo = kmalloc(sizeof(struct pde_opener), GFP_KERNEL); pdeo = kzalloc(sizeof(struct pde_opener), GFP_KERNEL); if (!pdeo) return -ENOMEM; Loading @@ -370,18 +351,17 @@ static int proc_reg_open(struct inode *inode, struct file *file) if (open) rv = open(inode, file); spin_lock(&pde->pde_unload_lock); if (rv == 0 && release) { /* To know what to release. */ mutex_init(&pdeo->mutex); pdeo->count = 0; pdeo->file = file; /* Strictly for "too late" ->release in proc_reg_release(). */ spin_lock(&pde->pde_unload_lock); list_add(&pdeo->lh, &pde->pde_openers); spin_unlock(&pde->pde_unload_lock); } else kfree(pdeo); __pde_users_dec(pde); spin_unlock(&pde->pde_unload_lock); unuse_pde(pde); return rv; } Loading
fs/proc/internal.h +2 −2 Original line number Diff line number Diff line Loading @@ -153,8 +153,8 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent, struct pde_opener { struct file *file; struct list_head lh; int count; /* number of threads in close_pdeo() */ struct mutex mutex; int closing; struct completion *c; }; ssize_t __proc_file_read(struct file *, char __user *, size_t, loff_t *); Loading
include/linux/proc_fs.h +1 −1 Original line number Diff line number Diff line Loading @@ -65,7 +65,7 @@ struct proc_dir_entry { void *data; read_proc_t *read_proc; atomic_t count; /* use count */ int pde_users; /* number of callers into module in progress; */ atomic_t in_use; /* number of callers into module in progress; */ /* negative -> it's going away RSN */ struct completion *pde_unload_completion; struct list_head pde_openers; /* who did ->open, but not ->release */ Loading