diff options
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 58 |
1 files changed, 37 insertions, 21 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 1776dbd8dc98..8299a25ffc8f 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -61,6 +61,8 @@ static void btrfs_put_super(struct super_block *sb) | |||
61 | 61 | ||
62 | ret = close_ctree(root); | 62 | ret = close_ctree(root); |
63 | sb->s_fs_info = NULL; | 63 | sb->s_fs_info = NULL; |
64 | |||
65 | (void)ret; /* FIXME: need to fix VFS to return error? */ | ||
64 | } | 66 | } |
65 | 67 | ||
66 | enum { | 68 | enum { |
@@ -68,7 +70,8 @@ enum { | |||
68 | Opt_nodatacow, Opt_max_inline, Opt_alloc_start, Opt_nobarrier, Opt_ssd, | 70 | Opt_nodatacow, Opt_max_inline, Opt_alloc_start, Opt_nobarrier, Opt_ssd, |
69 | Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl, Opt_compress, | 71 | Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl, Opt_compress, |
70 | Opt_compress_force, Opt_notreelog, Opt_ratio, Opt_flushoncommit, | 72 | Opt_compress_force, Opt_notreelog, Opt_ratio, Opt_flushoncommit, |
71 | Opt_discard, Opt_err, | 73 | Opt_discard, Opt_space_cache, Opt_clear_cache, Opt_err, |
74 | Opt_user_subvol_rm_allowed, | ||
72 | }; | 75 | }; |
73 | 76 | ||
74 | static match_table_t tokens = { | 77 | static match_table_t tokens = { |
@@ -92,6 +95,9 @@ static match_table_t tokens = { | |||
92 | {Opt_flushoncommit, "flushoncommit"}, | 95 | {Opt_flushoncommit, "flushoncommit"}, |
93 | {Opt_ratio, "metadata_ratio=%d"}, | 96 | {Opt_ratio, "metadata_ratio=%d"}, |
94 | {Opt_discard, "discard"}, | 97 | {Opt_discard, "discard"}, |
98 | {Opt_space_cache, "space_cache"}, | ||
99 | {Opt_clear_cache, "clear_cache"}, | ||
100 | {Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"}, | ||
95 | {Opt_err, NULL}, | 101 | {Opt_err, NULL}, |
96 | }; | 102 | }; |
97 | 103 | ||
@@ -235,6 +241,16 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
235 | case Opt_discard: | 241 | case Opt_discard: |
236 | btrfs_set_opt(info->mount_opt, DISCARD); | 242 | btrfs_set_opt(info->mount_opt, DISCARD); |
237 | break; | 243 | break; |
244 | case Opt_space_cache: | ||
245 | printk(KERN_INFO "btrfs: enabling disk space caching\n"); | ||
246 | btrfs_set_opt(info->mount_opt, SPACE_CACHE); | ||
247 | case Opt_clear_cache: | ||
248 | printk(KERN_INFO "btrfs: force clearing of disk cache\n"); | ||
249 | btrfs_set_opt(info->mount_opt, CLEAR_CACHE); | ||
250 | break; | ||
251 | case Opt_user_subvol_rm_allowed: | ||
252 | btrfs_set_opt(info->mount_opt, USER_SUBVOL_RM_ALLOWED); | ||
253 | break; | ||
238 | case Opt_err: | 254 | case Opt_err: |
239 | printk(KERN_INFO "btrfs: unrecognized mount option " | 255 | printk(KERN_INFO "btrfs: unrecognized mount option " |
240 | "'%s'\n", p); | 256 | "'%s'\n", p); |
@@ -380,7 +396,7 @@ static struct dentry *get_default_root(struct super_block *sb, | |||
380 | find_root: | 396 | find_root: |
381 | new_root = btrfs_read_fs_root_no_name(root->fs_info, &location); | 397 | new_root = btrfs_read_fs_root_no_name(root->fs_info, &location); |
382 | if (IS_ERR(new_root)) | 398 | if (IS_ERR(new_root)) |
383 | return ERR_PTR(PTR_ERR(new_root)); | 399 | return ERR_CAST(new_root); |
384 | 400 | ||
385 | if (btrfs_root_refs(&new_root->root_item) == 0) | 401 | if (btrfs_root_refs(&new_root->root_item) == 0) |
386 | return ERR_PTR(-ENOENT); | 402 | return ERR_PTR(-ENOENT); |
@@ -436,7 +452,6 @@ static int btrfs_fill_super(struct super_block *sb, | |||
436 | { | 452 | { |
437 | struct inode *inode; | 453 | struct inode *inode; |
438 | struct dentry *root_dentry; | 454 | struct dentry *root_dentry; |
439 | struct btrfs_super_block *disk_super; | ||
440 | struct btrfs_root *tree_root; | 455 | struct btrfs_root *tree_root; |
441 | struct btrfs_key key; | 456 | struct btrfs_key key; |
442 | int err; | 457 | int err; |
@@ -458,7 +473,6 @@ static int btrfs_fill_super(struct super_block *sb, | |||
458 | return PTR_ERR(tree_root); | 473 | return PTR_ERR(tree_root); |
459 | } | 474 | } |
460 | sb->s_fs_info = tree_root; | 475 | sb->s_fs_info = tree_root; |
461 | disk_super = &tree_root->fs_info->super_copy; | ||
462 | 476 | ||
463 | key.objectid = BTRFS_FIRST_FREE_OBJECTID; | 477 | key.objectid = BTRFS_FIRST_FREE_OBJECTID; |
464 | key.type = BTRFS_INODE_ITEM_KEY; | 478 | key.type = BTRFS_INODE_ITEM_KEY; |
@@ -560,8 +574,8 @@ static int btrfs_test_super(struct super_block *s, void *data) | |||
560 | * Note: This is based on get_sb_bdev from fs/super.c with a few additions | 574 | * Note: This is based on get_sb_bdev from fs/super.c with a few additions |
561 | * for multiple device setup. Make sure to keep it in sync. | 575 | * for multiple device setup. Make sure to keep it in sync. |
562 | */ | 576 | */ |
563 | static int btrfs_get_sb(struct file_system_type *fs_type, int flags, | 577 | static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, |
564 | const char *dev_name, void *data, struct vfsmount *mnt) | 578 | const char *dev_name, void *data) |
565 | { | 579 | { |
566 | struct block_device *bdev = NULL; | 580 | struct block_device *bdev = NULL; |
567 | struct super_block *s; | 581 | struct super_block *s; |
@@ -571,7 +585,6 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags, | |||
571 | char *subvol_name = NULL; | 585 | char *subvol_name = NULL; |
572 | u64 subvol_objectid = 0; | 586 | u64 subvol_objectid = 0; |
573 | int error = 0; | 587 | int error = 0; |
574 | int found = 0; | ||
575 | 588 | ||
576 | if (!(flags & MS_RDONLY)) | 589 | if (!(flags & MS_RDONLY)) |
577 | mode |= FMODE_WRITE; | 590 | mode |= FMODE_WRITE; |
@@ -580,7 +593,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags, | |||
580 | &subvol_name, &subvol_objectid, | 593 | &subvol_name, &subvol_objectid, |
581 | &fs_devices); | 594 | &fs_devices); |
582 | if (error) | 595 | if (error) |
583 | return error; | 596 | return ERR_PTR(error); |
584 | 597 | ||
585 | error = btrfs_scan_one_device(dev_name, mode, fs_type, &fs_devices); | 598 | error = btrfs_scan_one_device(dev_name, mode, fs_type, &fs_devices); |
586 | if (error) | 599 | if (error) |
@@ -607,7 +620,6 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags, | |||
607 | goto error_close_devices; | 620 | goto error_close_devices; |
608 | } | 621 | } |
609 | 622 | ||
610 | found = 1; | ||
611 | btrfs_close_devices(fs_devices); | 623 | btrfs_close_devices(fs_devices); |
612 | } else { | 624 | } else { |
613 | char b[BDEVNAME_SIZE]; | 625 | char b[BDEVNAME_SIZE]; |
@@ -629,7 +641,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags, | |||
629 | if (IS_ERR(root)) { | 641 | if (IS_ERR(root)) { |
630 | error = PTR_ERR(root); | 642 | error = PTR_ERR(root); |
631 | deactivate_locked_super(s); | 643 | deactivate_locked_super(s); |
632 | goto error; | 644 | goto error_free_subvol_name; |
633 | } | 645 | } |
634 | /* if they gave us a subvolume name bind mount into that */ | 646 | /* if they gave us a subvolume name bind mount into that */ |
635 | if (strcmp(subvol_name, ".")) { | 647 | if (strcmp(subvol_name, ".")) { |
@@ -643,24 +655,21 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags, | |||
643 | deactivate_locked_super(s); | 655 | deactivate_locked_super(s); |
644 | error = PTR_ERR(new_root); | 656 | error = PTR_ERR(new_root); |
645 | dput(root); | 657 | dput(root); |
646 | goto error_close_devices; | 658 | goto error_free_subvol_name; |
647 | } | 659 | } |
648 | if (!new_root->d_inode) { | 660 | if (!new_root->d_inode) { |
649 | dput(root); | 661 | dput(root); |
650 | dput(new_root); | 662 | dput(new_root); |
651 | deactivate_locked_super(s); | 663 | deactivate_locked_super(s); |
652 | error = -ENXIO; | 664 | error = -ENXIO; |
653 | goto error_close_devices; | 665 | goto error_free_subvol_name; |
654 | } | 666 | } |
655 | dput(root); | 667 | dput(root); |
656 | root = new_root; | 668 | root = new_root; |
657 | } | 669 | } |
658 | 670 | ||
659 | mnt->mnt_sb = s; | ||
660 | mnt->mnt_root = root; | ||
661 | |||
662 | kfree(subvol_name); | 671 | kfree(subvol_name); |
663 | return 0; | 672 | return root; |
664 | 673 | ||
665 | error_s: | 674 | error_s: |
666 | error = PTR_ERR(s); | 675 | error = PTR_ERR(s); |
@@ -668,8 +677,7 @@ error_close_devices: | |||
668 | btrfs_close_devices(fs_devices); | 677 | btrfs_close_devices(fs_devices); |
669 | error_free_subvol_name: | 678 | error_free_subvol_name: |
670 | kfree(subvol_name); | 679 | kfree(subvol_name); |
671 | error: | 680 | return ERR_PTR(error); |
672 | return error; | ||
673 | } | 681 | } |
674 | 682 | ||
675 | static int btrfs_remount(struct super_block *sb, int *flags, char *data) | 683 | static int btrfs_remount(struct super_block *sb, int *flags, char *data) |
@@ -716,18 +724,25 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
716 | struct list_head *head = &root->fs_info->space_info; | 724 | struct list_head *head = &root->fs_info->space_info; |
717 | struct btrfs_space_info *found; | 725 | struct btrfs_space_info *found; |
718 | u64 total_used = 0; | 726 | u64 total_used = 0; |
727 | u64 total_used_data = 0; | ||
719 | int bits = dentry->d_sb->s_blocksize_bits; | 728 | int bits = dentry->d_sb->s_blocksize_bits; |
720 | __be32 *fsid = (__be32 *)root->fs_info->fsid; | 729 | __be32 *fsid = (__be32 *)root->fs_info->fsid; |
721 | 730 | ||
722 | rcu_read_lock(); | 731 | rcu_read_lock(); |
723 | list_for_each_entry_rcu(found, head, list) | 732 | list_for_each_entry_rcu(found, head, list) { |
733 | if (found->flags & (BTRFS_BLOCK_GROUP_METADATA | | ||
734 | BTRFS_BLOCK_GROUP_SYSTEM)) | ||
735 | total_used_data += found->disk_total; | ||
736 | else | ||
737 | total_used_data += found->disk_used; | ||
724 | total_used += found->disk_used; | 738 | total_used += found->disk_used; |
739 | } | ||
725 | rcu_read_unlock(); | 740 | rcu_read_unlock(); |
726 | 741 | ||
727 | buf->f_namelen = BTRFS_NAME_LEN; | 742 | buf->f_namelen = BTRFS_NAME_LEN; |
728 | buf->f_blocks = btrfs_super_total_bytes(disk_super) >> bits; | 743 | buf->f_blocks = btrfs_super_total_bytes(disk_super) >> bits; |
729 | buf->f_bfree = buf->f_blocks - (total_used >> bits); | 744 | buf->f_bfree = buf->f_blocks - (total_used >> bits); |
730 | buf->f_bavail = buf->f_bfree; | 745 | buf->f_bavail = buf->f_blocks - (total_used_data >> bits); |
731 | buf->f_bsize = dentry->d_sb->s_blocksize; | 746 | buf->f_bsize = dentry->d_sb->s_blocksize; |
732 | buf->f_type = BTRFS_SUPER_MAGIC; | 747 | buf->f_type = BTRFS_SUPER_MAGIC; |
733 | 748 | ||
@@ -746,7 +761,7 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
746 | static struct file_system_type btrfs_fs_type = { | 761 | static struct file_system_type btrfs_fs_type = { |
747 | .owner = THIS_MODULE, | 762 | .owner = THIS_MODULE, |
748 | .name = "btrfs", | 763 | .name = "btrfs", |
749 | .get_sb = btrfs_get_sb, | 764 | .mount = btrfs_mount, |
750 | .kill_sb = kill_anon_super, | 765 | .kill_sb = kill_anon_super, |
751 | .fs_flags = FS_REQUIRES_DEV, | 766 | .fs_flags = FS_REQUIRES_DEV, |
752 | }; | 767 | }; |
@@ -815,6 +830,7 @@ static const struct file_operations btrfs_ctl_fops = { | |||
815 | .unlocked_ioctl = btrfs_control_ioctl, | 830 | .unlocked_ioctl = btrfs_control_ioctl, |
816 | .compat_ioctl = btrfs_control_ioctl, | 831 | .compat_ioctl = btrfs_control_ioctl, |
817 | .owner = THIS_MODULE, | 832 | .owner = THIS_MODULE, |
833 | .llseek = noop_llseek, | ||
818 | }; | 834 | }; |
819 | 835 | ||
820 | static struct miscdevice btrfs_misc = { | 836 | static struct miscdevice btrfs_misc = { |