diff options
author | Oleg Nesterov <oleg@redhat.com> | 2013-07-08 17:24:16 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-07-13 05:29:10 -0400 |
commit | 4f5e65a1cc90bbb15b9f6cdc362922af1bcc155a (patch) | |
tree | c635e87d98c9961ad95c2351bae6d9609eeb761f /fs | |
parent | 64372501e2af9b11e2ffd1ff79345dc4b1abe539 (diff) |
fput: turn "list_head delayed_fput_list" into llist_head
fput() and delayed_fput() can use llist and avoid the locking.
This is unlikely path, it is not that this change can improve
the performance, but this way the code looks simpler.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Suggested-by: Andrew Morton <akpm@linux-foundation.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Andrey Vagin <avagin@openvz.org>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: David Howells <dhowells@redhat.com>
Cc: Huang Ying <ying.huang@intel.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/file_table.c | 25 |
1 files changed, 10 insertions, 15 deletions
diff --git a/fs/file_table.c b/fs/file_table.c index b9a77ad08b4d..b44e4c559786 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -265,18 +265,15 @@ static void __fput(struct file *file) | |||
265 | mntput(mnt); | 265 | mntput(mnt); |
266 | } | 266 | } |
267 | 267 | ||
268 | static DEFINE_SPINLOCK(delayed_fput_lock); | 268 | static LLIST_HEAD(delayed_fput_list); |
269 | static LIST_HEAD(delayed_fput_list); | ||
270 | static void delayed_fput(struct work_struct *unused) | 269 | static void delayed_fput(struct work_struct *unused) |
271 | { | 270 | { |
272 | LIST_HEAD(head); | 271 | struct llist_node *node = llist_del_all(&delayed_fput_list); |
273 | spin_lock_irq(&delayed_fput_lock); | 272 | struct llist_node *next; |
274 | list_splice_init(&delayed_fput_list, &head); | 273 | |
275 | spin_unlock_irq(&delayed_fput_lock); | 274 | for (; node; node = next) { |
276 | while (!list_empty(&head)) { | 275 | next = llist_next(node); |
277 | struct file *f = list_first_entry(&head, struct file, f_u.fu_list); | 276 | __fput(llist_entry(node, struct file, f_u.fu_llist)); |
278 | list_del_init(&f->f_u.fu_list); | ||
279 | __fput(f); | ||
280 | } | 277 | } |
281 | } | 278 | } |
282 | 279 | ||
@@ -306,7 +303,6 @@ void fput(struct file *file) | |||
306 | { | 303 | { |
307 | if (atomic_long_dec_and_test(&file->f_count)) { | 304 | if (atomic_long_dec_and_test(&file->f_count)) { |
308 | struct task_struct *task = current; | 305 | struct task_struct *task = current; |
309 | unsigned long flags; | ||
310 | 306 | ||
311 | file_sb_list_del(file); | 307 | file_sb_list_del(file); |
312 | if (likely(!in_interrupt() && !(task->flags & PF_KTHREAD))) { | 308 | if (likely(!in_interrupt() && !(task->flags & PF_KTHREAD))) { |
@@ -320,10 +316,9 @@ void fput(struct file *file) | |||
320 | * fput to avoid leaking *file. | 316 | * fput to avoid leaking *file. |
321 | */ | 317 | */ |
322 | } | 318 | } |
323 | spin_lock_irqsave(&delayed_fput_lock, flags); | 319 | |
324 | list_add(&file->f_u.fu_list, &delayed_fput_list); | 320 | if (llist_add(&file->f_u.fu_llist, &delayed_fput_list)) |
325 | schedule_work(&delayed_fput_work); | 321 | schedule_work(&delayed_fput_work); |
326 | spin_unlock_irqrestore(&delayed_fput_lock, flags); | ||
327 | } | 322 | } |
328 | } | 323 | } |
329 | 324 | ||