aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r--fs/btrfs/super.c34
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
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;