aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2013-02-21 01:32:52 -0500
committerChris Mason <chris.mason@fusionio.com>2013-02-21 08:11:43 -0500
commitdc81cdc58ad2f413b96b9004f8d681e5dc554473 (patch)
tree71f87fc0e172167755f1f572af3b77cb7aff46a7 /fs/btrfs
parent172a50497ffaf84d60dff37fbeb03894268fe5c2 (diff)
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: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/file.c5
-rw-r--r--fs/btrfs/super.c40
3 files changed, 45 insertions, 2 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 3dcedfe4f759..ae8dcc406805 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -339,6 +339,7 @@ static inline unsigned long btrfs_chunk_item_size(int num_stripes)
339 * File system states 339 * File system states
340 */ 340 */
341#define BTRFS_FS_STATE_ERROR 0 341#define BTRFS_FS_STATE_ERROR 0
342#define BTRFS_FS_STATE_REMOUNTING 1
342 343
343/* Super block flags */ 344/* Super block flags */
344/* Errors detected */ 345/* Errors detected */
@@ -1902,6 +1903,7 @@ struct btrfs_ioctl_defrag_range_args {
1902 1903
1903#define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt) 1904#define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt)
1904#define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt) 1905#define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt)
1906#define btrfs_raw_test_opt(o, opt) ((o) & BTRFS_MOUNT_##opt)
1905#define btrfs_test_opt(root, opt) ((root)->fs_info->mount_opt & \ 1907#define btrfs_test_opt(root, opt) ((root)->fs_info->mount_opt & \
1906 BTRFS_MOUNT_##opt) 1908 BTRFS_MOUNT_##opt)
1907/* 1909/*
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 9f67e623206d..6e6dd8cdad92 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -374,6 +374,11 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info)
374 374
375 atomic_inc(&fs_info->defrag_running); 375 atomic_inc(&fs_info->defrag_running);
376 while(1) { 376 while(1) {
377 /* Pause the auto defragger. */
378 if (test_bit(BTRFS_FS_STATE_REMOUNTING,
379 &fs_info->fs_state))
380 break;
381
377 if (!__need_auto_defrag(fs_info->tree_root)) 382 if (!__need_auto_defrag(fs_info->tree_root))
378 break; 383 break;
379 384
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index db1ba9a2ed64..68a29a1ea068 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -1202,6 +1202,38 @@ static void btrfs_resize_thread_pool(struct btrfs_fs_info *fs_info,
1202 new_pool_size); 1202 new_pool_size);
1203} 1203}
1204 1204
1205static inline void btrfs_remount_prepare(struct btrfs_fs_info *fs_info,
1206 unsigned long old_opts, int flags)
1207{
1208 set_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state);
1209
1210 if (btrfs_raw_test_opt(old_opts, AUTO_DEFRAG) &&
1211 (!btrfs_raw_test_opt(fs_info->mount_opt, AUTO_DEFRAG) ||
1212 (flags & MS_RDONLY))) {
1213 /* wait for any defraggers to finish */
1214 wait_event(fs_info->transaction_wait,
1215 (atomic_read(&fs_info->defrag_running) == 0));
1216 if (flags & MS_RDONLY)
1217 sync_filesystem(fs_info->sb);
1218 }
1219}
1220
1221static inline void btrfs_remount_cleanup(struct btrfs_fs_info *fs_info,
1222 unsigned long old_opts)
1223{
1224 /*
1225 * We need cleanup all defragable inodes if the autodefragment is
1226 * close or the fs is R/O.
1227 */
1228 if (btrfs_raw_test_opt(old_opts, AUTO_DEFRAG) &&
1229 (!btrfs_raw_test_opt(fs_info->mount_opt, AUTO_DEFRAG) ||
1230 (fs_info->sb->s_flags & MS_RDONLY))) {
1231 btrfs_cleanup_defrag_inodes(fs_info);
1232 }
1233
1234 clear_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state);
1235}
1236
1205static int btrfs_remount(struct super_block *sb, int *flags, char *data) 1237static int btrfs_remount(struct super_block *sb, int *flags, char *data)
1206{ 1238{
1207 struct btrfs_fs_info *fs_info = btrfs_sb(sb); 1239 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)
1215 unsigned int old_metadata_ratio = fs_info->metadata_ratio; 1247 unsigned int old_metadata_ratio = fs_info->metadata_ratio;
1216 int ret; 1248 int ret;
1217 1249
1250 btrfs_remount_prepare(fs_info, old_opts, *flags);
1251
1218 ret = btrfs_parse_options(root, data); 1252 ret = btrfs_parse_options(root, data);
1219 if (ret) { 1253 if (ret) {
1220 ret = -EINVAL; 1254 ret = -EINVAL;
@@ -1225,7 +1259,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
1225 fs_info->thread_pool_size, old_thread_pool_size); 1259 fs_info->thread_pool_size, old_thread_pool_size);
1226 1260
1227 if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) 1261 if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
1228 return 0; 1262 goto out;
1229 1263
1230 if (*flags & MS_RDONLY) { 1264 if (*flags & MS_RDONLY) {
1231 /* 1265 /*
@@ -1280,7 +1314,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
1280 } 1314 }
1281 sb->s_flags &= ~MS_RDONLY; 1315 sb->s_flags &= ~MS_RDONLY;
1282 } 1316 }
1283 1317out:
1318 btrfs_remount_cleanup(fs_info, old_opts);
1284 return 0; 1319 return 0;
1285 1320
1286restore: 1321restore:
@@ -1297,6 +1332,7 @@ restore:
1297 btrfs_resize_thread_pool(fs_info, 1332 btrfs_resize_thread_pool(fs_info,
1298 old_thread_pool_size, fs_info->thread_pool_size); 1333 old_thread_pool_size, fs_info->thread_pool_size);
1299 fs_info->metadata_ratio = old_metadata_ratio; 1334 fs_info->metadata_ratio = old_metadata_ratio;
1335 btrfs_remount_cleanup(fs_info, old_opts);
1300 return ret; 1336 return ret;
1301} 1337}
1302 1338