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:
commit
988f1f576d
|
@ -3768,6 +3768,25 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
|
||||||
}
|
}
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
ret = write_one_cache_group(trans, root, path, cache);
|
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)
|
if (ret)
|
||||||
btrfs_abort_transaction(trans, root, ret);
|
btrfs_abort_transaction(trans, root, ret);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
|
||||||
struct dentry *dentry)
|
struct dentry *dentry)
|
||||||
{
|
{
|
||||||
struct btrfs_trans_handle *trans;
|
struct btrfs_trans_handle *trans = NULL;
|
||||||
struct btrfs_root *root = BTRFS_I(dir)->root;
|
struct btrfs_root *root = BTRFS_I(dir)->root;
|
||||||
struct inode *inode = d_inode(old_dentry);
|
struct inode *inode = d_inode(old_dentry);
|
||||||
u64 index;
|
u64 index;
|
||||||
|
@ -6504,6 +6504,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
|
||||||
trans = btrfs_start_transaction(root, 5);
|
trans = btrfs_start_transaction(root, 5);
|
||||||
if (IS_ERR(trans)) {
|
if (IS_ERR(trans)) {
|
||||||
err = PTR_ERR(trans);
|
err = PTR_ERR(trans);
|
||||||
|
trans = NULL;
|
||||||
goto fail;
|
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_log_new_name(trans, inode, NULL, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
btrfs_end_transaction(trans, root);
|
|
||||||
btrfs_balance_delayed_items(root);
|
btrfs_balance_delayed_items(root);
|
||||||
fail:
|
fail:
|
||||||
|
if (trans)
|
||||||
|
btrfs_end_transaction(trans, root);
|
||||||
if (drop_inode) {
|
if (drop_inode) {
|
||||||
inode_dec_link_count(inode);
|
inode_dec_link_count(inode);
|
||||||
iput(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 inode item and ref
|
||||||
* 2 items for dir items
|
* 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
|
* 1 item for xattr if selinux is on
|
||||||
*/
|
*/
|
||||||
trans = btrfs_start_transaction(root, 5);
|
trans = btrfs_start_transaction(root, 7);
|
||||||
if (IS_ERR(trans))
|
if (IS_ERR(trans))
|
||||||
return PTR_ERR(trans);
|
return PTR_ERR(trans);
|
||||||
|
|
||||||
|
@ -9688,10 +9692,6 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
|
||||||
if (err)
|
if (err)
|
||||||
goto out_unlock_inode;
|
goto out_unlock_inode;
|
||||||
|
|
||||||
err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
|
|
||||||
if (err)
|
|
||||||
goto out_unlock_inode;
|
|
||||||
|
|
||||||
path = btrfs_alloc_path();
|
path = btrfs_alloc_path();
|
||||||
if (!path) {
|
if (!path) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
|
@ -9728,6 +9728,13 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
|
||||||
inode_set_bytes(inode, name_len);
|
inode_set_bytes(inode, name_len);
|
||||||
btrfs_i_size_write(inode, name_len);
|
btrfs_i_size_write(inode, name_len);
|
||||||
err = btrfs_update_inode(trans, root, inode);
|
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) {
|
if (err) {
|
||||||
drop_inode = 1;
|
drop_inode = 1;
|
||||||
goto out_unlock_inode;
|
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);
|
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
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],
|
ei = btrfs_item_ptr(path->nodes[0], path->slots[0],
|
||||||
struct btrfs_file_extent_item);
|
struct btrfs_file_extent_item);
|
||||||
|
|
|
@ -1258,6 +1258,15 @@ int find_free_dev_extent_start(struct btrfs_transaction *transaction,
|
||||||
int ret;
|
int ret;
|
||||||
int slot;
|
int slot;
|
||||||
struct extent_buffer *l;
|
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();
|
path = btrfs_alloc_path();
|
||||||
if (!path)
|
if (!path)
|
||||||
|
@ -1398,18 +1407,9 @@ int find_free_dev_extent(struct btrfs_trans_handle *trans,
|
||||||
struct btrfs_device *device, u64 num_bytes,
|
struct btrfs_device *device, u64 num_bytes,
|
||||||
u64 *start, u64 *len)
|
u64 *start, u64 *len)
|
||||||
{
|
{
|
||||||
struct btrfs_root *root = device->dev_root;
|
|
||||||
u64 search_start;
|
|
||||||
|
|
||||||
/* FIXME use last free of some kind */
|
/* 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,
|
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,
|
static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans,
|
||||||
|
|
Loading…
Reference in New Issue