Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 370057
b: refs/heads/master
c: 05c0ae2
h: refs/heads/master
i:
  370055: c4efbec
v: v3
  • Loading branch information
Al Viro committed Apr 9, 2013
1 parent 772cffc commit a613c93
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 45 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ca469f35a8e9ef12571a4b80ac6d7fdc0260fb44
refs/heads/master: 05c0ae21c034a6f7c6f4c0c63a31167ebb4b061f
62 changes: 21 additions & 41 deletions trunk/fs/proc/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
DECLARE_COMPLETION_ONSTACK(c);
/* Wait until all existing callers into module are done. */
if (de->pde_users != BIAS) {
DECLARE_COMPLETION_ONSTACK(c);
de->pde_unload_completion = &c;
spin_unlock(&de->pde_unload_lock);

wait_for_completion(de->pde_unload_completion);

spin_lock(&de->pde_unload_lock);
}
de->pde_unload_completion = &c;
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);
Expand Down Expand Up @@ -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;

Expand All @@ -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;
}

Expand Down
4 changes: 2 additions & 2 deletions trunk/fs/proc/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down
2 changes: 1 addition & 1 deletion trunk/include/linux/proc_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down

0 comments on commit a613c93

Please sign in to comment.