diff options
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 80 |
1 files changed, 72 insertions, 8 deletions
diff --git a/fs/super.c b/fs/super.c index 2761d3e22ed9..19eb70b374bc 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -54,7 +54,7 @@ DEFINE_SPINLOCK(sb_lock); | |||
54 | static struct super_block *alloc_super(struct file_system_type *type) | 54 | static struct super_block *alloc_super(struct file_system_type *type) |
55 | { | 55 | { |
56 | struct super_block *s = kzalloc(sizeof(struct super_block), GFP_USER); | 56 | struct super_block *s = kzalloc(sizeof(struct super_block), GFP_USER); |
57 | static struct super_operations default_op; | 57 | static const struct super_operations default_op; |
58 | 58 | ||
59 | if (s) { | 59 | if (s) { |
60 | if (security_sb_alloc(s)) { | 60 | if (security_sb_alloc(s)) { |
@@ -62,9 +62,6 @@ static struct super_block *alloc_super(struct file_system_type *type) | |||
62 | s = NULL; | 62 | s = NULL; |
63 | goto out; | 63 | goto out; |
64 | } | 64 | } |
65 | INIT_LIST_HEAD(&s->s_dirty); | ||
66 | INIT_LIST_HEAD(&s->s_io); | ||
67 | INIT_LIST_HEAD(&s->s_more_io); | ||
68 | INIT_LIST_HEAD(&s->s_files); | 65 | INIT_LIST_HEAD(&s->s_files); |
69 | INIT_LIST_HEAD(&s->s_instances); | 66 | INIT_LIST_HEAD(&s->s_instances); |
70 | INIT_HLIST_HEAD(&s->s_anon); | 67 | INIT_HLIST_HEAD(&s->s_anon); |
@@ -171,7 +168,7 @@ int __put_super_and_need_restart(struct super_block *sb) | |||
171 | * Drops a temporary reference, frees superblock if there's no | 168 | * Drops a temporary reference, frees superblock if there's no |
172 | * references left. | 169 | * references left. |
173 | */ | 170 | */ |
174 | static void put_super(struct super_block *sb) | 171 | void put_super(struct super_block *sb) |
175 | { | 172 | { |
176 | spin_lock(&sb_lock); | 173 | spin_lock(&sb_lock); |
177 | __put_super(sb); | 174 | __put_super(sb); |
@@ -468,6 +465,48 @@ rescan: | |||
468 | } | 465 | } |
469 | 466 | ||
470 | EXPORT_SYMBOL(get_super); | 467 | EXPORT_SYMBOL(get_super); |
468 | |||
469 | /** | ||
470 | * get_active_super - get an active reference to the superblock of a device | ||
471 | * @bdev: device to get the superblock for | ||
472 | * | ||
473 | * Scans the superblock list and finds the superblock of the file system | ||
474 | * mounted on the device given. Returns the superblock with an active | ||
475 | * reference and s_umount held exclusively or %NULL if none was found. | ||
476 | */ | ||
477 | struct super_block *get_active_super(struct block_device *bdev) | ||
478 | { | ||
479 | struct super_block *sb; | ||
480 | |||
481 | if (!bdev) | ||
482 | return NULL; | ||
483 | |||
484 | spin_lock(&sb_lock); | ||
485 | list_for_each_entry(sb, &super_blocks, s_list) { | ||
486 | if (sb->s_bdev != bdev) | ||
487 | continue; | ||
488 | |||
489 | sb->s_count++; | ||
490 | spin_unlock(&sb_lock); | ||
491 | down_write(&sb->s_umount); | ||
492 | if (sb->s_root) { | ||
493 | spin_lock(&sb_lock); | ||
494 | if (sb->s_count > S_BIAS) { | ||
495 | atomic_inc(&sb->s_active); | ||
496 | sb->s_count--; | ||
497 | spin_unlock(&sb_lock); | ||
498 | return sb; | ||
499 | } | ||
500 | spin_unlock(&sb_lock); | ||
501 | } | ||
502 | up_write(&sb->s_umount); | ||
503 | put_super(sb); | ||
504 | yield(); | ||
505 | spin_lock(&sb_lock); | ||
506 | } | ||
507 | spin_unlock(&sb_lock); | ||
508 | return NULL; | ||
509 | } | ||
471 | 510 | ||
472 | struct super_block * user_get_super(dev_t dev) | 511 | struct super_block * user_get_super(dev_t dev) |
473 | { | 512 | { |
@@ -530,11 +569,15 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) | |||
530 | { | 569 | { |
531 | int retval; | 570 | int retval; |
532 | int remount_rw; | 571 | int remount_rw; |
533 | 572 | ||
573 | if (sb->s_frozen != SB_UNFROZEN) | ||
574 | return -EBUSY; | ||
575 | |||
534 | #ifdef CONFIG_BLOCK | 576 | #ifdef CONFIG_BLOCK |
535 | if (!(flags & MS_RDONLY) && bdev_read_only(sb->s_bdev)) | 577 | if (!(flags & MS_RDONLY) && bdev_read_only(sb->s_bdev)) |
536 | return -EACCES; | 578 | return -EACCES; |
537 | #endif | 579 | #endif |
580 | |||
538 | if (flags & MS_RDONLY) | 581 | if (flags & MS_RDONLY) |
539 | acct_auto_close(sb); | 582 | acct_auto_close(sb); |
540 | shrink_dcache_sb(sb); | 583 | shrink_dcache_sb(sb); |
@@ -710,6 +753,12 @@ static int set_bdev_super(struct super_block *s, void *data) | |||
710 | { | 753 | { |
711 | s->s_bdev = data; | 754 | s->s_bdev = data; |
712 | s->s_dev = s->s_bdev->bd_dev; | 755 | s->s_dev = s->s_bdev->bd_dev; |
756 | |||
757 | /* | ||
758 | * We set the bdi here to the queue backing, file systems can | ||
759 | * overwrite this in ->fill_super() | ||
760 | */ | ||
761 | s->s_bdi = &bdev_get_queue(s->s_bdev)->backing_dev_info; | ||
713 | return 0; | 762 | return 0; |
714 | } | 763 | } |
715 | 764 | ||
@@ -740,9 +789,14 @@ int get_sb_bdev(struct file_system_type *fs_type, | |||
740 | * will protect the lockfs code from trying to start a snapshot | 789 | * will protect the lockfs code from trying to start a snapshot |
741 | * while we are mounting | 790 | * while we are mounting |
742 | */ | 791 | */ |
743 | down(&bdev->bd_mount_sem); | 792 | mutex_lock(&bdev->bd_fsfreeze_mutex); |
793 | if (bdev->bd_fsfreeze_count > 0) { | ||
794 | mutex_unlock(&bdev->bd_fsfreeze_mutex); | ||
795 | error = -EBUSY; | ||
796 | goto error_bdev; | ||
797 | } | ||
744 | s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); | 798 | s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); |
745 | up(&bdev->bd_mount_sem); | 799 | mutex_unlock(&bdev->bd_fsfreeze_mutex); |
746 | if (IS_ERR(s)) | 800 | if (IS_ERR(s)) |
747 | goto error_s; | 801 | goto error_s; |
748 | 802 | ||
@@ -889,6 +943,16 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void | |||
889 | if (error) | 943 | if (error) |
890 | goto out_sb; | 944 | goto out_sb; |
891 | 945 | ||
946 | /* | ||
947 | * filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE | ||
948 | * but s_maxbytes was an unsigned long long for many releases. Throw | ||
949 | * this warning for a little while to try and catch filesystems that | ||
950 | * violate this rule. This warning should be either removed or | ||
951 | * converted to a BUG() in 2.6.34. | ||
952 | */ | ||
953 | WARN((mnt->mnt_sb->s_maxbytes < 0), "%s set sb->s_maxbytes to " | ||
954 | "negative value (%lld)\n", type->name, mnt->mnt_sb->s_maxbytes); | ||
955 | |||
892 | mnt->mnt_mountpoint = mnt->mnt_root; | 956 | mnt->mnt_mountpoint = mnt->mnt_root; |
893 | mnt->mnt_parent = mnt; | 957 | mnt->mnt_parent = mnt; |
894 | up_write(&mnt->mnt_sb->s_umount); | 958 | up_write(&mnt->mnt_sb->s_umount); |