Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[pandora-kernel.git] / fs / btrfs / super.c
index f878337..9ac612e 100644 (file)
@@ -96,31 +96,6 @@ static match_table_t tokens = {
        {Opt_err, NULL},
 };
 
-u64 btrfs_parse_size(char *str)
-{
-       u64 res;
-       int mult = 1;
-       char *end;
-       char last;
-
-       res = simple_strtoul(str, &end, 10);
-
-       last = end[0];
-       if (isalpha(last)) {
-               last = tolower(last);
-               switch (last) {
-               case 'g':
-                       mult *= 1024;
-               case 'm':
-                       mult *= 1024;
-               case 'k':
-                       mult *= 1024;
-               }
-               res = res * mult;
-       }
-       return res;
-}
-
 /*
  * Regular mount options parser.  Everything that is needed only when
  * reading in a new superblock is parsed here.
@@ -216,7 +191,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                case Opt_max_extent:
                        num = match_strdup(&args[0]);
                        if (num) {
-                               info->max_extent = btrfs_parse_size(num);
+                               info->max_extent = memparse(num, NULL);
                                kfree(num);
 
                                info->max_extent = max_t(u64,
@@ -228,7 +203,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                case Opt_max_inline:
                        num = match_strdup(&args[0]);
                        if (num) {
-                               info->max_inline = btrfs_parse_size(num);
+                               info->max_inline = memparse(num, NULL);
                                kfree(num);
 
                                if (info->max_inline) {
@@ -243,7 +218,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                case Opt_alloc_start:
                        num = match_strdup(&args[0]);
                        if (num) {
-                               info->alloc_start = btrfs_parse_size(num);
+                               info->alloc_start = memparse(num, NULL);
                                kfree(num);
                                printk(KERN_INFO
                                        "btrfs: allocations start at %llu\n",
@@ -325,9 +300,15 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,
                        break;
                case Opt_subvolid:
                        intarg = 0;
-                       match_int(&args[0], &intarg);
-                       if (intarg)
-                               *subvol_objectid = intarg;
+                       error = match_int(&args[0], &intarg);
+                       if (!error) {
+                               /* we want the original fs_tree */
+                               if (!intarg)
+                                       *subvol_objectid =
+                                               BTRFS_FS_TREE_OBJECTID;
+                               else
+                                       *subvol_objectid = intarg;
+                       }
                        break;
                case Opt_device:
                        error = btrfs_scan_one_device(match_strdup(&args[0]),
@@ -746,14 +727,37 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct btrfs_root *root = btrfs_sb(dentry->d_sb);
        struct btrfs_super_block *disk_super = &root->fs_info->super_copy;
+       struct list_head *head = &root->fs_info->space_info;
+       struct btrfs_space_info *found;
+       u64 total_used = 0;
+       u64 data_used = 0;
        int bits = dentry->d_sb->s_blocksize_bits;
        __be32 *fsid = (__be32 *)root->fs_info->fsid;
 
+       rcu_read_lock();
+       list_for_each_entry_rcu(found, head, list) {
+               if (found->flags & (BTRFS_BLOCK_GROUP_DUP|
+                                   BTRFS_BLOCK_GROUP_RAID10|
+                                   BTRFS_BLOCK_GROUP_RAID1)) {
+                       total_used += found->bytes_used;
+                       if (found->flags & BTRFS_BLOCK_GROUP_DATA)
+                               data_used += found->bytes_used;
+                       else
+                               data_used += found->total_bytes;
+               }
+
+               total_used += found->bytes_used;
+               if (found->flags & BTRFS_BLOCK_GROUP_DATA)
+                       data_used += found->bytes_used;
+               else
+                       data_used += found->total_bytes;
+       }
+       rcu_read_unlock();
+
        buf->f_namelen = BTRFS_NAME_LEN;
        buf->f_blocks = btrfs_super_total_bytes(disk_super) >> bits;
-       buf->f_bfree = buf->f_blocks -
-               (btrfs_super_bytes_used(disk_super) >> bits);
-       buf->f_bavail = buf->f_bfree;
+       buf->f_bfree = buf->f_blocks - (total_used >> bits);
+       buf->f_bavail = buf->f_blocks - (data_used >> bits);
        buf->f_bsize = dentry->d_sb->s_blocksize;
        buf->f_type = BTRFS_SUPER_MAGIC;