btrfs-progs: update generation_v2 in btrfs_update_root
authorEric Sandeen <sandeen@redhat.com>
Mon, 22 Apr 2013 05:16:41 +0000 (00:16 -0500)
committerDavid Sterba <dsterba@suse.cz>
Tue, 23 Apr 2013 16:56:28 +0000 (18:56 +0200)
This addresses the same issue as did:

2bd1169 btrfs-progs: root_item generation_v2 is out of sync after btrfsck

but rather than optionally updating generation_v2 based
on the size of the existing item, increase the size of the
item as needed, and unconditionally set generation_v2.
This matches the kernel code, and keeping things in sync is a
Good Thing.

Signed-off-by: Eric Sandeen <sandeen@redhat.com>
root-tree.c

index ef2190f..ba380bd 100644 (file)
@@ -69,6 +69,7 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
        int ret;
        int slot;
        unsigned long ptr;
+       u32 old_len;
 
        path = btrfs_alloc_path();
        BUG_ON(!path);
@@ -79,6 +80,42 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
        l = path->nodes[0];
        slot = path->slots[0];
        ptr = btrfs_item_ptr_offset(l, slot);
+       old_len = btrfs_item_size_nr(l, slot);
+
+       /*
+        * If this is the first time we update the root item which originated
+        * from an older kernel, we need to enlarge the item size to make room
+        * for the added fields.
+        */
+       if (old_len < sizeof(*item)) {
+               btrfs_release_path(root, path);
+               ret = btrfs_search_slot(trans, root, key, path,
+                               -1, 1);
+               if (ret < 0) {
+                       goto out;
+               }
+
+               ret = btrfs_del_item(trans, root, path);
+               if (ret < 0) {
+                       goto out;
+               }
+               btrfs_release_path(root, path);
+               ret = btrfs_insert_empty_item(trans, root, path,
+                               key, sizeof(*item));
+               if (ret < 0) {
+                       goto out;
+               }
+               l = path->nodes[0];
+               slot = path->slots[0];
+               ptr = btrfs_item_ptr_offset(l, slot);
+       }
+
+       /*
+        * Update generation_v2 so at the next mount we know the new root
+        * fields are valid.
+        */
+       btrfs_set_root_generation_v2(item, btrfs_root_generation(item));
+
        write_extent_buffer(l, item, ptr, sizeof(*item));
        btrfs_mark_buffer_dirty(path->nodes[0]);
 out: