diff options
Diffstat (limited to 'fs/btrfs/super.c')
| -rw-r--r-- | fs/btrfs/super.c | 39 | 
1 files changed, 35 insertions, 4 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index f452a94abdc3..a906315efd19 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -46,6 +46,7 @@  #include "sysfs.h"  #include "tests/btrfs-tests.h"  #include "block-group.h" +#include "discard.h"  #include "qgroup.h"  #define CREATE_TRACE_POINTS @@ -146,6 +147,8 @@ void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function  	if (sb_rdonly(sb))  		return; +	btrfs_discard_stop(fs_info); +  	/* btrfs handle error by forcing the filesystem readonly */  	sb->s_flags |= SB_RDONLY;  	btrfs_info(fs_info, "forced readonly"); @@ -313,6 +316,7 @@ enum {  	Opt_datasum, Opt_nodatasum,  	Opt_defrag, Opt_nodefrag,  	Opt_discard, Opt_nodiscard, +	Opt_discard_mode,  	Opt_nologreplay,  	Opt_norecovery,  	Opt_ratio, @@ -375,6 +379,7 @@ static const match_table_t tokens = {  	{Opt_defrag, "autodefrag"},  	{Opt_nodefrag, "noautodefrag"},  	{Opt_discard, "discard"}, +	{Opt_discard_mode, "discard=%s"},  	{Opt_nodiscard, "nodiscard"},  	{Opt_nologreplay, "nologreplay"},  	{Opt_norecovery, "norecovery"}, @@ -695,12 +700,26 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,  				   info->metadata_ratio);  			break;  		case Opt_discard: -			btrfs_set_and_info(info, DISCARD, -					   "turning on discard"); +		case Opt_discard_mode: +			if (token == Opt_discard || +			    strcmp(args[0].from, "sync") == 0) { +				btrfs_clear_opt(info->mount_opt, DISCARD_ASYNC); +				btrfs_set_and_info(info, DISCARD_SYNC, +						   "turning on sync discard"); +			} else if (strcmp(args[0].from, "async") == 0) { +				btrfs_clear_opt(info->mount_opt, DISCARD_SYNC); +				btrfs_set_and_info(info, DISCARD_ASYNC, +						   "turning on async discard"); +			} else { +				ret = -EINVAL; +				goto out; +			}  			break;  		case Opt_nodiscard: -			btrfs_clear_and_info(info, DISCARD, +			btrfs_clear_and_info(info, DISCARD_SYNC,  					     "turning off discard"); +			btrfs_clear_and_info(info, DISCARD_ASYNC, +					     "turning off async discard");  			break;  		case Opt_space_cache:  		case Opt_space_cache_version: @@ -1322,8 +1341,10 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)  		seq_puts(seq, ",nologreplay");  	if (btrfs_test_opt(info, FLUSHONCOMMIT))  		seq_puts(seq, ",flushoncommit"); -	if (btrfs_test_opt(info, DISCARD)) +	if (btrfs_test_opt(info, DISCARD_SYNC))  		seq_puts(seq, ",discard"); +	if (btrfs_test_opt(info, DISCARD_ASYNC)) +		seq_puts(seq, ",discard=async");  	if (!(info->sb->s_flags & SB_POSIXACL))  		seq_puts(seq, ",noacl");  	if (btrfs_test_opt(info, SPACE_CACHE)) @@ -1713,6 +1734,14 @@ static inline void btrfs_remount_cleanup(struct btrfs_fs_info *fs_info,  		btrfs_cleanup_defrag_inodes(fs_info);  	} +	/* If we toggled discard async */ +	if (!btrfs_raw_test_opt(old_opts, DISCARD_ASYNC) && +	    btrfs_test_opt(fs_info, DISCARD_ASYNC)) +		btrfs_discard_resume(fs_info); +	else if (btrfs_raw_test_opt(old_opts, DISCARD_ASYNC) && +		 !btrfs_test_opt(fs_info, DISCARD_ASYNC)) +		btrfs_discard_cleanup(fs_info); +  	clear_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state);  } @@ -1760,6 +1789,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)  		 */  		cancel_work_sync(&fs_info->async_reclaim_work); +		btrfs_discard_cleanup(fs_info); +  		/* wait for the uuid_scan task to finish */  		down(&fs_info->uuid_tree_rescan_sem);  		/* avoid complains from lockdep et al. */  |