aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2010-11-19 14:59:15 -0500
committerChris Mason <chris.mason@oracle.com>2010-11-27 13:37:51 -0500
commit450ba0ea06b6ed3612d27f2b7127a9de4160f285 (patch)
tree2276ddbcb65d7656416cdce69432a5858b35c413 /fs
parent975f84fee2e8a77ee5f41bfe7c5682bf29366b10 (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')
-rw-r--r--fs/btrfs/disk-io.c6
-rw-r--r--fs/btrfs/super.c34
2 files changed, 33 insertions, 7 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index a67b98d58c2a..57c9d8eeb7dc 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1561,10 +1561,8 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1561 GFP_NOFS); 1561 GFP_NOFS);
1562 struct btrfs_root *csum_root = kzalloc(sizeof(struct btrfs_root), 1562 struct btrfs_root *csum_root = kzalloc(sizeof(struct btrfs_root),
1563 GFP_NOFS); 1563 GFP_NOFS);
1564 struct btrfs_root *tree_root = kzalloc(sizeof(struct btrfs_root), 1564 struct btrfs_root *tree_root = btrfs_sb(sb);
1565 GFP_NOFS); 1565 struct btrfs_fs_info *fs_info = tree_root->fs_info;
1566 struct btrfs_fs_info *fs_info = kzalloc(sizeof(*fs_info),
1567 GFP_NOFS);
1568 struct btrfs_root *chunk_root = kzalloc(sizeof(struct btrfs_root), 1566 struct btrfs_root *chunk_root = kzalloc(sizeof(struct btrfs_root),
1569 GFP_NOFS); 1567 GFP_NOFS);
1570 struct btrfs_root *dev_root = kzalloc(sizeof(struct btrfs_root), 1568 struct btrfs_root *dev_root = kzalloc(sizeof(struct btrfs_root),
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
564static int btrfs_test_super(struct super_block *s, void *data) 564static 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
578static 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);
686error_close_devices: 712error_close_devices:
687 btrfs_close_devices(fs_devices); 713 btrfs_close_devices(fs_devices);
714 kfree(fs_info);
715 kfree(tree_root);
688error_free_subvol_name: 716error_free_subvol_name:
689 kfree(subvol_name); 717 kfree(subvol_name);
690 return error; 718 return error;