Merge branch 'for-chris-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/fdmanana/linux into for-linus-4.5
Signed-off-by: Chris Mason <clm@fb.com>
This commit is contained in:
Коммит
988f1f576d
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -6478,7 +6478,7 @@ out_unlock_inode:
|
|||
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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче