aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c116
1 files changed, 107 insertions, 9 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 52569b57692d..31ca9f89388d 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -16,6 +16,7 @@
16 * Boston, MA 021110-1307, USA. 16 * Boston, MA 021110-1307, USA.
17 */ 17 */
18 18
19#include <linux/version.h>
19#include <linux/fs.h> 20#include <linux/fs.h>
20#include <linux/blkdev.h> 21#include <linux/blkdev.h>
21#include <linux/scatterlist.h> 22#include <linux/scatterlist.h>
@@ -24,6 +25,12 @@
24#include <linux/writeback.h> 25#include <linux/writeback.h>
25#include <linux/buffer_head.h> // for block_sync_page 26#include <linux/buffer_head.h> // for block_sync_page
26#include <linux/workqueue.h> 27#include <linux/workqueue.h>
28#include <linux/kthread.h>
29#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
30# include <linux/freezer.h>
31#else
32# include <linux/sched.h>
33#endif
27#include "crc32c.h" 34#include "crc32c.h"
28#include "ctree.h" 35#include "ctree.h"
29#include "disk-io.h" 36#include "disk-io.h"
@@ -1100,6 +1107,87 @@ static void end_workqueue_fn(struct btrfs_work *work)
1100#endif 1107#endif
1101} 1108}
1102 1109
1110static int cleaner_kthread(void *arg)
1111{
1112 struct btrfs_root *root = arg;
1113
1114 do {
1115 smp_mb();
1116 if (root->fs_info->closing)
1117 break;
1118
1119 vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE);
1120 mutex_lock(&root->fs_info->cleaner_mutex);
1121printk("cleaner awake\n");
1122 btrfs_clean_old_snapshots(root);
1123printk("cleaner done\n");
1124 mutex_unlock(&root->fs_info->cleaner_mutex);
1125
1126 if (freezing(current)) {
1127 refrigerator();
1128 } else {
1129 smp_mb();
1130 if (root->fs_info->closing)
1131 break;
1132 set_current_state(TASK_INTERRUPTIBLE);
1133 schedule();
1134 __set_current_state(TASK_RUNNING);
1135 }
1136 } while (!kthread_should_stop());
1137 return 0;
1138}
1139
1140static int transaction_kthread(void *arg)
1141{
1142 struct btrfs_root *root = arg;
1143 struct btrfs_trans_handle *trans;
1144 struct btrfs_transaction *cur;
1145 unsigned long now;
1146 unsigned long delay;
1147 int ret;
1148
1149 do {
1150 smp_mb();
1151 if (root->fs_info->closing)
1152 break;
1153
1154 delay = HZ * 30;
1155 vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE);
1156 mutex_lock(&root->fs_info->transaction_kthread_mutex);
1157
1158 mutex_lock(&root->fs_info->trans_mutex);
1159 cur = root->fs_info->running_transaction;
1160 if (!cur) {
1161 mutex_unlock(&root->fs_info->trans_mutex);
1162 goto sleep;
1163 }
1164 now = get_seconds();
1165 if (now < cur->start_time || now - cur->start_time < 30) {
1166 mutex_unlock(&root->fs_info->trans_mutex);
1167 delay = HZ * 5;
1168 goto sleep;
1169 }
1170 mutex_unlock(&root->fs_info->trans_mutex);
1171 btrfs_defrag_dirty_roots(root->fs_info);
1172 trans = btrfs_start_transaction(root, 1);
1173 ret = btrfs_commit_transaction(trans, root);
1174sleep:
1175 wake_up_process(root->fs_info->cleaner_kthread);
1176 mutex_unlock(&root->fs_info->transaction_kthread_mutex);
1177
1178 if (freezing(current)) {
1179 refrigerator();
1180 } else {
1181 if (root->fs_info->closing)
1182 break;
1183 set_current_state(TASK_INTERRUPTIBLE);
1184 schedule_timeout(delay);
1185 __set_current_state(TASK_RUNNING);
1186 }
1187 } while (!kthread_should_stop());
1188 return 0;
1189}
1190
1103struct btrfs_root *open_ctree(struct super_block *sb, 1191struct btrfs_root *open_ctree(struct super_block *sb,
1104 struct btrfs_fs_devices *fs_devices, 1192 struct btrfs_fs_devices *fs_devices,
1105 char *options) 1193 char *options)
@@ -1189,11 +1277,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1189 fs_info->btree_inode->i_mapping, GFP_NOFS); 1277 fs_info->btree_inode->i_mapping, GFP_NOFS);
1190 fs_info->do_barriers = 1; 1278 fs_info->do_barriers = 1;
1191 1279
1192#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
1193 INIT_WORK(&fs_info->trans_work, btrfs_transaction_cleaner, fs_info);
1194#else
1195 INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner);
1196#endif
1197 BTRFS_I(fs_info->btree_inode)->root = tree_root; 1280 BTRFS_I(fs_info->btree_inode)->root = tree_root;
1198 memset(&BTRFS_I(fs_info->btree_inode)->location, 0, 1281 memset(&BTRFS_I(fs_info->btree_inode)->location, 0,
1199 sizeof(struct btrfs_key)); 1282 sizeof(struct btrfs_key));
@@ -1204,6 +1287,8 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1204 mutex_init(&fs_info->drop_mutex); 1287 mutex_init(&fs_info->drop_mutex);
1205 mutex_init(&fs_info->alloc_mutex); 1288 mutex_init(&fs_info->alloc_mutex);
1206 mutex_init(&fs_info->chunk_mutex); 1289 mutex_init(&fs_info->chunk_mutex);
1290 mutex_init(&fs_info->transaction_kthread_mutex);
1291 mutex_init(&fs_info->cleaner_mutex);
1207 1292
1208#if 0 1293#if 0
1209 ret = add_hasher(fs_info, "crc32c"); 1294 ret = add_hasher(fs_info, "crc32c");
@@ -1247,7 +1332,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1247 btrfs_start_workers(&fs_info->submit_workers, 1); 1332 btrfs_start_workers(&fs_info->submit_workers, 1);
1248 btrfs_start_workers(&fs_info->endio_workers, fs_info->thread_pool_size); 1333 btrfs_start_workers(&fs_info->endio_workers, fs_info->thread_pool_size);
1249 1334
1250
1251 err = -EINVAL; 1335 err = -EINVAL;
1252 if (btrfs_super_num_devices(disk_super) > fs_devices->open_devices) { 1336 if (btrfs_super_num_devices(disk_super) > fs_devices->open_devices) {
1253 printk("Btrfs: wanted %llu devices, but found %llu\n", 1337 printk("Btrfs: wanted %llu devices, but found %llu\n",
@@ -1341,9 +1425,22 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1341 fs_info->data_alloc_profile = (u64)-1; 1425 fs_info->data_alloc_profile = (u64)-1;
1342 fs_info->metadata_alloc_profile = (u64)-1; 1426 fs_info->metadata_alloc_profile = (u64)-1;
1343 fs_info->system_alloc_profile = fs_info->metadata_alloc_profile; 1427 fs_info->system_alloc_profile = fs_info->metadata_alloc_profile;
1428 fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root,
1429 "btrfs-cleaner");
1430 if (!fs_info->cleaner_kthread)
1431 goto fail_extent_root;
1432
1433 fs_info->transaction_kthread = kthread_run(transaction_kthread,
1434 tree_root,
1435 "btrfs-transaction");
1436 if (!fs_info->transaction_kthread)
1437 goto fail_trans_kthread;
1438
1344 1439
1345 return tree_root; 1440 return tree_root;
1346 1441
1442fail_trans_kthread:
1443 kthread_stop(fs_info->cleaner_kthread);
1347fail_extent_root: 1444fail_extent_root:
1348 free_extent_buffer(extent_root->node); 1445 free_extent_buffer(extent_root->node);
1349fail_tree_root: 1446fail_tree_root:
@@ -1562,8 +1659,11 @@ int close_ctree(struct btrfs_root *root)
1562 fs_info->closing = 1; 1659 fs_info->closing = 1;
1563 smp_mb(); 1660 smp_mb();
1564 1661
1565 btrfs_transaction_flush_work(root); 1662 kthread_stop(root->fs_info->transaction_kthread);
1663 kthread_stop(root->fs_info->cleaner_kthread);
1664
1566 btrfs_defrag_dirty_roots(root->fs_info); 1665 btrfs_defrag_dirty_roots(root->fs_info);
1666 btrfs_clean_old_snapshots(root);
1567 trans = btrfs_start_transaction(root, 1); 1667 trans = btrfs_start_transaction(root, 1);
1568 ret = btrfs_commit_transaction(trans, root); 1668 ret = btrfs_commit_transaction(trans, root);
1569 /* run commit again to drop the original snapshot */ 1669 /* run commit again to drop the original snapshot */
@@ -1574,8 +1674,6 @@ int close_ctree(struct btrfs_root *root)
1574 1674
1575 write_ctree_super(NULL, root); 1675 write_ctree_super(NULL, root);
1576 1676
1577 btrfs_transaction_flush_work(root);
1578
1579 if (fs_info->delalloc_bytes) { 1677 if (fs_info->delalloc_bytes) {
1580 printk("btrfs: at unmount delalloc count %Lu\n", 1678 printk("btrfs: at unmount delalloc count %Lu\n",
1581 fs_info->delalloc_bytes); 1679 fs_info->delalloc_bytes);