Commit 6e68b996 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from David Sterba:
 "More material for stable trees.

   - tree-checker: check item end overflow

   - fix false warning during relocation regarding extent type

   - fix inode flushing logic, caused notable performance regression
     (since 5.10)

   - debugging fixups:
      - print correct offset for reloc tree key
      - pass reliable fs_info pointer to error reporting helper"

* tag 'for-5.11-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: shrink delalloc pages instead of full inodes
  btrfs: reloc: fix wrong file extent type check to avoid false ENOENT
  btrfs: tree-checker: check if chunk item end overflows
  btrfs: prevent NULL pointer dereference in extent_io_tree_panic
  btrfs: print the actual offset in btrfs_root_name
parents c912fd05 e076ab2a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1457,7 +1457,7 @@ void btrfs_check_leaked_roots(struct btrfs_fs_info *fs_info)
		root = list_first_entry(&fs_info->allocated_roots,
					struct btrfs_root, leak_list);
		btrfs_err(fs_info, "leaked root %s refcount %d",
			  btrfs_root_name(root->root_key.objectid, buf),
			  btrfs_root_name(&root->root_key, buf),
			  refcount_read(&root->refs));
		while (refcount_read(&root->refs) > 1)
			btrfs_put_root(root);
+1 −3
Original line number Diff line number Diff line
@@ -676,9 +676,7 @@ alloc_extent_state_atomic(struct extent_state *prealloc)

static void extent_io_tree_panic(struct extent_io_tree *tree, int err)
{
	struct inode *inode = tree->private_data;

	btrfs_panic(btrfs_sb(inode->i_sb), err,
	btrfs_panic(tree->fs_info, err,
	"locking error: extent tree was modified by another thread while locked");
}

+43 −17
Original line number Diff line number Diff line
@@ -9390,7 +9390,8 @@ static struct btrfs_delalloc_work *btrfs_alloc_delalloc_work(struct inode *inode
 * some fairly slow code that needs optimization. This walks the list
 * of all the inodes with pending delalloc and forces them to disk.
 */
static int start_delalloc_inodes(struct btrfs_root *root, u64 *nr, bool snapshot,
static int start_delalloc_inodes(struct btrfs_root *root,
				 struct writeback_control *wbc, bool snapshot,
				 bool in_reclaim_context)
{
	struct btrfs_inode *binode;
@@ -9399,6 +9400,7 @@ static int start_delalloc_inodes(struct btrfs_root *root, u64 *nr, bool snapshot
	struct list_head works;
	struct list_head splice;
	int ret = 0;
	bool full_flush = wbc->nr_to_write == LONG_MAX;

	INIT_LIST_HEAD(&works);
	INIT_LIST_HEAD(&splice);
@@ -9427,6 +9429,7 @@ static int start_delalloc_inodes(struct btrfs_root *root, u64 *nr, bool snapshot
		if (snapshot)
			set_bit(BTRFS_INODE_SNAPSHOT_FLUSH,
				&binode->runtime_flags);
		if (full_flush) {
			work = btrfs_alloc_delalloc_work(inode);
			if (!work) {
				iput(inode);
@@ -9436,9 +9439,14 @@ static int start_delalloc_inodes(struct btrfs_root *root, u64 *nr, bool snapshot
			list_add_tail(&work->list, &works);
			btrfs_queue_work(root->fs_info->flush_workers,
					 &work->work);
		if (*nr != U64_MAX) {
			(*nr)--;
			if (*nr == 0)
		} else {
			ret = sync_inode(inode, wbc);
			if (!ret &&
			    test_bit(BTRFS_INODE_HAS_ASYNC_EXTENT,
				     &BTRFS_I(inode)->runtime_flags))
				ret = sync_inode(inode, wbc);
			btrfs_add_delayed_iput(inode);
			if (ret || wbc->nr_to_write <= 0)
				goto out;
		}
		cond_resched();
@@ -9464,18 +9472,29 @@ static int start_delalloc_inodes(struct btrfs_root *root, u64 *nr, bool snapshot

int btrfs_start_delalloc_snapshot(struct btrfs_root *root)
{
	struct writeback_control wbc = {
		.nr_to_write = LONG_MAX,
		.sync_mode = WB_SYNC_NONE,
		.range_start = 0,
		.range_end = LLONG_MAX,
	};
	struct btrfs_fs_info *fs_info = root->fs_info;
	u64 nr = U64_MAX;

	if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state))
		return -EROFS;

	return start_delalloc_inodes(root, &nr, true, false);
	return start_delalloc_inodes(root, &wbc, true, false);
}

int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, u64 nr,
			       bool in_reclaim_context)
{
	struct writeback_control wbc = {
		.nr_to_write = (nr == U64_MAX) ? LONG_MAX : (unsigned long)nr,
		.sync_mode = WB_SYNC_NONE,
		.range_start = 0,
		.range_end = LLONG_MAX,
	};
	struct btrfs_root *root;
	struct list_head splice;
	int ret;
@@ -9489,6 +9508,13 @@ int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, u64 nr,
	spin_lock(&fs_info->delalloc_root_lock);
	list_splice_init(&fs_info->delalloc_roots, &splice);
	while (!list_empty(&splice) && nr) {
		/*
		 * Reset nr_to_write here so we know that we're doing a full
		 * flush.
		 */
		if (nr == U64_MAX)
			wbc.nr_to_write = LONG_MAX;

		root = list_first_entry(&splice, struct btrfs_root,
					delalloc_root);
		root = btrfs_grab_root(root);
@@ -9497,9 +9523,9 @@ int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, u64 nr,
			       &fs_info->delalloc_roots);
		spin_unlock(&fs_info->delalloc_root_lock);

		ret = start_delalloc_inodes(root, &nr, false, in_reclaim_context);
		ret = start_delalloc_inodes(root, &wbc, false, in_reclaim_context);
		btrfs_put_root(root);
		if (ret < 0)
		if (ret < 0 || wbc.nr_to_write <= 0)
			goto out;
		spin_lock(&fs_info->delalloc_root_lock);
	}
+5 −5
Original line number Diff line number Diff line
@@ -26,22 +26,22 @@ static const struct root_name_map root_map[] = {
	{ BTRFS_DATA_RELOC_TREE_OBJECTID,	"DATA_RELOC_TREE"	},
};

const char *btrfs_root_name(u64 objectid, char *buf)
const char *btrfs_root_name(const struct btrfs_key *key, char *buf)
{
	int i;

	if (objectid == BTRFS_TREE_RELOC_OBJECTID) {
	if (key->objectid == BTRFS_TREE_RELOC_OBJECTID) {
		snprintf(buf, BTRFS_ROOT_NAME_BUF_LEN,
			 "TREE_RELOC offset=%llu", objectid);
			 "TREE_RELOC offset=%llu", key->offset);
		return buf;
	}

	for (i = 0; i < ARRAY_SIZE(root_map); i++) {
		if (root_map[i].id == objectid)
		if (root_map[i].id == key->objectid)
			return root_map[i].name;
	}

	snprintf(buf, BTRFS_ROOT_NAME_BUF_LEN, "%llu", objectid);
	snprintf(buf, BTRFS_ROOT_NAME_BUF_LEN, "%llu", key->objectid);
	return buf;
}

+1 −1
Original line number Diff line number Diff line
@@ -11,6 +11,6 @@

void btrfs_print_leaf(struct extent_buffer *l);
void btrfs_print_tree(struct extent_buffer *c, bool follow);
const char *btrfs_root_name(u64 objectid, char *buf);
const char *btrfs_root_name(const struct btrfs_key *key, char *buf);

#endif
Loading