Commit 988f1f57 authored by Chris Mason's avatar Chris Mason

Merge branch 'for-chris-4.5' of...

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: default avatarChris Mason <clm@fb.com>
parents b28cf572 8cdc7c5b
...@@ -3768,6 +3768,25 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment