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

Commit 4c6459f9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from Chris Mason:
 "The most user visible change here is a fix for our recent superblock
  validation checks that were causing problems on non-4k pagesized
  systems"

* 'for-linus-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
  Btrfs: btrfs_check_super_valid: Allow 4096 as stripesize
  btrfs: remove build fixup for qgroup_account_snapshot
  btrfs: use new error message helper in qgroup_account_snapshot
  btrfs: avoid blocking open_ctree from cleaner_kthread
  Btrfs: don't BUG_ON() in btrfs_orphan_add
  btrfs: account for non-CoW'd blocks in btrfs_abort_transaction
  Btrfs: check if extent buffer is aligned to sectorsize
  btrfs: Use correct format specifier
parents d9e66146 de18c165
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -2645,7 +2645,7 @@ static void btrfsic_dump_tree_sub(const struct btrfsic_state *state,
	 * This algorithm is recursive because the amount of used stack space
	 * This algorithm is recursive because the amount of used stack space
	 * is very small and the max recursion depth is limited.
	 * is very small and the max recursion depth is limited.
	 */
	 */
	indent_add = sprintf(buf, "%c-%llu(%s/%llu/%d)",
	indent_add = sprintf(buf, "%c-%llu(%s/%llu/%u)",
			     btrfsic_get_block_type(state, block),
			     btrfsic_get_block_type(state, block),
			     block->logical_bytenr, block->dev_state->name,
			     block->logical_bytenr, block->dev_state->name,
			     block->dev_bytenr, block->mirror_num);
			     block->dev_bytenr, block->mirror_num);
+6 −1
Original line number Original line Diff line number Diff line
@@ -1554,6 +1554,7 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans,
		       trans->transid, root->fs_info->generation);
		       trans->transid, root->fs_info->generation);


	if (!should_cow_block(trans, root, buf)) {
	if (!should_cow_block(trans, root, buf)) {
		trans->dirty = true;
		*cow_ret = buf;
		*cow_ret = buf;
		return 0;
		return 0;
	}
	}
@@ -2512,6 +2513,8 @@ read_block_for_search(struct btrfs_trans_handle *trans,
		if (!btrfs_buffer_uptodate(tmp, 0, 0))
		if (!btrfs_buffer_uptodate(tmp, 0, 0))
			ret = -EIO;
			ret = -EIO;
		free_extent_buffer(tmp);
		free_extent_buffer(tmp);
	} else {
		ret = PTR_ERR(tmp);
	}
	}
	return ret;
	return ret;
}
}
@@ -2775,8 +2778,10 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
			 * then we don't want to set the path blocking,
			 * then we don't want to set the path blocking,
			 * so we test it here
			 * so we test it here
			 */
			 */
			if (!should_cow_block(trans, root, b))
			if (!should_cow_block(trans, root, b)) {
				trans->dirty = true;
				goto cow_done;
				goto cow_done;
			}


			/*
			/*
			 * must have write locks on this node and the
			 * must have write locks on this node and the
+16 −20
Original line number Original line Diff line number Diff line
@@ -1098,7 +1098,7 @@ void readahead_tree_block(struct btrfs_root *root, u64 bytenr)
	struct inode *btree_inode = root->fs_info->btree_inode;
	struct inode *btree_inode = root->fs_info->btree_inode;


	buf = btrfs_find_create_tree_block(root, bytenr);
	buf = btrfs_find_create_tree_block(root, bytenr);
	if (!buf)
	if (IS_ERR(buf))
		return;
		return;
	read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree,
	read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree,
				 buf, 0, WAIT_NONE, btree_get_extent, 0);
				 buf, 0, WAIT_NONE, btree_get_extent, 0);
@@ -1114,7 +1114,7 @@ int reada_tree_block_flagged(struct btrfs_root *root, u64 bytenr,
	int ret;
	int ret;


	buf = btrfs_find_create_tree_block(root, bytenr);
	buf = btrfs_find_create_tree_block(root, bytenr);
	if (!buf)
	if (IS_ERR(buf))
		return 0;
		return 0;


	set_bit(EXTENT_BUFFER_READAHEAD, &buf->bflags);
	set_bit(EXTENT_BUFFER_READAHEAD, &buf->bflags);
@@ -1172,8 +1172,8 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
	int ret;
	int ret;


	buf = btrfs_find_create_tree_block(root, bytenr);
	buf = btrfs_find_create_tree_block(root, bytenr);
	if (!buf)
	if (IS_ERR(buf))
		return ERR_PTR(-ENOMEM);
		return buf;


	ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
	ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
	if (ret) {
	if (ret) {
@@ -1806,6 +1806,13 @@ static int cleaner_kthread(void *arg)
		if (btrfs_need_cleaner_sleep(root))
		if (btrfs_need_cleaner_sleep(root))
			goto sleep;
			goto sleep;


		/*
		 * Do not do anything if we might cause open_ctree() to block
		 * before we have finished mounting the filesystem.
		 */
		if (!root->fs_info->open)
			goto sleep;

		if (!mutex_trylock(&root->fs_info->cleaner_mutex))
		if (!mutex_trylock(&root->fs_info->cleaner_mutex))
			goto sleep;
			goto sleep;


@@ -2520,7 +2527,6 @@ int open_ctree(struct super_block *sb,
	int num_backups_tried = 0;
	int num_backups_tried = 0;
	int backup_index = 0;
	int backup_index = 0;
	int max_active;
	int max_active;
	bool cleaner_mutex_locked = false;


	tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info, GFP_KERNEL);
	tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info, GFP_KERNEL);
	chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info, GFP_KERNEL);
	chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info, GFP_KERNEL);
@@ -2999,13 +3005,6 @@ int open_ctree(struct super_block *sb,
		goto fail_sysfs;
		goto fail_sysfs;
	}
	}


	/*
	 * Hold the cleaner_mutex thread here so that we don't block
	 * for a long time on btrfs_recover_relocation.  cleaner_kthread
	 * will wait for us to finish mounting the filesystem.
	 */
	mutex_lock(&fs_info->cleaner_mutex);
	cleaner_mutex_locked = true;
	fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root,
	fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root,
					       "btrfs-cleaner");
					       "btrfs-cleaner");
	if (IS_ERR(fs_info->cleaner_kthread))
	if (IS_ERR(fs_info->cleaner_kthread))
@@ -3065,8 +3064,10 @@ int open_ctree(struct super_block *sb,
		ret = btrfs_cleanup_fs_roots(fs_info);
		ret = btrfs_cleanup_fs_roots(fs_info);
		if (ret)
		if (ret)
			goto fail_qgroup;
			goto fail_qgroup;
		/* We locked cleaner_mutex before creating cleaner_kthread. */

		mutex_lock(&fs_info->cleaner_mutex);
		ret = btrfs_recover_relocation(tree_root);
		ret = btrfs_recover_relocation(tree_root);
		mutex_unlock(&fs_info->cleaner_mutex);
		if (ret < 0) {
		if (ret < 0) {
			btrfs_warn(fs_info, "failed to recover relocation: %d",
			btrfs_warn(fs_info, "failed to recover relocation: %d",
					ret);
					ret);
@@ -3074,8 +3075,6 @@ int open_ctree(struct super_block *sb,
			goto fail_qgroup;
			goto fail_qgroup;
		}
		}
	}
	}
	mutex_unlock(&fs_info->cleaner_mutex);
	cleaner_mutex_locked = false;


	location.objectid = BTRFS_FS_TREE_OBJECTID;
	location.objectid = BTRFS_FS_TREE_OBJECTID;
	location.type = BTRFS_ROOT_ITEM_KEY;
	location.type = BTRFS_ROOT_ITEM_KEY;
@@ -3189,10 +3188,6 @@ int open_ctree(struct super_block *sb,
	filemap_write_and_wait(fs_info->btree_inode->i_mapping);
	filemap_write_and_wait(fs_info->btree_inode->i_mapping);


fail_sysfs:
fail_sysfs:
	if (cleaner_mutex_locked) {
		mutex_unlock(&fs_info->cleaner_mutex);
		cleaner_mutex_locked = false;
	}
	btrfs_sysfs_remove_mounted(fs_info);
	btrfs_sysfs_remove_mounted(fs_info);


fail_fsdev_sysfs:
fail_fsdev_sysfs:
@@ -4139,7 +4134,8 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
		ret = -EINVAL;
		ret = -EINVAL;
	}
	}
	if (!is_power_of_2(btrfs_super_stripesize(sb)) ||
	if (!is_power_of_2(btrfs_super_stripesize(sb)) ||
	    btrfs_super_stripesize(sb) != sectorsize) {
		((btrfs_super_stripesize(sb) != sectorsize) &&
			(btrfs_super_stripesize(sb) != 4096))) {
		btrfs_err(fs_info, "invalid stripesize %u",
		btrfs_err(fs_info, "invalid stripesize %u",
		       btrfs_super_stripesize(sb));
		       btrfs_super_stripesize(sb));
		ret = -EINVAL;
		ret = -EINVAL;
+7 −5
Original line number Original line Diff line number Diff line
@@ -8016,8 +8016,9 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
	struct extent_buffer *buf;
	struct extent_buffer *buf;


	buf = btrfs_find_create_tree_block(root, bytenr);
	buf = btrfs_find_create_tree_block(root, bytenr);
	if (!buf)
	if (IS_ERR(buf))
		return ERR_PTR(-ENOMEM);
		return buf;

	btrfs_set_header_generation(buf, trans->transid);
	btrfs_set_header_generation(buf, trans->transid);
	btrfs_set_buffer_lockdep_class(root->root_key.objectid, buf, level);
	btrfs_set_buffer_lockdep_class(root->root_key.objectid, buf, level);
	btrfs_tree_lock(buf);
	btrfs_tree_lock(buf);
@@ -8044,7 +8045,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		set_extent_dirty(&trans->transaction->dirty_pages, buf->start,
		set_extent_dirty(&trans->transaction->dirty_pages, buf->start,
			 buf->start + buf->len - 1, GFP_NOFS);
			 buf->start + buf->len - 1, GFP_NOFS);
	}
	}
	trans->blocks_used++;
	trans->dirty = true;
	/* this returns a buffer locked for blocking */
	/* this returns a buffer locked for blocking */
	return buf;
	return buf;
}
}
@@ -8659,8 +8660,9 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
	next = btrfs_find_tree_block(root->fs_info, bytenr);
	next = btrfs_find_tree_block(root->fs_info, bytenr);
	if (!next) {
	if (!next) {
		next = btrfs_find_create_tree_block(root, bytenr);
		next = btrfs_find_create_tree_block(root, bytenr);
		if (!next)
		if (IS_ERR(next))
			return -ENOMEM;
			return PTR_ERR(next);

		btrfs_set_buffer_lockdep_class(root->root_key.objectid, next,
		btrfs_set_buffer_lockdep_class(root->root_key.objectid, next,
					       level - 1);
					       level - 1);
		reada = 1;
		reada = 1;
+12 −3
Original line number Original line Diff line number Diff line
@@ -4892,18 +4892,25 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
	int uptodate = 1;
	int uptodate = 1;
	int ret;
	int ret;


	if (!IS_ALIGNED(start, fs_info->tree_root->sectorsize)) {
		btrfs_err(fs_info, "bad tree block start %llu", start);
		return ERR_PTR(-EINVAL);
	}

	eb = find_extent_buffer(fs_info, start);
	eb = find_extent_buffer(fs_info, start);
	if (eb)
	if (eb)
		return eb;
		return eb;


	eb = __alloc_extent_buffer(fs_info, start, len);
	eb = __alloc_extent_buffer(fs_info, start, len);
	if (!eb)
	if (!eb)
		return NULL;
		return ERR_PTR(-ENOMEM);


	for (i = 0; i < num_pages; i++, index++) {
	for (i = 0; i < num_pages; i++, index++) {
		p = find_or_create_page(mapping, index, GFP_NOFS|__GFP_NOFAIL);
		p = find_or_create_page(mapping, index, GFP_NOFS|__GFP_NOFAIL);
		if (!p)
		if (!p) {
			exists = ERR_PTR(-ENOMEM);
			goto free_eb;
			goto free_eb;
		}


		spin_lock(&mapping->private_lock);
		spin_lock(&mapping->private_lock);
		if (PagePrivate(p)) {
		if (PagePrivate(p)) {
@@ -4948,8 +4955,10 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
		set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
		set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
again:
again:
	ret = radix_tree_preload(GFP_NOFS);
	ret = radix_tree_preload(GFP_NOFS);
	if (ret)
	if (ret) {
		exists = ERR_PTR(ret);
		goto free_eb;
		goto free_eb;
	}


	spin_lock(&fs_info->buffer_lock);
	spin_lock(&fs_info->buffer_lock);
	ret = radix_tree_insert(&fs_info->buffer_radix,
	ret = radix_tree_insert(&fs_info->buffer_radix,
Loading