Loading fs/btrfs/extent-tree.c +19 −0 Original line number Diff line number Diff line Loading @@ -3768,6 +3768,25 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, } if (!ret) { ret = write_one_cache_group(trans, root, path, cache); /* * One of the free space endio workers might have * created a new block group while updating a free space * cache's inode (at inode.c:btrfs_finish_ordered_io()) * and hasn't released its transaction handle yet, in * which case the new block group is still attached to * its transaction handle and its creation has not * finished yet (no block group item in the extent tree * yet, etc). If this is the case, wait for all free * space endio workers to finish and retry. This is a * a very rare case so no need for a more efficient and * complex approach. */ if (ret == -ENOENT) { wait_event(cur_trans->writer_wait, atomic_read(&cur_trans->num_writers) == 1); ret = write_one_cache_group(trans, root, path, cache); } if (ret) btrfs_abort_transaction(trans, root, ret); } Loading fs/btrfs/inode.c +14 −7 Original line number Diff line number Diff line Loading @@ -6478,7 +6478,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, static int btrfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans = NULL; struct btrfs_root *root = BTRFS_I(dir)->root; struct inode *inode = d_inode(old_dentry); u64 index; Loading @@ -6504,6 +6504,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, trans = btrfs_start_transaction(root, 5); if (IS_ERR(trans)) { err = PTR_ERR(trans); trans = NULL; goto fail; } Loading Loading @@ -6537,9 +6538,10 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, btrfs_log_new_name(trans, inode, NULL, parent); } btrfs_end_transaction(trans, root); btrfs_balance_delayed_items(root); fail: if (trans) btrfs_end_transaction(trans, root); if (drop_inode) { inode_dec_link_count(inode); iput(inode); Loading Loading @@ -9655,9 +9657,11 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, /* * 2 items for inode item and ref * 2 items for dir items * 1 item for updating parent inode item * 1 item for the inline extent item * 1 item for xattr if selinux is on */ trans = btrfs_start_transaction(root, 5); trans = btrfs_start_transaction(root, 7); if (IS_ERR(trans)) return PTR_ERR(trans); Loading Loading @@ -9688,10 +9692,6 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, if (err) goto out_unlock_inode; err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); if (err) goto out_unlock_inode; path = btrfs_alloc_path(); if (!path) { err = -ENOMEM; Loading Loading @@ -9728,6 +9728,13 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, inode_set_bytes(inode, name_len); btrfs_i_size_write(inode, name_len); err = btrfs_update_inode(trans, root, inode); /* * Last step, add directory indexes for our symlink inode. This is the * last step to avoid extra cleanup of these indexes if an error happens * elsewhere above. */ if (!err) err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); if (err) { drop_inode = 1; goto out_unlock_inode; Loading fs/btrfs/send.c +15 −1 Original line number Diff line number Diff line Loading @@ -1469,7 +1469,21 @@ static int read_symlink(struct btrfs_root *root, ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); if (ret < 0) goto out; BUG_ON(ret); if (ret) { /* * An empty symlink inode. Can happen in rare error paths when * creating a symlink (transaction committed before the inode * eviction handler removed the symlink inode items and a crash * happened in between or the subvol was snapshoted in between). * Print an informative message to dmesg/syslog so that the user * can delete the symlink. */ btrfs_err(root->fs_info, "Found empty symlink inode %llu at root %llu", ino, root->root_key.objectid); ret = -EIO; goto out; } ei = btrfs_item_ptr(path->nodes[0], path->slots[0], struct btrfs_file_extent_item); Loading fs/btrfs/volumes.c +10 −10 Original line number Diff line number Diff line Loading @@ -1258,6 +1258,15 @@ int find_free_dev_extent_start(struct btrfs_transaction *transaction, int ret; int slot; struct extent_buffer *l; u64 min_search_start; /* * We don't want to overwrite the superblock on the drive nor any area * used by the boot loader (grub for example), so we make sure to start * at an offset of at least 1MB. */ min_search_start = max(root->fs_info->alloc_start, 1024ull * 1024); search_start = max(search_start, min_search_start); path = btrfs_alloc_path(); if (!path) Loading Loading @@ -1398,18 +1407,9 @@ int find_free_dev_extent(struct btrfs_trans_handle *trans, struct btrfs_device *device, u64 num_bytes, u64 *start, u64 *len) { struct btrfs_root *root = device->dev_root; u64 search_start; /* FIXME use last free of some kind */ /* * we don't want to overwrite the superblock on the drive, * so we make sure to start at an offset of at least 1MB */ search_start = max_t(u64, root->fs_info->alloc_start, SZ_1M); return find_free_dev_extent_start(trans->transaction, device, num_bytes, search_start, start, len); num_bytes, 0, start, len); } static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans, Loading Loading
fs/btrfs/extent-tree.c +19 −0 Original line number Diff line number Diff line Loading @@ -3768,6 +3768,25 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, } if (!ret) { ret = write_one_cache_group(trans, root, path, cache); /* * One of the free space endio workers might have * created a new block group while updating a free space * cache's inode (at inode.c:btrfs_finish_ordered_io()) * and hasn't released its transaction handle yet, in * which case the new block group is still attached to * its transaction handle and its creation has not * finished yet (no block group item in the extent tree * yet, etc). If this is the case, wait for all free * space endio workers to finish and retry. This is a * a very rare case so no need for a more efficient and * complex approach. */ if (ret == -ENOENT) { wait_event(cur_trans->writer_wait, atomic_read(&cur_trans->num_writers) == 1); ret = write_one_cache_group(trans, root, path, cache); } if (ret) btrfs_abort_transaction(trans, root, ret); } Loading
fs/btrfs/inode.c +14 −7 Original line number Diff line number Diff line Loading @@ -6478,7 +6478,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, static int btrfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans = NULL; struct btrfs_root *root = BTRFS_I(dir)->root; struct inode *inode = d_inode(old_dentry); u64 index; Loading @@ -6504,6 +6504,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, trans = btrfs_start_transaction(root, 5); if (IS_ERR(trans)) { err = PTR_ERR(trans); trans = NULL; goto fail; } Loading Loading @@ -6537,9 +6538,10 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, btrfs_log_new_name(trans, inode, NULL, parent); } btrfs_end_transaction(trans, root); btrfs_balance_delayed_items(root); fail: if (trans) btrfs_end_transaction(trans, root); if (drop_inode) { inode_dec_link_count(inode); iput(inode); Loading Loading @@ -9655,9 +9657,11 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, /* * 2 items for inode item and ref * 2 items for dir items * 1 item for updating parent inode item * 1 item for the inline extent item * 1 item for xattr if selinux is on */ trans = btrfs_start_transaction(root, 5); trans = btrfs_start_transaction(root, 7); if (IS_ERR(trans)) return PTR_ERR(trans); Loading Loading @@ -9688,10 +9692,6 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, if (err) goto out_unlock_inode; err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); if (err) goto out_unlock_inode; path = btrfs_alloc_path(); if (!path) { err = -ENOMEM; Loading Loading @@ -9728,6 +9728,13 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, inode_set_bytes(inode, name_len); btrfs_i_size_write(inode, name_len); err = btrfs_update_inode(trans, root, inode); /* * Last step, add directory indexes for our symlink inode. This is the * last step to avoid extra cleanup of these indexes if an error happens * elsewhere above. */ if (!err) err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); if (err) { drop_inode = 1; goto out_unlock_inode; Loading
fs/btrfs/send.c +15 −1 Original line number Diff line number Diff line Loading @@ -1469,7 +1469,21 @@ static int read_symlink(struct btrfs_root *root, ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); if (ret < 0) goto out; BUG_ON(ret); if (ret) { /* * An empty symlink inode. Can happen in rare error paths when * creating a symlink (transaction committed before the inode * eviction handler removed the symlink inode items and a crash * happened in between or the subvol was snapshoted in between). * Print an informative message to dmesg/syslog so that the user * can delete the symlink. */ btrfs_err(root->fs_info, "Found empty symlink inode %llu at root %llu", ino, root->root_key.objectid); ret = -EIO; goto out; } ei = btrfs_item_ptr(path->nodes[0], path->slots[0], struct btrfs_file_extent_item); Loading
fs/btrfs/volumes.c +10 −10 Original line number Diff line number Diff line Loading @@ -1258,6 +1258,15 @@ int find_free_dev_extent_start(struct btrfs_transaction *transaction, int ret; int slot; struct extent_buffer *l; u64 min_search_start; /* * We don't want to overwrite the superblock on the drive nor any area * used by the boot loader (grub for example), so we make sure to start * at an offset of at least 1MB. */ min_search_start = max(root->fs_info->alloc_start, 1024ull * 1024); search_start = max(search_start, min_search_start); path = btrfs_alloc_path(); if (!path) Loading Loading @@ -1398,18 +1407,9 @@ int find_free_dev_extent(struct btrfs_trans_handle *trans, struct btrfs_device *device, u64 num_bytes, u64 *start, u64 *len) { struct btrfs_root *root = device->dev_root; u64 search_start; /* FIXME use last free of some kind */ /* * we don't want to overwrite the superblock on the drive, * so we make sure to start at an offset of at least 1MB */ search_start = max_t(u64, root->fs_info->alloc_start, SZ_1M); return find_free_dev_extent_start(trans->transaction, device, num_bytes, search_start, start, len); num_bytes, 0, start, len); } static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans, Loading