From: Omar Sandoval <osan...@fb.com>

To start, let's tell btrfs-progs to read the free space root and how to
print the on-disk format of the free space tree. However, we're not
adding the FREE_SPACE_TREE read-only compat bit to the set of supported
bits because progs doesn't know how to keep the free space tree
consistent.

Signed-off-by: Omar Sandoval <osan...@fb.com>
---
 btrfs-debug-tree.c |  4 ++++
 ctree.h            | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
 disk-io.c          | 16 +++++++++++++++-
 print-tree.c       | 25 +++++++++++++++++++++++++
 4 files changed, 92 insertions(+), 2 deletions(-)

diff --git a/btrfs-debug-tree.c b/btrfs-debug-tree.c
index 7d8e876f1a2d..2aa5bd11d1b6 100644
--- a/btrfs-debug-tree.c
+++ b/btrfs-debug-tree.c
@@ -375,6 +375,10 @@ again:
                                if (!skip)
                                        printf("uuid");
                                break;
+                       case BTRFS_FREE_SPACE_TREE_OBJECTID:
+                               if (!skip)
+                                       printf("free space");
+                               break;
                        case BTRFS_MULTIPLE_OBJECTIDS:
                                if (!skip) {
                                        printf("multiple");
diff --git a/ctree.h b/ctree.h
index c57f9cad5082..a37f3d1fcc48 100644
--- a/ctree.h
+++ b/ctree.h
@@ -76,6 +76,9 @@ struct btrfs_free_space_ctl;
 /* for storing items that use the BTRFS_UUID_KEY* */
 #define BTRFS_UUID_TREE_OBJECTID 9ULL
 
+/* tracks free space in block groups. */
+#define BTRFS_FREE_SPACE_TREE_OBJECTID 10ULL
+
 /* for storing balance parameters in the root tree */
 #define BTRFS_BALANCE_OBJECTID -4ULL
 
@@ -453,6 +456,8 @@ struct btrfs_super_block {
  * Compat flags that we support.  If any incompat flags are set other than the
  * ones specified below then we will fail to mount
  */
+#define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE        (1ULL << 0)
+
 #define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF   (1ULL << 0)
 #define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL  (1ULL << 1)
 #define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS    (1ULL << 2)
@@ -476,9 +481,10 @@ struct btrfs_super_block {
 #define BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA (1ULL << 8)
 #define BTRFS_FEATURE_INCOMPAT_NO_HOLES                (1ULL << 9)
 
-
 #define BTRFS_FEATURE_COMPAT_SUPP              0ULL
+
 #define BTRFS_FEATURE_COMPAT_RO_SUPP           0ULL
+
 #define BTRFS_FEATURE_INCOMPAT_SUPP                    \
        (BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF |         \
         BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL |        \
@@ -898,6 +904,13 @@ struct btrfs_block_group_item {
        __le64 flags;
 } __attribute__ ((__packed__));
 
+struct btrfs_free_space_info {
+       __le32 extent_count;
+       __le32 flags;
+} __attribute__ ((__packed__));
+
+#define BTRFS_FREE_SPACE_USING_BITMAPS (1ULL << 0)
+
 struct btrfs_qgroup_info_item {
        __le64 generation;
        __le64 referenced;
@@ -965,6 +978,7 @@ struct btrfs_fs_info {
        struct btrfs_root *dev_root;
        struct btrfs_root *csum_root;
        struct btrfs_root *quota_root;
+       struct btrfs_root *free_space_root;
 
        struct rb_root fs_root_tree;
 
@@ -1157,6 +1171,27 @@ struct btrfs_root {
  */
 #define BTRFS_BLOCK_GROUP_ITEM_KEY 192
 
+/*
+ * Every block group is represented in the free space tree by a free space info
+ * item, which stores some accounting information. It is keyed on
+ * (block_group_start, FREE_SPACE_INFO, block_group_length).
+ */
+#define BTRFS_FREE_SPACE_INFO_KEY 198
+
+/*
+ * A free space extent tracks an extent of space that is free in a block group.
+ * It is keyed on (start, FREE_SPACE_EXTENT, length).
+ */
+#define BTRFS_FREE_SPACE_EXTENT_KEY 199
+
+/*
+ * When a block group becomes very fragmented, we convert it to use bitmaps
+ * instead of extents. A free space bitmap is keyed on
+ * (start, FREE_SPACE_BITMAP, length); the corresponding item is a bitmap with
+ * (length / sectorsize) bits.
+ */
+#define BTRFS_FREE_SPACE_BITMAP_KEY 200
+
 #define BTRFS_DEV_EXTENT_KEY   204
 #define BTRFS_DEV_ITEM_KEY     216
 #define BTRFS_CHUNK_ITEM_KEY   228
@@ -1394,6 +1429,11 @@ BTRFS_SETGET_FUNCS(disk_block_group_flags,
 BTRFS_SETGET_STACK_FUNCS(block_group_flags,
                        struct btrfs_block_group_item, flags, 64);
 
+/* struct btrfs_free_space_info */
+BTRFS_SETGET_FUNCS(free_space_extent_count, struct btrfs_free_space_info,
+                  extent_count, 32);
+BTRFS_SETGET_FUNCS(free_space_flags, struct btrfs_free_space_info, flags, 32);
+
 /* struct btrfs_inode_ref */
 BTRFS_SETGET_FUNCS(inode_ref_name_len, struct btrfs_inode_ref, name_len, 16);
 BTRFS_SETGET_STACK_FUNCS(stack_inode_ref_name_len, struct btrfs_inode_ref, 
name_len, 16);
@@ -2193,6 +2233,13 @@ static inline int btrfs_fs_incompat(struct btrfs_fs_info 
*fs_info, u64 flag)
        return !!(btrfs_super_incompat_flags(disk_super) & flag);
 }
 
+static inline int btrfs_fs_compat_ro(struct btrfs_fs_info *fs_info, u64 flag)
+{
+       struct btrfs_super_block *disk_super;
+       disk_super = fs_info->super_copy;
+       return !!(btrfs_super_compat_ro_flags(disk_super) & flag);
+}
+
 /* helper function to cast into the data area of the leaf. */
 #define btrfs_item_ptr(leaf, slot, type) \
        ((type *)(btrfs_leaf_data(leaf) + \
diff --git a/disk-io.c b/disk-io.c
index 8496aded31c4..ae9d6e1abb23 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -818,6 +818,7 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
        free(fs_info->dev_root);
        free(fs_info->csum_root);
        free(fs_info->quota_root);
+       free(fs_info->free_space_root);
        free(fs_info->super_copy);
        free(fs_info->log_root_tree);
        free(fs_info);
@@ -839,12 +840,13 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 
sb_bytenr)
        fs_info->dev_root = calloc(1, sizeof(struct btrfs_root));
        fs_info->csum_root = calloc(1, sizeof(struct btrfs_root));
        fs_info->quota_root = calloc(1, sizeof(struct btrfs_root));
+       fs_info->free_space_root = calloc(1, sizeof(struct btrfs_root));
        fs_info->super_copy = calloc(1, BTRFS_SUPER_INFO_SIZE);
 
        if (!fs_info->tree_root || !fs_info->extent_root ||
            !fs_info->chunk_root || !fs_info->dev_root ||
            !fs_info->csum_root || !fs_info->quota_root ||
-           !fs_info->super_copy)
+           !fs_info->free_space_root || !fs_info->super_copy)
                goto free_all;
 
        extent_io_tree_init(&fs_info->extent_cache);
@@ -1025,6 +1027,16 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, 
u64 root_tree_bytenr,
        if (ret == 0)
                fs_info->quota_enabled = 1;
 
+       if (btrfs_fs_compat_ro(fs_info, 
BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE)) {
+               ret = find_and_setup_root(root, fs_info, 
BTRFS_FREE_SPACE_TREE_OBJECTID,
+                                         fs_info->free_space_root);
+               if (ret) {
+                       printk("Couldn't read free space tree\n");
+                       return -EIO;
+               }
+               fs_info->free_space_root->track_dirty = 1;
+       }
+
        ret = find_and_setup_log_root(root, fs_info, sb);
        if (ret) {
                printk("Couldn't setup log root tree\n");
@@ -1050,6 +1062,8 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, 
u64 root_tree_bytenr,
 
 void btrfs_release_all_roots(struct btrfs_fs_info *fs_info)
 {
+       if (fs_info->free_space_root)
+               free_extent_buffer(fs_info->free_space_root->node);
        if (fs_info->quota_root)
                free_extent_buffer(fs_info->quota_root->node);
        if (fs_info->csum_root)
diff --git a/print-tree.c b/print-tree.c
index dc1d2764ae91..9dc058b58bde 100644
--- a/print-tree.c
+++ b/print-tree.c
@@ -610,6 +610,15 @@ static void print_key_type(u64 objectid, u8 type)
        case BTRFS_BLOCK_GROUP_ITEM_KEY:
                printf("BLOCK_GROUP_ITEM");
                break;
+       case BTRFS_FREE_SPACE_INFO_KEY:
+               printf("FREE_SPACE_INFO");
+               break;
+       case BTRFS_FREE_SPACE_EXTENT_KEY:
+               printf("FREE_SPACE_EXTENT");
+               break;
+       case BTRFS_FREE_SPACE_BITMAP_KEY:
+               printf("FREE_SPACE_BITMAP");
+               break;
        case BTRFS_CHUNK_ITEM_KEY:
                printf("CHUNK_ITEM");
                break;
@@ -728,6 +737,9 @@ static void print_objectid(u64 objectid, u8 type)
        case BTRFS_UUID_TREE_OBJECTID:
                printf("UUID_TREE");
                break;
+       case BTRFS_FREE_SPACE_TREE_OBJECTID:
+               printf("FREE_SPACE_TREE");
+               break;
        case BTRFS_MULTIPLE_OBJECTIDS:
                printf("MULTIPLE");
                break;
@@ -810,6 +822,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct 
extent_buffer *l)
        struct btrfs_dev_extent *dev_extent;
        struct btrfs_disk_key disk_key;
        struct btrfs_block_group_item bg_item;
+       struct btrfs_free_space_info *free_info;
        struct btrfs_dir_log_item *dlog;
        struct btrfs_qgroup_info_item *qg_info;
        struct btrfs_qgroup_limit_item *qg_limit;
@@ -947,6 +960,18 @@ void btrfs_print_leaf(struct btrfs_root *root, struct 
extent_buffer *l)
                               (unsigned long 
long)btrfs_block_group_chunk_objectid(&bg_item),
                               flags_str);
                        break;
+               case BTRFS_FREE_SPACE_INFO_KEY:
+                       free_info = btrfs_item_ptr(l, i, struct 
btrfs_free_space_info);
+                       printf("\t\tfree space info extent count %u flags %u\n",
+                              (unsigned)btrfs_free_space_extent_count(l, 
free_info),
+                              (unsigned)btrfs_free_space_flags(l, free_info));
+                       break;
+               case BTRFS_FREE_SPACE_EXTENT_KEY:
+                       printf("\t\tfree space extent\n");
+                       break;
+               case BTRFS_FREE_SPACE_BITMAP_KEY:
+                       printf("\t\tfree space bitmap\n");
+                       break;
                case BTRFS_CHUNK_ITEM_KEY:
                        print_chunk(l, btrfs_item_ptr(l, i, struct 
btrfs_chunk));
                        break;
-- 
2.6.0

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to