Hello,

This patch updates btrfs-progs according to kernel module's code. It
updates btrfs-progs to properly handle back reference and exports some
functions in extent-tree.c

Regards
YZ
----
diff -r a1a37f51dcb2 ctree.c
--- a/ctree.c   Fri Dec 14 11:00:30 2007 -0500
+++ b/ctree.c   Wed Dec 19 19:52:02 2007 +0800
@@ -53,10 +53,10 @@ void btrfs_release_path(struct btrfs_roo
        }
        memset(p, 0, sizeof(*p));
 }
+
 int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
-                          *root, struct btrfs_buffer *buf, struct btrfs_buffer
-                          *parent, int parent_slot, struct btrfs_buffer
-                          **cow_ret)
+                   *root, struct btrfs_buffer *buf, struct btrfs_buffer
+                   *parent, int parent_slot, struct btrfs_buffer **cow_ret)
 {
        struct btrfs_buffer *cow;
        u64 root_gen;
diff -r a1a37f51dcb2 ctree.h
--- a/ctree.h   Fri Dec 14 11:00:30 2007 -0500
+++ b/ctree.h   Wed Dec 19 19:52:02 2007 +0800
@@ -432,8 +432,8 @@ BTRFS_SETGET_STACK_FUNCS(inode_compat_fl
 BTRFS_SETGET_STACK_FUNCS(inode_compat_flags, struct btrfs_inode_item,
                         compat_flags, 16);

-BTRFS_SETGET_STACK_FUNCS(timpsec_sec, struct btrfs_inode_timespec, sec, 64);
-BTRFS_SETGET_STACK_FUNCS(timpsec_nsec, struct btrfs_inode_timespec, nsec, 32);
+BTRFS_SETGET_STACK_FUNCS(timespec_sec, struct btrfs_inode_timespec, sec, 64);
+BTRFS_SETGET_STACK_FUNCS(timespec_nsec, struct btrfs_inode_timespec, nsec, 32);
 BTRFS_SETGET_STACK_FUNCS(extent_refs, struct btrfs_extent_item, refs, 32);

 BTRFS_SETGET_STACK_FUNCS(inode_ref_name_len, struct btrfs_inode_ref,
@@ -607,7 +607,7 @@ BTRFS_SETGET_STACK_FUNCS(file_extent_num
        btrfs_item_offset((leaf)->items + (slot))))
 #define btrfs_item_ptr_offset(leaf, slot) \
        ((unsigned long)(btrfs_leaf_data(leaf) + \
-       btrfs_item_offset_nr(leaf, slot)))
+       btrfs_item_offset((leaf)->items + (slot))))

 static inline u32 btrfs_level_size(struct btrfs_root *root, int level)
 {
@@ -616,9 +616,28 @@ static inline u32 btrfs_level_size(struc
        return root->nodesize;
 }
 int btrfs_comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2);
+int update_block_group(struct btrfs_trans_handle *trans, struct btrfs_root
+                      *root, u64 bytenr, u64 num, int alloc);
+int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
+                        struct btrfs_root *root);
 struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
                                            struct btrfs_root *root,
                                            u32 blocksize);
+u64 hash_extent_ref(u64 root_objectid, u64 ref_generation, u64 owner,
+                   u64 owner_offset);
+int lookup_extent_backref(struct btrfs_trans_handle *trans,
+                         struct btrfs_root *root, struct btrfs_path *path,
+                         u64 bytenr, u64 root_objectid, u64 ref_generation,    
+                         u64 owner, u64 owner_offset, int del);
+int insert_extent_backref(struct btrfs_trans_handle *trans,
+                         struct btrfs_root *root, struct btrfs_path *path,
+                         u64 bytenr,    u64 root_objectid, u64 ref_generation,
+                         u64 owner, u64 owner_offset);
+int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
+                    *root, u64 bytenr, u32 blocksize, u32 *refs);
+int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
+                 *root, u64 bytenr, u32 blocksize, u64 root_objectid,
+                 u64 ref_generation, u64 owner, u64 owner_offset);
 int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                  struct btrfs_buffer *buf);
 int btrfs_inc_root_ref(struct btrfs_trans_handle *trans,
diff -r a1a37f51dcb2 disk-io.c
--- a/disk-io.c Fri Dec 14 11:00:30 2007 -0500
+++ b/disk-io.c Wed Dec 19 19:52:02 2007 +0800
@@ -298,12 +298,13 @@ int btrfs_commit_transaction(struct btrf
        btrfs_finish_extent_commit(trans, root->fs_info->extent_root);
        btrfs_finish_extent_commit(trans, root->fs_info->tree_root);

+       ret = btrfs_drop_snapshot(trans, root, snap);
+       BUG_ON(ret);
+       ret = btrfs_del_root(trans, root->fs_info->tree_root, &snap_key);
+       BUG_ON(ret);
+       
        root->commit_root = root->node;
        root->node->count++;
-       ret = btrfs_drop_snapshot(trans, root, snap);
-       BUG_ON(ret);
-       ret = btrfs_del_root(trans, root->fs_info->tree_root, &snap_key);
-       BUG_ON(ret);
        btrfs_free_transaction(root, trans);
        return ret;
 }
diff -r a1a37f51dcb2 extent-tree.c
--- a/extent-tree.c     Fri Dec 14 11:00:30 2007 -0500
+++ b/extent-tree.c     Wed Dec 19 19:52:02 2007 +0800
@@ -31,8 +31,8 @@ static int run_pending(struct btrfs_tran
 static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root
                       *extent_root);

-static u64 hash_extent_ref(u64 root_objectid, u64 ref_generation,
-                          u64 owner, u64 owner_offset)
+u64 hash_extent_ref(u64 root_objectid, u64 ref_generation,
+                   u64 owner, u64 owner_offset)
 {
        u32 high_crc = ~(u32)0;
        u32 low_crc = ~(u32)0;
@@ -55,15 +55,22 @@ static int match_extent_ref(struct btrfs
 static int match_extent_ref(struct btrfs_extent_ref *disk_ref,
                            struct btrfs_extent_ref *cpu_ref)
 {
-       int ret = memcmp(cpu_ref, disk_ref, sizeof(*cpu_ref));
+       int ret;
+       int len;
+
+       if (cpu_ref->objectid)
+               len = sizeof(*cpu_ref);
+       else
+               len = 2 * sizeof(u64);
+       ret = memcmp(cpu_ref, disk_ref, len);
        return ret == 0;
 }

-static int lookup_extent_backref(struct btrfs_trans_handle *trans,
-                                struct btrfs_root *root,
-                                struct btrfs_path *path, u64 bytenr,
-                                u64 root_objectid, u64 ref_generation,
-                                u64 owner, u64 owner_offset, int del)
+int lookup_extent_backref(struct btrfs_trans_handle *trans,
+                         struct btrfs_root *root,
+                         struct btrfs_path *path, u64 bytenr,
+                         u64 root_objectid, u64 ref_generation,        
+                         u64 owner, u64 owner_offset, int del)
 {
        u64 hash;
        struct btrfs_key key;
@@ -126,11 +133,11 @@ out:
        return ret;
 }

-static int insert_extent_backref(struct btrfs_trans_handle *trans,
-                                struct btrfs_root *root,
-                                struct btrfs_path *path, u64 bytenr,
-                                u64 root_objectid, u64 ref_generation,
-                                u64 owner, u64 owner_offset)
+int insert_extent_backref(struct btrfs_trans_handle *trans,
+                         struct btrfs_root *root,
+                         struct btrfs_path *path, u64 bytenr,  
+                         u64 root_objectid, u64 ref_generation,
+                         u64 owner, u64 owner_offset)
 {
        u64 hash;
        struct btrfs_key key;
@@ -156,6 +163,7 @@ static int insert_extent_backref(struct
                if (match_extent_ref(disk_ref, &ref))
                        goto out;
                key.offset++;
+               btrfs_release_path(root, path);
                ret = btrfs_insert_empty_item(trans, root, path, &key,
                                              sizeof(ref));
        }
@@ -164,16 +172,16 @@ static int insert_extent_backref(struct
        disk_ref = btrfs_item_ptr(&path->nodes[0]->leaf, path->slots[0],
                                  struct btrfs_extent_ref);
        memcpy(disk_ref, &ref, sizeof(ref));
-       dirty_tree_block(trans, root, path->nodes[0]);
+       BUG_ON(list_empty(&path->nodes[0]->dirty));
 out:
        btrfs_release_path(root, path);
        return ret;
 }

-static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
-                        *root, u64 bytenr, u32 blocksize,
-                        u64 root_objectid, u64 ref_generation,
-                        u64 owner, u64 owner_offset)
+int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
+                 *root, u64 bytenr, u32 blocksize,
+                 u64 root_objectid, u64 ref_generation,
+                 u64 owner, u64 owner_offset)
 {
        struct btrfs_path path;
        int ret;
@@ -209,8 +217,8 @@ static int inc_block_ref(struct btrfs_tr
        return 0;
 }

-static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
-                           *root, u64 bytenr, u32 blocksize, u32 *refs)
+int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
+                    *root, u64 bytenr, u32 blocksize, u32 *refs)
 {
        struct btrfs_path path;
        int ret;
@@ -226,38 +234,66 @@ static int lookup_block_ref(struct btrfs
        ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, &path,
                                0, 0);
        if (ret != 0)
-               BUG();
+               goto out;
        l = &path.nodes[0]->leaf;
        item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item);
        *refs = btrfs_extent_refs(item);
+out:
        btrfs_release_path(root->fs_info->extent_root, &path);
-       return 0;
+       return ret;
 }

 int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                  struct btrfs_buffer *buf)
 {
        u64 bytenr;
-       u32 blocksize;
+       u32 nritems;
+       struct btrfs_key key;
+       struct btrfs_file_extent_item *fi;
        int i;
        int level;
+       int ret;

        if (!root->ref_cows)
                return 0;

-       level = btrfs_header_level(&buf->node.header) - 1;
-       blocksize = btrfs_level_size(root, level);
-
-       if (btrfs_is_leaf(&buf->node))
-               return 0;
-
-       for (i = 0; i < btrfs_header_nritems(&buf->node.header); i++) {
-               bytenr = btrfs_node_blockptr(&buf->node, i);
-               inc_block_ref(trans, root, bytenr, blocksize,
-                             root->root_key.objectid, trans->transid, 0, 0);
-       }
-
-       return 0;
+       level = btrfs_header_level(&buf->node.header);
+       nritems = btrfs_header_nritems(&buf->node.header);
+       for (i = 0; i < nritems; i++) {
+               if (level == 0) {
+                       u64 disk_bytenr;
+                       btrfs_disk_key_to_cpu(&key, &buf->leaf.items[i].key);
+                       if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY)
+                               continue;
+                       fi = btrfs_item_ptr(&buf->leaf, i,
+                                           struct btrfs_file_extent_item);
+                       if (btrfs_file_extent_type(fi) ==
+                           BTRFS_FILE_EXTENT_INLINE)
+                               continue;
+                       disk_bytenr = btrfs_file_extent_disk_bytenr(fi);
+                       if (disk_bytenr == 0)
+                               continue;
+                       ret = inc_block_ref(trans, root, disk_bytenr,
+                                   btrfs_file_extent_disk_num_bytes(fi),
+                                   root->root_key.objectid, trans->transid,
+                                   key.objectid, key.offset);
+                       if (ret)
+                               goto fail;
+               } else {
+                       btrfs_disk_key_to_cpu(&key, &buf->node.ptrs[i].key);
+                       bytenr = btrfs_node_blockptr(&buf->node, i);
+                       ret = inc_block_ref(trans, root, bytenr,
+                                   btrfs_level_size(root, level - 1),
+                                   root->root_key.objectid, trans->transid,    
+                                   level - 1, key.objectid);
+                       if (ret)
+                               goto fail;
+               }
+       }
+       return 0;
+fail:
+       BUG();
+       return ret;
 }

 int btrfs_inc_root_ref(struct btrfs_trans_handle *trans,
@@ -326,9 +362,9 @@ int btrfs_write_dirty_block_groups(struc
        return werr;
 }

-static int update_block_group(struct btrfs_trans_handle *trans,
-                             struct btrfs_root *root,
-                             u64 bytenr, u64 num, int alloc)
+int update_block_group(struct btrfs_trans_handle *trans,
+                      struct btrfs_root *root,
+                      u64 bytenr, u64 num, int alloc)
 {
        struct btrfs_block_group_cache *bg;
        struct cache_extent *cache;
@@ -388,12 +424,15 @@ static int finish_current_insert(struct
 {
        struct btrfs_key ins;
        struct btrfs_extent_item extent_item;
-       int ret;
        struct btrfs_fs_info *info = extent_root->fs_info;
+       struct btrfs_buffer *buf;
        struct cache_extent *pe;
        struct cache_extent *next;
        struct cache_tree *pending_tree = &info->pending_tree;
+       struct btrfs_disk_key *first_key;
        struct btrfs_path path;
+       int ret;
+       int level;

        btrfs_init_path(&path);
        btrfs_set_extent_refs(&extent_item, 1);
@@ -419,10 +458,18 @@ static int finish_current_insert(struct
                }
                BUG_ON(ret);

-               ret = insert_extent_backref(trans, extent_root, &path,
-                                           ins.objectid,
-                                           extent_root->root_key.objectid,
-                                           0, 0, 0);
+               buf = read_tree_block(extent_root, ins.objectid, ins.offset);
+               level = btrfs_header_level(&buf->node.header);
+               if (level == 0) {
+                       first_key = &buf->leaf.items[0].key;
+               } else {
+                       first_key = &buf->node.ptrs[0].key;
+               }
+
+               ret = insert_extent_backref(trans, extent_root, &path,
+                               ins.objectid, extent_root->root_key.objectid,
+                               0, level, btrfs_disk_key_objectid(first_key));
+               btrfs_block_release(extent_root, buf);
                BUG_ON(ret);
        }
        return 0;
@@ -490,11 +537,10 @@ static int __free_extent(struct btrfs_tr
                                          root_bytes_used - num_bytes);

                ret = btrfs_del_item(trans, extent_root, &path);
+               BUG_ON(ret);
                if (!pin && extent_root->fs_info->last_insert.objectid >
                    bytenr)
                        extent_root->fs_info->last_insert.objectid = bytenr;
-               if (ret)
-                       BUG();
                ret = update_block_group(trans, root, bytenr, num_bytes, 0);
                BUG_ON(ret);
        }
@@ -539,6 +585,13 @@ static int run_pending(struct btrfs_tran
        return 0;
 }

+int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
+                        struct btrfs_root *root)
+{
+       finish_current_insert(trans, root->fs_info->extent_root);
+       del_pending_extents(trans, root->fs_info->extent_root);
+       return 0;
+}

 /*
  * remove an extent from the root, returns 0 on success
@@ -711,6 +764,7 @@ static int alloc_extent(struct btrfs_tra

        ret = find_free_extent(trans, root, num_bytes, search_start,
                               search_end, ins);
+       BUG_ON(ret);
        if (ret)
                return ret;

@@ -777,8 +831,45 @@ struct btrfs_buffer *btrfs_alloc_free_bl
        memcpy(buf->node.header.fsid, root->fs_info->disk_super->fsid,
               sizeof(buf->node.header.fsid));
        dirty_tree_block(trans, root, buf);
+       trans->blocks_used++;
        return buf;
-
+}
+
+static int drop_leaf_ref(struct btrfs_trans_handle *trans,
+                        struct btrfs_root *root, struct btrfs_buffer *buf)
+{
+       u64 leaf_owner;
+       u64 leaf_generation;
+       struct btrfs_key key;
+       struct btrfs_leaf *leaf = &buf->leaf;
+       struct btrfs_file_extent_item *fi;
+       int i;
+       int nritems;
+       int ret;
+
+       nritems = btrfs_header_nritems(&leaf->header);
+       leaf_owner = btrfs_header_owner(&leaf->header);
+       leaf_generation = btrfs_header_generation(&leaf->header);
+
+       for (i = 0; i < nritems; i++) {
+               u64 disk_bytenr;
+
+               btrfs_disk_key_to_cpu(&key, &leaf->items[i].key);
+               if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY)
+                       continue;
+               fi = btrfs_item_ptr(leaf, i, struct btrfs_file_extent_item);
+               if (btrfs_file_extent_type(fi) == BTRFS_FILE_EXTENT_INLINE)
+                       continue;
+               disk_bytenr = btrfs_file_extent_disk_bytenr(fi);
+               if (disk_bytenr == 0)
+                       continue;
+               ret = btrfs_free_extent(trans, root, disk_bytenr,
+                               btrfs_file_extent_disk_num_bytes(fi),
+                               leaf_owner, leaf_generation,
+                               key.objectid, key.offset, 0);
+               BUG_ON(ret);
+       }
+       return 0;
 }

 /*
@@ -805,16 +896,22 @@ static int walk_down_tree(struct btrfs_t
        /*
         * walk down to the last node level and free all the leaves
         */
-       while(*level > 0) {
+       while(*level >= 0) {
                u32 size = btrfs_level_size(root, *level - 1);

                cur = path->nodes[*level];
                if (path->slots[*level] >=
                    btrfs_header_nritems(&cur->node.header))
                        break;
+               if (*level == 0) {
+                       ret = drop_leaf_ref(trans, root, cur);
+                       BUG_ON(ret);
+                       break;
+               }
                bytenr = btrfs_node_blockptr(&cur->node, path->slots[*level]);
                ret = lookup_block_ref(trans, root, bytenr, size, &refs);
-               if (refs != 1 || *level == 1) {
+               BUG_ON(ret);
+               if (refs != 1) {
                        parent = path->nodes[*level];
                        root_owner = btrfs_header_owner(&parent->node.header);
                        root_gen =
@@ -834,12 +931,14 @@ static int walk_down_tree(struct btrfs_t
                path->slots[*level] = 0;
        }
 out:
-       if (*level == BTRFS_MAX_LEVEL - 1 || !path->nodes[*level + 1])
+       if (path->nodes[*level] == root->commit_root) {
+               root_owner = root->root_key.objectid;
                parent = path->nodes[*level];
-       else
+       } else {
                parent = path->nodes[*level + 1];
-
-       root_owner = btrfs_header_owner(&parent->node.header);
+               root_owner = btrfs_header_owner(&parent->node.header);
+       }
+
        root_gen = btrfs_header_generation(&parent->node.header);
        ret = btrfs_free_extent(trans, root, path->nodes[*level]->bytenr,
                                btrfs_level_size(root, *level),
@@ -864,7 +963,7 @@ static int walk_up_tree(struct btrfs_tra
        int ret;
        u64 root_owner;
        u64 root_gen;
-       struct btrfs_buffer *parent;
+       struct btrfs_node *node;
        for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) {
                slot = path->slots[i];
                if (slot <
@@ -873,14 +972,14 @@ static int walk_up_tree(struct btrfs_tra
                        *level = i;
                        return 0;
                } else {
-                       if (path->nodes[*level] == root->node)
-                               parent = path->nodes[*level];
-                       else
-                               parent = path->nodes[*level + 1];
-
-                       root_owner = btrfs_header_owner(&parent->node.header);
-                       root_gen =
-                               btrfs_header_generation(&parent->node.header);
+                       if (path->nodes[*level] == root->commit_root) {
+                               node = &path->nodes[*level]->node;
+                               root_owner = root->root_key.objectid;
+                       } else {
+                               node = &path->nodes[*level + 1]->node;
+                               root_owner = btrfs_header_owner(&node->header);
+                       }
+                       root_gen = btrfs_header_generation(&node->header);
                        ret = btrfs_free_extent(trans, root,
                                        path->nodes[*level]->bytenr,
                                        btrfs_level_size(root, *level),
diff -r a1a37f51dcb2 inode-item.c
--- a/inode-item.c      Fri Dec 14 11:00:30 2007 -0500
+++ b/inode-item.c      Wed Dec 19 19:52:02 2007 +0800
@@ -24,6 +24,35 @@
 #include "disk-io.h"
 #include "transaction.h"

+int find_name_in_backref(struct btrfs_path *path, const char * name,
+                        int name_len, struct btrfs_inode_ref **ref_ret)
+{
+       struct btrfs_leaf *leaf;
+       struct btrfs_inode_ref *ref;
+       char *ptr;
+       char *name_ptr;
+       u32 item_size;
+       u32 cur_offset = 0;
+       int len;
+
+       leaf = &path->nodes[0]->leaf;
+       item_size = btrfs_item_size(leaf->items + path->slots[0]);
+       ptr = btrfs_item_ptr(leaf, path->slots[0], char);
+       while (cur_offset < item_size) {
+               ref = (struct btrfs_inode_ref *)(ptr + cur_offset);
+               len = btrfs_inode_ref_name_len(ref);
+               name_ptr = (char *)(ref + 1);
+               cur_offset += len + sizeof(*ref);
+               if (len != name_len)
+                       continue;
+               if (memcmp(name, name_ptr, name_len) == 0) {
+                       *ref_ret = ref;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
 int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root,
                           const char *name, int name_len,
@@ -31,6 +60,7 @@ int btrfs_insert_inode_ref(struct btrfs_
 {
        struct btrfs_path path;
        struct btrfs_key key;
+       struct btrfs_leaf *leaf;
        struct btrfs_inode_ref *ref;
        char *ptr;
        int ret;
@@ -44,23 +74,21 @@ int btrfs_insert_inode_ref(struct btrfs_
        ret = btrfs_insert_empty_item(trans, root, &path, &key,
                                      ins_len);
        if (ret == -EEXIST) {
-#if 0
                u32 old_size;

-               if (find_name_in_backref(path, name, name_len, &ref))
+               if (find_name_in_backref(&path, name, name_len, &ref))
                        goto out;

-               old_size = btrfs_item_size_nr(path->nodes[0], path->slots[0]);
-               ret = btrfs_extend_item(trans, root, path, ins_len);
+               leaf = &path.nodes[0]->leaf;
+               old_size = btrfs_item_size(leaf->items + path.slots[0]);
+               ret = btrfs_extend_item(trans, root, &path, ins_len);
                BUG_ON(ret);
-               ref = btrfs_item_ptr(path->nodes[0], path->slots[0],
+               ref = btrfs_item_ptr(leaf, path.slots[0],
                                     struct btrfs_inode_ref);
                ref = (struct btrfs_inode_ref *)((unsigned long)ref + old_size);
-               btrfs_set_inode_ref_name_len(path->nodes[0], ref, name_len);
-               ptr = (unsigned long)(ref + 1);
+               btrfs_set_inode_ref_name_len(ref, name_len);
+               ptr = (char *)(ref + 1);
                ret = 0;
-#endif
-               goto out;
        } else if (ret < 0) {
                goto out;
        } else {
@@ -70,8 +98,7 @@ int btrfs_insert_inode_ref(struct btrfs_
                ptr = (char *)(ref + 1);
        }
        memcpy(ptr, name, name_len);
-       dirty_tree_block(trans, root, path.nodes[0]);
-
+       BUG_ON(list_empty(&path.nodes[0]->dirty));
 out:
        btrfs_release_path(root, &path);
        return ret;

_______________________________________________
Btrfs-devel mailing list
[email protected]
http://oss.oracle.com/mailman/listinfo/btrfs-devel

Reply via email to