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

Commit dc81cdc5 authored by Miao Xie's avatar Miao Xie Committed by Chris Mason
Browse files

Btrfs: fix remount vs autodefrag



If we remount the fs to close the auto defragment or make the fs R/O,
we should stop the auto defragment.

Signed-off-by: default avatarMiao Xie <miaox@cn.fujitsu.com>
Signed-off-by: default avatarChris Mason <chris.mason@fusionio.com>
parent 172a5049
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -339,6 +339,7 @@ static inline unsigned long btrfs_chunk_item_size(int num_stripes)
 * File system states
 */
#define BTRFS_FS_STATE_ERROR		0
#define BTRFS_FS_STATE_REMOUNTING	1

/* Super block flags */
/* Errors detected */
@@ -1902,6 +1903,7 @@ struct btrfs_ioctl_defrag_range_args {

#define btrfs_clear_opt(o, opt)		((o) &= ~BTRFS_MOUNT_##opt)
#define btrfs_set_opt(o, opt)		((o) |= BTRFS_MOUNT_##opt)
#define btrfs_raw_test_opt(o, opt)	((o) & BTRFS_MOUNT_##opt)
#define btrfs_test_opt(root, opt)	((root)->fs_info->mount_opt & \
					 BTRFS_MOUNT_##opt)
/*
+5 −0
Original line number Diff line number Diff line
@@ -374,6 +374,11 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info)

	atomic_inc(&fs_info->defrag_running);
	while(1) {
		/* Pause the auto defragger. */
		if (test_bit(BTRFS_FS_STATE_REMOUNTING,
			     &fs_info->fs_state))
			break;

		if (!__need_auto_defrag(fs_info->tree_root))
			break;

+38 −2
Original line number Diff line number Diff line
@@ -1202,6 +1202,38 @@ static void btrfs_resize_thread_pool(struct btrfs_fs_info *fs_info,
			      new_pool_size);
}

static inline void btrfs_remount_prepare(struct btrfs_fs_info *fs_info,
					 unsigned long old_opts, int flags)
{
	set_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state);

	if (btrfs_raw_test_opt(old_opts, AUTO_DEFRAG) &&
	    (!btrfs_raw_test_opt(fs_info->mount_opt, AUTO_DEFRAG) ||
	     (flags & MS_RDONLY))) {
		/* wait for any defraggers to finish */
		wait_event(fs_info->transaction_wait,
			   (atomic_read(&fs_info->defrag_running) == 0));
		if (flags & MS_RDONLY)
			sync_filesystem(fs_info->sb);
	}
}

static inline void btrfs_remount_cleanup(struct btrfs_fs_info *fs_info,
					 unsigned long old_opts)
{
	/*
	 * We need cleanup all defragable inodes if the autodefragment is
	 * close or the fs is R/O.
	 */
	if (btrfs_raw_test_opt(old_opts, AUTO_DEFRAG) &&
	    (!btrfs_raw_test_opt(fs_info->mount_opt, AUTO_DEFRAG) ||
	     (fs_info->sb->s_flags & MS_RDONLY))) {
		btrfs_cleanup_defrag_inodes(fs_info);
	}

	clear_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state);
}

static int btrfs_remount(struct super_block *sb, int *flags, char *data)
{
	struct btrfs_fs_info *fs_info = btrfs_sb(sb);
@@ -1215,6 +1247,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
	unsigned int old_metadata_ratio = fs_info->metadata_ratio;
	int ret;

	btrfs_remount_prepare(fs_info, old_opts, *flags);

	ret = btrfs_parse_options(root, data);
	if (ret) {
		ret = -EINVAL;
@@ -1225,7 +1259,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
		fs_info->thread_pool_size, old_thread_pool_size);

	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
		return 0;
		goto out;

	if (*flags & MS_RDONLY) {
		/*
@@ -1280,7 +1314,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
		}
		sb->s_flags &= ~MS_RDONLY;
	}

out:
	btrfs_remount_cleanup(fs_info, old_opts);
	return 0;

restore:
@@ -1297,6 +1332,7 @@ restore:
	btrfs_resize_thread_pool(fs_info,
		old_thread_pool_size, fs_info->thread_pool_size);
	fs_info->metadata_ratio = old_metadata_ratio;
	btrfs_remount_cleanup(fs_info, old_opts);
	return ret;
}