diff options
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 315 |
1 files changed, 196 insertions, 119 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 15634d4648d7..e28ad4baf483 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/magic.h> | 40 | #include <linux/magic.h> |
41 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
42 | #include <linux/cleancache.h> | 42 | #include <linux/cleancache.h> |
43 | #include <linux/mnt_namespace.h> | ||
43 | #include "compat.h" | 44 | #include "compat.h" |
44 | #include "delayed-inode.h" | 45 | #include "delayed-inode.h" |
45 | #include "ctree.h" | 46 | #include "ctree.h" |
@@ -58,6 +59,7 @@ | |||
58 | #include <trace/events/btrfs.h> | 59 | #include <trace/events/btrfs.h> |
59 | 60 | ||
60 | static const struct super_operations btrfs_super_ops; | 61 | static const struct super_operations btrfs_super_ops; |
62 | static struct file_system_type btrfs_fs_type; | ||
61 | 63 | ||
62 | static const char *btrfs_decode_error(struct btrfs_fs_info *fs_info, int errno, | 64 | static const char *btrfs_decode_error(struct btrfs_fs_info *fs_info, int errno, |
63 | char nbuf[16]) | 65 | char nbuf[16]) |
@@ -162,7 +164,7 @@ enum { | |||
162 | Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard, | 164 | Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard, |
163 | Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, | 165 | Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, |
164 | Opt_enospc_debug, Opt_subvolrootid, Opt_defrag, | 166 | Opt_enospc_debug, Opt_subvolrootid, Opt_defrag, |
165 | Opt_inode_cache, Opt_err, | 167 | Opt_inode_cache, Opt_no_space_cache, Opt_recovery, Opt_err, |
166 | }; | 168 | }; |
167 | 169 | ||
168 | static match_table_t tokens = { | 170 | static match_table_t tokens = { |
@@ -195,6 +197,8 @@ static match_table_t tokens = { | |||
195 | {Opt_subvolrootid, "subvolrootid=%d"}, | 197 | {Opt_subvolrootid, "subvolrootid=%d"}, |
196 | {Opt_defrag, "autodefrag"}, | 198 | {Opt_defrag, "autodefrag"}, |
197 | {Opt_inode_cache, "inode_cache"}, | 199 | {Opt_inode_cache, "inode_cache"}, |
200 | {Opt_no_space_cache, "nospace_cache"}, | ||
201 | {Opt_recovery, "recovery"}, | ||
198 | {Opt_err, NULL}, | 202 | {Opt_err, NULL}, |
199 | }; | 203 | }; |
200 | 204 | ||
@@ -206,14 +210,19 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
206 | { | 210 | { |
207 | struct btrfs_fs_info *info = root->fs_info; | 211 | struct btrfs_fs_info *info = root->fs_info; |
208 | substring_t args[MAX_OPT_ARGS]; | 212 | substring_t args[MAX_OPT_ARGS]; |
209 | char *p, *num, *orig; | 213 | char *p, *num, *orig = NULL; |
214 | u64 cache_gen; | ||
210 | int intarg; | 215 | int intarg; |
211 | int ret = 0; | 216 | int ret = 0; |
212 | char *compress_type; | 217 | char *compress_type; |
213 | bool compress_force = false; | 218 | bool compress_force = false; |
214 | 219 | ||
220 | cache_gen = btrfs_super_cache_generation(root->fs_info->super_copy); | ||
221 | if (cache_gen) | ||
222 | btrfs_set_opt(info->mount_opt, SPACE_CACHE); | ||
223 | |||
215 | if (!options) | 224 | if (!options) |
216 | return 0; | 225 | goto out; |
217 | 226 | ||
218 | /* | 227 | /* |
219 | * strsep changes the string, duplicate it because parse_options | 228 | * strsep changes the string, duplicate it because parse_options |
@@ -360,9 +369,12 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
360 | btrfs_set_opt(info->mount_opt, DISCARD); | 369 | btrfs_set_opt(info->mount_opt, DISCARD); |
361 | break; | 370 | break; |
362 | case Opt_space_cache: | 371 | case Opt_space_cache: |
363 | printk(KERN_INFO "btrfs: enabling disk space caching\n"); | ||
364 | btrfs_set_opt(info->mount_opt, SPACE_CACHE); | 372 | btrfs_set_opt(info->mount_opt, SPACE_CACHE); |
365 | break; | 373 | break; |
374 | case Opt_no_space_cache: | ||
375 | printk(KERN_INFO "btrfs: disabling disk space caching\n"); | ||
376 | btrfs_clear_opt(info->mount_opt, SPACE_CACHE); | ||
377 | break; | ||
366 | case Opt_inode_cache: | 378 | case Opt_inode_cache: |
367 | printk(KERN_INFO "btrfs: enabling inode map caching\n"); | 379 | printk(KERN_INFO "btrfs: enabling inode map caching\n"); |
368 | btrfs_set_opt(info->mount_opt, INODE_MAP_CACHE); | 380 | btrfs_set_opt(info->mount_opt, INODE_MAP_CACHE); |
@@ -381,6 +393,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
381 | printk(KERN_INFO "btrfs: enabling auto defrag"); | 393 | printk(KERN_INFO "btrfs: enabling auto defrag"); |
382 | btrfs_set_opt(info->mount_opt, AUTO_DEFRAG); | 394 | btrfs_set_opt(info->mount_opt, AUTO_DEFRAG); |
383 | break; | 395 | break; |
396 | case Opt_recovery: | ||
397 | printk(KERN_INFO "btrfs: enabling auto recovery"); | ||
398 | btrfs_set_opt(info->mount_opt, RECOVERY); | ||
399 | break; | ||
384 | case Opt_err: | 400 | case Opt_err: |
385 | printk(KERN_INFO "btrfs: unrecognized mount option " | 401 | printk(KERN_INFO "btrfs: unrecognized mount option " |
386 | "'%s'\n", p); | 402 | "'%s'\n", p); |
@@ -391,6 +407,8 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
391 | } | 407 | } |
392 | } | 408 | } |
393 | out: | 409 | out: |
410 | if (!ret && btrfs_test_opt(root, SPACE_CACHE)) | ||
411 | printk(KERN_INFO "btrfs: disk space caching is enabled\n"); | ||
394 | kfree(orig); | 412 | kfree(orig); |
395 | return ret; | 413 | return ret; |
396 | } | 414 | } |
@@ -406,12 +424,12 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags, | |||
406 | u64 *subvol_rootid, struct btrfs_fs_devices **fs_devices) | 424 | u64 *subvol_rootid, struct btrfs_fs_devices **fs_devices) |
407 | { | 425 | { |
408 | substring_t args[MAX_OPT_ARGS]; | 426 | substring_t args[MAX_OPT_ARGS]; |
409 | char *opts, *orig, *p; | 427 | char *device_name, *opts, *orig, *p; |
410 | int error = 0; | 428 | int error = 0; |
411 | int intarg; | 429 | int intarg; |
412 | 430 | ||
413 | if (!options) | 431 | if (!options) |
414 | goto out; | 432 | return 0; |
415 | 433 | ||
416 | /* | 434 | /* |
417 | * strsep changes the string, duplicate it because parse_options | 435 | * strsep changes the string, duplicate it because parse_options |
@@ -430,6 +448,7 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags, | |||
430 | token = match_token(p, tokens, args); | 448 | token = match_token(p, tokens, args); |
431 | switch (token) { | 449 | switch (token) { |
432 | case Opt_subvol: | 450 | case Opt_subvol: |
451 | kfree(*subvol_name); | ||
433 | *subvol_name = match_strdup(&args[0]); | 452 | *subvol_name = match_strdup(&args[0]); |
434 | break; | 453 | break; |
435 | case Opt_subvolid: | 454 | case Opt_subvolid: |
@@ -457,29 +476,24 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags, | |||
457 | } | 476 | } |
458 | break; | 477 | break; |
459 | case Opt_device: | 478 | case Opt_device: |
460 | error = btrfs_scan_one_device(match_strdup(&args[0]), | 479 | device_name = match_strdup(&args[0]); |
480 | if (!device_name) { | ||
481 | error = -ENOMEM; | ||
482 | goto out; | ||
483 | } | ||
484 | error = btrfs_scan_one_device(device_name, | ||
461 | flags, holder, fs_devices); | 485 | flags, holder, fs_devices); |
486 | kfree(device_name); | ||
462 | if (error) | 487 | if (error) |
463 | goto out_free_opts; | 488 | goto out; |
464 | break; | 489 | break; |
465 | default: | 490 | default: |
466 | break; | 491 | break; |
467 | } | 492 | } |
468 | } | 493 | } |
469 | 494 | ||
470 | out_free_opts: | 495 | out: |
471 | kfree(orig); | 496 | kfree(orig); |
472 | out: | ||
473 | /* | ||
474 | * If no subvolume name is specified we use the default one. Allocate | ||
475 | * a copy of the string "." here so that code later in the | ||
476 | * mount path doesn't care if it's the default volume or another one. | ||
477 | */ | ||
478 | if (!*subvol_name) { | ||
479 | *subvol_name = kstrdup(".", GFP_KERNEL); | ||
480 | if (!*subvol_name) | ||
481 | return -ENOMEM; | ||
482 | } | ||
483 | return error; | 497 | return error; |
484 | } | 498 | } |
485 | 499 | ||
@@ -492,7 +506,6 @@ static struct dentry *get_default_root(struct super_block *sb, | |||
492 | struct btrfs_path *path; | 506 | struct btrfs_path *path; |
493 | struct btrfs_key location; | 507 | struct btrfs_key location; |
494 | struct inode *inode; | 508 | struct inode *inode; |
495 | struct dentry *dentry; | ||
496 | u64 dir_id; | 509 | u64 dir_id; |
497 | int new = 0; | 510 | int new = 0; |
498 | 511 | ||
@@ -517,7 +530,7 @@ static struct dentry *get_default_root(struct super_block *sb, | |||
517 | * will mount by default if we haven't been given a specific subvolume | 530 | * will mount by default if we haven't been given a specific subvolume |
518 | * to mount. | 531 | * to mount. |
519 | */ | 532 | */ |
520 | dir_id = btrfs_super_root_dir(&root->fs_info->super_copy); | 533 | dir_id = btrfs_super_root_dir(root->fs_info->super_copy); |
521 | di = btrfs_lookup_dir_item(NULL, root, path, dir_id, "default", 7, 0); | 534 | di = btrfs_lookup_dir_item(NULL, root, path, dir_id, "default", 7, 0); |
522 | if (IS_ERR(di)) { | 535 | if (IS_ERR(di)) { |
523 | btrfs_free_path(path); | 536 | btrfs_free_path(path); |
@@ -566,29 +579,7 @@ setup_root: | |||
566 | return dget(sb->s_root); | 579 | return dget(sb->s_root); |
567 | } | 580 | } |
568 | 581 | ||
569 | if (new) { | 582 | return d_obtain_alias(inode); |
570 | const struct qstr name = { .name = "/", .len = 1 }; | ||
571 | |||
572 | /* | ||
573 | * New inode, we need to make the dentry a sibling of s_root so | ||
574 | * everything gets cleaned up properly on unmount. | ||
575 | */ | ||
576 | dentry = d_alloc(sb->s_root, &name); | ||
577 | if (!dentry) { | ||
578 | iput(inode); | ||
579 | return ERR_PTR(-ENOMEM); | ||
580 | } | ||
581 | d_splice_alias(inode, dentry); | ||
582 | } else { | ||
583 | /* | ||
584 | * We found the inode in cache, just find a dentry for it and | ||
585 | * put the reference to the inode we just got. | ||
586 | */ | ||
587 | dentry = d_find_alias(inode); | ||
588 | iput(inode); | ||
589 | } | ||
590 | |||
591 | return dentry; | ||
592 | } | 583 | } |
593 | 584 | ||
594 | static int btrfs_fill_super(struct super_block *sb, | 585 | static int btrfs_fill_super(struct super_block *sb, |
@@ -719,6 +710,8 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
719 | seq_puts(seq, ",noacl"); | 710 | seq_puts(seq, ",noacl"); |
720 | if (btrfs_test_opt(root, SPACE_CACHE)) | 711 | if (btrfs_test_opt(root, SPACE_CACHE)) |
721 | seq_puts(seq, ",space_cache"); | 712 | seq_puts(seq, ",space_cache"); |
713 | else | ||
714 | seq_puts(seq, ",nospace_cache"); | ||
722 | if (btrfs_test_opt(root, CLEAR_CACHE)) | 715 | if (btrfs_test_opt(root, CLEAR_CACHE)) |
723 | seq_puts(seq, ",clear_cache"); | 716 | seq_puts(seq, ",clear_cache"); |
724 | if (btrfs_test_opt(root, USER_SUBVOL_RM_ALLOWED)) | 717 | if (btrfs_test_opt(root, USER_SUBVOL_RM_ALLOWED)) |
@@ -753,6 +746,111 @@ static int btrfs_set_super(struct super_block *s, void *data) | |||
753 | return set_anon_super(s, data); | 746 | return set_anon_super(s, data); |
754 | } | 747 | } |
755 | 748 | ||
749 | /* | ||
750 | * subvolumes are identified by ino 256 | ||
751 | */ | ||
752 | static inline int is_subvolume_inode(struct inode *inode) | ||
753 | { | ||
754 | if (inode && inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) | ||
755 | return 1; | ||
756 | return 0; | ||
757 | } | ||
758 | |||
759 | /* | ||
760 | * This will strip out the subvol=%s argument for an argument string and add | ||
761 | * subvolid=0 to make sure we get the actual tree root for path walking to the | ||
762 | * subvol we want. | ||
763 | */ | ||
764 | static char *setup_root_args(char *args) | ||
765 | { | ||
766 | unsigned copied = 0; | ||
767 | unsigned len = strlen(args) + 2; | ||
768 | char *pos; | ||
769 | char *ret; | ||
770 | |||
771 | /* | ||
772 | * We need the same args as before, but minus | ||
773 | * | ||
774 | * subvol=a | ||
775 | * | ||
776 | * and add | ||
777 | * | ||
778 | * subvolid=0 | ||
779 | * | ||
780 | * which is a difference of 2 characters, so we allocate strlen(args) + | ||
781 | * 2 characters. | ||
782 | */ | ||
783 | ret = kzalloc(len * sizeof(char), GFP_NOFS); | ||
784 | if (!ret) | ||
785 | return NULL; | ||
786 | pos = strstr(args, "subvol="); | ||
787 | |||
788 | /* This shouldn't happen, but just in case.. */ | ||
789 | if (!pos) { | ||
790 | kfree(ret); | ||
791 | return NULL; | ||
792 | } | ||
793 | |||
794 | /* | ||
795 | * The subvol=<> arg is not at the front of the string, copy everybody | ||
796 | * up to that into ret. | ||
797 | */ | ||
798 | if (pos != args) { | ||
799 | *pos = '\0'; | ||
800 | strcpy(ret, args); | ||
801 | copied += strlen(args); | ||
802 | pos++; | ||
803 | } | ||
804 | |||
805 | strncpy(ret + copied, "subvolid=0", len - copied); | ||
806 | |||
807 | /* Length of subvolid=0 */ | ||
808 | copied += 10; | ||
809 | |||
810 | /* | ||
811 | * If there is no , after the subvol= option then we know there's no | ||
812 | * other options and we can just return. | ||
813 | */ | ||
814 | pos = strchr(pos, ','); | ||
815 | if (!pos) | ||
816 | return ret; | ||
817 | |||
818 | /* Copy the rest of the arguments into our buffer */ | ||
819 | strncpy(ret + copied, pos, len - copied); | ||
820 | copied += strlen(pos); | ||
821 | |||
822 | return ret; | ||
823 | } | ||
824 | |||
825 | static struct dentry *mount_subvol(const char *subvol_name, int flags, | ||
826 | const char *device_name, char *data) | ||
827 | { | ||
828 | struct dentry *root; | ||
829 | struct vfsmount *mnt; | ||
830 | char *newargs; | ||
831 | |||
832 | newargs = setup_root_args(data); | ||
833 | if (!newargs) | ||
834 | return ERR_PTR(-ENOMEM); | ||
835 | mnt = vfs_kern_mount(&btrfs_fs_type, flags, device_name, | ||
836 | newargs); | ||
837 | kfree(newargs); | ||
838 | if (IS_ERR(mnt)) | ||
839 | return ERR_CAST(mnt); | ||
840 | |||
841 | root = mount_subtree(mnt, subvol_name); | ||
842 | |||
843 | if (!IS_ERR(root) && !is_subvolume_inode(root->d_inode)) { | ||
844 | struct super_block *s = root->d_sb; | ||
845 | dput(root); | ||
846 | root = ERR_PTR(-EINVAL); | ||
847 | deactivate_locked_super(s); | ||
848 | printk(KERN_ERR "btrfs: '%s' is not a valid subvolume\n", | ||
849 | subvol_name); | ||
850 | } | ||
851 | |||
852 | return root; | ||
853 | } | ||
756 | 854 | ||
757 | /* | 855 | /* |
758 | * Find a superblock for the given device / mount point. | 856 | * Find a superblock for the given device / mount point. |
@@ -767,7 +865,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
767 | struct super_block *s; | 865 | struct super_block *s; |
768 | struct dentry *root; | 866 | struct dentry *root; |
769 | struct btrfs_fs_devices *fs_devices = NULL; | 867 | struct btrfs_fs_devices *fs_devices = NULL; |
770 | struct btrfs_root *tree_root = NULL; | ||
771 | struct btrfs_fs_info *fs_info = NULL; | 868 | struct btrfs_fs_info *fs_info = NULL; |
772 | fmode_t mode = FMODE_READ; | 869 | fmode_t mode = FMODE_READ; |
773 | char *subvol_name = NULL; | 870 | char *subvol_name = NULL; |
@@ -781,21 +878,20 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
781 | error = btrfs_parse_early_options(data, mode, fs_type, | 878 | error = btrfs_parse_early_options(data, mode, fs_type, |
782 | &subvol_name, &subvol_objectid, | 879 | &subvol_name, &subvol_objectid, |
783 | &subvol_rootid, &fs_devices); | 880 | &subvol_rootid, &fs_devices); |
784 | if (error) | 881 | if (error) { |
882 | kfree(subvol_name); | ||
785 | return ERR_PTR(error); | 883 | return ERR_PTR(error); |
884 | } | ||
786 | 885 | ||
787 | error = btrfs_scan_one_device(device_name, mode, fs_type, &fs_devices); | 886 | if (subvol_name) { |
788 | if (error) | 887 | root = mount_subvol(subvol_name, flags, device_name, data); |
789 | goto error_free_subvol_name; | 888 | kfree(subvol_name); |
889 | return root; | ||
890 | } | ||
790 | 891 | ||
791 | error = btrfs_open_devices(fs_devices, mode, fs_type); | 892 | error = btrfs_scan_one_device(device_name, mode, fs_type, &fs_devices); |
792 | if (error) | 893 | if (error) |
793 | goto error_free_subvol_name; | 894 | return ERR_PTR(error); |
794 | |||
795 | if (!(flags & MS_RDONLY) && fs_devices->rw_devices == 0) { | ||
796 | error = -EACCES; | ||
797 | goto error_close_devices; | ||
798 | } | ||
799 | 895 | ||
800 | /* | 896 | /* |
801 | * Setup a dummy root and fs_info for test/set super. This is because | 897 | * Setup a dummy root and fs_info for test/set super. This is because |
@@ -804,19 +900,40 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
804 | * then open_ctree will properly initialize everything later. | 900 | * then open_ctree will properly initialize everything later. |
805 | */ | 901 | */ |
806 | fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS); | 902 | fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS); |
807 | tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS); | 903 | if (!fs_info) |
808 | if (!fs_info || !tree_root) { | 904 | return ERR_PTR(-ENOMEM); |
905 | |||
906 | fs_info->tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS); | ||
907 | if (!fs_info->tree_root) { | ||
809 | error = -ENOMEM; | 908 | error = -ENOMEM; |
810 | goto error_close_devices; | 909 | goto error_fs_info; |
811 | } | 910 | } |
812 | fs_info->tree_root = tree_root; | 911 | fs_info->tree_root->fs_info = fs_info; |
813 | fs_info->fs_devices = fs_devices; | 912 | fs_info->fs_devices = fs_devices; |
814 | tree_root->fs_info = fs_info; | 913 | |
914 | fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS); | ||
915 | fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS); | ||
916 | if (!fs_info->super_copy || !fs_info->super_for_commit) { | ||
917 | error = -ENOMEM; | ||
918 | goto error_fs_info; | ||
919 | } | ||
920 | |||
921 | error = btrfs_open_devices(fs_devices, mode, fs_type); | ||
922 | if (error) | ||
923 | goto error_fs_info; | ||
924 | |||
925 | if (!(flags & MS_RDONLY) && fs_devices->rw_devices == 0) { | ||
926 | error = -EACCES; | ||
927 | goto error_close_devices; | ||
928 | } | ||
815 | 929 | ||
816 | bdev = fs_devices->latest_bdev; | 930 | bdev = fs_devices->latest_bdev; |
817 | s = sget(fs_type, btrfs_test_super, btrfs_set_super, tree_root); | 931 | s = sget(fs_type, btrfs_test_super, btrfs_set_super, |
818 | if (IS_ERR(s)) | 932 | fs_info->tree_root); |
819 | goto error_s; | 933 | if (IS_ERR(s)) { |
934 | error = PTR_ERR(s); | ||
935 | goto error_close_devices; | ||
936 | } | ||
820 | 937 | ||
821 | if (s->s_root) { | 938 | if (s->s_root) { |
822 | if ((flags ^ s->s_flags) & MS_RDONLY) { | 939 | if ((flags ^ s->s_flags) & MS_RDONLY) { |
@@ -826,75 +943,35 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
826 | } | 943 | } |
827 | 944 | ||
828 | btrfs_close_devices(fs_devices); | 945 | btrfs_close_devices(fs_devices); |
829 | kfree(fs_info); | 946 | free_fs_info(fs_info); |
830 | kfree(tree_root); | ||
831 | } else { | 947 | } else { |
832 | char b[BDEVNAME_SIZE]; | 948 | char b[BDEVNAME_SIZE]; |
833 | 949 | ||
834 | s->s_flags = flags | MS_NOSEC; | 950 | s->s_flags = flags | MS_NOSEC; |
835 | strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); | 951 | strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); |
952 | btrfs_sb(s)->fs_info->bdev_holder = fs_type; | ||
836 | error = btrfs_fill_super(s, fs_devices, data, | 953 | error = btrfs_fill_super(s, fs_devices, data, |
837 | flags & MS_SILENT ? 1 : 0); | 954 | flags & MS_SILENT ? 1 : 0); |
838 | if (error) { | 955 | if (error) { |
839 | deactivate_locked_super(s); | 956 | deactivate_locked_super(s); |
840 | goto error_free_subvol_name; | 957 | return ERR_PTR(error); |
841 | } | 958 | } |
842 | 959 | ||
843 | btrfs_sb(s)->fs_info->bdev_holder = fs_type; | ||
844 | s->s_flags |= MS_ACTIVE; | 960 | s->s_flags |= MS_ACTIVE; |
845 | } | 961 | } |
846 | 962 | ||
847 | /* if they gave us a subvolume name bind mount into that */ | 963 | root = get_default_root(s, subvol_objectid); |
848 | if (strcmp(subvol_name, ".")) { | 964 | if (IS_ERR(root)) { |
849 | struct dentry *new_root; | 965 | deactivate_locked_super(s); |
850 | 966 | return root; | |
851 | root = get_default_root(s, subvol_rootid); | ||
852 | if (IS_ERR(root)) { | ||
853 | error = PTR_ERR(root); | ||
854 | deactivate_locked_super(s); | ||
855 | goto error_free_subvol_name; | ||
856 | } | ||
857 | |||
858 | mutex_lock(&root->d_inode->i_mutex); | ||
859 | new_root = lookup_one_len(subvol_name, root, | ||
860 | strlen(subvol_name)); | ||
861 | mutex_unlock(&root->d_inode->i_mutex); | ||
862 | |||
863 | if (IS_ERR(new_root)) { | ||
864 | dput(root); | ||
865 | deactivate_locked_super(s); | ||
866 | error = PTR_ERR(new_root); | ||
867 | goto error_free_subvol_name; | ||
868 | } | ||
869 | if (!new_root->d_inode) { | ||
870 | dput(root); | ||
871 | dput(new_root); | ||
872 | deactivate_locked_super(s); | ||
873 | error = -ENXIO; | ||
874 | goto error_free_subvol_name; | ||
875 | } | ||
876 | dput(root); | ||
877 | root = new_root; | ||
878 | } else { | ||
879 | root = get_default_root(s, subvol_objectid); | ||
880 | if (IS_ERR(root)) { | ||
881 | error = PTR_ERR(root); | ||
882 | deactivate_locked_super(s); | ||
883 | goto error_free_subvol_name; | ||
884 | } | ||
885 | } | 967 | } |
886 | 968 | ||
887 | kfree(subvol_name); | ||
888 | return root; | 969 | return root; |
889 | 970 | ||
890 | error_s: | ||
891 | error = PTR_ERR(s); | ||
892 | error_close_devices: | 971 | error_close_devices: |
893 | btrfs_close_devices(fs_devices); | 972 | btrfs_close_devices(fs_devices); |
894 | kfree(fs_info); | 973 | error_fs_info: |
895 | kfree(tree_root); | 974 | free_fs_info(fs_info); |
896 | error_free_subvol_name: | ||
897 | kfree(subvol_name); | ||
898 | return ERR_PTR(error); | 975 | return ERR_PTR(error); |
899 | } | 976 | } |
900 | 977 | ||
@@ -919,7 +996,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) | |||
919 | if (root->fs_info->fs_devices->rw_devices == 0) | 996 | if (root->fs_info->fs_devices->rw_devices == 0) |
920 | return -EACCES; | 997 | return -EACCES; |
921 | 998 | ||
922 | if (btrfs_super_log_root(&root->fs_info->super_copy) != 0) | 999 | if (btrfs_super_log_root(root->fs_info->super_copy) != 0) |
923 | return -EINVAL; | 1000 | return -EINVAL; |
924 | 1001 | ||
925 | ret = btrfs_cleanup_fs_roots(root->fs_info); | 1002 | ret = btrfs_cleanup_fs_roots(root->fs_info); |
@@ -980,7 +1057,7 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes) | |||
980 | int i = 0, nr_devices; | 1057 | int i = 0, nr_devices; |
981 | int ret; | 1058 | int ret; |
982 | 1059 | ||
983 | nr_devices = fs_info->fs_devices->rw_devices; | 1060 | nr_devices = fs_info->fs_devices->open_devices; |
984 | BUG_ON(!nr_devices); | 1061 | BUG_ON(!nr_devices); |
985 | 1062 | ||
986 | devices_info = kmalloc(sizeof(*devices_info) * nr_devices, | 1063 | devices_info = kmalloc(sizeof(*devices_info) * nr_devices, |
@@ -1002,8 +1079,8 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes) | |||
1002 | else | 1079 | else |
1003 | min_stripe_size = BTRFS_STRIPE_LEN; | 1080 | min_stripe_size = BTRFS_STRIPE_LEN; |
1004 | 1081 | ||
1005 | list_for_each_entry(device, &fs_devices->alloc_list, dev_alloc_list) { | 1082 | list_for_each_entry(device, &fs_devices->devices, dev_list) { |
1006 | if (!device->in_fs_metadata) | 1083 | if (!device->in_fs_metadata || !device->bdev) |
1007 | continue; | 1084 | continue; |
1008 | 1085 | ||
1009 | avail_space = device->total_bytes - device->bytes_used; | 1086 | avail_space = device->total_bytes - device->bytes_used; |
@@ -1085,7 +1162,7 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes) | |||
1085 | static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 1162 | static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
1086 | { | 1163 | { |
1087 | struct btrfs_root *root = btrfs_sb(dentry->d_sb); | 1164 | struct btrfs_root *root = btrfs_sb(dentry->d_sb); |
1088 | struct btrfs_super_block *disk_super = &root->fs_info->super_copy; | 1165 | struct btrfs_super_block *disk_super = root->fs_info->super_copy; |
1089 | struct list_head *head = &root->fs_info->space_info; | 1166 | struct list_head *head = &root->fs_info->space_info; |
1090 | struct btrfs_space_info *found; | 1167 | struct btrfs_space_info *found; |
1091 | u64 total_used = 0; | 1168 | u64 total_used = 0; |