diff options
Diffstat (limited to 'fs/file_table.c')
-rw-r--r-- | fs/file_table.c | 81 |
1 files changed, 71 insertions, 10 deletions
diff --git a/fs/file_table.c b/fs/file_table.c index a305d9e2d1b2..b3fc4d67a26b 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/lglock.h> | 23 | #include <linux/lglock.h> |
24 | #include <linux/percpu_counter.h> | 24 | #include <linux/percpu_counter.h> |
25 | #include <linux/percpu.h> | 25 | #include <linux/percpu.h> |
26 | #include <linux/hardirq.h> | ||
27 | #include <linux/task_work.h> | ||
26 | #include <linux/ima.h> | 28 | #include <linux/ima.h> |
27 | 29 | ||
28 | #include <linux/atomic.h> | 30 | #include <linux/atomic.h> |
@@ -251,7 +253,6 @@ static void __fput(struct file *file) | |||
251 | } | 253 | } |
252 | fops_put(file->f_op); | 254 | fops_put(file->f_op); |
253 | put_pid(file->f_owner.pid); | 255 | put_pid(file->f_owner.pid); |
254 | file_sb_list_del(file); | ||
255 | if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | 256 | if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) |
256 | i_readcount_dec(inode); | 257 | i_readcount_dec(inode); |
257 | if (file->f_mode & FMODE_WRITE) | 258 | if (file->f_mode & FMODE_WRITE) |
@@ -263,10 +264,77 @@ static void __fput(struct file *file) | |||
263 | mntput(mnt); | 264 | mntput(mnt); |
264 | } | 265 | } |
265 | 266 | ||
267 | static DEFINE_SPINLOCK(delayed_fput_lock); | ||
268 | static LIST_HEAD(delayed_fput_list); | ||
269 | static void delayed_fput(struct work_struct *unused) | ||
270 | { | ||
271 | LIST_HEAD(head); | ||
272 | spin_lock_irq(&delayed_fput_lock); | ||
273 | list_splice_init(&delayed_fput_list, &head); | ||
274 | spin_unlock_irq(&delayed_fput_lock); | ||
275 | while (!list_empty(&head)) { | ||
276 | struct file *f = list_first_entry(&head, struct file, f_u.fu_list); | ||
277 | list_del_init(&f->f_u.fu_list); | ||
278 | __fput(f); | ||
279 | } | ||
280 | } | ||
281 | |||
282 | static void ____fput(struct callback_head *work) | ||
283 | { | ||
284 | __fput(container_of(work, struct file, f_u.fu_rcuhead)); | ||
285 | } | ||
286 | |||
287 | /* | ||
288 | * If kernel thread really needs to have the final fput() it has done | ||
289 | * to complete, call this. The only user right now is the boot - we | ||
290 | * *do* need to make sure our writes to binaries on initramfs has | ||
291 | * not left us with opened struct file waiting for __fput() - execve() | ||
292 | * won't work without that. Please, don't add more callers without | ||
293 | * very good reasons; in particular, never call that with locks | ||
294 | * held and never call that from a thread that might need to do | ||
295 | * some work on any kind of umount. | ||
296 | */ | ||
297 | void flush_delayed_fput(void) | ||
298 | { | ||
299 | delayed_fput(NULL); | ||
300 | } | ||
301 | |||
302 | static DECLARE_WORK(delayed_fput_work, delayed_fput); | ||
303 | |||
266 | void fput(struct file *file) | 304 | void fput(struct file *file) |
267 | { | 305 | { |
268 | if (atomic_long_dec_and_test(&file->f_count)) | 306 | if (atomic_long_dec_and_test(&file->f_count)) { |
307 | struct task_struct *task = current; | ||
308 | file_sb_list_del(file); | ||
309 | if (unlikely(in_interrupt() || task->flags & PF_KTHREAD)) { | ||
310 | unsigned long flags; | ||
311 | spin_lock_irqsave(&delayed_fput_lock, flags); | ||
312 | list_add(&file->f_u.fu_list, &delayed_fput_list); | ||
313 | schedule_work(&delayed_fput_work); | ||
314 | spin_unlock_irqrestore(&delayed_fput_lock, flags); | ||
315 | return; | ||
316 | } | ||
317 | init_task_work(&file->f_u.fu_rcuhead, ____fput); | ||
318 | task_work_add(task, &file->f_u.fu_rcuhead, true); | ||
319 | } | ||
320 | } | ||
321 | |||
322 | /* | ||
323 | * synchronous analog of fput(); for kernel threads that might be needed | ||
324 | * in some umount() (and thus can't use flush_delayed_fput() without | ||
325 | * risking deadlocks), need to wait for completion of __fput() and know | ||
326 | * for this specific struct file it won't involve anything that would | ||
327 | * need them. Use only if you really need it - at the very least, | ||
328 | * don't blindly convert fput() by kernel thread to that. | ||
329 | */ | ||
330 | void __fput_sync(struct file *file) | ||
331 | { | ||
332 | if (atomic_long_dec_and_test(&file->f_count)) { | ||
333 | struct task_struct *task = current; | ||
334 | file_sb_list_del(file); | ||
335 | BUG_ON(!(task->flags & PF_KTHREAD)); | ||
269 | __fput(file); | 336 | __fput(file); |
337 | } | ||
270 | } | 338 | } |
271 | 339 | ||
272 | EXPORT_SYMBOL(fput); | 340 | EXPORT_SYMBOL(fput); |
@@ -483,10 +551,8 @@ void mark_files_ro(struct super_block *sb) | |||
483 | { | 551 | { |
484 | struct file *f; | 552 | struct file *f; |
485 | 553 | ||
486 | retry: | ||
487 | lg_global_lock(&files_lglock); | 554 | lg_global_lock(&files_lglock); |
488 | do_file_list_for_each_entry(sb, f) { | 555 | do_file_list_for_each_entry(sb, f) { |
489 | struct vfsmount *mnt; | ||
490 | if (!S_ISREG(f->f_path.dentry->d_inode->i_mode)) | 556 | if (!S_ISREG(f->f_path.dentry->d_inode->i_mode)) |
491 | continue; | 557 | continue; |
492 | if (!file_count(f)) | 558 | if (!file_count(f)) |
@@ -499,12 +565,7 @@ retry: | |||
499 | if (file_check_writeable(f) != 0) | 565 | if (file_check_writeable(f) != 0) |
500 | continue; | 566 | continue; |
501 | file_release_write(f); | 567 | file_release_write(f); |
502 | mnt = mntget(f->f_path.mnt); | 568 | mnt_drop_write_file(f); |
503 | /* This can sleep, so we can't hold the spinlock. */ | ||
504 | lg_global_unlock(&files_lglock); | ||
505 | mnt_drop_write(mnt); | ||
506 | mntput(mnt); | ||
507 | goto retry; | ||
508 | } while_file_list_for_each_entry; | 569 | } while_file_list_for_each_entry; |
509 | lg_global_unlock(&files_lglock); | 570 | lg_global_unlock(&files_lglock); |
510 | } | 571 | } |