diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-21 20:49:22 +0300 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-21 20:49:22 +0300 | 
| commit | 07be1337b9e8bfcd855c6e9175b5066a30ac609b (patch) | |
| tree | e40ad01dc89f6eb17d461939b809fea3387fc2a5 /fs/btrfs/disk-io.c | |
| parent | 63d222b9d277c4d7bf08afd1631a7f8e327a825c (diff) | |
| parent | c315ef8d9db7f1a0ebd023a395ebdfde1c68057e (diff) | |
| download | linux-07be1337b9e8bfcd855c6e9175b5066a30ac609b.tar.xz | |
Merge branch 'for-linus-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs updates from Chris Mason:
 "This has our merge window series of cleanups and fixes.  These target
  a wide range of issues, but do include some important fixes for
  qgroups, O_DIRECT, and fsync handling.  Jeff Mahoney moved around a
  few definitions to make them easier for userland to consume.
  Also whiteout support is included now that issues with overlayfs have
  been cleared up.
  I have one more fix pending for page faults during btrfs_copy_from_user,
  but I wanted to get this bulk out the door first"
* 'for-linus-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (90 commits)
  btrfs: fix memory leak during RAID 5/6 device replacement
  Btrfs: add semaphore to synchronize direct IO writes with fsync
  Btrfs: fix race between block group relocation and nocow writes
  Btrfs: fix race between fsync and direct IO writes for prealloc extents
  Btrfs: fix number of transaction units for renames with whiteout
  Btrfs: pin logs earlier when doing a rename exchange operation
  Btrfs: unpin logs if rename exchange operation fails
  Btrfs: fix inode leak on failure to setup whiteout inode in rename
  btrfs: add support for RENAME_EXCHANGE and RENAME_WHITEOUT
  Btrfs: pin log earlier when renaming
  Btrfs: unpin log if rename operation fails
  Btrfs: don't do unnecessary delalloc flushes when relocating
  Btrfs: don't wait for unrelated IO to finish before relocation
  Btrfs: fix empty symlink after creating symlink and fsync parent dir
  Btrfs: fix for incorrect directory entries after fsync log replay
  btrfs: build fixup for qgroup_account_snapshot
  btrfs: qgroup: Fix qgroup accounting when creating snapshot
  Btrfs: fix fspath error deallocation
  btrfs: make find_workspace warn if there are no workspaces
  btrfs: make find_workspace always succeed
  ...
Diffstat (limited to 'fs/btrfs/disk-io.c')
| -rw-r--r-- | fs/btrfs/disk-io.c | 130 | 
1 files changed, 70 insertions, 60 deletions
| diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 4e47849d7427..91d123938cef 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1640,7 +1640,7 @@ int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info,  {  	int ret; -	ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM); +	ret = radix_tree_preload(GFP_NOFS);  	if (ret)  		return ret; @@ -2417,7 +2417,7 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info,  	/* returns with log_tree_root freed on success */  	ret = btrfs_recover_log_trees(log_tree_root);  	if (ret) { -		btrfs_std_error(tree_root->fs_info, ret, +		btrfs_handle_fs_error(tree_root->fs_info, ret,  			    "Failed to recover log tree");  		free_extent_buffer(log_tree_root->node);  		kfree(log_tree_root); @@ -2517,6 +2517,7 @@ 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); @@ -2713,7 +2714,7 @@ int open_ctree(struct super_block *sb,  	 * Pass the whole disk block of size BTRFS_SUPER_INFO_SIZE (4k).  	 */  	if (btrfs_check_super_csum(bh->b_data)) { -		printk(KERN_ERR "BTRFS: superblock checksum mismatch\n"); +		btrfs_err(fs_info, "superblock checksum mismatch");  		err = -EINVAL;  		brelse(bh);  		goto fail_alloc; @@ -2733,7 +2734,7 @@ int open_ctree(struct super_block *sb,  	ret = btrfs_check_super_valid(fs_info, sb->s_flags & MS_RDONLY);  	if (ret) { -		printk(KERN_ERR "BTRFS: superblock contains fatal errors\n"); +		btrfs_err(fs_info, "superblock contains fatal errors");  		err = -EINVAL;  		goto fail_alloc;  	} @@ -2768,9 +2769,9 @@ int open_ctree(struct super_block *sb,  	features = btrfs_super_incompat_flags(disk_super) &  		~BTRFS_FEATURE_INCOMPAT_SUPP;  	if (features) { -		printk(KERN_ERR "BTRFS: couldn't mount because of " -		       "unsupported optional features (%Lx).\n", -		       features); +		btrfs_err(fs_info, +		    "cannot mount because of unsupported optional features (%llx)", +		    features);  		err = -EINVAL;  		goto fail_alloc;  	} @@ -2781,7 +2782,7 @@ int open_ctree(struct super_block *sb,  		features |= BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO;  	if (features & BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA) -		printk(KERN_INFO "BTRFS: has skinny extents\n"); +		btrfs_info(fs_info, "has skinny extents");  	/*  	 * flag our filesystem as having big metadata blocks if @@ -2789,7 +2790,8 @@ int open_ctree(struct super_block *sb,  	 */  	if (btrfs_super_nodesize(disk_super) > PAGE_SIZE) {  		if (!(features & BTRFS_FEATURE_INCOMPAT_BIG_METADATA)) -			printk(KERN_INFO "BTRFS: flagging fs with big metadata feature\n"); +			btrfs_info(fs_info, +				"flagging fs with big metadata feature");  		features |= BTRFS_FEATURE_INCOMPAT_BIG_METADATA;  	} @@ -2805,9 +2807,9 @@ int open_ctree(struct super_block *sb,  	 */  	if ((features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) &&  	    (sectorsize != nodesize)) { -		printk(KERN_ERR "BTRFS: unequal leaf/node/sector sizes " -				"are not allowed for mixed block groups on %s\n", -				sb->s_id); +		btrfs_err(fs_info, +"unequal nodesize/sectorsize (%u != %u) are not allowed for mixed block groups", +			nodesize, sectorsize);  		goto fail_alloc;  	} @@ -2820,8 +2822,8 @@ int open_ctree(struct super_block *sb,  	features = btrfs_super_compat_ro_flags(disk_super) &  		~BTRFS_FEATURE_COMPAT_RO_SUPP;  	if (!(sb->s_flags & MS_RDONLY) && features) { -		printk(KERN_ERR "BTRFS: couldn't mount RDWR because of " -		       "unsupported option features (%Lx).\n", +		btrfs_err(fs_info, +	"cannot mount read-write because of unsupported optional features (%llx)",  		       features);  		err = -EINVAL;  		goto fail_alloc; @@ -2850,8 +2852,7 @@ int open_ctree(struct super_block *sb,  	ret = btrfs_read_sys_array(tree_root);  	mutex_unlock(&fs_info->chunk_mutex);  	if (ret) { -		printk(KERN_ERR "BTRFS: failed to read the system " -		       "array on %s\n", sb->s_id); +		btrfs_err(fs_info, "failed to read the system array: %d", ret);  		goto fail_sb_buffer;  	} @@ -2865,8 +2866,7 @@ int open_ctree(struct super_block *sb,  					   generation);  	if (IS_ERR(chunk_root->node) ||  	    !extent_buffer_uptodate(chunk_root->node)) { -		printk(KERN_ERR "BTRFS: failed to read chunk root on %s\n", -		       sb->s_id); +		btrfs_err(fs_info, "failed to read chunk root");  		if (!IS_ERR(chunk_root->node))  			free_extent_buffer(chunk_root->node);  		chunk_root->node = NULL; @@ -2880,8 +2880,7 @@ int open_ctree(struct super_block *sb,  	ret = btrfs_read_chunk_tree(chunk_root);  	if (ret) { -		printk(KERN_ERR "BTRFS: failed to read chunk tree on %s\n", -		       sb->s_id); +		btrfs_err(fs_info, "failed to read chunk tree: %d", ret);  		goto fail_tree_roots;  	} @@ -2892,8 +2891,7 @@ int open_ctree(struct super_block *sb,  	btrfs_close_extra_devices(fs_devices, 0);  	if (!fs_devices->latest_bdev) { -		printk(KERN_ERR "BTRFS: failed to read devices on %s\n", -		       sb->s_id); +		btrfs_err(fs_info, "failed to read devices");  		goto fail_tree_roots;  	} @@ -2905,8 +2903,7 @@ retry_root_backup:  					  generation);  	if (IS_ERR(tree_root->node) ||  	    !extent_buffer_uptodate(tree_root->node)) { -		printk(KERN_WARNING "BTRFS: failed to read tree root on %s\n", -		       sb->s_id); +		btrfs_warn(fs_info, "failed to read tree root");  		if (!IS_ERR(tree_root->node))  			free_extent_buffer(tree_root->node);  		tree_root->node = NULL; @@ -2938,20 +2935,19 @@ retry_root_backup:  	ret = btrfs_recover_balance(fs_info);  	if (ret) { -		printk(KERN_ERR "BTRFS: failed to recover balance\n"); +		btrfs_err(fs_info, "failed to recover balance: %d", ret);  		goto fail_block_groups;  	}  	ret = btrfs_init_dev_stats(fs_info);  	if (ret) { -		printk(KERN_ERR "BTRFS: failed to init dev_stats: %d\n", -		       ret); +		btrfs_err(fs_info, "failed to init dev_stats: %d", ret);  		goto fail_block_groups;  	}  	ret = btrfs_init_dev_replace(fs_info);  	if (ret) { -		pr_err("BTRFS: failed to init dev_replace: %d\n", ret); +		btrfs_err(fs_info, "failed to init dev_replace: %d", ret);  		goto fail_block_groups;  	} @@ -2959,31 +2955,33 @@ retry_root_backup:  	ret = btrfs_sysfs_add_fsid(fs_devices, NULL);  	if (ret) { -		pr_err("BTRFS: failed to init sysfs fsid interface: %d\n", ret); +		btrfs_err(fs_info, "failed to init sysfs fsid interface: %d", +				ret);  		goto fail_block_groups;  	}  	ret = btrfs_sysfs_add_device(fs_devices);  	if (ret) { -		pr_err("BTRFS: failed to init sysfs device interface: %d\n", ret); +		btrfs_err(fs_info, "failed to init sysfs device interface: %d", +				ret);  		goto fail_fsdev_sysfs;  	}  	ret = btrfs_sysfs_add_mounted(fs_info);  	if (ret) { -		pr_err("BTRFS: failed to init sysfs interface: %d\n", ret); +		btrfs_err(fs_info, "failed to init sysfs interface: %d", ret);  		goto fail_fsdev_sysfs;  	}  	ret = btrfs_init_space_info(fs_info);  	if (ret) { -		printk(KERN_ERR "BTRFS: Failed to initial space info: %d\n", ret); +		btrfs_err(fs_info, "failed to initialize space info: %d", ret);  		goto fail_sysfs;  	}  	ret = btrfs_read_block_groups(fs_info->extent_root);  	if (ret) { -		printk(KERN_ERR "BTRFS: Failed to read block groups: %d\n", ret); +		btrfs_err(fs_info, "failed to read block groups: %d", ret);  		goto fail_sysfs;  	}  	fs_info->num_tolerated_disk_barrier_failures = @@ -2991,12 +2989,20 @@ retry_root_backup:  	if (fs_info->fs_devices->missing_devices >  	     fs_info->num_tolerated_disk_barrier_failures &&  	    !(sb->s_flags & MS_RDONLY)) { -		pr_warn("BTRFS: missing devices(%llu) exceeds the limit(%d), writeable mount is not allowed\n", +		btrfs_warn(fs_info, +"missing devices (%llu) exceeds the limit (%d), writeable mount is not allowed",  			fs_info->fs_devices->missing_devices,  			fs_info->num_tolerated_disk_barrier_failures);  		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)) @@ -3011,8 +3017,7 @@ retry_root_backup:  	if (!btrfs_test_opt(tree_root, SSD) &&  	    !btrfs_test_opt(tree_root, NOSSD) &&  	    !fs_info->fs_devices->rotating) { -		printk(KERN_INFO "BTRFS: detected SSD devices, enabling SSD " -		       "mode\n"); +		btrfs_info(fs_info, "detected SSD devices, enabling SSD mode");  		btrfs_set_opt(fs_info->mount_opt, SSD);  	} @@ -3030,8 +3035,9 @@ retry_root_backup:  				    1 : 0,  				    fs_info->check_integrity_print_mask);  		if (ret) -			printk(KERN_WARNING "BTRFS: failed to initialize" -			       " integrity check module %s\n", sb->s_id); +			btrfs_warn(fs_info, +				"failed to initialize integrity check module: %d", +				ret);  	}  #endif  	ret = btrfs_read_qgroup_config(fs_info); @@ -3056,17 +3062,17 @@ retry_root_backup:  		ret = btrfs_cleanup_fs_roots(fs_info);  		if (ret)  			goto fail_qgroup; - -		mutex_lock(&fs_info->cleaner_mutex); +		/* We locked cleaner_mutex before creating cleaner_kthread. */  		ret = btrfs_recover_relocation(tree_root); -		mutex_unlock(&fs_info->cleaner_mutex);  		if (ret < 0) { -			printk(KERN_WARNING -			       "BTRFS: failed to recover relocation\n"); +			btrfs_warn(fs_info, "failed to recover relocation: %d", +					ret);  			err = -EINVAL;  			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; @@ -3083,11 +3089,11 @@ retry_root_backup:  	if (btrfs_test_opt(tree_root, FREE_SPACE_TREE) &&  	    !btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) { -		pr_info("BTRFS: creating free space tree\n"); +		btrfs_info(fs_info, "creating free space tree");  		ret = btrfs_create_free_space_tree(fs_info);  		if (ret) { -			pr_warn("BTRFS: failed to create free space tree %d\n", -				ret); +			btrfs_warn(fs_info, +				"failed to create free space tree: %d", ret);  			close_ctree(tree_root);  			return ret;  		} @@ -3104,14 +3110,14 @@ retry_root_backup:  	ret = btrfs_resume_balance_async(fs_info);  	if (ret) { -		printk(KERN_WARNING "BTRFS: failed to resume balance\n"); +		btrfs_warn(fs_info, "failed to resume balance: %d", ret);  		close_ctree(tree_root);  		return ret;  	}  	ret = btrfs_resume_dev_replace_async(fs_info);  	if (ret) { -		pr_warn("BTRFS: failed to resume dev_replace\n"); +		btrfs_warn(fs_info, "failed to resume device replace: %d", ret);  		close_ctree(tree_root);  		return ret;  	} @@ -3120,33 +3126,33 @@ retry_root_backup:  	if (btrfs_test_opt(tree_root, CLEAR_CACHE) &&  	    btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) { -		pr_info("BTRFS: clearing free space tree\n"); +		btrfs_info(fs_info, "clearing free space tree");  		ret = btrfs_clear_free_space_tree(fs_info);  		if (ret) { -			pr_warn("BTRFS: failed to clear free space tree %d\n", -				ret); +			btrfs_warn(fs_info, +				"failed to clear free space tree: %d", ret);  			close_ctree(tree_root);  			return ret;  		}  	}  	if (!fs_info->uuid_root) { -		pr_info("BTRFS: creating UUID tree\n"); +		btrfs_info(fs_info, "creating UUID tree");  		ret = btrfs_create_uuid_tree(fs_info);  		if (ret) { -			pr_warn("BTRFS: failed to create the UUID tree %d\n", -				ret); +			btrfs_warn(fs_info, +				"failed to create the UUID tree: %d", ret);  			close_ctree(tree_root);  			return ret;  		}  	} else if (btrfs_test_opt(tree_root, RESCAN_UUID_TREE) ||  		   fs_info->generation !=  				btrfs_super_uuid_tree_generation(disk_super)) { -		pr_info("BTRFS: checking UUID tree\n"); +		btrfs_info(fs_info, "checking UUID tree");  		ret = btrfs_check_uuid_tree(fs_info);  		if (ret) { -			pr_warn("BTRFS: failed to check the UUID tree %d\n", -				ret); +			btrfs_warn(fs_info, +				"failed to check the UUID tree: %d", ret);  			close_ctree(tree_root);  			return ret;  		} @@ -3180,6 +3186,10 @@ 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: @@ -3646,7 +3656,7 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors)  		if (ret) {  			mutex_unlock(  				&root->fs_info->fs_devices->device_list_mutex); -			btrfs_std_error(root->fs_info, ret, +			btrfs_handle_fs_error(root->fs_info, ret,  				    "errors while submitting device barriers.");  			return ret;  		} @@ -3686,7 +3696,7 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors)  		mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);  		/* FUA is masked off if unsupported and can't be the reason */ -		btrfs_std_error(root->fs_info, -EIO, +		btrfs_handle_fs_error(root->fs_info, -EIO,  			    "%d errors while writing supers", total_errors);  		return -EIO;  	} @@ -3704,7 +3714,7 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors)  	}  	mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);  	if (total_errors > max_errors) { -		btrfs_std_error(root->fs_info, -EIO, +		btrfs_handle_fs_error(root->fs_info, -EIO,  			    "%d errors while writing supers", total_errors);  		return -EIO;  	} | 
