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

Commit 2101ae42 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull more btrfs updates from Chris Mason:
 "These are mostly fixes that we've been testing, but also we grabbed
  and tested a few small cleanups that had been on the list for a while.

  Zhao Lei's patchset also fixes some early ENOSPC buglets"

* 'for-linus-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (21 commits)
  btrfs: raid56: Use raid_write_end_io for scrub
  btrfs: Remove unnecessary ClearPageUptodate for raid56
  btrfs: use rbio->nr_pages to reduce calculation
  btrfs: Use unified stripe_page's index calculation
  btrfs: Fix calculation of rbio->dbitmap's size calculation
  btrfs: Fix no_space in write and rm loop
  btrfs: merge functions for wait snapshot creation
  btrfs: delete unused argument in btrfs_copy_from_user
  btrfs: Use direct way to determine raid56 write/recover mode
  btrfs: Small cleanup for get index_srcdev loop
  btrfs: Enhance chunk validation check
  btrfs: Enhance super validation check
  Btrfs: fix deadlock running delayed iputs at transaction commit time
  Btrfs: fix typo in log message when starting a balance
  btrfs: remove duplicate const specifier
  btrfs: initialize the seq counter in struct btrfs_device
  Btrfs: clean up an error code in btrfs_init_space_info()
  btrfs: fix iterator with update error in backref.c
  Btrfs: fix output of compression message in btrfs_parse_options()
  Btrfs: Initialize btrfs_root->highest_objectid when loading tree root and subvolume roots
  ...
parents 391f2a16 a6111d11
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -560,13 +560,13 @@ static int __add_missing_keys(struct btrfs_fs_info *fs_info,
 */
static void __merge_refs(struct list_head *head, int mode)
{
	struct __prelim_ref *ref1;
	struct __prelim_ref *pos1;

	list_for_each_entry(ref1, head, list) {
		struct __prelim_ref *ref2 = ref1, *tmp;
	list_for_each_entry(pos1, head, list) {
		struct __prelim_ref *pos2 = pos1, *tmp;

		list_for_each_entry_safe_continue(ref2, tmp, head, list) {
			struct __prelim_ref *xchg;
		list_for_each_entry_safe_continue(pos2, tmp, head, list) {
			struct __prelim_ref *xchg, *ref1 = pos1, *ref2 = pos2;
			struct extent_inode_elem *eie;

			if (!ref_for_same_block(ref1, ref2))
+2 −1
Original line number Diff line number Diff line
@@ -1614,7 +1614,7 @@ struct btrfs_fs_info {

	spinlock_t delayed_iput_lock;
	struct list_head delayed_iputs;
	struct rw_semaphore delayed_iput_sem;
	struct mutex cleaner_delayed_iput_mutex;

	/* this protects tree_mod_seq_list */
	spinlock_t tree_mod_seq_lock;
@@ -3641,6 +3641,7 @@ int btrfs_delayed_refs_qgroup_accounting(struct btrfs_trans_handle *trans,
int __get_raid_index(u64 flags);
int btrfs_start_write_no_snapshoting(struct btrfs_root *root);
void btrfs_end_write_no_snapshoting(struct btrfs_root *root);
void btrfs_wait_for_snapshot_creation(struct btrfs_root *root);
void check_system_chunk(struct btrfs_trans_handle *trans,
			struct btrfs_root *root,
			const u64 type);
+1 −1
Original line number Diff line number Diff line
@@ -614,7 +614,7 @@ static void btrfs_dev_replace_update_device_in_mapping_tree(
		em = lookup_extent_mapping(em_tree, start, (u64)-1);
		if (!em)
			break;
		map = (struct map_lookup *)em->bdev;
		map = em->map_lookup;
		for (i = 0; i < map->num_stripes; i++)
			if (srcdev == map->stripes[i].dev)
				map->stripes[i].dev = tgtdev;
+79 −50
Original line number Diff line number Diff line
@@ -55,6 +55,12 @@
#include <asm/cpufeature.h>
#endif

#define BTRFS_SUPER_FLAG_SUPP	(BTRFS_HEADER_FLAG_WRITTEN |\
				 BTRFS_HEADER_FLAG_RELOC |\
				 BTRFS_SUPER_FLAG_ERROR |\
				 BTRFS_SUPER_FLAG_SEEDING |\
				 BTRFS_SUPER_FLAG_METADUMP)

static const struct extent_io_ops btree_extent_io_ops;
static void end_workqueue_fn(struct btrfs_work *work);
static void free_fs_root(struct btrfs_root *root);
@@ -1583,8 +1589,23 @@ int btrfs_init_fs_root(struct btrfs_root *root)
	ret = get_anon_bdev(&root->anon_dev);
	if (ret)
		goto free_writers;

	mutex_lock(&root->objectid_mutex);
	ret = btrfs_find_highest_objectid(root,
					&root->highest_objectid);
	if (ret) {
		mutex_unlock(&root->objectid_mutex);
		goto free_root_dev;
	}

	ASSERT(root->highest_objectid <= BTRFS_LAST_FREE_OBJECTID);

	mutex_unlock(&root->objectid_mutex);

	return 0;

free_root_dev:
	free_anon_bdev(root->anon_dev);
free_writers:
	btrfs_free_subvolume_writers(root->subv_writers);
fail:
@@ -1786,7 +1807,10 @@ static int cleaner_kthread(void *arg)
			goto sleep;
		}

		mutex_lock(&root->fs_info->cleaner_delayed_iput_mutex);
		btrfs_run_delayed_iputs(root);
		mutex_unlock(&root->fs_info->cleaner_delayed_iput_mutex);

		again = btrfs_clean_one_deleted_snapshot(root);
		mutex_unlock(&root->fs_info->cleaner_mutex);

@@ -2556,8 +2580,8 @@ int open_ctree(struct super_block *sb,
	mutex_init(&fs_info->delete_unused_bgs_mutex);
	mutex_init(&fs_info->reloc_mutex);
	mutex_init(&fs_info->delalloc_root_mutex);
	mutex_init(&fs_info->cleaner_delayed_iput_mutex);
	seqlock_init(&fs_info->profiles_lock);
	init_rwsem(&fs_info->delayed_iput_sem);

	INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots);
	INIT_LIST_HEAD(&fs_info->space_info);
@@ -2742,26 +2766,6 @@ int open_ctree(struct super_block *sb,
		goto fail_alloc;
	}

	/*
	 * Leafsize and nodesize were always equal, this is only a sanity check.
	 */
	if (le32_to_cpu(disk_super->__unused_leafsize) !=
	    btrfs_super_nodesize(disk_super)) {
		printk(KERN_ERR "BTRFS: couldn't mount because metadata "
		       "blocksizes don't match.  node %d leaf %d\n",
		       btrfs_super_nodesize(disk_super),
		       le32_to_cpu(disk_super->__unused_leafsize));
		err = -EINVAL;
		goto fail_alloc;
	}
	if (btrfs_super_nodesize(disk_super) > BTRFS_MAX_METADATA_BLOCKSIZE) {
		printk(KERN_ERR "BTRFS: couldn't mount because metadata "
		       "blocksize (%d) was too large\n",
		       btrfs_super_nodesize(disk_super));
		err = -EINVAL;
		goto fail_alloc;
	}

	features = btrfs_super_incompat_flags(disk_super);
	features |= BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF;
	if (tree_root->fs_info->compress_type == BTRFS_COMPRESS_LZO)
@@ -2833,17 +2837,6 @@ int open_ctree(struct super_block *sb,
	sb->s_blocksize = sectorsize;
	sb->s_blocksize_bits = blksize_bits(sectorsize);

	if (btrfs_super_magic(disk_super) != BTRFS_MAGIC) {
		printk(KERN_ERR "BTRFS: valid FS not found on %s\n", sb->s_id);
		goto fail_sb_buffer;
	}

	if (sectorsize != PAGE_SIZE) {
		printk(KERN_ERR "BTRFS: incompatible sector size (%lu) "
		       "found on %s\n", (unsigned long)sectorsize, sb->s_id);
		goto fail_sb_buffer;
	}

	mutex_lock(&fs_info->chunk_mutex);
	ret = btrfs_read_sys_array(tree_root);
	mutex_unlock(&fs_info->chunk_mutex);
@@ -2915,6 +2908,18 @@ int open_ctree(struct super_block *sb,
	tree_root->commit_root = btrfs_root_node(tree_root);
	btrfs_set_root_refs(&tree_root->root_item, 1);

	mutex_lock(&tree_root->objectid_mutex);
	ret = btrfs_find_highest_objectid(tree_root,
					&tree_root->highest_objectid);
	if (ret) {
		mutex_unlock(&tree_root->objectid_mutex);
		goto recovery_tree_root;
	}

	ASSERT(tree_root->highest_objectid <= BTRFS_LAST_FREE_OBJECTID);

	mutex_unlock(&tree_root->objectid_mutex);

	ret = btrfs_read_roots(fs_info, tree_root);
	if (ret)
		goto recovery_tree_root;
@@ -4018,8 +4023,17 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
			      int read_only)
{
	struct btrfs_super_block *sb = fs_info->super_copy;
	u64 nodesize = btrfs_super_nodesize(sb);
	u64 sectorsize = btrfs_super_sectorsize(sb);
	int ret = 0;

	if (btrfs_super_magic(sb) != BTRFS_MAGIC) {
		printk(KERN_ERR "BTRFS: no valid FS found\n");
		ret = -EINVAL;
	}
	if (btrfs_super_flags(sb) & ~BTRFS_SUPER_FLAG_SUPP)
		printk(KERN_WARNING "BTRFS: unrecognized super flag: %llu\n",
				btrfs_super_flags(sb) & ~BTRFS_SUPER_FLAG_SUPP);
	if (btrfs_super_root_level(sb) >= BTRFS_MAX_LEVEL) {
		printk(KERN_ERR "BTRFS: tree_root level too big: %d >= %d\n",
				btrfs_super_root_level(sb), BTRFS_MAX_LEVEL);
@@ -4037,31 +4051,46 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
	}

	/*
	 * The common minimum, we don't know if we can trust the nodesize/sectorsize
	 * items yet, they'll be verified later. Issue just a warning.
	 * Check sectorsize and nodesize first, other check will need it.
	 * Check all possible sectorsize(4K, 8K, 16K, 32K, 64K) here.
	 */
	if (!IS_ALIGNED(btrfs_super_root(sb), 4096))
	if (!is_power_of_2(sectorsize) || sectorsize < 4096 ||
	    sectorsize > BTRFS_MAX_METADATA_BLOCKSIZE) {
		printk(KERN_ERR "BTRFS: invalid sectorsize %llu\n", sectorsize);
		ret = -EINVAL;
	}
	/* Only PAGE SIZE is supported yet */
	if (sectorsize != PAGE_CACHE_SIZE) {
		printk(KERN_ERR "BTRFS: sectorsize %llu not supported yet, only support %lu\n",
				sectorsize, PAGE_CACHE_SIZE);
		ret = -EINVAL;
	}
	if (!is_power_of_2(nodesize) || nodesize < sectorsize ||
	    nodesize > BTRFS_MAX_METADATA_BLOCKSIZE) {
		printk(KERN_ERR "BTRFS: invalid nodesize %llu\n", nodesize);
		ret = -EINVAL;
	}
	if (nodesize != le32_to_cpu(sb->__unused_leafsize)) {
		printk(KERN_ERR "BTRFS: invalid leafsize %u, should be %llu\n",
				le32_to_cpu(sb->__unused_leafsize),
				nodesize);
		ret = -EINVAL;
	}

	/* Root alignment check */
	if (!IS_ALIGNED(btrfs_super_root(sb), sectorsize)) {
		printk(KERN_WARNING "BTRFS: tree_root block unaligned: %llu\n",
				btrfs_super_root(sb));
	if (!IS_ALIGNED(btrfs_super_chunk_root(sb), 4096))
		ret = -EINVAL;
	}
	if (!IS_ALIGNED(btrfs_super_chunk_root(sb), sectorsize)) {
		printk(KERN_WARNING "BTRFS: chunk_root block unaligned: %llu\n",
				btrfs_super_chunk_root(sb));
	if (!IS_ALIGNED(btrfs_super_log_root(sb), 4096))
		printk(KERN_WARNING "BTRFS: log_root block unaligned: %llu\n",
				btrfs_super_log_root(sb));

	/*
	 * Check the lower bound, the alignment and other constraints are
	 * checked later.
	 */
	if (btrfs_super_nodesize(sb) < 4096) {
		printk(KERN_ERR "BTRFS: nodesize too small: %u < 4096\n",
				btrfs_super_nodesize(sb));
		ret = -EINVAL;
	}
	if (btrfs_super_sectorsize(sb) < 4096) {
		printk(KERN_ERR "BTRFS: sectorsize too small: %u < 4096\n",
				btrfs_super_sectorsize(sb));
	if (!IS_ALIGNED(btrfs_super_log_root(sb), sectorsize)) {
		printk(KERN_WARNING "BTRFS: log_root block unaligned: %llu\n",
				btrfs_super_log_root(sb));
		ret = -EINVAL;
	}

+30 −7
Original line number Diff line number Diff line
@@ -4139,8 +4139,10 @@ int btrfs_alloc_data_chunk_ondemand(struct inode *inode, u64 bytes)
		    !atomic_read(&root->fs_info->open_ioctl_trans)) {
			need_commit--;

			if (need_commit > 0)
			if (need_commit > 0) {
				btrfs_start_delalloc_roots(fs_info, 0, -1);
				btrfs_wait_ordered_roots(fs_info, -1);
			}

			trans = btrfs_join_transaction(root);
			if (IS_ERR(trans))
@@ -4153,11 +4155,12 @@ int btrfs_alloc_data_chunk_ondemand(struct inode *inode, u64 bytes)
				if (ret)
					return ret;
				/*
				 * make sure that all running delayed iput are
				 * done
				 * The cleaner kthread might still be doing iput
				 * operations. Wait for it to finish so that
				 * more space is released.
				 */
				down_write(&root->fs_info->delayed_iput_sem);
				up_write(&root->fs_info->delayed_iput_sem);
				mutex_lock(&root->fs_info->cleaner_delayed_iput_mutex);
				mutex_unlock(&root->fs_info->cleaner_delayed_iput_mutex);
				goto again;
			} else {
				btrfs_end_transaction(trans, root);
@@ -10399,7 +10402,7 @@ btrfs_start_trans_remove_block_group(struct btrfs_fs_info *fs_info,
	 * more device items and remove one chunk item), but this is done at
	 * btrfs_remove_chunk() through a call to check_system_chunk().
	 */
	map = (struct map_lookup *)em->bdev;
	map = em->map_lookup;
	num_items = 3 + map->num_stripes;
	free_extent_map(em);

@@ -10586,7 +10589,7 @@ int btrfs_init_space_info(struct btrfs_fs_info *fs_info)

	disk_super = fs_info->super_copy;
	if (!btrfs_super_root(disk_super))
		return 1;
		return -EINVAL;

	features = btrfs_super_incompat_flags(disk_super);
	if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS)
@@ -10816,3 +10819,23 @@ int btrfs_start_write_no_snapshoting(struct btrfs_root *root)
	}
	return 1;
}

static int wait_snapshoting_atomic_t(atomic_t *a)
{
	schedule();
	return 0;
}

void btrfs_wait_for_snapshot_creation(struct btrfs_root *root)
{
	while (true) {
		int ret;

		ret = btrfs_start_write_no_snapshoting(root);
		if (ret)
			break;
		wait_on_atomic_t(&root->will_be_snapshoted,
				 wait_snapshoting_atomic_t,
				 TASK_UNINTERRUPTIBLE);
	}
}
Loading