Btrfs: patch queue: fix corruption when splitting large items
authorChris Mason <chris.mason@oracle.com>
Fri, 11 May 2007 15:33:21 +0000 (11:33 -0400)
committerDavid Woodhouse <dwmw2@hera.kernel.org>
Fri, 11 May 2007 15:33:21 +0000 (11:33 -0400)
Signed-off-by: Chris Mason <chris.mason@oracle.com>
fs/btrfs/ctree.c
fs/btrfs/super.c

index 990d297..20e01f9 100644 (file)
@@ -871,6 +871,7 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
        btrfs_set_node_blockptr(lower, slot, blocknr);
        btrfs_set_header_nritems(&lower->header, nritems + 1);
        btrfs_mark_buffer_dirty(path->nodes[level]);
+       check_node(root, path, level);
        return 0;
 }
 
@@ -1101,6 +1102,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
        } else {
                btrfs_block_release(root, right_buf);
        }
+       if (path->nodes[1])
+               check_node(root, path, 1);
        return 0;
 }
 /*
@@ -1216,6 +1219,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
 
        btrfs_mark_buffer_dirty(t);
        btrfs_mark_buffer_dirty(right_buf);
+
        wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1);
        if (wret)
                ret = wret;
@@ -1231,6 +1235,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
                path->slots[0] -= push_items;
        }
        BUG_ON(path->slots[0] < 0);
+       if (path->nodes[1])
+               check_node(root, path, 1);
        return ret;
 }
 
@@ -1326,13 +1332,12 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
                                wret = insert_ptr(trans, root, path,
                                                  &disk_key,
                                                  bh_blocknr(right_buffer),
-                                                 path->slots[1] - 1, 1);
+                                                 path->slots[1], 1);
                                if (wret)
                                        ret = wret;
                                btrfs_block_release(root, path->nodes[0]);
                                path->nodes[0] = right_buffer;
                                path->slots[0] = 0;
-                               path->slots[1] -= 1;
                                if (path->slots[1] == 0) {
                                        wret = fixup_low_keys(trans, root,
                                                   path, &disk_key, 1);
@@ -1379,6 +1384,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
        } else
                btrfs_block_release(root, right_buffer);
        BUG_ON(path->slots[0] < 0);
+       check_node(root, path, 1);
 
        if (!double_split)
                return ret;
index 4c2870e..eaa48f0 100644 (file)
@@ -1529,7 +1529,8 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
                        btrfs_set_file_extent_type(ei,
                                                   BTRFS_FILE_EXTENT_INLINE);
                        ptr = btrfs_file_extent_inline_start(ei);
-                       memcpy(ptr, bh->b_data, offset + write_bytes);
+                       btrfs_memcpy(root, path->nodes[0]->b_data,
+                                    ptr, bh->b_data, offset + write_bytes);
                        mark_buffer_dirty(path->nodes[0]);
                        btrfs_free_path(path);
                } else {
@@ -1686,9 +1687,9 @@ static int drop_extents(struct btrfs_trans_handle *trans,
                        ret = btrfs_del_item(trans, root, path);
                        BUG_ON(ret);
                        btrfs_release_path(root, path);
+                       extent = NULL;
                        if (found_extent) {
-                               inode->i_blocks -=
-                               btrfs_file_extent_num_blocks(extent) << 3;
+                               inode->i_blocks -= extent_num_blocks << 3;
                                ret = btrfs_free_extent(trans, root,
                                                        disk_blocknr,
                                                        disk_num_blocks, 0);
@@ -1832,7 +1833,6 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
        u64 alloc_extent_start;
        struct btrfs_trans_handle *trans;
        struct btrfs_key ins;
-
        pinned[0] = NULL;
        pinned[1] = NULL;
        if (file->f_flags & O_DIRECT)