Loading fs/btrfs/acl.c +13 −10 Original line number Diff line number Diff line Loading @@ -94,7 +94,8 @@ static int btrfs_xattr_acl_get(struct dentry *dentry, const char *name, /* * Needs to be called with fs_mutex held */ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) static int btrfs_set_acl(struct btrfs_trans_handle *trans, struct inode *inode, struct posix_acl *acl, int type) { int ret, size = 0; const char *name; Loading Loading @@ -140,8 +141,7 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) goto out; } ret = __btrfs_setxattr(inode, name, value, size, 0); ret = __btrfs_setxattr(trans, inode, name, value, size, 0); out: kfree(value); Loading @@ -154,7 +154,7 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) { int ret = 0; int ret; struct posix_acl *acl = NULL; if (value) { Loading @@ -167,7 +167,7 @@ static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name, } } ret = btrfs_set_acl(dentry->d_inode, acl, type); ret = btrfs_set_acl(NULL, dentry->d_inode, acl, type); posix_acl_release(acl); Loading Loading @@ -196,7 +196,8 @@ int btrfs_check_acl(struct inode *inode, int mask) * stuff has been fixed to work with that. If the locking stuff changes, we * need to re-evaluate the acl locking stuff. */ int btrfs_init_acl(struct inode *inode, struct inode *dir) int btrfs_init_acl(struct btrfs_trans_handle *trans, struct inode *inode, struct inode *dir) { struct posix_acl *acl = NULL; int ret = 0; Loading @@ -221,7 +222,8 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir) mode_t mode; if (S_ISDIR(inode->i_mode)) { ret = btrfs_set_acl(inode, acl, ACL_TYPE_DEFAULT); ret = btrfs_set_acl(trans, inode, acl, ACL_TYPE_DEFAULT); if (ret) goto failed; } Loading @@ -236,7 +238,7 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir) inode->i_mode = mode; if (ret > 0) { /* we need an acl */ ret = btrfs_set_acl(inode, clone, ret = btrfs_set_acl(trans, inode, clone, ACL_TYPE_ACCESS); } } Loading Loading @@ -269,7 +271,7 @@ int btrfs_acl_chmod(struct inode *inode) ret = posix_acl_chmod_masq(clone, inode->i_mode); if (!ret) ret = btrfs_set_acl(inode, clone, ACL_TYPE_ACCESS); ret = btrfs_set_acl(NULL, inode, clone, ACL_TYPE_ACCESS); posix_acl_release(clone); Loading Loading @@ -297,7 +299,8 @@ int btrfs_acl_chmod(struct inode *inode) return 0; } int btrfs_init_acl(struct inode *inode, struct inode *dir) int btrfs_init_acl(struct btrfs_trans_handle *trans, struct inode *inode, struct inode *dir) { return 0; } Loading fs/btrfs/btrfs_inode.h +1 −4 Original line number Diff line number Diff line Loading @@ -44,9 +44,6 @@ struct btrfs_inode { */ struct extent_io_tree io_failure_tree; /* held while inesrting or deleting extents from files */ struct mutex extent_mutex; /* held while logging the inode in tree-log.c */ struct mutex log_mutex; Loading Loading @@ -166,7 +163,7 @@ static inline struct btrfs_inode *BTRFS_I(struct inode *inode) static inline void btrfs_i_size_write(struct inode *inode, u64 size) { inode->i_size = size; i_size_write(inode, size); BTRFS_I(inode)->disk_i_size = size; } Loading fs/btrfs/ctree.c +153 −76 Original line number Diff line number Diff line Loading @@ -37,6 +37,11 @@ static int balance_node_right(struct btrfs_trans_handle *trans, struct extent_buffer *src_buf); static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int level, int slot); static int setup_items_for_insert(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *cpu_key, u32 *data_size, u32 total_data, u32 total_size, int nr); struct btrfs_path *btrfs_alloc_path(void) { Loading Loading @@ -451,9 +456,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, extent_buffer_get(cow); spin_unlock(&root->node_lock); btrfs_free_extent(trans, root, buf->start, buf->len, parent_start, root->root_key.objectid, level, 0); btrfs_free_tree_block(trans, root, buf->start, buf->len, parent_start, root->root_key.objectid, level); free_extent_buffer(buf); add_root_to_dirty_list(root); } else { Loading @@ -468,9 +472,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, btrfs_set_node_ptr_generation(parent, parent_slot, trans->transid); btrfs_mark_buffer_dirty(parent); btrfs_free_extent(trans, root, buf->start, buf->len, parent_start, root->root_key.objectid, level, 0); btrfs_free_tree_block(trans, root, buf->start, buf->len, parent_start, root->root_key.objectid, level); } if (unlock_orig) btrfs_tree_unlock(buf); Loading Loading @@ -1030,8 +1033,8 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, btrfs_tree_unlock(mid); /* once for the path */ free_extent_buffer(mid); ret = btrfs_free_extent(trans, root, mid->start, mid->len, 0, root->root_key.objectid, level, 1); ret = btrfs_free_tree_block(trans, root, mid->start, mid->len, 0, root->root_key.objectid, level); /* once for the root ptr */ free_extent_buffer(mid); return ret; Loading Loading @@ -1095,10 +1098,10 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, 1); if (wret) ret = wret; wret = btrfs_free_extent(trans, root, bytenr, blocksize, 0, wret = btrfs_free_tree_block(trans, root, bytenr, blocksize, 0, root->root_key.objectid, level, 0); level); if (wret) ret = wret; } else { Loading Loading @@ -1143,9 +1146,8 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, wret = del_ptr(trans, root, path, level + 1, pslot); if (wret) ret = wret; wret = btrfs_free_extent(trans, root, bytenr, blocksize, 0, root->root_key.objectid, level, 0); wret = btrfs_free_tree_block(trans, root, bytenr, blocksize, 0, root->root_key.objectid, level); if (wret) ret = wret; } else { Loading Loading @@ -2997,75 +2999,85 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, return ret; } /* * This function splits a single item into two items, * giving 'new_key' to the new item and splitting the * old one at split_offset (from the start of the item). * * The path may be released by this operation. After * the split, the path is pointing to the old item. The * new item is going to be in the same node as the old one. * * Note, the item being split must be smaller enough to live alone on * a tree block with room for one extra struct btrfs_item * * This allows us to split the item in place, keeping a lock on the * leaf the entire time. */ int btrfs_split_item(struct btrfs_trans_handle *trans, static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *new_key, unsigned long split_offset) struct btrfs_path *path, int ins_len) { u32 item_size; struct btrfs_key key; struct extent_buffer *leaf; struct btrfs_key orig_key; struct btrfs_item *item; struct btrfs_item *new_item; int ret = 0; int slot; u32 nritems; u32 orig_offset; struct btrfs_disk_key disk_key; char *buf; struct btrfs_file_extent_item *fi; u64 extent_len = 0; u32 item_size; int ret; leaf = path->nodes[0]; btrfs_item_key_to_cpu(leaf, &orig_key, path->slots[0]); if (btrfs_leaf_free_space(root, leaf) >= sizeof(struct btrfs_item)) goto split; btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); BUG_ON(key.type != BTRFS_EXTENT_DATA_KEY && key.type != BTRFS_EXTENT_CSUM_KEY); if (btrfs_leaf_free_space(root, leaf) >= ins_len) return 0; item_size = btrfs_item_size_nr(leaf, path->slots[0]); if (key.type == BTRFS_EXTENT_DATA_KEY) { fi = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item); extent_len = btrfs_file_extent_num_bytes(leaf, fi); } btrfs_release_path(root, path); path->search_for_split = 1; path->keep_locks = 1; ret = btrfs_search_slot(trans, root, &orig_key, path, 0, 1); path->search_for_split = 1; ret = btrfs_search_slot(trans, root, &key, path, 0, 1); path->search_for_split = 0; if (ret < 0) goto err; ret = -EAGAIN; leaf = path->nodes[0]; /* if our item isn't there or got smaller, return now */ if (ret != 0 || item_size != btrfs_item_size_nr(path->nodes[0], path->slots[0])) { path->keep_locks = 0; return -EAGAIN; if (ret > 0 || item_size != btrfs_item_size_nr(leaf, path->slots[0])) goto err; if (key.type == BTRFS_EXTENT_DATA_KEY) { fi = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item); if (extent_len != btrfs_file_extent_num_bytes(leaf, fi)) goto err; } btrfs_set_path_blocking(path); ret = split_leaf(trans, root, &orig_key, path, sizeof(struct btrfs_item), 1); path->keep_locks = 0; ret = split_leaf(trans, root, &key, path, ins_len, 1); BUG_ON(ret); path->keep_locks = 0; btrfs_unlock_up_safe(path, 1); return 0; err: path->keep_locks = 0; return ret; } static noinline int split_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *new_key, unsigned long split_offset) { struct extent_buffer *leaf; struct btrfs_item *item; struct btrfs_item *new_item; int slot; char *buf; u32 nritems; u32 item_size; u32 orig_offset; struct btrfs_disk_key disk_key; leaf = path->nodes[0]; BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item)); split: /* * make sure any changes to the path from split_leaf leave it * in a blocking state */ btrfs_set_path_blocking(path); item = btrfs_item_nr(leaf, path->slots[0]); Loading @@ -3073,19 +3085,19 @@ int btrfs_split_item(struct btrfs_trans_handle *trans, item_size = btrfs_item_size(leaf, item); buf = kmalloc(item_size, GFP_NOFS); if (!buf) return -ENOMEM; read_extent_buffer(leaf, buf, btrfs_item_ptr_offset(leaf, path->slots[0]), item_size); slot = path->slots[0] + 1; leaf = path->nodes[0]; slot = path->slots[0] + 1; nritems = btrfs_header_nritems(leaf); if (slot != nritems) { /* shift the items */ memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + 1), btrfs_item_nr_offset(slot), (nritems - slot) * sizeof(struct btrfs_item)); } btrfs_cpu_key_to_disk(&disk_key, new_key); Loading Loading @@ -3113,15 +3125,80 @@ int btrfs_split_item(struct btrfs_trans_handle *trans, item_size - split_offset); btrfs_mark_buffer_dirty(leaf); ret = 0; if (btrfs_leaf_free_space(root, leaf) < 0) { btrfs_print_leaf(root, leaf); BUG(); } BUG_ON(btrfs_leaf_free_space(root, leaf) < 0); kfree(buf); return 0; } /* * This function splits a single item into two items, * giving 'new_key' to the new item and splitting the * old one at split_offset (from the start of the item). * * The path may be released by this operation. After * the split, the path is pointing to the old item. The * new item is going to be in the same node as the old one. * * Note, the item being split must be smaller enough to live alone on * a tree block with room for one extra struct btrfs_item * * This allows us to split the item in place, keeping a lock on the * leaf the entire time. */ int btrfs_split_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *new_key, unsigned long split_offset) { int ret; ret = setup_leaf_for_split(trans, root, path, sizeof(struct btrfs_item)); if (ret) return ret; ret = split_item(trans, root, path, new_key, split_offset); return ret; } /* * This function duplicate a item, giving 'new_key' to the new item. * It guarantees both items live in the same tree leaf and the new item * is contiguous with the original item. * * This allows us to split file extent in place, keeping a lock on the * leaf the entire time. */ int btrfs_duplicate_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *new_key) { struct extent_buffer *leaf; int ret; u32 item_size; leaf = path->nodes[0]; item_size = btrfs_item_size_nr(leaf, path->slots[0]); ret = setup_leaf_for_split(trans, root, path, item_size + sizeof(struct btrfs_item)); if (ret) return ret; path->slots[0]++; ret = setup_items_for_insert(trans, root, path, new_key, &item_size, item_size, item_size + sizeof(struct btrfs_item), 1); BUG_ON(ret); leaf = path->nodes[0]; memcpy_extent_buffer(leaf, btrfs_item_ptr_offset(leaf, path->slots[0]), btrfs_item_ptr_offset(leaf, path->slots[0] - 1), item_size); return 0; } /* * make the item pointed to by the path smaller. new_size indicates * how small to make it, and from_end tells us if we just chop bytes Loading Loading @@ -3714,8 +3791,8 @@ static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans, */ btrfs_unlock_up_safe(path, 0); ret = btrfs_free_extent(trans, root, leaf->start, leaf->len, 0, root->root_key.objectid, 0, 0); ret = btrfs_free_tree_block(trans, root, leaf->start, leaf->len, 0, root->root_key.objectid, 0); return ret; } /* Loading fs/btrfs/ctree.h +28 −12 Original line number Diff line number Diff line Loading @@ -310,6 +310,9 @@ struct btrfs_header { #define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \ sizeof(struct btrfs_item) - \ sizeof(struct btrfs_file_extent_item)) #define BTRFS_MAX_XATTR_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \ sizeof(struct btrfs_item) -\ sizeof(struct btrfs_dir_item)) /* Loading Loading @@ -859,8 +862,9 @@ struct btrfs_fs_info { struct mutex ordered_operations_mutex; struct rw_semaphore extent_commit_sem; struct rw_semaphore subvol_sem; struct rw_semaphore cleanup_work_sem; struct rw_semaphore subvol_sem; struct srcu_struct subvol_srcu; struct list_head trans_list; Loading @@ -868,6 +872,9 @@ struct btrfs_fs_info { struct list_head dead_roots; struct list_head caching_block_groups; spinlock_t delayed_iput_lock; struct list_head delayed_iputs; atomic_t nr_async_submits; atomic_t async_submit_draining; atomic_t nr_async_bios; Loading Loading @@ -1034,12 +1041,12 @@ struct btrfs_root { int ref_cows; int track_dirty; int in_radix; int clean_orphans; u64 defrag_trans_start; struct btrfs_key defrag_progress; struct btrfs_key defrag_max; int defrag_running; int defrag_level; char *name; int in_sysfs; Loading Loading @@ -1975,6 +1982,10 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, u64 parent, u64 root_objectid, struct btrfs_disk_key *key, int level, u64 hint, u64 empty_size); int btrfs_free_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 bytenr, u32 blocksize, u64 parent, u64 root_objectid, int level); struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 bytenr, u32 blocksize, Loading Loading @@ -2089,6 +2100,10 @@ int btrfs_split_item(struct btrfs_trans_handle *trans, struct btrfs_path *path, struct btrfs_key *new_key, unsigned long split_offset); int btrfs_duplicate_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *new_key); int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *key, struct btrfs_path *p, int ins_len, int cow); Loading Loading @@ -2196,9 +2211,10 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans, struct btrfs_path *path, struct btrfs_dir_item *di); int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, const char *name, u16 name_len, const void *data, u16 data_len, u64 dir); struct btrfs_root *root, struct btrfs_path *path, u64 objectid, const char *name, u16 name_len, const void *data, u16 data_len); struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, u64 dir, Loading Loading @@ -2292,7 +2308,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, struct inode *inode, u64 new_size, u32 min_type); int btrfs_start_delalloc_inodes(struct btrfs_root *root); int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput); int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end); int btrfs_writepages(struct address_space *mapping, struct writeback_control *wbc); Loading Loading @@ -2332,6 +2348,8 @@ int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode); void btrfs_orphan_cleanup(struct btrfs_root *root); int btrfs_cont_expand(struct inode *inode, loff_t size); int btrfs_invalidate_inodes(struct btrfs_root *root); void btrfs_add_delayed_iput(struct inode *inode); void btrfs_run_delayed_iputs(struct btrfs_root *root); extern const struct dentry_operations btrfs_dentry_operations; /* ioctl.c */ Loading @@ -2345,12 +2363,9 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, int skip_pinned); int btrfs_check_file(struct btrfs_root *root, struct inode *inode); extern const struct file_operations btrfs_file_operations; int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct inode *inode, u64 start, u64 end, u64 locked_end, u64 inline_limit, u64 *hint_block, int drop_cache); int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode, u64 start, u64 end, u64 *hint_byte, int drop_cache); int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct inode *inode, u64 start, u64 end); int btrfs_release_file(struct inode *inode, struct file *file); Loading Loading @@ -2380,7 +2395,8 @@ int btrfs_check_acl(struct inode *inode, int mask); #else #define btrfs_check_acl NULL #endif int btrfs_init_acl(struct inode *inode, struct inode *dir); int btrfs_init_acl(struct btrfs_trans_handle *trans, struct inode *inode, struct inode *dir); int btrfs_acl_chmod(struct inode *inode); /* relocation.c */ Loading fs/btrfs/dir-item.c +7 −12 Original line number Diff line number Diff line Loading @@ -68,12 +68,12 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle * into the tree */ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, const char *name, u16 name_len, const void *data, u16 data_len, u64 dir) struct btrfs_root *root, struct btrfs_path *path, u64 objectid, const char *name, u16 name_len, const void *data, u16 data_len) { int ret = 0; struct btrfs_path *path; struct btrfs_dir_item *dir_item; unsigned long name_ptr, data_ptr; struct btrfs_key key, location; Loading @@ -81,15 +81,11 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans, struct extent_buffer *leaf; u32 data_size; key.objectid = dir; BUG_ON(name_len + data_len > BTRFS_MAX_XATTR_SIZE(root)); key.objectid = objectid; btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY); key.offset = btrfs_name_hash(name, name_len); path = btrfs_alloc_path(); if (!path) return -ENOMEM; if (name_len + data_len + sizeof(struct btrfs_dir_item) > BTRFS_LEAF_DATA_SIZE(root) - sizeof(struct btrfs_item)) return -ENOSPC; data_size = sizeof(*dir_item) + name_len + data_len; dir_item = insert_with_overflow(trans, root, path, &key, data_size, Loading Loading @@ -117,7 +113,6 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans, write_extent_buffer(leaf, data, data_ptr, data_len); btrfs_mark_buffer_dirty(path->nodes[0]); btrfs_free_path(path); return ret; } Loading Loading
fs/btrfs/acl.c +13 −10 Original line number Diff line number Diff line Loading @@ -94,7 +94,8 @@ static int btrfs_xattr_acl_get(struct dentry *dentry, const char *name, /* * Needs to be called with fs_mutex held */ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) static int btrfs_set_acl(struct btrfs_trans_handle *trans, struct inode *inode, struct posix_acl *acl, int type) { int ret, size = 0; const char *name; Loading Loading @@ -140,8 +141,7 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) goto out; } ret = __btrfs_setxattr(inode, name, value, size, 0); ret = __btrfs_setxattr(trans, inode, name, value, size, 0); out: kfree(value); Loading @@ -154,7 +154,7 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) { int ret = 0; int ret; struct posix_acl *acl = NULL; if (value) { Loading @@ -167,7 +167,7 @@ static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name, } } ret = btrfs_set_acl(dentry->d_inode, acl, type); ret = btrfs_set_acl(NULL, dentry->d_inode, acl, type); posix_acl_release(acl); Loading Loading @@ -196,7 +196,8 @@ int btrfs_check_acl(struct inode *inode, int mask) * stuff has been fixed to work with that. If the locking stuff changes, we * need to re-evaluate the acl locking stuff. */ int btrfs_init_acl(struct inode *inode, struct inode *dir) int btrfs_init_acl(struct btrfs_trans_handle *trans, struct inode *inode, struct inode *dir) { struct posix_acl *acl = NULL; int ret = 0; Loading @@ -221,7 +222,8 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir) mode_t mode; if (S_ISDIR(inode->i_mode)) { ret = btrfs_set_acl(inode, acl, ACL_TYPE_DEFAULT); ret = btrfs_set_acl(trans, inode, acl, ACL_TYPE_DEFAULT); if (ret) goto failed; } Loading @@ -236,7 +238,7 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir) inode->i_mode = mode; if (ret > 0) { /* we need an acl */ ret = btrfs_set_acl(inode, clone, ret = btrfs_set_acl(trans, inode, clone, ACL_TYPE_ACCESS); } } Loading Loading @@ -269,7 +271,7 @@ int btrfs_acl_chmod(struct inode *inode) ret = posix_acl_chmod_masq(clone, inode->i_mode); if (!ret) ret = btrfs_set_acl(inode, clone, ACL_TYPE_ACCESS); ret = btrfs_set_acl(NULL, inode, clone, ACL_TYPE_ACCESS); posix_acl_release(clone); Loading Loading @@ -297,7 +299,8 @@ int btrfs_acl_chmod(struct inode *inode) return 0; } int btrfs_init_acl(struct inode *inode, struct inode *dir) int btrfs_init_acl(struct btrfs_trans_handle *trans, struct inode *inode, struct inode *dir) { return 0; } Loading
fs/btrfs/btrfs_inode.h +1 −4 Original line number Diff line number Diff line Loading @@ -44,9 +44,6 @@ struct btrfs_inode { */ struct extent_io_tree io_failure_tree; /* held while inesrting or deleting extents from files */ struct mutex extent_mutex; /* held while logging the inode in tree-log.c */ struct mutex log_mutex; Loading Loading @@ -166,7 +163,7 @@ static inline struct btrfs_inode *BTRFS_I(struct inode *inode) static inline void btrfs_i_size_write(struct inode *inode, u64 size) { inode->i_size = size; i_size_write(inode, size); BTRFS_I(inode)->disk_i_size = size; } Loading
fs/btrfs/ctree.c +153 −76 Original line number Diff line number Diff line Loading @@ -37,6 +37,11 @@ static int balance_node_right(struct btrfs_trans_handle *trans, struct extent_buffer *src_buf); static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int level, int slot); static int setup_items_for_insert(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *cpu_key, u32 *data_size, u32 total_data, u32 total_size, int nr); struct btrfs_path *btrfs_alloc_path(void) { Loading Loading @@ -451,9 +456,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, extent_buffer_get(cow); spin_unlock(&root->node_lock); btrfs_free_extent(trans, root, buf->start, buf->len, parent_start, root->root_key.objectid, level, 0); btrfs_free_tree_block(trans, root, buf->start, buf->len, parent_start, root->root_key.objectid, level); free_extent_buffer(buf); add_root_to_dirty_list(root); } else { Loading @@ -468,9 +472,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, btrfs_set_node_ptr_generation(parent, parent_slot, trans->transid); btrfs_mark_buffer_dirty(parent); btrfs_free_extent(trans, root, buf->start, buf->len, parent_start, root->root_key.objectid, level, 0); btrfs_free_tree_block(trans, root, buf->start, buf->len, parent_start, root->root_key.objectid, level); } if (unlock_orig) btrfs_tree_unlock(buf); Loading Loading @@ -1030,8 +1033,8 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, btrfs_tree_unlock(mid); /* once for the path */ free_extent_buffer(mid); ret = btrfs_free_extent(trans, root, mid->start, mid->len, 0, root->root_key.objectid, level, 1); ret = btrfs_free_tree_block(trans, root, mid->start, mid->len, 0, root->root_key.objectid, level); /* once for the root ptr */ free_extent_buffer(mid); return ret; Loading Loading @@ -1095,10 +1098,10 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, 1); if (wret) ret = wret; wret = btrfs_free_extent(trans, root, bytenr, blocksize, 0, wret = btrfs_free_tree_block(trans, root, bytenr, blocksize, 0, root->root_key.objectid, level, 0); level); if (wret) ret = wret; } else { Loading Loading @@ -1143,9 +1146,8 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, wret = del_ptr(trans, root, path, level + 1, pslot); if (wret) ret = wret; wret = btrfs_free_extent(trans, root, bytenr, blocksize, 0, root->root_key.objectid, level, 0); wret = btrfs_free_tree_block(trans, root, bytenr, blocksize, 0, root->root_key.objectid, level); if (wret) ret = wret; } else { Loading Loading @@ -2997,75 +2999,85 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, return ret; } /* * This function splits a single item into two items, * giving 'new_key' to the new item and splitting the * old one at split_offset (from the start of the item). * * The path may be released by this operation. After * the split, the path is pointing to the old item. The * new item is going to be in the same node as the old one. * * Note, the item being split must be smaller enough to live alone on * a tree block with room for one extra struct btrfs_item * * This allows us to split the item in place, keeping a lock on the * leaf the entire time. */ int btrfs_split_item(struct btrfs_trans_handle *trans, static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *new_key, unsigned long split_offset) struct btrfs_path *path, int ins_len) { u32 item_size; struct btrfs_key key; struct extent_buffer *leaf; struct btrfs_key orig_key; struct btrfs_item *item; struct btrfs_item *new_item; int ret = 0; int slot; u32 nritems; u32 orig_offset; struct btrfs_disk_key disk_key; char *buf; struct btrfs_file_extent_item *fi; u64 extent_len = 0; u32 item_size; int ret; leaf = path->nodes[0]; btrfs_item_key_to_cpu(leaf, &orig_key, path->slots[0]); if (btrfs_leaf_free_space(root, leaf) >= sizeof(struct btrfs_item)) goto split; btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); BUG_ON(key.type != BTRFS_EXTENT_DATA_KEY && key.type != BTRFS_EXTENT_CSUM_KEY); if (btrfs_leaf_free_space(root, leaf) >= ins_len) return 0; item_size = btrfs_item_size_nr(leaf, path->slots[0]); if (key.type == BTRFS_EXTENT_DATA_KEY) { fi = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item); extent_len = btrfs_file_extent_num_bytes(leaf, fi); } btrfs_release_path(root, path); path->search_for_split = 1; path->keep_locks = 1; ret = btrfs_search_slot(trans, root, &orig_key, path, 0, 1); path->search_for_split = 1; ret = btrfs_search_slot(trans, root, &key, path, 0, 1); path->search_for_split = 0; if (ret < 0) goto err; ret = -EAGAIN; leaf = path->nodes[0]; /* if our item isn't there or got smaller, return now */ if (ret != 0 || item_size != btrfs_item_size_nr(path->nodes[0], path->slots[0])) { path->keep_locks = 0; return -EAGAIN; if (ret > 0 || item_size != btrfs_item_size_nr(leaf, path->slots[0])) goto err; if (key.type == BTRFS_EXTENT_DATA_KEY) { fi = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item); if (extent_len != btrfs_file_extent_num_bytes(leaf, fi)) goto err; } btrfs_set_path_blocking(path); ret = split_leaf(trans, root, &orig_key, path, sizeof(struct btrfs_item), 1); path->keep_locks = 0; ret = split_leaf(trans, root, &key, path, ins_len, 1); BUG_ON(ret); path->keep_locks = 0; btrfs_unlock_up_safe(path, 1); return 0; err: path->keep_locks = 0; return ret; } static noinline int split_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *new_key, unsigned long split_offset) { struct extent_buffer *leaf; struct btrfs_item *item; struct btrfs_item *new_item; int slot; char *buf; u32 nritems; u32 item_size; u32 orig_offset; struct btrfs_disk_key disk_key; leaf = path->nodes[0]; BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item)); split: /* * make sure any changes to the path from split_leaf leave it * in a blocking state */ btrfs_set_path_blocking(path); item = btrfs_item_nr(leaf, path->slots[0]); Loading @@ -3073,19 +3085,19 @@ int btrfs_split_item(struct btrfs_trans_handle *trans, item_size = btrfs_item_size(leaf, item); buf = kmalloc(item_size, GFP_NOFS); if (!buf) return -ENOMEM; read_extent_buffer(leaf, buf, btrfs_item_ptr_offset(leaf, path->slots[0]), item_size); slot = path->slots[0] + 1; leaf = path->nodes[0]; slot = path->slots[0] + 1; nritems = btrfs_header_nritems(leaf); if (slot != nritems) { /* shift the items */ memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + 1), btrfs_item_nr_offset(slot), (nritems - slot) * sizeof(struct btrfs_item)); } btrfs_cpu_key_to_disk(&disk_key, new_key); Loading Loading @@ -3113,15 +3125,80 @@ int btrfs_split_item(struct btrfs_trans_handle *trans, item_size - split_offset); btrfs_mark_buffer_dirty(leaf); ret = 0; if (btrfs_leaf_free_space(root, leaf) < 0) { btrfs_print_leaf(root, leaf); BUG(); } BUG_ON(btrfs_leaf_free_space(root, leaf) < 0); kfree(buf); return 0; } /* * This function splits a single item into two items, * giving 'new_key' to the new item and splitting the * old one at split_offset (from the start of the item). * * The path may be released by this operation. After * the split, the path is pointing to the old item. The * new item is going to be in the same node as the old one. * * Note, the item being split must be smaller enough to live alone on * a tree block with room for one extra struct btrfs_item * * This allows us to split the item in place, keeping a lock on the * leaf the entire time. */ int btrfs_split_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *new_key, unsigned long split_offset) { int ret; ret = setup_leaf_for_split(trans, root, path, sizeof(struct btrfs_item)); if (ret) return ret; ret = split_item(trans, root, path, new_key, split_offset); return ret; } /* * This function duplicate a item, giving 'new_key' to the new item. * It guarantees both items live in the same tree leaf and the new item * is contiguous with the original item. * * This allows us to split file extent in place, keeping a lock on the * leaf the entire time. */ int btrfs_duplicate_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *new_key) { struct extent_buffer *leaf; int ret; u32 item_size; leaf = path->nodes[0]; item_size = btrfs_item_size_nr(leaf, path->slots[0]); ret = setup_leaf_for_split(trans, root, path, item_size + sizeof(struct btrfs_item)); if (ret) return ret; path->slots[0]++; ret = setup_items_for_insert(trans, root, path, new_key, &item_size, item_size, item_size + sizeof(struct btrfs_item), 1); BUG_ON(ret); leaf = path->nodes[0]; memcpy_extent_buffer(leaf, btrfs_item_ptr_offset(leaf, path->slots[0]), btrfs_item_ptr_offset(leaf, path->slots[0] - 1), item_size); return 0; } /* * make the item pointed to by the path smaller. new_size indicates * how small to make it, and from_end tells us if we just chop bytes Loading Loading @@ -3714,8 +3791,8 @@ static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans, */ btrfs_unlock_up_safe(path, 0); ret = btrfs_free_extent(trans, root, leaf->start, leaf->len, 0, root->root_key.objectid, 0, 0); ret = btrfs_free_tree_block(trans, root, leaf->start, leaf->len, 0, root->root_key.objectid, 0); return ret; } /* Loading
fs/btrfs/ctree.h +28 −12 Original line number Diff line number Diff line Loading @@ -310,6 +310,9 @@ struct btrfs_header { #define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \ sizeof(struct btrfs_item) - \ sizeof(struct btrfs_file_extent_item)) #define BTRFS_MAX_XATTR_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \ sizeof(struct btrfs_item) -\ sizeof(struct btrfs_dir_item)) /* Loading Loading @@ -859,8 +862,9 @@ struct btrfs_fs_info { struct mutex ordered_operations_mutex; struct rw_semaphore extent_commit_sem; struct rw_semaphore subvol_sem; struct rw_semaphore cleanup_work_sem; struct rw_semaphore subvol_sem; struct srcu_struct subvol_srcu; struct list_head trans_list; Loading @@ -868,6 +872,9 @@ struct btrfs_fs_info { struct list_head dead_roots; struct list_head caching_block_groups; spinlock_t delayed_iput_lock; struct list_head delayed_iputs; atomic_t nr_async_submits; atomic_t async_submit_draining; atomic_t nr_async_bios; Loading Loading @@ -1034,12 +1041,12 @@ struct btrfs_root { int ref_cows; int track_dirty; int in_radix; int clean_orphans; u64 defrag_trans_start; struct btrfs_key defrag_progress; struct btrfs_key defrag_max; int defrag_running; int defrag_level; char *name; int in_sysfs; Loading Loading @@ -1975,6 +1982,10 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, u64 parent, u64 root_objectid, struct btrfs_disk_key *key, int level, u64 hint, u64 empty_size); int btrfs_free_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 bytenr, u32 blocksize, u64 parent, u64 root_objectid, int level); struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 bytenr, u32 blocksize, Loading Loading @@ -2089,6 +2100,10 @@ int btrfs_split_item(struct btrfs_trans_handle *trans, struct btrfs_path *path, struct btrfs_key *new_key, unsigned long split_offset); int btrfs_duplicate_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *new_key); int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *key, struct btrfs_path *p, int ins_len, int cow); Loading Loading @@ -2196,9 +2211,10 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans, struct btrfs_path *path, struct btrfs_dir_item *di); int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, const char *name, u16 name_len, const void *data, u16 data_len, u64 dir); struct btrfs_root *root, struct btrfs_path *path, u64 objectid, const char *name, u16 name_len, const void *data, u16 data_len); struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, u64 dir, Loading Loading @@ -2292,7 +2308,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, struct inode *inode, u64 new_size, u32 min_type); int btrfs_start_delalloc_inodes(struct btrfs_root *root); int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput); int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end); int btrfs_writepages(struct address_space *mapping, struct writeback_control *wbc); Loading Loading @@ -2332,6 +2348,8 @@ int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode); void btrfs_orphan_cleanup(struct btrfs_root *root); int btrfs_cont_expand(struct inode *inode, loff_t size); int btrfs_invalidate_inodes(struct btrfs_root *root); void btrfs_add_delayed_iput(struct inode *inode); void btrfs_run_delayed_iputs(struct btrfs_root *root); extern const struct dentry_operations btrfs_dentry_operations; /* ioctl.c */ Loading @@ -2345,12 +2363,9 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, int skip_pinned); int btrfs_check_file(struct btrfs_root *root, struct inode *inode); extern const struct file_operations btrfs_file_operations; int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct inode *inode, u64 start, u64 end, u64 locked_end, u64 inline_limit, u64 *hint_block, int drop_cache); int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode, u64 start, u64 end, u64 *hint_byte, int drop_cache); int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct inode *inode, u64 start, u64 end); int btrfs_release_file(struct inode *inode, struct file *file); Loading Loading @@ -2380,7 +2395,8 @@ int btrfs_check_acl(struct inode *inode, int mask); #else #define btrfs_check_acl NULL #endif int btrfs_init_acl(struct inode *inode, struct inode *dir); int btrfs_init_acl(struct btrfs_trans_handle *trans, struct inode *inode, struct inode *dir); int btrfs_acl_chmod(struct inode *inode); /* relocation.c */ Loading
fs/btrfs/dir-item.c +7 −12 Original line number Diff line number Diff line Loading @@ -68,12 +68,12 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle * into the tree */ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, const char *name, u16 name_len, const void *data, u16 data_len, u64 dir) struct btrfs_root *root, struct btrfs_path *path, u64 objectid, const char *name, u16 name_len, const void *data, u16 data_len) { int ret = 0; struct btrfs_path *path; struct btrfs_dir_item *dir_item; unsigned long name_ptr, data_ptr; struct btrfs_key key, location; Loading @@ -81,15 +81,11 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans, struct extent_buffer *leaf; u32 data_size; key.objectid = dir; BUG_ON(name_len + data_len > BTRFS_MAX_XATTR_SIZE(root)); key.objectid = objectid; btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY); key.offset = btrfs_name_hash(name, name_len); path = btrfs_alloc_path(); if (!path) return -ENOMEM; if (name_len + data_len + sizeof(struct btrfs_dir_item) > BTRFS_LEAF_DATA_SIZE(root) - sizeof(struct btrfs_item)) return -ENOSPC; data_size = sizeof(*dir_item) + name_len + data_len; dir_item = insert_with_overflow(trans, root, path, &key, data_size, Loading Loading @@ -117,7 +113,6 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans, write_extent_buffer(leaf, data, data_ptr, data_len); btrfs_mark_buffer_dirty(path->nodes[0]); btrfs_free_path(path); return ret; } Loading