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>

authored by Josef Bacik and committed by Chris Mason 450ba0ea 975f84fe

+33 -7
+2 -4
fs/btrfs/disk-io.c
··· 1561 GFP_NOFS); 1562 struct btrfs_root *csum_root = kzalloc(sizeof(struct btrfs_root), 1563 GFP_NOFS); 1564 - struct btrfs_root *tree_root = kzalloc(sizeof(struct btrfs_root), 1565 - GFP_NOFS); 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), 1569 GFP_NOFS); 1570 struct btrfs_root *dev_root = kzalloc(sizeof(struct btrfs_root),
··· 1561 GFP_NOFS); 1562 struct btrfs_root *csum_root = kzalloc(sizeof(struct btrfs_root), 1563 GFP_NOFS); 1564 + struct btrfs_root *tree_root = btrfs_sb(sb); 1565 + struct btrfs_fs_info *fs_info = tree_root->fs_info; 1566 struct btrfs_root *chunk_root = kzalloc(sizeof(struct btrfs_root), 1567 GFP_NOFS); 1568 struct btrfs_root *dev_root = kzalloc(sizeof(struct btrfs_root),
+31 -3
fs/btrfs/super.c
··· 563 564 static int btrfs_test_super(struct super_block *s, void *data) 565 { 566 - struct btrfs_fs_devices *test_fs_devices = data; 567 struct btrfs_root *root = btrfs_sb(s); 568 569 /* ··· 572 */ 573 if (!atomic_read(&s->s_active)) 574 return 0; 575 - return root->fs_info->fs_devices == test_fs_devices; 576 } 577 578 /* 579 * Find a superblock for the given device / mount point. ··· 596 struct super_block *s; 597 struct dentry *root; 598 struct btrfs_fs_devices *fs_devices = NULL; 599 fmode_t mode = FMODE_READ; 600 char *subvol_name = NULL; 601 u64 subvol_objectid = 0; ··· 625 goto error_close_devices; 626 } 627 628 bdev = fs_devices->latest_bdev; 629 - s = sget(fs_type, btrfs_test_super, set_anon_super, fs_devices); 630 if (IS_ERR(s)) 631 goto error_s; 632 ··· 711 error = PTR_ERR(s); 712 error_close_devices: 713 btrfs_close_devices(fs_devices); 714 error_free_subvol_name: 715 kfree(subvol_name); 716 return error;
··· 563 564 static int btrfs_test_super(struct super_block *s, void *data) 565 { 566 + struct btrfs_root *test_root = data; 567 struct btrfs_root *root = btrfs_sb(s); 568 569 /* ··· 572 */ 573 if (!atomic_read(&s->s_active)) 574 return 0; 575 + return root->fs_info->fs_devices == test_root->fs_info->fs_devices; 576 } 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 586 /* 587 * Find a superblock for the given device / mount point. ··· 588 struct super_block *s; 589 struct dentry *root; 590 struct btrfs_fs_devices *fs_devices = NULL; 591 + struct btrfs_root *tree_root = NULL; 592 + struct btrfs_fs_info *fs_info = NULL; 593 fmode_t mode = FMODE_READ; 594 char *subvol_name = NULL; 595 u64 subvol_objectid = 0; ··· 615 goto error_close_devices; 616 } 617 618 + /* 619 + * Setup a dummy root and fs_info for test/set super. This is because 620 + * we don't actually fill this stuff out until open_ctree, but we need 621 + * it for searching for existing supers, so this lets us do that and 622 + * then open_ctree will properly initialize everything later. 623 + */ 624 + fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS); 625 + tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS); 626 + if (!fs_info || !tree_root) { 627 + error = -ENOMEM; 628 + goto error_close_devices; 629 + } 630 + fs_info->tree_root = tree_root; 631 + fs_info->fs_devices = fs_devices; 632 + tree_root->fs_info = fs_info; 633 + 634 bdev = fs_devices->latest_bdev; 635 + s = sget(fs_type, btrfs_test_super, btrfs_set_super, tree_root); 636 if (IS_ERR(s)) 637 goto error_s; 638 ··· 685 error = PTR_ERR(s); 686 error_close_devices: 687 btrfs_close_devices(fs_devices); 688 + kfree(fs_info); 689 + kfree(tree_root); 690 error_free_subvol_name: 691 kfree(subvol_name); 692 return error;