diff options
-rw-r--r-- | fs/btrfs/ctree.h | 2 | ||||
-rw-r--r-- | fs/btrfs/file.c | 5 | ||||
-rw-r--r-- | fs/btrfs/super.c | 40 |
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 | ||
1205 | static 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 | |||
1221 | static 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 | |||
1205 | static int btrfs_remount(struct super_block *sb, int *flags, char *data) | 1237 | static 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 | 1317 | out: | |
1318 | btrfs_remount_cleanup(fs_info, old_opts); | ||
1284 | return 0; | 1319 | return 0; |
1285 | 1320 | ||
1286 | restore: | 1321 | restore: |
@@ -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 | ||