Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8be57013 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents dfe91c97 ed958762
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -2296,9 +2296,22 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans,
static inline struct btrfs_delayed_ref_node *
select_delayed_ref(struct btrfs_delayed_ref_head *head)
{
	struct btrfs_delayed_ref_node *ref;

	if (list_empty(&head->ref_list))
		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,
			  list);
}
+2 −3
Original line number Diff line number Diff line
@@ -4209,7 +4209,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
	u64 extent_num_bytes = 0;
	u64 extent_offset = 0;
	u64 item_end = 0;
	u64 last_size = (u64)-1;
	u64 last_size = new_size;
	u32 found_type = (u8)-1;
	int found_extent;
	int del_item;
@@ -4493,8 +4493,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
			btrfs_abort_transaction(trans, root, ret);
	}
error:
	if (last_size != (u64)-1 &&
	    root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
	if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
		btrfs_ordered_update_i_size(inode, last_size, NULL);

	btrfs_free_path(path);
+17 −1
Original line number Diff line number Diff line
@@ -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,
			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 inode *src = file_inode(file);
	u64 off;
@@ -3120,6 +3120,7 @@ static long btrfs_ioctl_file_extent_same(struct file *file,

	if (IS_ERR(same)) {
		ret = PTR_ERR(same);
		same = NULL;
		goto out;
	}

@@ -3190,6 +3191,7 @@ static long btrfs_ioctl_file_extent_same(struct file *file,

out:
	mnt_drop_write_file(file);
	kfree(same);
	return ret;
}

@@ -3586,6 +3588,20 @@ static int btrfs_clone(struct inode *src, struct inode *inode,
				u64 trim = 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) {
					skip = off - key.offset;
					new_key.offset += skip;
+2 −2
Original line number Diff line number Diff line
@@ -761,7 +761,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,

	if (!list_empty(&trans->ordered)) {
		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);
	}

@@ -1866,7 +1866,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
	}

	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) {
		spin_unlock(&root->fs_info->trans_lock);
		atomic_inc(&cur_trans->use_count);