diff options
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 81 |
1 files changed, 60 insertions, 21 deletions
diff --git a/fs/super.c b/fs/super.c index c183835566c1..1709ed029a2c 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -244,7 +244,6 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags, | |||
244 | mutex_init(&s->s_vfs_rename_mutex); | 244 | mutex_init(&s->s_vfs_rename_mutex); |
245 | lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key); | 245 | lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key); |
246 | mutex_init(&s->s_dquot.dqio_mutex); | 246 | mutex_init(&s->s_dquot.dqio_mutex); |
247 | mutex_init(&s->s_dquot.dqonoff_mutex); | ||
248 | s->s_maxbytes = MAX_NON_LFS; | 247 | s->s_maxbytes = MAX_NON_LFS; |
249 | s->s_op = &default_op; | 248 | s->s_op = &default_op; |
250 | s->s_time_gran = 1000000000; | 249 | s->s_time_gran = 1000000000; |
@@ -558,6 +557,13 @@ void drop_super(struct super_block *sb) | |||
558 | 557 | ||
559 | EXPORT_SYMBOL(drop_super); | 558 | EXPORT_SYMBOL(drop_super); |
560 | 559 | ||
560 | void drop_super_exclusive(struct super_block *sb) | ||
561 | { | ||
562 | up_write(&sb->s_umount); | ||
563 | put_super(sb); | ||
564 | } | ||
565 | EXPORT_SYMBOL(drop_super_exclusive); | ||
566 | |||
561 | /** | 567 | /** |
562 | * iterate_supers - call function for all active superblocks | 568 | * iterate_supers - call function for all active superblocks |
563 | * @f: function to call | 569 | * @f: function to call |
@@ -628,15 +634,7 @@ void iterate_supers_type(struct file_system_type *type, | |||
628 | 634 | ||
629 | EXPORT_SYMBOL(iterate_supers_type); | 635 | EXPORT_SYMBOL(iterate_supers_type); |
630 | 636 | ||
631 | /** | 637 | static struct super_block *__get_super(struct block_device *bdev, bool excl) |
632 | * get_super - get the superblock of a device | ||
633 | * @bdev: device to get the superblock for | ||
634 | * | ||
635 | * Scans the superblock list and finds the superblock of the file system | ||
636 | * mounted on the device given. %NULL is returned if no match is found. | ||
637 | */ | ||
638 | |||
639 | struct super_block *get_super(struct block_device *bdev) | ||
640 | { | 638 | { |
641 | struct super_block *sb; | 639 | struct super_block *sb; |
642 | 640 | ||
@@ -651,11 +649,17 @@ rescan: | |||
651 | if (sb->s_bdev == bdev) { | 649 | if (sb->s_bdev == bdev) { |
652 | sb->s_count++; | 650 | sb->s_count++; |
653 | spin_unlock(&sb_lock); | 651 | spin_unlock(&sb_lock); |
654 | down_read(&sb->s_umount); | 652 | if (!excl) |
653 | down_read(&sb->s_umount); | ||
654 | else | ||
655 | down_write(&sb->s_umount); | ||
655 | /* still alive? */ | 656 | /* still alive? */ |
656 | if (sb->s_root && (sb->s_flags & MS_BORN)) | 657 | if (sb->s_root && (sb->s_flags & MS_BORN)) |
657 | return sb; | 658 | return sb; |
658 | up_read(&sb->s_umount); | 659 | if (!excl) |
660 | up_read(&sb->s_umount); | ||
661 | else | ||
662 | up_write(&sb->s_umount); | ||
659 | /* nope, got unmounted */ | 663 | /* nope, got unmounted */ |
660 | spin_lock(&sb_lock); | 664 | spin_lock(&sb_lock); |
661 | __put_super(sb); | 665 | __put_super(sb); |
@@ -666,32 +670,67 @@ rescan: | |||
666 | return NULL; | 670 | return NULL; |
667 | } | 671 | } |
668 | 672 | ||
669 | EXPORT_SYMBOL(get_super); | ||
670 | |||
671 | /** | 673 | /** |
672 | * get_super_thawed - get thawed superblock of a device | 674 | * get_super - get the superblock of a device |
673 | * @bdev: device to get the superblock for | 675 | * @bdev: device to get the superblock for |
674 | * | 676 | * |
675 | * Scans the superblock list and finds the superblock of the file system | 677 | * Scans the superblock list and finds the superblock of the file system |
676 | * mounted on the device. The superblock is returned once it is thawed | 678 | * mounted on the device given. %NULL is returned if no match is found. |
677 | * (or immediately if it was not frozen). %NULL is returned if no match | ||
678 | * is found. | ||
679 | */ | 679 | */ |
680 | struct super_block *get_super_thawed(struct block_device *bdev) | 680 | struct super_block *get_super(struct block_device *bdev) |
681 | { | ||
682 | return __get_super(bdev, false); | ||
683 | } | ||
684 | EXPORT_SYMBOL(get_super); | ||
685 | |||
686 | static struct super_block *__get_super_thawed(struct block_device *bdev, | ||
687 | bool excl) | ||
681 | { | 688 | { |
682 | while (1) { | 689 | while (1) { |
683 | struct super_block *s = get_super(bdev); | 690 | struct super_block *s = __get_super(bdev, excl); |
684 | if (!s || s->s_writers.frozen == SB_UNFROZEN) | 691 | if (!s || s->s_writers.frozen == SB_UNFROZEN) |
685 | return s; | 692 | return s; |
686 | up_read(&s->s_umount); | 693 | if (!excl) |
694 | up_read(&s->s_umount); | ||
695 | else | ||
696 | up_write(&s->s_umount); | ||
687 | wait_event(s->s_writers.wait_unfrozen, | 697 | wait_event(s->s_writers.wait_unfrozen, |
688 | s->s_writers.frozen == SB_UNFROZEN); | 698 | s->s_writers.frozen == SB_UNFROZEN); |
689 | put_super(s); | 699 | put_super(s); |
690 | } | 700 | } |
691 | } | 701 | } |
702 | |||
703 | /** | ||
704 | * get_super_thawed - get thawed superblock of a device | ||
705 | * @bdev: device to get the superblock for | ||
706 | * | ||
707 | * Scans the superblock list and finds the superblock of the file system | ||
708 | * mounted on the device. The superblock is returned once it is thawed | ||
709 | * (or immediately if it was not frozen). %NULL is returned if no match | ||
710 | * is found. | ||
711 | */ | ||
712 | struct super_block *get_super_thawed(struct block_device *bdev) | ||
713 | { | ||
714 | return __get_super_thawed(bdev, false); | ||
715 | } | ||
692 | EXPORT_SYMBOL(get_super_thawed); | 716 | EXPORT_SYMBOL(get_super_thawed); |
693 | 717 | ||
694 | /** | 718 | /** |
719 | * get_super_exclusive_thawed - get thawed superblock of a device | ||
720 | * @bdev: device to get the superblock for | ||
721 | * | ||
722 | * Scans the superblock list and finds the superblock of the file system | ||
723 | * mounted on the device. The superblock is returned once it is thawed | ||
724 | * (or immediately if it was not frozen) and s_umount semaphore is held | ||
725 | * in exclusive mode. %NULL is returned if no match is found. | ||
726 | */ | ||
727 | struct super_block *get_super_exclusive_thawed(struct block_device *bdev) | ||
728 | { | ||
729 | return __get_super_thawed(bdev, true); | ||
730 | } | ||
731 | EXPORT_SYMBOL(get_super_exclusive_thawed); | ||
732 | |||
733 | /** | ||
695 | * get_active_super - get an active reference to the superblock of a device | 734 | * get_active_super - get an active reference to the superblock of a device |
696 | * @bdev: device to get the superblock for | 735 | * @bdev: device to get the superblock for |
697 | * | 736 | * |