mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-15 15:15:47 +00:00
Merge branch 'for-linus-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason: "These are all from Filipe, and cover a few problems we've had reported on the list recently (along with ones he found on his own)" * 'for-linus-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: Btrfs: fix file corruption after cloning inline extents Btrfs: fix order by which delayed references are run Btrfs: fix list transaction->pending_ordered corruption Btrfs: fix memory leak in the extent_same ioctl Btrfs: fix shrinking truncate when the no_holes feature is enabled
This commit is contained in:
commit
8be5701342
4 changed files with 34 additions and 6 deletions
|
@ -2296,9 +2296,22 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans,
|
||||||
static inline struct btrfs_delayed_ref_node *
|
static inline struct btrfs_delayed_ref_node *
|
||||||
select_delayed_ref(struct btrfs_delayed_ref_head *head)
|
select_delayed_ref(struct btrfs_delayed_ref_head *head)
|
||||||
{
|
{
|
||||||
|
struct btrfs_delayed_ref_node *ref;
|
||||||
|
|
||||||
if (list_empty(&head->ref_list))
|
if (list_empty(&head->ref_list))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Select a delayed ref of type BTRFS_ADD_DELAYED_REF first.
|
||||||
|
* This is to prevent a ref count from going down to zero, which deletes
|
||||||
|
* the extent item from the extent tree, when there still are references
|
||||||
|
* to add, which would fail because they would not find the extent item.
|
||||||
|
*/
|
||||||
|
list_for_each_entry(ref, &head->ref_list, list) {
|
||||||
|
if (ref->action == BTRFS_ADD_DELAYED_REF)
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
return list_entry(head->ref_list.next, struct btrfs_delayed_ref_node,
|
return list_entry(head->ref_list.next, struct btrfs_delayed_ref_node,
|
||||||
list);
|
list);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4209,7 +4209,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
|
||||||
u64 extent_num_bytes = 0;
|
u64 extent_num_bytes = 0;
|
||||||
u64 extent_offset = 0;
|
u64 extent_offset = 0;
|
||||||
u64 item_end = 0;
|
u64 item_end = 0;
|
||||||
u64 last_size = (u64)-1;
|
u64 last_size = new_size;
|
||||||
u32 found_type = (u8)-1;
|
u32 found_type = (u8)-1;
|
||||||
int found_extent;
|
int found_extent;
|
||||||
int del_item;
|
int del_item;
|
||||||
|
@ -4493,8 +4493,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
|
||||||
btrfs_abort_transaction(trans, root, ret);
|
btrfs_abort_transaction(trans, root, ret);
|
||||||
}
|
}
|
||||||
error:
|
error:
|
||||||
if (last_size != (u64)-1 &&
|
if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
|
||||||
root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
|
|
||||||
btrfs_ordered_update_i_size(inode, last_size, NULL);
|
btrfs_ordered_update_i_size(inode, last_size, NULL);
|
||||||
|
|
||||||
btrfs_free_path(path);
|
btrfs_free_path(path);
|
||||||
|
|
|
@ -3090,7 +3090,7 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen,
|
||||||
static long btrfs_ioctl_file_extent_same(struct file *file,
|
static long btrfs_ioctl_file_extent_same(struct file *file,
|
||||||
struct btrfs_ioctl_same_args __user *argp)
|
struct btrfs_ioctl_same_args __user *argp)
|
||||||
{
|
{
|
||||||
struct btrfs_ioctl_same_args *same;
|
struct btrfs_ioctl_same_args *same = NULL;
|
||||||
struct btrfs_ioctl_same_extent_info *info;
|
struct btrfs_ioctl_same_extent_info *info;
|
||||||
struct inode *src = file_inode(file);
|
struct inode *src = file_inode(file);
|
||||||
u64 off;
|
u64 off;
|
||||||
|
@ -3120,6 +3120,7 @@ static long btrfs_ioctl_file_extent_same(struct file *file,
|
||||||
|
|
||||||
if (IS_ERR(same)) {
|
if (IS_ERR(same)) {
|
||||||
ret = PTR_ERR(same);
|
ret = PTR_ERR(same);
|
||||||
|
same = NULL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3190,6 +3191,7 @@ static long btrfs_ioctl_file_extent_same(struct file *file,
|
||||||
|
|
||||||
out:
|
out:
|
||||||
mnt_drop_write_file(file);
|
mnt_drop_write_file(file);
|
||||||
|
kfree(same);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3586,6 +3588,20 @@ static int btrfs_clone(struct inode *src, struct inode *inode,
|
||||||
u64 trim = 0;
|
u64 trim = 0;
|
||||||
u64 aligned_end = 0;
|
u64 aligned_end = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't copy an inline extent into an offset
|
||||||
|
* greater than zero. Having an inline extent
|
||||||
|
* at such an offset results in chaos as btrfs
|
||||||
|
* isn't prepared for such cases. Just skip
|
||||||
|
* this case for the same reasons as commented
|
||||||
|
* at btrfs_ioctl_clone().
|
||||||
|
*/
|
||||||
|
if (last_dest_end > 0) {
|
||||||
|
ret = -EOPNOTSUPP;
|
||||||
|
btrfs_end_transaction(trans, root);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (off > key.offset) {
|
if (off > key.offset) {
|
||||||
skip = off - key.offset;
|
skip = off - key.offset;
|
||||||
new_key.offset += skip;
|
new_key.offset += skip;
|
||||||
|
|
|
@ -761,7 +761,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
|
||||||
|
|
||||||
if (!list_empty(&trans->ordered)) {
|
if (!list_empty(&trans->ordered)) {
|
||||||
spin_lock(&info->trans_lock);
|
spin_lock(&info->trans_lock);
|
||||||
list_splice(&trans->ordered, &cur_trans->pending_ordered);
|
list_splice_init(&trans->ordered, &cur_trans->pending_ordered);
|
||||||
spin_unlock(&info->trans_lock);
|
spin_unlock(&info->trans_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1866,7 +1866,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&root->fs_info->trans_lock);
|
spin_lock(&root->fs_info->trans_lock);
|
||||||
list_splice(&trans->ordered, &cur_trans->pending_ordered);
|
list_splice_init(&trans->ordered, &cur_trans->pending_ordered);
|
||||||
if (cur_trans->state >= TRANS_STATE_COMMIT_START) {
|
if (cur_trans->state >= TRANS_STATE_COMMIT_START) {
|
||||||
spin_unlock(&root->fs_info->trans_lock);
|
spin_unlock(&root->fs_info->trans_lock);
|
||||||
atomic_inc(&cur_trans->use_count);
|
atomic_inc(&cur_trans->use_count);
|
||||||
|
|
Loading…
Reference in a new issue