diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
| -rw-r--r-- | fs/btrfs/disk-io.c | 54 | 
1 files changed, 31 insertions, 23 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 6628fca9f4ed..60ce1190307b 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1098,7 +1098,7 @@ void readahead_tree_block(struct btrfs_root *root, u64 bytenr)  	struct inode *btree_inode = root->fs_info->btree_inode;  	buf = btrfs_find_create_tree_block(root, bytenr); -	if (!buf) +	if (IS_ERR(buf))  		return;  	read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree,  				 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;  	buf = btrfs_find_create_tree_block(root, bytenr); -	if (!buf) +	if (IS_ERR(buf))  		return 0;  	set_bit(EXTENT_BUFFER_READAHEAD, &buf->bflags); @@ -1147,7 +1147,8 @@ struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,  						 u64 bytenr)  {  	if (btrfs_test_is_dummy_root(root)) -		return alloc_test_extent_buffer(root->fs_info, bytenr); +		return alloc_test_extent_buffer(root->fs_info, bytenr, +				root->nodesize);  	return alloc_extent_buffer(root->fs_info, bytenr);  } @@ -1171,8 +1172,8 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,  	int ret;  	buf = btrfs_find_create_tree_block(root, bytenr); -	if (!buf) -		return ERR_PTR(-ENOMEM); +	if (IS_ERR(buf)) +		return buf;  	ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);  	if (ret) { @@ -1314,14 +1315,16 @@ static struct btrfs_root *btrfs_alloc_root(struct btrfs_fs_info *fs_info,  #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS  /* Should only be used by the testing infrastructure */ -struct btrfs_root *btrfs_alloc_dummy_root(void) +struct btrfs_root *btrfs_alloc_dummy_root(u32 sectorsize, u32 nodesize)  {  	struct btrfs_root *root;  	root = btrfs_alloc_root(NULL, GFP_KERNEL);  	if (!root)  		return ERR_PTR(-ENOMEM); -	__setup_root(4096, 4096, 4096, root, NULL, 1); +	/* We don't use the stripesize in selftest, set it as sectorsize */ +	__setup_root(nodesize, sectorsize, sectorsize, root, NULL, +			BTRFS_ROOT_TREE_OBJECTID);  	set_bit(BTRFS_ROOT_DUMMY_ROOT, &root->state);  	root->alloc_bytenr = 0; @@ -1803,6 +1806,13 @@ static int cleaner_kthread(void *arg)  		if (btrfs_need_cleaner_sleep(root))  			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))  			goto sleep; @@ -2517,7 +2527,6 @@ int open_ctree(struct super_block *sb,  	int num_backups_tried = 0;  	int backup_index = 0;  	int max_active; -	bool cleaner_mutex_locked = false;  	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); @@ -2797,7 +2806,7 @@ int open_ctree(struct super_block *sb,  	nodesize = btrfs_super_nodesize(disk_super);  	sectorsize = btrfs_super_sectorsize(disk_super); -	stripesize = btrfs_super_stripesize(disk_super); +	stripesize = sectorsize;  	fs_info->dirty_metadata_batch = nodesize * (1 + ilog2(nr_cpu_ids));  	fs_info->delalloc_batch = sectorsize * 512 * (1 + ilog2(nr_cpu_ids)); @@ -2996,13 +3005,6 @@ retry_root_backup:  		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,  					       "btrfs-cleaner");  	if (IS_ERR(fs_info->cleaner_kthread)) @@ -3062,8 +3064,10 @@ retry_root_backup:  		ret = btrfs_cleanup_fs_roots(fs_info);  		if (ret)  			goto fail_qgroup; -		/* We locked cleaner_mutex before creating cleaner_kthread. */ + +		mutex_lock(&fs_info->cleaner_mutex);  		ret = btrfs_recover_relocation(tree_root); +		mutex_unlock(&fs_info->cleaner_mutex);  		if (ret < 0) {  			btrfs_warn(fs_info, "failed to recover relocation: %d",  					ret); @@ -3071,8 +3075,6 @@ retry_root_backup:  			goto fail_qgroup;  		}  	} -	mutex_unlock(&fs_info->cleaner_mutex); -	cleaner_mutex_locked = false;  	location.objectid = BTRFS_FS_TREE_OBJECTID;  	location.type = BTRFS_ROOT_ITEM_KEY; @@ -3186,10 +3188,6 @@ fail_cleaner:  	filemap_write_and_wait(fs_info->btree_inode->i_mapping);  fail_sysfs: -	if (cleaner_mutex_locked) { -		mutex_unlock(&fs_info->cleaner_mutex); -		cleaner_mutex_locked = false; -	}  	btrfs_sysfs_remove_mounted(fs_info);  fail_fsdev_sysfs: @@ -4130,6 +4128,16 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,  	 * Hint to catch really bogus numbers, bitflips or so, more exact checks are  	 * done later  	 */ +	if (btrfs_super_bytes_used(sb) < 6 * btrfs_super_nodesize(sb)) { +		btrfs_err(fs_info, "bytes_used is too small %llu", +		       btrfs_super_bytes_used(sb)); +		ret = -EINVAL; +	} +	if (!is_power_of_2(btrfs_super_stripesize(sb))) { +		btrfs_err(fs_info, "invalid stripesize %u", +		       btrfs_super_stripesize(sb)); +		ret = -EINVAL; +	}  	if (btrfs_super_num_devices(sb) > (1UL << 31))  		printk(KERN_WARNING "BTRFS: suspicious number of devices: %llu\n",  				btrfs_super_num_devices(sb));  |