diff options
author | Josef Bacik <josef@redhat.com> | 2010-11-19 14:59:15 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2010-11-27 13:37:51 -0500 |
commit | 450ba0ea06b6ed3612d27f2b7127a9de4160f285 (patch) | |
tree | 2276ddbcb65d7656416cdce69432a5858b35c413 /fs/btrfs/super.c | |
parent | 975f84fee2e8a77ee5f41bfe7c5682bf29366b10 (diff) |
Btrfs: setup blank root and fs_info for mount time
There is a problem with how we use sget, it searches through the list of supers
attached to the fs_type looking for a super with the same fs_devices as what
we're trying to mount. This depends on sb->s_fs_info being filled, but we don't
fill that in until we get to btrfs_fill_super, so we could hit supers on the
fs_type super list that have a null s_fs_info. In order to fix that we need to
go ahead and setup a blank root with a blank fs_info to hold fs_devices, that
way our test will work out right and then we can set s_fs_info in
btrfs_set_super, and then open_ctree will simply use our pre-allocated root and
fs_info when setting everything up. Thanks,
Signed-off-by: Josef Bacik <josef@redhat.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 141fb317d3bc..47bf67cbe6bf 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -563,7 +563,7 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
563 | 563 | ||
564 | static int btrfs_test_super(struct super_block *s, void *data) | 564 | static int btrfs_test_super(struct super_block *s, void *data) |
565 | { | 565 | { |
566 | struct btrfs_fs_devices *test_fs_devices = data; | 566 | struct btrfs_root *test_root = data; |
567 | struct btrfs_root *root = btrfs_sb(s); | 567 | struct btrfs_root *root = btrfs_sb(s); |
568 | 568 | ||
569 | /* | 569 | /* |
@@ -572,9 +572,17 @@ static int btrfs_test_super(struct super_block *s, void *data) | |||
572 | */ | 572 | */ |
573 | if (!atomic_read(&s->s_active)) | 573 | if (!atomic_read(&s->s_active)) |
574 | return 0; | 574 | return 0; |
575 | return root->fs_info->fs_devices == test_fs_devices; | 575 | return root->fs_info->fs_devices == test_root->fs_info->fs_devices; |
576 | } | 576 | } |
577 | 577 | ||
578 | static int btrfs_set_super(struct super_block *s, void *data) | ||
579 | { | ||
580 | s->s_fs_info = data; | ||
581 | |||
582 | return set_anon_super(s, data); | ||
583 | } | ||
584 | |||
585 | |||
578 | /* | 586 | /* |
579 | * Find a superblock for the given device / mount point. | 587 | * Find a superblock for the given device / mount point. |
580 | * | 588 | * |
@@ -588,6 +596,8 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags, | |||
588 | struct super_block *s; | 596 | struct super_block *s; |
589 | struct dentry *root; | 597 | struct dentry *root; |
590 | struct btrfs_fs_devices *fs_devices = NULL; | 598 | struct btrfs_fs_devices *fs_devices = NULL; |
599 | struct btrfs_root *tree_root = NULL; | ||
600 | struct btrfs_fs_info *fs_info = NULL; | ||
591 | fmode_t mode = FMODE_READ; | 601 | fmode_t mode = FMODE_READ; |
592 | char *subvol_name = NULL; | 602 | char *subvol_name = NULL; |
593 | u64 subvol_objectid = 0; | 603 | u64 subvol_objectid = 0; |
@@ -615,8 +625,24 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags, | |||
615 | goto error_close_devices; | 625 | goto error_close_devices; |
616 | } | 626 | } |
617 | 627 | ||
628 | /* | ||
629 | * Setup a dummy root and fs_info for test/set super. This is because | ||
630 | * we don't actually fill this stuff out until open_ctree, but we need | ||
631 | * it for searching for existing supers, so this lets us do that and | ||
632 | * then open_ctree will properly initialize everything later. | ||
633 | */ | ||
634 | fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS); | ||
635 | tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS); | ||
636 | if (!fs_info || !tree_root) { | ||
637 | error = -ENOMEM; | ||
638 | goto error_close_devices; | ||
639 | } | ||
640 | fs_info->tree_root = tree_root; | ||
641 | fs_info->fs_devices = fs_devices; | ||
642 | tree_root->fs_info = fs_info; | ||
643 | |||
618 | bdev = fs_devices->latest_bdev; | 644 | bdev = fs_devices->latest_bdev; |
619 | s = sget(fs_type, btrfs_test_super, set_anon_super, fs_devices); | 645 | s = sget(fs_type, btrfs_test_super, btrfs_set_super, tree_root); |
620 | if (IS_ERR(s)) | 646 | if (IS_ERR(s)) |
621 | goto error_s; | 647 | goto error_s; |
622 | 648 | ||
@@ -685,6 +711,8 @@ error_s: | |||
685 | error = PTR_ERR(s); | 711 | error = PTR_ERR(s); |
686 | error_close_devices: | 712 | error_close_devices: |
687 | btrfs_close_devices(fs_devices); | 713 | btrfs_close_devices(fs_devices); |
714 | kfree(fs_info); | ||
715 | kfree(tree_root); | ||
688 | error_free_subvol_name: | 716 | error_free_subvol_name: |
689 | kfree(subvol_name); | 717 | kfree(subvol_name); |
690 | return error; | 718 | return error; |