Loading fs/btrfs/ctree.c +20 −18 Original line number Diff line number Diff line Loading @@ -2514,34 +2514,36 @@ static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, * delete the item at the leaf level in path. If that empties * the leaf, remove it from the tree */ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path) int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int slot, int nr) { int slot; struct extent_buffer *leaf; struct btrfs_item *item; int doff; int dsize; int last_off; int dsize = 0; int ret = 0; int wret; int i; u32 nritems; leaf = path->nodes[0]; slot = path->slots[0]; doff = btrfs_item_offset_nr(leaf, slot); dsize = btrfs_item_size_nr(leaf, slot); last_off = btrfs_item_offset_nr(leaf, slot + nr - 1); for (i = 0; i < nr; i++) dsize += btrfs_item_size_nr(leaf, slot + i); nritems = btrfs_header_nritems(leaf); if (slot != nritems - 1) { if (slot + nr != nritems) { int i; int data_end = leaf_data_end(root, leaf); memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) + data_end + dsize, btrfs_leaf_data(leaf) + data_end, doff - data_end); last_off - data_end); for (i = slot + 1; i < nritems; i++) { for (i = slot + nr; i < nritems; i++) { u32 ioff; item = btrfs_item_nr(leaf, i); Loading @@ -2562,12 +2564,12 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, } memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot), btrfs_item_nr_offset(slot + 1), btrfs_item_nr_offset(slot + nr), sizeof(struct btrfs_item) * (nritems - slot - 1)); (nritems - slot - nr)); } btrfs_set_header_nritems(leaf, nritems - 1); nritems--; btrfs_set_header_nritems(leaf, nritems - nr); nritems -= nr; /* delete the leaf if we've emptied it */ if (nritems == 0) { Loading Loading @@ -2600,7 +2602,7 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, } /* delete the leaf if it is mostly empty */ if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) { if (used < BTRFS_LEAF_DATA_SIZE(root) / 4) { /* push_leaf_left fixes the path. * make sure the path still points to our leaf * for possible call to del_ptr below Loading @@ -2608,13 +2610,13 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, slot = path->slots[1]; extent_buffer_get(leaf); wret = push_leaf_right(trans, root, path, 1, 1); wret = push_leaf_left(trans, root, path, 1, 1); if (wret < 0 && wret != -ENOSPC) ret = wret; if (path->nodes[0] == leaf && btrfs_header_nritems(leaf)) { wret = push_leaf_left(trans, root, path, 1, 1); wret = push_leaf_right(trans, root, path, 1, 1); if (wret < 0 && wret != -ENOSPC) ret = wret; } Loading fs/btrfs/ctree.h +10 −2 Original line number Diff line number Diff line Loading @@ -1038,8 +1038,16 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p); struct btrfs_path *btrfs_alloc_path(void); void btrfs_free_path(struct btrfs_path *p); void btrfs_init_path(struct btrfs_path *p); int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path); int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int slot, int nr); static inline int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path) { return btrfs_del_items(trans, root, path, path->slots[0], 1); } int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *key, void *data, u32 data_size); int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root Loading fs/btrfs/extent_io.c +0 −1 Original line number Diff line number Diff line Loading @@ -2863,7 +2863,6 @@ int read_extent_buffer_pages(struct extent_io_tree *tree, if (ret || !wait) { return ret; } for (i = start_i; i < num_pages; i++) { page = extent_buffer_page(eb, i); wait_on_page_locked(page); Loading fs/btrfs/inode.c +65 −49 Original line number Diff line number Diff line Loading @@ -692,27 +692,6 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) return err; } static int btrfs_free_inode(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct inode *inode) { struct btrfs_path *path; int ret; clear_inode(inode); path = btrfs_alloc_path(); BUG_ON(!path); ret = btrfs_lookup_inode(trans, root, path, &BTRFS_I(inode)->location, -1); if (ret > 0) ret = -ENOENT; if (!ret) ret = btrfs_del_item(trans, root, path); btrfs_free_path(path); return ret; } /* * this can truncate away extent items, csum items and directory items. * It starts at a high offset and removes keys until it can't find Loading @@ -723,7 +702,8 @@ static int btrfs_free_inode(struct btrfs_trans_handle *trans, */ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct inode *inode) struct inode *inode, u32 min_type) { int ret; struct btrfs_path *path; Loading @@ -739,6 +719,8 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, u64 root_owner = 0; int found_extent; int del_item; int pending_del_nr = 0; int pending_del_slot = 0; int extent_type = -1; btrfs_drop_extent_cache(inode, inode->i_size, (u64)-1); Loading @@ -751,9 +733,8 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, key.offset = (u64)-1; key.type = (u8)-1; while(1) { btrfs_init_path(path); fi = NULL; search_again: ret = btrfs_search_slot(trans, root, &key, path, -1, 1); if (ret < 0) { goto error; Loading @@ -762,6 +743,9 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, BUG_ON(path->slots[0] == 0); path->slots[0]--; } while(1) { fi = NULL; leaf = path->nodes[0]; btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); found_type = btrfs_key_type(&found_key); Loading @@ -769,10 +753,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, if (found_key.objectid != inode->i_ino) break; if (found_type != BTRFS_CSUM_ITEM_KEY && found_type != BTRFS_DIR_ITEM_KEY && found_type != BTRFS_DIR_INDEX_KEY && found_type != BTRFS_EXTENT_DATA_KEY) if (found_type < min_type) break; item_end = found_key.offset; Loading Loading @@ -801,14 +782,17 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, found_type = BTRFS_INODE_ITEM_KEY; } else if (found_type == BTRFS_EXTENT_ITEM_KEY) { found_type = BTRFS_CSUM_ITEM_KEY; } else if (found_type == BTRFS_EXTENT_DATA_KEY) { found_type = BTRFS_XATTR_ITEM_KEY; } else if (found_type == BTRFS_XATTR_ITEM_KEY) { found_type = BTRFS_INODE_REF_KEY; } else if (found_type) { found_type--; } else { break; } btrfs_set_key_type(&key, found_type); btrfs_release_path(root, path); continue; goto next; } if (found_key.offset >= inode->i_size) del_item = 1; Loading Loading @@ -860,13 +844,21 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, } delete: if (del_item) { ret = btrfs_del_item(trans, root, path); if (ret) goto error; if (!pending_del_nr) { /* no pending yet, add ourselves */ pending_del_slot = path->slots[0]; pending_del_nr = 1; } else if (pending_del_nr && path->slots[0] + 1 == pending_del_slot) { /* hop on the pending chunk */ pending_del_nr++; pending_del_slot = path->slots[0]; } else { printk("bad pending slot %d pending_del_nr %d pending_del_slot %d\n", path->slots[0], pending_del_nr, pending_del_slot); } } else { break; } btrfs_release_path(root, path); if (found_extent) { ret = btrfs_free_extent(trans, root, extent_start, extent_num_bytes, Loading @@ -875,9 +867,36 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, found_key.offset, 0); BUG_ON(ret); } next: if (path->slots[0] == 0) { if (pending_del_nr) goto del_pending; btrfs_release_path(root, path); goto search_again; } path->slots[0]--; if (pending_del_nr && path->slots[0] + 1 != pending_del_slot) { struct btrfs_key debug; del_pending: btrfs_item_key_to_cpu(path->nodes[0], &debug, pending_del_slot); ret = btrfs_del_items(trans, root, path, pending_del_slot, pending_del_nr); BUG_ON(ret); pending_del_nr = 0; btrfs_release_path(root, path); goto search_again; } } ret = 0; error: if (pending_del_nr) { ret = btrfs_del_items(trans, root, path, pending_del_slot, pending_del_nr); } btrfs_release_path(root, path); btrfs_free_path(path); inode->i_sb->s_dirt = 1; Loading Loading @@ -1067,16 +1086,12 @@ void btrfs_delete_inode(struct inode *inode) trans = btrfs_start_transaction(root, 1); btrfs_set_trans_block_group(trans, inode); ret = btrfs_truncate_in_trans(trans, root, inode); if (ret) goto no_delete_lock; ret = btrfs_delete_xattrs(trans, root, inode); if (ret) goto no_delete_lock; ret = btrfs_free_inode(trans, root, inode); ret = btrfs_truncate_in_trans(trans, root, inode, 0); if (ret) goto no_delete_lock; nr = trans->blocks_used; clear_inode(inode); btrfs_end_transaction(trans, root); mutex_unlock(&root->fs_info->fs_mutex); Loading Loading @@ -2190,7 +2205,8 @@ static void btrfs_truncate(struct inode *inode) btrfs_set_trans_block_group(trans, inode); /* FIXME, add redo link to tree so we don't leak on crash */ ret = btrfs_truncate_in_trans(trans, root, inode); ret = btrfs_truncate_in_trans(trans, root, inode, BTRFS_EXTENT_DATA_KEY); btrfs_update_inode(trans, root, inode); nr = trans->blocks_used; Loading Loading
fs/btrfs/ctree.c +20 −18 Original line number Diff line number Diff line Loading @@ -2514,34 +2514,36 @@ static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, * delete the item at the leaf level in path. If that empties * the leaf, remove it from the tree */ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path) int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int slot, int nr) { int slot; struct extent_buffer *leaf; struct btrfs_item *item; int doff; int dsize; int last_off; int dsize = 0; int ret = 0; int wret; int i; u32 nritems; leaf = path->nodes[0]; slot = path->slots[0]; doff = btrfs_item_offset_nr(leaf, slot); dsize = btrfs_item_size_nr(leaf, slot); last_off = btrfs_item_offset_nr(leaf, slot + nr - 1); for (i = 0; i < nr; i++) dsize += btrfs_item_size_nr(leaf, slot + i); nritems = btrfs_header_nritems(leaf); if (slot != nritems - 1) { if (slot + nr != nritems) { int i; int data_end = leaf_data_end(root, leaf); memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) + data_end + dsize, btrfs_leaf_data(leaf) + data_end, doff - data_end); last_off - data_end); for (i = slot + 1; i < nritems; i++) { for (i = slot + nr; i < nritems; i++) { u32 ioff; item = btrfs_item_nr(leaf, i); Loading @@ -2562,12 +2564,12 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, } memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot), btrfs_item_nr_offset(slot + 1), btrfs_item_nr_offset(slot + nr), sizeof(struct btrfs_item) * (nritems - slot - 1)); (nritems - slot - nr)); } btrfs_set_header_nritems(leaf, nritems - 1); nritems--; btrfs_set_header_nritems(leaf, nritems - nr); nritems -= nr; /* delete the leaf if we've emptied it */ if (nritems == 0) { Loading Loading @@ -2600,7 +2602,7 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, } /* delete the leaf if it is mostly empty */ if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) { if (used < BTRFS_LEAF_DATA_SIZE(root) / 4) { /* push_leaf_left fixes the path. * make sure the path still points to our leaf * for possible call to del_ptr below Loading @@ -2608,13 +2610,13 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, slot = path->slots[1]; extent_buffer_get(leaf); wret = push_leaf_right(trans, root, path, 1, 1); wret = push_leaf_left(trans, root, path, 1, 1); if (wret < 0 && wret != -ENOSPC) ret = wret; if (path->nodes[0] == leaf && btrfs_header_nritems(leaf)) { wret = push_leaf_left(trans, root, path, 1, 1); wret = push_leaf_right(trans, root, path, 1, 1); if (wret < 0 && wret != -ENOSPC) ret = wret; } Loading
fs/btrfs/ctree.h +10 −2 Original line number Diff line number Diff line Loading @@ -1038,8 +1038,16 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p); struct btrfs_path *btrfs_alloc_path(void); void btrfs_free_path(struct btrfs_path *p); void btrfs_init_path(struct btrfs_path *p); int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path); int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int slot, int nr); static inline int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path) { return btrfs_del_items(trans, root, path, path->slots[0], 1); } int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *key, void *data, u32 data_size); int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root Loading
fs/btrfs/extent_io.c +0 −1 Original line number Diff line number Diff line Loading @@ -2863,7 +2863,6 @@ int read_extent_buffer_pages(struct extent_io_tree *tree, if (ret || !wait) { return ret; } for (i = start_i; i < num_pages; i++) { page = extent_buffer_page(eb, i); wait_on_page_locked(page); Loading
fs/btrfs/inode.c +65 −49 Original line number Diff line number Diff line Loading @@ -692,27 +692,6 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) return err; } static int btrfs_free_inode(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct inode *inode) { struct btrfs_path *path; int ret; clear_inode(inode); path = btrfs_alloc_path(); BUG_ON(!path); ret = btrfs_lookup_inode(trans, root, path, &BTRFS_I(inode)->location, -1); if (ret > 0) ret = -ENOENT; if (!ret) ret = btrfs_del_item(trans, root, path); btrfs_free_path(path); return ret; } /* * this can truncate away extent items, csum items and directory items. * It starts at a high offset and removes keys until it can't find Loading @@ -723,7 +702,8 @@ static int btrfs_free_inode(struct btrfs_trans_handle *trans, */ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct inode *inode) struct inode *inode, u32 min_type) { int ret; struct btrfs_path *path; Loading @@ -739,6 +719,8 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, u64 root_owner = 0; int found_extent; int del_item; int pending_del_nr = 0; int pending_del_slot = 0; int extent_type = -1; btrfs_drop_extent_cache(inode, inode->i_size, (u64)-1); Loading @@ -751,9 +733,8 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, key.offset = (u64)-1; key.type = (u8)-1; while(1) { btrfs_init_path(path); fi = NULL; search_again: ret = btrfs_search_slot(trans, root, &key, path, -1, 1); if (ret < 0) { goto error; Loading @@ -762,6 +743,9 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, BUG_ON(path->slots[0] == 0); path->slots[0]--; } while(1) { fi = NULL; leaf = path->nodes[0]; btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); found_type = btrfs_key_type(&found_key); Loading @@ -769,10 +753,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, if (found_key.objectid != inode->i_ino) break; if (found_type != BTRFS_CSUM_ITEM_KEY && found_type != BTRFS_DIR_ITEM_KEY && found_type != BTRFS_DIR_INDEX_KEY && found_type != BTRFS_EXTENT_DATA_KEY) if (found_type < min_type) break; item_end = found_key.offset; Loading Loading @@ -801,14 +782,17 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, found_type = BTRFS_INODE_ITEM_KEY; } else if (found_type == BTRFS_EXTENT_ITEM_KEY) { found_type = BTRFS_CSUM_ITEM_KEY; } else if (found_type == BTRFS_EXTENT_DATA_KEY) { found_type = BTRFS_XATTR_ITEM_KEY; } else if (found_type == BTRFS_XATTR_ITEM_KEY) { found_type = BTRFS_INODE_REF_KEY; } else if (found_type) { found_type--; } else { break; } btrfs_set_key_type(&key, found_type); btrfs_release_path(root, path); continue; goto next; } if (found_key.offset >= inode->i_size) del_item = 1; Loading Loading @@ -860,13 +844,21 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, } delete: if (del_item) { ret = btrfs_del_item(trans, root, path); if (ret) goto error; if (!pending_del_nr) { /* no pending yet, add ourselves */ pending_del_slot = path->slots[0]; pending_del_nr = 1; } else if (pending_del_nr && path->slots[0] + 1 == pending_del_slot) { /* hop on the pending chunk */ pending_del_nr++; pending_del_slot = path->slots[0]; } else { printk("bad pending slot %d pending_del_nr %d pending_del_slot %d\n", path->slots[0], pending_del_nr, pending_del_slot); } } else { break; } btrfs_release_path(root, path); if (found_extent) { ret = btrfs_free_extent(trans, root, extent_start, extent_num_bytes, Loading @@ -875,9 +867,36 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, found_key.offset, 0); BUG_ON(ret); } next: if (path->slots[0] == 0) { if (pending_del_nr) goto del_pending; btrfs_release_path(root, path); goto search_again; } path->slots[0]--; if (pending_del_nr && path->slots[0] + 1 != pending_del_slot) { struct btrfs_key debug; del_pending: btrfs_item_key_to_cpu(path->nodes[0], &debug, pending_del_slot); ret = btrfs_del_items(trans, root, path, pending_del_slot, pending_del_nr); BUG_ON(ret); pending_del_nr = 0; btrfs_release_path(root, path); goto search_again; } } ret = 0; error: if (pending_del_nr) { ret = btrfs_del_items(trans, root, path, pending_del_slot, pending_del_nr); } btrfs_release_path(root, path); btrfs_free_path(path); inode->i_sb->s_dirt = 1; Loading Loading @@ -1067,16 +1086,12 @@ void btrfs_delete_inode(struct inode *inode) trans = btrfs_start_transaction(root, 1); btrfs_set_trans_block_group(trans, inode); ret = btrfs_truncate_in_trans(trans, root, inode); if (ret) goto no_delete_lock; ret = btrfs_delete_xattrs(trans, root, inode); if (ret) goto no_delete_lock; ret = btrfs_free_inode(trans, root, inode); ret = btrfs_truncate_in_trans(trans, root, inode, 0); if (ret) goto no_delete_lock; nr = trans->blocks_used; clear_inode(inode); btrfs_end_transaction(trans, root); mutex_unlock(&root->fs_info->fs_mutex); Loading Loading @@ -2190,7 +2205,8 @@ static void btrfs_truncate(struct inode *inode) btrfs_set_trans_block_group(trans, inode); /* FIXME, add redo link to tree so we don't leak on crash */ ret = btrfs_truncate_in_trans(trans, root, inode); ret = btrfs_truncate_in_trans(trans, root, inode, BTRFS_EXTENT_DATA_KEY); btrfs_update_inode(trans, root, inode); nr = trans->blocks_used; Loading