aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/generic.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-08-15 12:15:17 -0400
committerIngo Molnar <mingo@elte.hu>2008-08-15 12:15:17 -0400
commitf3efbe582b5396d134024c03a5fa253f2a85d9a6 (patch)
treee4e15b7567b82d24cb1e7327398286a2b88df04c /fs/proc/generic.c
parent05d3ed0a1fe3ea05ab9f3b8d32576a0bc2e19660 (diff)
parentb635acec48bcaa9183fcbf4e3955616b0d4119b5 (diff)
Merge branch 'linus' into x86/gart
Diffstat (limited to 'fs/proc/generic.c')
-rw-r--r--fs/proc/generic.c46
1 files changed, 27 insertions, 19 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 43e54e86cefd..4fb81e9c94e3 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -300,10 +300,10 @@ out:
300 return rtn; 300 return rtn;
301} 301}
302 302
303static DEFINE_IDR(proc_inum_idr); 303static DEFINE_IDA(proc_inum_ida);
304static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */ 304static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */
305 305
306#define PROC_DYNAMIC_FIRST 0xF0000000UL 306#define PROC_DYNAMIC_FIRST 0xF0000000U
307 307
308/* 308/*
309 * Return an inode number between PROC_DYNAMIC_FIRST and 309 * Return an inode number between PROC_DYNAMIC_FIRST and
@@ -311,36 +311,33 @@ static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */
311 */ 311 */
312static unsigned int get_inode_number(void) 312static unsigned int get_inode_number(void)
313{ 313{
314 int i, inum = 0; 314 unsigned int i;
315 int error; 315 int error;
316 316
317retry: 317retry:
318 if (idr_pre_get(&proc_inum_idr, GFP_KERNEL) == 0) 318 if (ida_pre_get(&proc_inum_ida, GFP_KERNEL) == 0)
319 return 0; 319 return 0;
320 320
321 spin_lock(&proc_inum_lock); 321 spin_lock(&proc_inum_lock);
322 error = idr_get_new(&proc_inum_idr, NULL, &i); 322 error = ida_get_new(&proc_inum_ida, &i);
323 spin_unlock(&proc_inum_lock); 323 spin_unlock(&proc_inum_lock);
324 if (error == -EAGAIN) 324 if (error == -EAGAIN)
325 goto retry; 325 goto retry;
326 else if (error) 326 else if (error)
327 return 0; 327 return 0;
328 328
329 inum = (i & MAX_ID_MASK) + PROC_DYNAMIC_FIRST; 329 if (i > UINT_MAX - PROC_DYNAMIC_FIRST) {
330 330 spin_lock(&proc_inum_lock);
331 /* inum will never be more than 0xf0ffffff, so no check 331 ida_remove(&proc_inum_ida, i);
332 * for overflow. 332 spin_unlock(&proc_inum_lock);
333 */ 333 }
334 334 return PROC_DYNAMIC_FIRST + i;
335 return inum;
336} 335}
337 336
338static void release_inode_number(unsigned int inum) 337static void release_inode_number(unsigned int inum)
339{ 338{
340 int id = (inum - PROC_DYNAMIC_FIRST) | ~MAX_ID_MASK;
341
342 spin_lock(&proc_inum_lock); 339 spin_lock(&proc_inum_lock);
343 idr_remove(&proc_inum_idr, id); 340 ida_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST);
344 spin_unlock(&proc_inum_lock); 341 spin_unlock(&proc_inum_lock);
345} 342}
346 343
@@ -597,6 +594,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
597 ent->pde_users = 0; 594 ent->pde_users = 0;
598 spin_lock_init(&ent->pde_unload_lock); 595 spin_lock_init(&ent->pde_unload_lock);
599 ent->pde_unload_completion = NULL; 596 ent->pde_unload_completion = NULL;
597 INIT_LIST_HEAD(&ent->pde_openers);
600 out: 598 out:
601 return ent; 599 return ent;
602} 600}
@@ -789,15 +787,25 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
789 spin_unlock(&de->pde_unload_lock); 787 spin_unlock(&de->pde_unload_lock);
790 788
791continue_removing: 789continue_removing:
790 spin_lock(&de->pde_unload_lock);
791 while (!list_empty(&de->pde_openers)) {
792 struct pde_opener *pdeo;
793
794 pdeo = list_first_entry(&de->pde_openers, struct pde_opener, lh);
795 list_del(&pdeo->lh);
796 spin_unlock(&de->pde_unload_lock);
797 pdeo->release(pdeo->inode, pdeo->file);
798 kfree(pdeo);
799 spin_lock(&de->pde_unload_lock);
800 }
801 spin_unlock(&de->pde_unload_lock);
802
792 if (S_ISDIR(de->mode)) 803 if (S_ISDIR(de->mode))
793 parent->nlink--; 804 parent->nlink--;
794 de->nlink = 0; 805 de->nlink = 0;
795 if (de->subdir) { 806 WARN(de->subdir, KERN_WARNING "%s: removing non-empty directory "
796 printk(KERN_WARNING "%s: removing non-empty directory "
797 "'%s/%s', leaking at least '%s'\n", __func__, 807 "'%s/%s', leaking at least '%s'\n", __func__,
798 de->parent->name, de->name, de->subdir->name); 808 de->parent->name, de->name, de->subdir->name);
799 WARN_ON(1);
800 }
801 if (atomic_dec_and_test(&de->count)) 809 if (atomic_dec_and_test(&de->count))
802 free_proc_entry(de); 810 free_proc_entry(de);
803} 811}