diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-17 18:52:51 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-17 18:52:51 -0500 |
commit | d65773b22b749252b2805dcf96bdeb951a9481d8 (patch) | |
tree | 1839656e894933267e7466e32ba6ad73b24fa60a /fs/btrfs/super.c | |
parent | f9156c7288e2d11501ded4d7fe6d9a3a41ee4057 (diff) | |
parent | f84a8bd60e3ee49eacc9ba824babf149ba3dad7e (diff) |
Merge branch 'btrfs' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
* 'btrfs' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
btrfs: take allocation of ->tree_root into open_ctree()
btrfs: let ->s_fs_info point to fs_info, not root...
btrfs: consolidate failure exits in btrfs_mount() a bit
btrfs: make free_fs_info() call ->kill_sb() unconditional
btrfs: merge free_fs_info() calls on fill_super failures
btrfs: kill pointless reassignment of ->s_fs_info in btrfs_fill_super()
btrfs: make open_ctree() return int
btrfs: sanitizing ->fs_info, part 5
btrfs: sanitizing ->fs_info, part 4
btrfs: sanitizing ->fs_info, part 3
btrfs: sanitizing ->fs_info, part 2
btrfs: sanitizing ->fs_info, part 1
btrfs: fix a deadlock in btrfs_scan_one_device()
btrfs: fix mount/umount race
btrfs: get ->kill_sb() of its own
btrfs: preparation to fixing mount/umount race
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 143 |
1 files changed, 64 insertions, 79 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 8ffaaa8e3df8..3ce97b217cbe 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -147,13 +147,13 @@ void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function, | |||
147 | 147 | ||
148 | static void btrfs_put_super(struct super_block *sb) | 148 | static void btrfs_put_super(struct super_block *sb) |
149 | { | 149 | { |
150 | struct btrfs_root *root = btrfs_sb(sb); | 150 | (void)close_ctree(btrfs_sb(sb)->tree_root); |
151 | int ret; | 151 | /* FIXME: need to fix VFS to return error? */ |
152 | 152 | /* AV: return it _where_? ->put_super() can be triggered by any number | |
153 | ret = close_ctree(root); | 153 | * of async events, up to and including delivery of SIGKILL to the |
154 | sb->s_fs_info = NULL; | 154 | * last process that kept it busy. Or segfault in the aforementioned |
155 | 155 | * process... Whom would you report that to? | |
156 | (void)ret; /* FIXME: need to fix VFS to return error? */ | 156 | */ |
157 | } | 157 | } |
158 | 158 | ||
159 | enum { | 159 | enum { |
@@ -541,7 +541,8 @@ out: | |||
541 | static struct dentry *get_default_root(struct super_block *sb, | 541 | static struct dentry *get_default_root(struct super_block *sb, |
542 | u64 subvol_objectid) | 542 | u64 subvol_objectid) |
543 | { | 543 | { |
544 | struct btrfs_root *root = sb->s_fs_info; | 544 | struct btrfs_fs_info *fs_info = btrfs_sb(sb); |
545 | struct btrfs_root *root = fs_info->tree_root; | ||
545 | struct btrfs_root *new_root; | 546 | struct btrfs_root *new_root; |
546 | struct btrfs_dir_item *di; | 547 | struct btrfs_dir_item *di; |
547 | struct btrfs_path *path; | 548 | struct btrfs_path *path; |
@@ -571,7 +572,7 @@ static struct dentry *get_default_root(struct super_block *sb, | |||
571 | * will mount by default if we haven't been given a specific subvolume | 572 | * will mount by default if we haven't been given a specific subvolume |
572 | * to mount. | 573 | * to mount. |
573 | */ | 574 | */ |
574 | dir_id = btrfs_super_root_dir(root->fs_info->super_copy); | 575 | dir_id = btrfs_super_root_dir(fs_info->super_copy); |
575 | di = btrfs_lookup_dir_item(NULL, root, path, dir_id, "default", 7, 0); | 576 | di = btrfs_lookup_dir_item(NULL, root, path, dir_id, "default", 7, 0); |
576 | if (IS_ERR(di)) { | 577 | if (IS_ERR(di)) { |
577 | btrfs_free_path(path); | 578 | btrfs_free_path(path); |
@@ -585,7 +586,7 @@ static struct dentry *get_default_root(struct super_block *sb, | |||
585 | */ | 586 | */ |
586 | btrfs_free_path(path); | 587 | btrfs_free_path(path); |
587 | dir_id = BTRFS_FIRST_FREE_OBJECTID; | 588 | dir_id = BTRFS_FIRST_FREE_OBJECTID; |
588 | new_root = root->fs_info->fs_root; | 589 | new_root = fs_info->fs_root; |
589 | goto setup_root; | 590 | goto setup_root; |
590 | } | 591 | } |
591 | 592 | ||
@@ -593,7 +594,7 @@ static struct dentry *get_default_root(struct super_block *sb, | |||
593 | btrfs_free_path(path); | 594 | btrfs_free_path(path); |
594 | 595 | ||
595 | find_root: | 596 | find_root: |
596 | new_root = btrfs_read_fs_root_no_name(root->fs_info, &location); | 597 | new_root = btrfs_read_fs_root_no_name(fs_info, &location); |
597 | if (IS_ERR(new_root)) | 598 | if (IS_ERR(new_root)) |
598 | return ERR_CAST(new_root); | 599 | return ERR_CAST(new_root); |
599 | 600 | ||
@@ -629,7 +630,7 @@ static int btrfs_fill_super(struct super_block *sb, | |||
629 | { | 630 | { |
630 | struct inode *inode; | 631 | struct inode *inode; |
631 | struct dentry *root_dentry; | 632 | struct dentry *root_dentry; |
632 | struct btrfs_root *tree_root; | 633 | struct btrfs_fs_info *fs_info = btrfs_sb(sb); |
633 | struct btrfs_key key; | 634 | struct btrfs_key key; |
634 | int err; | 635 | int err; |
635 | 636 | ||
@@ -644,18 +645,16 @@ static int btrfs_fill_super(struct super_block *sb, | |||
644 | sb->s_flags |= MS_POSIXACL; | 645 | sb->s_flags |= MS_POSIXACL; |
645 | #endif | 646 | #endif |
646 | 647 | ||
647 | tree_root = open_ctree(sb, fs_devices, (char *)data); | 648 | err = open_ctree(sb, fs_devices, (char *)data); |
648 | 649 | if (err) { | |
649 | if (IS_ERR(tree_root)) { | ||
650 | printk("btrfs: open_ctree failed\n"); | 650 | printk("btrfs: open_ctree failed\n"); |
651 | return PTR_ERR(tree_root); | 651 | return err; |
652 | } | 652 | } |
653 | sb->s_fs_info = tree_root; | ||
654 | 653 | ||
655 | key.objectid = BTRFS_FIRST_FREE_OBJECTID; | 654 | key.objectid = BTRFS_FIRST_FREE_OBJECTID; |
656 | key.type = BTRFS_INODE_ITEM_KEY; | 655 | key.type = BTRFS_INODE_ITEM_KEY; |
657 | key.offset = 0; | 656 | key.offset = 0; |
658 | inode = btrfs_iget(sb, &key, tree_root->fs_info->fs_root, NULL); | 657 | inode = btrfs_iget(sb, &key, fs_info->fs_root, NULL); |
659 | if (IS_ERR(inode)) { | 658 | if (IS_ERR(inode)) { |
660 | err = PTR_ERR(inode); | 659 | err = PTR_ERR(inode); |
661 | goto fail_close; | 660 | goto fail_close; |
@@ -672,23 +671,25 @@ static int btrfs_fill_super(struct super_block *sb, | |||
672 | 671 | ||
673 | save_mount_options(sb, data); | 672 | save_mount_options(sb, data); |
674 | cleancache_init_fs(sb); | 673 | cleancache_init_fs(sb); |
674 | sb->s_flags |= MS_ACTIVE; | ||
675 | return 0; | 675 | return 0; |
676 | 676 | ||
677 | fail_close: | 677 | fail_close: |
678 | close_ctree(tree_root); | 678 | close_ctree(fs_info->tree_root); |
679 | return err; | 679 | return err; |
680 | } | 680 | } |
681 | 681 | ||
682 | int btrfs_sync_fs(struct super_block *sb, int wait) | 682 | int btrfs_sync_fs(struct super_block *sb, int wait) |
683 | { | 683 | { |
684 | struct btrfs_trans_handle *trans; | 684 | struct btrfs_trans_handle *trans; |
685 | struct btrfs_root *root = btrfs_sb(sb); | 685 | struct btrfs_fs_info *fs_info = btrfs_sb(sb); |
686 | struct btrfs_root *root = fs_info->tree_root; | ||
686 | int ret; | 687 | int ret; |
687 | 688 | ||
688 | trace_btrfs_sync_fs(wait); | 689 | trace_btrfs_sync_fs(wait); |
689 | 690 | ||
690 | if (!wait) { | 691 | if (!wait) { |
691 | filemap_flush(root->fs_info->btree_inode->i_mapping); | 692 | filemap_flush(fs_info->btree_inode->i_mapping); |
692 | return 0; | 693 | return 0; |
693 | } | 694 | } |
694 | 695 | ||
@@ -704,8 +705,8 @@ int btrfs_sync_fs(struct super_block *sb, int wait) | |||
704 | 705 | ||
705 | static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry) | 706 | static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry) |
706 | { | 707 | { |
707 | struct btrfs_root *root = btrfs_sb(dentry->d_sb); | 708 | struct btrfs_fs_info *info = btrfs_sb(dentry->d_sb); |
708 | struct btrfs_fs_info *info = root->fs_info; | 709 | struct btrfs_root *root = info->tree_root; |
709 | char *compress_type; | 710 | char *compress_type; |
710 | 711 | ||
711 | if (btrfs_test_opt(root, DEGRADED)) | 712 | if (btrfs_test_opt(root, DEGRADED)) |
@@ -770,23 +771,18 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry) | |||
770 | 771 | ||
771 | static int btrfs_test_super(struct super_block *s, void *data) | 772 | static int btrfs_test_super(struct super_block *s, void *data) |
772 | { | 773 | { |
773 | struct btrfs_root *test_root = data; | 774 | struct btrfs_fs_info *p = data; |
774 | struct btrfs_root *root = btrfs_sb(s); | 775 | struct btrfs_fs_info *fs_info = btrfs_sb(s); |
775 | 776 | ||
776 | /* | 777 | return fs_info->fs_devices == p->fs_devices; |
777 | * If this super block is going away, return false as it | ||
778 | * can't match as an existing super block. | ||
779 | */ | ||
780 | if (!atomic_read(&s->s_active)) | ||
781 | return 0; | ||
782 | return root->fs_info->fs_devices == test_root->fs_info->fs_devices; | ||
783 | } | 778 | } |
784 | 779 | ||
785 | static int btrfs_set_super(struct super_block *s, void *data) | 780 | static int btrfs_set_super(struct super_block *s, void *data) |
786 | { | 781 | { |
787 | s->s_fs_info = data; | 782 | int err = set_anon_super(s, data); |
788 | 783 | if (!err) | |
789 | return set_anon_super(s, data); | 784 | s->s_fs_info = data; |
785 | return err; | ||
790 | } | 786 | } |
791 | 787 | ||
792 | /* | 788 | /* |
@@ -946,12 +942,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
946 | if (!fs_info) | 942 | if (!fs_info) |
947 | return ERR_PTR(-ENOMEM); | 943 | return ERR_PTR(-ENOMEM); |
948 | 944 | ||
949 | fs_info->tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS); | ||
950 | if (!fs_info->tree_root) { | ||
951 | error = -ENOMEM; | ||
952 | goto error_fs_info; | ||
953 | } | ||
954 | fs_info->tree_root->fs_info = fs_info; | ||
955 | fs_info->fs_devices = fs_devices; | 945 | fs_info->fs_devices = fs_devices; |
956 | 946 | ||
957 | fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS); | 947 | fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS); |
@@ -971,43 +961,30 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
971 | } | 961 | } |
972 | 962 | ||
973 | bdev = fs_devices->latest_bdev; | 963 | bdev = fs_devices->latest_bdev; |
974 | s = sget(fs_type, btrfs_test_super, btrfs_set_super, | 964 | s = sget(fs_type, btrfs_test_super, btrfs_set_super, fs_info); |
975 | fs_info->tree_root); | ||
976 | if (IS_ERR(s)) { | 965 | if (IS_ERR(s)) { |
977 | error = PTR_ERR(s); | 966 | error = PTR_ERR(s); |
978 | goto error_close_devices; | 967 | goto error_close_devices; |
979 | } | 968 | } |
980 | 969 | ||
981 | if (s->s_root) { | 970 | if (s->s_root) { |
982 | if ((flags ^ s->s_flags) & MS_RDONLY) { | ||
983 | deactivate_locked_super(s); | ||
984 | error = -EBUSY; | ||
985 | goto error_close_devices; | ||
986 | } | ||
987 | |||
988 | btrfs_close_devices(fs_devices); | 971 | btrfs_close_devices(fs_devices); |
989 | free_fs_info(fs_info); | 972 | free_fs_info(fs_info); |
973 | if ((flags ^ s->s_flags) & MS_RDONLY) | ||
974 | error = -EBUSY; | ||
990 | } else { | 975 | } else { |
991 | char b[BDEVNAME_SIZE]; | 976 | char b[BDEVNAME_SIZE]; |
992 | 977 | ||
993 | s->s_flags = flags | MS_NOSEC; | 978 | s->s_flags = flags | MS_NOSEC; |
994 | strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); | 979 | strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); |
995 | btrfs_sb(s)->fs_info->bdev_holder = fs_type; | 980 | btrfs_sb(s)->bdev_holder = fs_type; |
996 | error = btrfs_fill_super(s, fs_devices, data, | 981 | error = btrfs_fill_super(s, fs_devices, data, |
997 | flags & MS_SILENT ? 1 : 0); | 982 | flags & MS_SILENT ? 1 : 0); |
998 | if (error) { | ||
999 | deactivate_locked_super(s); | ||
1000 | return ERR_PTR(error); | ||
1001 | } | ||
1002 | |||
1003 | s->s_flags |= MS_ACTIVE; | ||
1004 | } | 983 | } |
1005 | 984 | ||
1006 | root = get_default_root(s, subvol_objectid); | 985 | root = !error ? get_default_root(s, subvol_objectid) : ERR_PTR(error); |
1007 | if (IS_ERR(root)) { | 986 | if (IS_ERR(root)) |
1008 | deactivate_locked_super(s); | 987 | deactivate_locked_super(s); |
1009 | return root; | ||
1010 | } | ||
1011 | 988 | ||
1012 | return root; | 989 | return root; |
1013 | 990 | ||
@@ -1020,7 +997,8 @@ error_fs_info: | |||
1020 | 997 | ||
1021 | static int btrfs_remount(struct super_block *sb, int *flags, char *data) | 998 | static int btrfs_remount(struct super_block *sb, int *flags, char *data) |
1022 | { | 999 | { |
1023 | struct btrfs_root *root = btrfs_sb(sb); | 1000 | struct btrfs_fs_info *fs_info = btrfs_sb(sb); |
1001 | struct btrfs_root *root = fs_info->tree_root; | ||
1024 | int ret; | 1002 | int ret; |
1025 | 1003 | ||
1026 | ret = btrfs_parse_options(root, data); | 1004 | ret = btrfs_parse_options(root, data); |
@@ -1036,13 +1014,13 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) | |||
1036 | ret = btrfs_commit_super(root); | 1014 | ret = btrfs_commit_super(root); |
1037 | WARN_ON(ret); | 1015 | WARN_ON(ret); |
1038 | } else { | 1016 | } else { |
1039 | if (root->fs_info->fs_devices->rw_devices == 0) | 1017 | if (fs_info->fs_devices->rw_devices == 0) |
1040 | return -EACCES; | 1018 | return -EACCES; |
1041 | 1019 | ||
1042 | if (btrfs_super_log_root(root->fs_info->super_copy) != 0) | 1020 | if (btrfs_super_log_root(fs_info->super_copy) != 0) |
1043 | return -EINVAL; | 1021 | return -EINVAL; |
1044 | 1022 | ||
1045 | ret = btrfs_cleanup_fs_roots(root->fs_info); | 1023 | ret = btrfs_cleanup_fs_roots(fs_info); |
1046 | WARN_ON(ret); | 1024 | WARN_ON(ret); |
1047 | 1025 | ||
1048 | /* recover relocation */ | 1026 | /* recover relocation */ |
@@ -1211,18 +1189,18 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes) | |||
1211 | 1189 | ||
1212 | static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 1190 | static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
1213 | { | 1191 | { |
1214 | struct btrfs_root *root = btrfs_sb(dentry->d_sb); | 1192 | struct btrfs_fs_info *fs_info = btrfs_sb(dentry->d_sb); |
1215 | struct btrfs_super_block *disk_super = root->fs_info->super_copy; | 1193 | struct btrfs_super_block *disk_super = fs_info->super_copy; |
1216 | struct list_head *head = &root->fs_info->space_info; | 1194 | struct list_head *head = &fs_info->space_info; |
1217 | struct btrfs_space_info *found; | 1195 | struct btrfs_space_info *found; |
1218 | u64 total_used = 0; | 1196 | u64 total_used = 0; |
1219 | u64 total_free_data = 0; | 1197 | u64 total_free_data = 0; |
1220 | int bits = dentry->d_sb->s_blocksize_bits; | 1198 | int bits = dentry->d_sb->s_blocksize_bits; |
1221 | __be32 *fsid = (__be32 *)root->fs_info->fsid; | 1199 | __be32 *fsid = (__be32 *)fs_info->fsid; |
1222 | int ret; | 1200 | int ret; |
1223 | 1201 | ||
1224 | /* holding chunk_muext to avoid allocating new chunks */ | 1202 | /* holding chunk_muext to avoid allocating new chunks */ |
1225 | mutex_lock(&root->fs_info->chunk_mutex); | 1203 | mutex_lock(&fs_info->chunk_mutex); |
1226 | rcu_read_lock(); | 1204 | rcu_read_lock(); |
1227 | list_for_each_entry_rcu(found, head, list) { | 1205 | list_for_each_entry_rcu(found, head, list) { |
1228 | if (found->flags & BTRFS_BLOCK_GROUP_DATA) { | 1206 | if (found->flags & BTRFS_BLOCK_GROUP_DATA) { |
@@ -1241,14 +1219,14 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
1241 | buf->f_bsize = dentry->d_sb->s_blocksize; | 1219 | buf->f_bsize = dentry->d_sb->s_blocksize; |
1242 | buf->f_type = BTRFS_SUPER_MAGIC; | 1220 | buf->f_type = BTRFS_SUPER_MAGIC; |
1243 | buf->f_bavail = total_free_data; | 1221 | buf->f_bavail = total_free_data; |
1244 | ret = btrfs_calc_avail_data_space(root, &total_free_data); | 1222 | ret = btrfs_calc_avail_data_space(fs_info->tree_root, &total_free_data); |
1245 | if (ret) { | 1223 | if (ret) { |
1246 | mutex_unlock(&root->fs_info->chunk_mutex); | 1224 | mutex_unlock(&fs_info->chunk_mutex); |
1247 | return ret; | 1225 | return ret; |
1248 | } | 1226 | } |
1249 | buf->f_bavail += total_free_data; | 1227 | buf->f_bavail += total_free_data; |
1250 | buf->f_bavail = buf->f_bavail >> bits; | 1228 | buf->f_bavail = buf->f_bavail >> bits; |
1251 | mutex_unlock(&root->fs_info->chunk_mutex); | 1229 | mutex_unlock(&fs_info->chunk_mutex); |
1252 | 1230 | ||
1253 | /* We treat it as constant endianness (it doesn't matter _which_) | 1231 | /* We treat it as constant endianness (it doesn't matter _which_) |
1254 | because we want the fsid to come out the same whether mounted | 1232 | because we want the fsid to come out the same whether mounted |
@@ -1262,11 +1240,18 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
1262 | return 0; | 1240 | return 0; |
1263 | } | 1241 | } |
1264 | 1242 | ||
1243 | static void btrfs_kill_super(struct super_block *sb) | ||
1244 | { | ||
1245 | struct btrfs_fs_info *fs_info = btrfs_sb(sb); | ||
1246 | kill_anon_super(sb); | ||
1247 | free_fs_info(fs_info); | ||
1248 | } | ||
1249 | |||
1265 | static struct file_system_type btrfs_fs_type = { | 1250 | static struct file_system_type btrfs_fs_type = { |
1266 | .owner = THIS_MODULE, | 1251 | .owner = THIS_MODULE, |
1267 | .name = "btrfs", | 1252 | .name = "btrfs", |
1268 | .mount = btrfs_mount, | 1253 | .mount = btrfs_mount, |
1269 | .kill_sb = kill_anon_super, | 1254 | .kill_sb = btrfs_kill_super, |
1270 | .fs_flags = FS_REQUIRES_DEV, | 1255 | .fs_flags = FS_REQUIRES_DEV, |
1271 | }; | 1256 | }; |
1272 | 1257 | ||
@@ -1300,17 +1285,17 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd, | |||
1300 | 1285 | ||
1301 | static int btrfs_freeze(struct super_block *sb) | 1286 | static int btrfs_freeze(struct super_block *sb) |
1302 | { | 1287 | { |
1303 | struct btrfs_root *root = btrfs_sb(sb); | 1288 | struct btrfs_fs_info *fs_info = btrfs_sb(sb); |
1304 | mutex_lock(&root->fs_info->transaction_kthread_mutex); | 1289 | mutex_lock(&fs_info->transaction_kthread_mutex); |
1305 | mutex_lock(&root->fs_info->cleaner_mutex); | 1290 | mutex_lock(&fs_info->cleaner_mutex); |
1306 | return 0; | 1291 | return 0; |
1307 | } | 1292 | } |
1308 | 1293 | ||
1309 | static int btrfs_unfreeze(struct super_block *sb) | 1294 | static int btrfs_unfreeze(struct super_block *sb) |
1310 | { | 1295 | { |
1311 | struct btrfs_root *root = btrfs_sb(sb); | 1296 | struct btrfs_fs_info *fs_info = btrfs_sb(sb); |
1312 | mutex_unlock(&root->fs_info->cleaner_mutex); | 1297 | mutex_unlock(&fs_info->cleaner_mutex); |
1313 | mutex_unlock(&root->fs_info->transaction_kthread_mutex); | 1298 | mutex_unlock(&fs_info->transaction_kthread_mutex); |
1314 | return 0; | 1299 | return 0; |
1315 | } | 1300 | } |
1316 | 1301 | ||