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

Commit 098f59c2 authored by Chris Mason's avatar Chris Mason Committed by David Woodhouse
Browse files

Btrfs: patch queue: fix corruption when splitting large items

parent 509659cd
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -871,6 +871,7 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
	btrfs_set_node_blockptr(lower, slot, blocknr);
	btrfs_set_header_nritems(&lower->header, nritems + 1);
	btrfs_mark_buffer_dirty(path->nodes[level]);
	check_node(root, path, level);
	return 0;
}

@@ -1101,6 +1102,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
	} else {
		btrfs_block_release(root, right_buf);
	}
	if (path->nodes[1])
		check_node(root, path, 1);
	return 0;
}
/*
@@ -1216,6 +1219,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root

	btrfs_mark_buffer_dirty(t);
	btrfs_mark_buffer_dirty(right_buf);

	wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1);
	if (wret)
		ret = wret;
@@ -1231,6 +1235,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
		path->slots[0] -= push_items;
	}
	BUG_ON(path->slots[0] < 0);
	if (path->nodes[1])
		check_node(root, path, 1);
	return ret;
}

@@ -1326,13 +1332,12 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
				wret = insert_ptr(trans, root, path,
						  &disk_key,
						  bh_blocknr(right_buffer),
						  path->slots[1] - 1, 1);
						  path->slots[1], 1);
				if (wret)
					ret = wret;
				btrfs_block_release(root, path->nodes[0]);
				path->nodes[0] = right_buffer;
				path->slots[0] = 0;
				path->slots[1] -= 1;
				if (path->slots[1] == 0) {
					wret = fixup_low_keys(trans, root,
					           path, &disk_key, 1);
@@ -1379,6 +1384,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
	} else
		btrfs_block_release(root, right_buffer);
	BUG_ON(path->slots[0] < 0);
	check_node(root, path, 1);

	if (!double_split)
		return ret;
+4 −4
Original line number Diff line number Diff line
@@ -1529,7 +1529,8 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
			btrfs_set_file_extent_type(ei,
						   BTRFS_FILE_EXTENT_INLINE);
			ptr = btrfs_file_extent_inline_start(ei);
			memcpy(ptr, bh->b_data, offset + write_bytes);
			btrfs_memcpy(root, path->nodes[0]->b_data,
				     ptr, bh->b_data, offset + write_bytes);
			mark_buffer_dirty(path->nodes[0]);
			btrfs_free_path(path);
		} else {
@@ -1686,9 +1687,9 @@ static int drop_extents(struct btrfs_trans_handle *trans,
			ret = btrfs_del_item(trans, root, path);
			BUG_ON(ret);
			btrfs_release_path(root, path);
			extent = NULL;
			if (found_extent) {
				inode->i_blocks -=
				btrfs_file_extent_num_blocks(extent) << 3;
				inode->i_blocks -= extent_num_blocks << 3;
				ret = btrfs_free_extent(trans, root,
							disk_blocknr,
							disk_num_blocks, 0);
@@ -1832,7 +1833,6 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
	u64 alloc_extent_start;
	struct btrfs_trans_handle *trans;
	struct btrfs_key ins;

	pinned[0] = NULL;
	pinned[1] = NULL;
	if (file->f_flags & O_DIRECT)