diff options
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 189 |
1 files changed, 28 insertions, 161 deletions
diff --git a/fs/super.c b/fs/super.c index 1943fdf655fa..2761d3e22ed9 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/blkdev.h> | 28 | #include <linux/blkdev.h> |
29 | #include <linux/quotaops.h> | 29 | #include <linux/quotaops.h> |
30 | #include <linux/namei.h> | 30 | #include <linux/namei.h> |
31 | #include <linux/buffer_head.h> /* for fsync_super() */ | ||
32 | #include <linux/mount.h> | 31 | #include <linux/mount.h> |
33 | #include <linux/security.h> | 32 | #include <linux/security.h> |
34 | #include <linux/syscalls.h> | 33 | #include <linux/syscalls.h> |
@@ -38,7 +37,6 @@ | |||
38 | #include <linux/kobject.h> | 37 | #include <linux/kobject.h> |
39 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
40 | #include <linux/file.h> | 39 | #include <linux/file.h> |
41 | #include <linux/async.h> | ||
42 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
43 | #include "internal.h" | 41 | #include "internal.h" |
44 | 42 | ||
@@ -72,7 +70,6 @@ static struct super_block *alloc_super(struct file_system_type *type) | |||
72 | INIT_HLIST_HEAD(&s->s_anon); | 70 | INIT_HLIST_HEAD(&s->s_anon); |
73 | INIT_LIST_HEAD(&s->s_inodes); | 71 | INIT_LIST_HEAD(&s->s_inodes); |
74 | INIT_LIST_HEAD(&s->s_dentry_lru); | 72 | INIT_LIST_HEAD(&s->s_dentry_lru); |
75 | INIT_LIST_HEAD(&s->s_async_list); | ||
76 | init_rwsem(&s->s_umount); | 73 | init_rwsem(&s->s_umount); |
77 | mutex_init(&s->s_lock); | 74 | mutex_init(&s->s_lock); |
78 | lockdep_set_class(&s->s_umount, &type->s_umount_key); | 75 | lockdep_set_class(&s->s_umount, &type->s_umount_key); |
@@ -285,38 +282,6 @@ void unlock_super(struct super_block * sb) | |||
285 | EXPORT_SYMBOL(lock_super); | 282 | EXPORT_SYMBOL(lock_super); |
286 | EXPORT_SYMBOL(unlock_super); | 283 | EXPORT_SYMBOL(unlock_super); |
287 | 284 | ||
288 | /* | ||
289 | * Write out and wait upon all dirty data associated with this | ||
290 | * superblock. Filesystem data as well as the underlying block | ||
291 | * device. Takes the superblock lock. Requires a second blkdev | ||
292 | * flush by the caller to complete the operation. | ||
293 | */ | ||
294 | void __fsync_super(struct super_block *sb) | ||
295 | { | ||
296 | sync_inodes_sb(sb, 0); | ||
297 | vfs_dq_sync(sb); | ||
298 | lock_super(sb); | ||
299 | if (sb->s_dirt && sb->s_op->write_super) | ||
300 | sb->s_op->write_super(sb); | ||
301 | unlock_super(sb); | ||
302 | if (sb->s_op->sync_fs) | ||
303 | sb->s_op->sync_fs(sb, 1); | ||
304 | sync_blockdev(sb->s_bdev); | ||
305 | sync_inodes_sb(sb, 1); | ||
306 | } | ||
307 | |||
308 | /* | ||
309 | * Write out and wait upon all dirty data associated with this | ||
310 | * superblock. Filesystem data as well as the underlying block | ||
311 | * device. Takes the superblock lock. | ||
312 | */ | ||
313 | int fsync_super(struct super_block *sb) | ||
314 | { | ||
315 | __fsync_super(sb); | ||
316 | return sync_blockdev(sb->s_bdev); | ||
317 | } | ||
318 | EXPORT_SYMBOL_GPL(fsync_super); | ||
319 | |||
320 | /** | 285 | /** |
321 | * generic_shutdown_super - common helper for ->kill_sb() | 286 | * generic_shutdown_super - common helper for ->kill_sb() |
322 | * @sb: superblock to kill | 287 | * @sb: superblock to kill |
@@ -338,21 +303,13 @@ void generic_shutdown_super(struct super_block *sb) | |||
338 | 303 | ||
339 | if (sb->s_root) { | 304 | if (sb->s_root) { |
340 | shrink_dcache_for_umount(sb); | 305 | shrink_dcache_for_umount(sb); |
341 | fsync_super(sb); | 306 | sync_filesystem(sb); |
342 | lock_super(sb); | 307 | get_fs_excl(); |
343 | sb->s_flags &= ~MS_ACTIVE; | 308 | sb->s_flags &= ~MS_ACTIVE; |
344 | 309 | ||
345 | /* | ||
346 | * wait for asynchronous fs operations to finish before going further | ||
347 | */ | ||
348 | async_synchronize_full_domain(&sb->s_async_list); | ||
349 | |||
350 | /* bad name - it should be evict_inodes() */ | 310 | /* bad name - it should be evict_inodes() */ |
351 | invalidate_inodes(sb); | 311 | invalidate_inodes(sb); |
352 | lock_kernel(); | ||
353 | 312 | ||
354 | if (sop->write_super && sb->s_dirt) | ||
355 | sop->write_super(sb); | ||
356 | if (sop->put_super) | 313 | if (sop->put_super) |
357 | sop->put_super(sb); | 314 | sop->put_super(sb); |
358 | 315 | ||
@@ -362,9 +319,7 @@ void generic_shutdown_super(struct super_block *sb) | |||
362 | "Self-destruct in 5 seconds. Have a nice day...\n", | 319 | "Self-destruct in 5 seconds. Have a nice day...\n", |
363 | sb->s_id); | 320 | sb->s_id); |
364 | } | 321 | } |
365 | 322 | put_fs_excl(); | |
366 | unlock_kernel(); | ||
367 | unlock_super(sb); | ||
368 | } | 323 | } |
369 | spin_lock(&sb_lock); | 324 | spin_lock(&sb_lock); |
370 | /* should be initialized for __put_super_and_need_restart() */ | 325 | /* should be initialized for __put_super_and_need_restart() */ |
@@ -441,16 +396,14 @@ void drop_super(struct super_block *sb) | |||
441 | 396 | ||
442 | EXPORT_SYMBOL(drop_super); | 397 | EXPORT_SYMBOL(drop_super); |
443 | 398 | ||
444 | static inline void write_super(struct super_block *sb) | 399 | /** |
445 | { | 400 | * sync_supers - helper for periodic superblock writeback |
446 | lock_super(sb); | 401 | * |
447 | if (sb->s_root && sb->s_dirt) | 402 | * Call the write_super method if present on all dirty superblocks in |
448 | if (sb->s_op->write_super) | 403 | * the system. This is for the periodic writeback used by most older |
449 | sb->s_op->write_super(sb); | 404 | * filesystems. For data integrity superblock writeback use |
450 | unlock_super(sb); | 405 | * sync_filesystems() instead. |
451 | } | 406 | * |
452 | |||
453 | /* | ||
454 | * Note: check the dirty flag before waiting, so we don't | 407 | * Note: check the dirty flag before waiting, so we don't |
455 | * hold up the sync while mounting a device. (The newly | 408 | * hold up the sync while mounting a device. (The newly |
456 | * mounted device won't need syncing.) | 409 | * mounted device won't need syncing.) |
@@ -462,12 +415,15 @@ void sync_supers(void) | |||
462 | spin_lock(&sb_lock); | 415 | spin_lock(&sb_lock); |
463 | restart: | 416 | restart: |
464 | list_for_each_entry(sb, &super_blocks, s_list) { | 417 | list_for_each_entry(sb, &super_blocks, s_list) { |
465 | if (sb->s_dirt) { | 418 | if (sb->s_op->write_super && sb->s_dirt) { |
466 | sb->s_count++; | 419 | sb->s_count++; |
467 | spin_unlock(&sb_lock); | 420 | spin_unlock(&sb_lock); |
421 | |||
468 | down_read(&sb->s_umount); | 422 | down_read(&sb->s_umount); |
469 | write_super(sb); | 423 | if (sb->s_root && sb->s_dirt) |
424 | sb->s_op->write_super(sb); | ||
470 | up_read(&sb->s_umount); | 425 | up_read(&sb->s_umount); |
426 | |||
471 | spin_lock(&sb_lock); | 427 | spin_lock(&sb_lock); |
472 | if (__put_super_and_need_restart(sb)) | 428 | if (__put_super_and_need_restart(sb)) |
473 | goto restart; | 429 | goto restart; |
@@ -476,60 +432,6 @@ restart: | |||
476 | spin_unlock(&sb_lock); | 432 | spin_unlock(&sb_lock); |
477 | } | 433 | } |
478 | 434 | ||
479 | /* | ||
480 | * Call the ->sync_fs super_op against all filesystems which are r/w and | ||
481 | * which implement it. | ||
482 | * | ||
483 | * This operation is careful to avoid the livelock which could easily happen | ||
484 | * if two or more filesystems are being continuously dirtied. s_need_sync_fs | ||
485 | * is used only here. We set it against all filesystems and then clear it as | ||
486 | * we sync them. So redirtied filesystems are skipped. | ||
487 | * | ||
488 | * But if process A is currently running sync_filesystems and then process B | ||
489 | * calls sync_filesystems as well, process B will set all the s_need_sync_fs | ||
490 | * flags again, which will cause process A to resync everything. Fix that with | ||
491 | * a local mutex. | ||
492 | * | ||
493 | * (Fabian) Avoid sync_fs with clean fs & wait mode 0 | ||
494 | */ | ||
495 | void sync_filesystems(int wait) | ||
496 | { | ||
497 | struct super_block *sb; | ||
498 | static DEFINE_MUTEX(mutex); | ||
499 | |||
500 | mutex_lock(&mutex); /* Could be down_interruptible */ | ||
501 | spin_lock(&sb_lock); | ||
502 | list_for_each_entry(sb, &super_blocks, s_list) { | ||
503 | if (!sb->s_op->sync_fs) | ||
504 | continue; | ||
505 | if (sb->s_flags & MS_RDONLY) | ||
506 | continue; | ||
507 | sb->s_need_sync_fs = 1; | ||
508 | } | ||
509 | |||
510 | restart: | ||
511 | list_for_each_entry(sb, &super_blocks, s_list) { | ||
512 | if (!sb->s_need_sync_fs) | ||
513 | continue; | ||
514 | sb->s_need_sync_fs = 0; | ||
515 | if (sb->s_flags & MS_RDONLY) | ||
516 | continue; /* hm. Was remounted r/o meanwhile */ | ||
517 | sb->s_count++; | ||
518 | spin_unlock(&sb_lock); | ||
519 | down_read(&sb->s_umount); | ||
520 | async_synchronize_full_domain(&sb->s_async_list); | ||
521 | if (sb->s_root && (wait || sb->s_dirt)) | ||
522 | sb->s_op->sync_fs(sb, wait); | ||
523 | up_read(&sb->s_umount); | ||
524 | /* restart only when sb is no longer on the list */ | ||
525 | spin_lock(&sb_lock); | ||
526 | if (__put_super_and_need_restart(sb)) | ||
527 | goto restart; | ||
528 | } | ||
529 | spin_unlock(&sb_lock); | ||
530 | mutex_unlock(&mutex); | ||
531 | } | ||
532 | |||
533 | /** | 435 | /** |
534 | * get_super - get the superblock of a device | 436 | * get_super - get the superblock of a device |
535 | * @bdev: device to get the superblock for | 437 | * @bdev: device to get the superblock for |
@@ -616,45 +518,6 @@ out: | |||
616 | } | 518 | } |
617 | 519 | ||
618 | /** | 520 | /** |
619 | * mark_files_ro - mark all files read-only | ||
620 | * @sb: superblock in question | ||
621 | * | ||
622 | * All files are marked read-only. We don't care about pending | ||
623 | * delete files so this should be used in 'force' mode only. | ||
624 | */ | ||
625 | |||
626 | static void mark_files_ro(struct super_block *sb) | ||
627 | { | ||
628 | struct file *f; | ||
629 | |||
630 | retry: | ||
631 | file_list_lock(); | ||
632 | list_for_each_entry(f, &sb->s_files, f_u.fu_list) { | ||
633 | struct vfsmount *mnt; | ||
634 | if (!S_ISREG(f->f_path.dentry->d_inode->i_mode)) | ||
635 | continue; | ||
636 | if (!file_count(f)) | ||
637 | continue; | ||
638 | if (!(f->f_mode & FMODE_WRITE)) | ||
639 | continue; | ||
640 | f->f_mode &= ~FMODE_WRITE; | ||
641 | if (file_check_writeable(f) != 0) | ||
642 | continue; | ||
643 | file_release_write(f); | ||
644 | mnt = mntget(f->f_path.mnt); | ||
645 | file_list_unlock(); | ||
646 | /* | ||
647 | * This can sleep, so we can't hold | ||
648 | * the file_list_lock() spinlock. | ||
649 | */ | ||
650 | mnt_drop_write(mnt); | ||
651 | mntput(mnt); | ||
652 | goto retry; | ||
653 | } | ||
654 | file_list_unlock(); | ||
655 | } | ||
656 | |||
657 | /** | ||
658 | * do_remount_sb - asks filesystem to change mount options. | 521 | * do_remount_sb - asks filesystem to change mount options. |
659 | * @sb: superblock in question | 522 | * @sb: superblock in question |
660 | * @flags: numeric part of options | 523 | * @flags: numeric part of options |
@@ -675,7 +538,7 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) | |||
675 | if (flags & MS_RDONLY) | 538 | if (flags & MS_RDONLY) |
676 | acct_auto_close(sb); | 539 | acct_auto_close(sb); |
677 | shrink_dcache_sb(sb); | 540 | shrink_dcache_sb(sb); |
678 | fsync_super(sb); | 541 | sync_filesystem(sb); |
679 | 542 | ||
680 | /* If we are remounting RDONLY and current sb is read/write, | 543 | /* If we are remounting RDONLY and current sb is read/write, |
681 | make sure there are no rw files opened */ | 544 | make sure there are no rw files opened */ |
@@ -691,9 +554,7 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) | |||
691 | remount_rw = !(flags & MS_RDONLY) && (sb->s_flags & MS_RDONLY); | 554 | remount_rw = !(flags & MS_RDONLY) && (sb->s_flags & MS_RDONLY); |
692 | 555 | ||
693 | if (sb->s_op->remount_fs) { | 556 | if (sb->s_op->remount_fs) { |
694 | lock_super(sb); | ||
695 | retval = sb->s_op->remount_fs(sb, &flags, data); | 557 | retval = sb->s_op->remount_fs(sb, &flags, data); |
696 | unlock_super(sb); | ||
697 | if (retval) | 558 | if (retval) |
698 | return retval; | 559 | return retval; |
699 | } | 560 | } |
@@ -711,18 +572,17 @@ static void do_emergency_remount(struct work_struct *work) | |||
711 | list_for_each_entry(sb, &super_blocks, s_list) { | 572 | list_for_each_entry(sb, &super_blocks, s_list) { |
712 | sb->s_count++; | 573 | sb->s_count++; |
713 | spin_unlock(&sb_lock); | 574 | spin_unlock(&sb_lock); |
714 | down_read(&sb->s_umount); | 575 | down_write(&sb->s_umount); |
715 | if (sb->s_root && sb->s_bdev && !(sb->s_flags & MS_RDONLY)) { | 576 | if (sb->s_root && sb->s_bdev && !(sb->s_flags & MS_RDONLY)) { |
716 | /* | 577 | /* |
717 | * ->remount_fs needs lock_kernel(). | 578 | * ->remount_fs needs lock_kernel(). |
718 | * | 579 | * |
719 | * What lock protects sb->s_flags?? | 580 | * What lock protects sb->s_flags?? |
720 | */ | 581 | */ |
721 | lock_kernel(); | ||
722 | do_remount_sb(sb, MS_RDONLY, NULL, 1); | 582 | do_remount_sb(sb, MS_RDONLY, NULL, 1); |
723 | unlock_kernel(); | ||
724 | } | 583 | } |
725 | drop_super(sb); | 584 | up_write(&sb->s_umount); |
585 | put_super(sb); | ||
726 | spin_lock(&sb_lock); | 586 | spin_lock(&sb_lock); |
727 | } | 587 | } |
728 | spin_unlock(&sb_lock); | 588 | spin_unlock(&sb_lock); |
@@ -748,6 +608,7 @@ void emergency_remount(void) | |||
748 | 608 | ||
749 | static DEFINE_IDA(unnamed_dev_ida); | 609 | static DEFINE_IDA(unnamed_dev_ida); |
750 | static DEFINE_SPINLOCK(unnamed_dev_lock);/* protects the above */ | 610 | static DEFINE_SPINLOCK(unnamed_dev_lock);/* protects the above */ |
611 | static int unnamed_dev_start = 0; /* don't bother trying below it */ | ||
751 | 612 | ||
752 | int set_anon_super(struct super_block *s, void *data) | 613 | int set_anon_super(struct super_block *s, void *data) |
753 | { | 614 | { |
@@ -758,7 +619,9 @@ int set_anon_super(struct super_block *s, void *data) | |||
758 | if (ida_pre_get(&unnamed_dev_ida, GFP_ATOMIC) == 0) | 619 | if (ida_pre_get(&unnamed_dev_ida, GFP_ATOMIC) == 0) |
759 | return -ENOMEM; | 620 | return -ENOMEM; |
760 | spin_lock(&unnamed_dev_lock); | 621 | spin_lock(&unnamed_dev_lock); |
761 | error = ida_get_new(&unnamed_dev_ida, &dev); | 622 | error = ida_get_new_above(&unnamed_dev_ida, unnamed_dev_start, &dev); |
623 | if (!error) | ||
624 | unnamed_dev_start = dev + 1; | ||
762 | spin_unlock(&unnamed_dev_lock); | 625 | spin_unlock(&unnamed_dev_lock); |
763 | if (error == -EAGAIN) | 626 | if (error == -EAGAIN) |
764 | /* We raced and lost with another CPU. */ | 627 | /* We raced and lost with another CPU. */ |
@@ -769,6 +632,8 @@ int set_anon_super(struct super_block *s, void *data) | |||
769 | if ((dev & MAX_ID_MASK) == (1 << MINORBITS)) { | 632 | if ((dev & MAX_ID_MASK) == (1 << MINORBITS)) { |
770 | spin_lock(&unnamed_dev_lock); | 633 | spin_lock(&unnamed_dev_lock); |
771 | ida_remove(&unnamed_dev_ida, dev); | 634 | ida_remove(&unnamed_dev_ida, dev); |
635 | if (unnamed_dev_start > dev) | ||
636 | unnamed_dev_start = dev; | ||
772 | spin_unlock(&unnamed_dev_lock); | 637 | spin_unlock(&unnamed_dev_lock); |
773 | return -EMFILE; | 638 | return -EMFILE; |
774 | } | 639 | } |
@@ -785,6 +650,8 @@ void kill_anon_super(struct super_block *sb) | |||
785 | generic_shutdown_super(sb); | 650 | generic_shutdown_super(sb); |
786 | spin_lock(&unnamed_dev_lock); | 651 | spin_lock(&unnamed_dev_lock); |
787 | ida_remove(&unnamed_dev_ida, slot); | 652 | ida_remove(&unnamed_dev_ida, slot); |
653 | if (slot < unnamed_dev_start) | ||
654 | unnamed_dev_start = slot; | ||
788 | spin_unlock(&unnamed_dev_lock); | 655 | spin_unlock(&unnamed_dev_lock); |
789 | } | 656 | } |
790 | 657 | ||