diff options
author | Tejun Heo <tj@kernel.org> | 2013-02-27 20:04:50 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-27 22:10:19 -0500 |
commit | 4542da631ad210716d097aa803a0828f9fed5e87 (patch) | |
tree | ea7254bb010ea1cd95cc7893657838e6e0860ee4 /fs/notify | |
parent | 2a86b3e74f12bcdd13ceb1bf333bc2d5f43b3c02 (diff) |
inotify: convert to idr_alloc()
Convert to the much saner new idr interface.
Note that the adhoc cyclic id allocation is buggy. If wraparound
happens, the previous code with idr_get_new_above() may segfault and
the converted code will trigger WARN and return -EINVAL. Even if it's
fixed to wrap to zero, the code will be prone to unnecessary -ENOSPC
failures after the first wraparound. We probably need to implement
proper cyclic support in idr.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: John McCutchan <john@johnmccutchan.com>
Cc: Robert Love <rlove@rlove.org>
Cc: Eric Paris <eparis@parisplace.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/notify')
-rw-r--r-- | fs/notify/inotify/inotify_user.c | 24 |
1 files changed, 11 insertions, 13 deletions
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 07f7a92fe88e..e0f7c1241a6a 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c | |||
@@ -364,22 +364,20 @@ static int inotify_add_to_idr(struct idr *idr, spinlock_t *idr_lock, | |||
364 | { | 364 | { |
365 | int ret; | 365 | int ret; |
366 | 366 | ||
367 | do { | 367 | idr_preload(GFP_KERNEL); |
368 | if (unlikely(!idr_pre_get(idr, GFP_KERNEL))) | 368 | spin_lock(idr_lock); |
369 | return -ENOMEM; | ||
370 | 369 | ||
371 | spin_lock(idr_lock); | 370 | ret = idr_alloc(idr, i_mark, *last_wd + 1, 0, GFP_NOWAIT); |
372 | ret = idr_get_new_above(idr, i_mark, *last_wd + 1, | 371 | if (ret >= 0) { |
373 | &i_mark->wd); | ||
374 | /* we added the mark to the idr, take a reference */ | 372 | /* we added the mark to the idr, take a reference */ |
375 | if (!ret) { | 373 | i_mark->wd = ret; |
376 | *last_wd = i_mark->wd; | 374 | *last_wd = i_mark->wd; |
377 | fsnotify_get_mark(&i_mark->fsn_mark); | 375 | fsnotify_get_mark(&i_mark->fsn_mark); |
378 | } | 376 | } |
379 | spin_unlock(idr_lock); | ||
380 | } while (ret == -EAGAIN); | ||
381 | 377 | ||
382 | return ret; | 378 | spin_unlock(idr_lock); |
379 | idr_preload_end(); | ||
380 | return ret < 0 ? ret : 0; | ||
383 | } | 381 | } |
384 | 382 | ||
385 | static struct inotify_inode_mark *inotify_idr_find_locked(struct fsnotify_group *group, | 383 | static struct inotify_inode_mark *inotify_idr_find_locked(struct fsnotify_group *group, |