diff options
Diffstat (limited to 'fs/btrfs/super.c')
| -rw-r--r-- | fs/btrfs/super.c | 43 |
1 files changed, 39 insertions, 4 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 8299a25ffc8f..883c6fa1367e 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
| @@ -244,6 +244,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
| 244 | case Opt_space_cache: | 244 | case Opt_space_cache: |
| 245 | printk(KERN_INFO "btrfs: enabling disk space caching\n"); | 245 | printk(KERN_INFO "btrfs: enabling disk space caching\n"); |
| 246 | btrfs_set_opt(info->mount_opt, SPACE_CACHE); | 246 | btrfs_set_opt(info->mount_opt, SPACE_CACHE); |
| 247 | break; | ||
| 247 | case Opt_clear_cache: | 248 | case Opt_clear_cache: |
| 248 | printk(KERN_INFO "btrfs: force clearing of disk cache\n"); | 249 | printk(KERN_INFO "btrfs: force clearing of disk cache\n"); |
| 249 | btrfs_set_opt(info->mount_opt, CLEAR_CACHE); | 250 | btrfs_set_opt(info->mount_opt, CLEAR_CACHE); |
| @@ -562,12 +563,26 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
| 562 | 563 | ||
| 563 | static int btrfs_test_super(struct super_block *s, void *data) | 564 | static int btrfs_test_super(struct super_block *s, void *data) |
| 564 | { | 565 | { |
| 565 | struct btrfs_fs_devices *test_fs_devices = data; | 566 | struct btrfs_root *test_root = data; |
| 566 | struct btrfs_root *root = btrfs_sb(s); | 567 | struct btrfs_root *root = btrfs_sb(s); |
| 567 | 568 | ||
| 568 | return root->fs_info->fs_devices == test_fs_devices; | 569 | /* |
| 570 | * If this super block is going away, return false as it | ||
| 571 | * can't match as an existing super block. | ||
| 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); | ||
| 569 | } | 583 | } |
| 570 | 584 | ||
| 585 | |||
| 571 | /* | 586 | /* |
| 572 | * Find a superblock for the given device / mount point. | 587 | * Find a superblock for the given device / mount point. |
| 573 | * | 588 | * |
| @@ -581,6 +596,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
| 581 | struct super_block *s; | 596 | struct super_block *s; |
| 582 | struct dentry *root; | 597 | struct dentry *root; |
| 583 | 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; | ||
| 584 | fmode_t mode = FMODE_READ; | 601 | fmode_t mode = FMODE_READ; |
| 585 | char *subvol_name = NULL; | 602 | char *subvol_name = NULL; |
| 586 | u64 subvol_objectid = 0; | 603 | u64 subvol_objectid = 0; |
| @@ -608,8 +625,24 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
| 608 | goto error_close_devices; | 625 | goto error_close_devices; |
| 609 | } | 626 | } |
| 610 | 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 | |||
| 611 | bdev = fs_devices->latest_bdev; | 644 | bdev = fs_devices->latest_bdev; |
| 612 | 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); |
| 613 | if (IS_ERR(s)) | 646 | if (IS_ERR(s)) |
| 614 | goto error_s; | 647 | goto error_s; |
| 615 | 648 | ||
| @@ -652,9 +685,9 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
| 652 | mutex_unlock(&root->d_inode->i_mutex); | 685 | mutex_unlock(&root->d_inode->i_mutex); |
| 653 | 686 | ||
| 654 | if (IS_ERR(new_root)) { | 687 | if (IS_ERR(new_root)) { |
| 688 | dput(root); | ||
| 655 | deactivate_locked_super(s); | 689 | deactivate_locked_super(s); |
| 656 | error = PTR_ERR(new_root); | 690 | error = PTR_ERR(new_root); |
| 657 | dput(root); | ||
| 658 | goto error_free_subvol_name; | 691 | goto error_free_subvol_name; |
| 659 | } | 692 | } |
| 660 | if (!new_root->d_inode) { | 693 | if (!new_root->d_inode) { |
| @@ -675,6 +708,8 @@ error_s: | |||
| 675 | error = PTR_ERR(s); | 708 | error = PTR_ERR(s); |
| 676 | error_close_devices: | 709 | error_close_devices: |
| 677 | btrfs_close_devices(fs_devices); | 710 | btrfs_close_devices(fs_devices); |
| 711 | kfree(fs_info); | ||
| 712 | kfree(tree_root); | ||
| 678 | error_free_subvol_name: | 713 | error_free_subvol_name: |
| 679 | kfree(subvol_name); | 714 | kfree(subvol_name); |
| 680 | return ERR_PTR(error); | 715 | return ERR_PTR(error); |
