summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/transaction.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-08-10 14:06:19 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-08-10 14:06:19 -0400
commite9d0b13b5bbb58c9b840e407a8d181442f799966 (patch)
treed51a7e111a824e883c347c83745109400231de1c /fs/btrfs/transaction.c
parent409eb95d7f6632d5af32b795244ce68a29e49319 (diff)
downloadlinux-e9d0b13b5bbb58c9b840e407a8d181442f799966.tar.bz2
Btrfs: Btree defrag on the extent-mapping tree as well
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r--fs/btrfs/transaction.c91
1 files changed, 49 insertions, 42 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 204337c5ca0f..c9d52dc83e48 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -317,18 +317,47 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans,
return err;
}
+int btrfs_defrag_root(struct btrfs_root *root, int cacheonly)
+{
+ struct btrfs_fs_info *info = root->fs_info;
+ int ret;
+ struct btrfs_trans_handle *trans;
+
+ if (root->defrag_running)
+ return 0;
+
+ trans = btrfs_start_transaction(root, 1);
+ while (1) {
+ root->defrag_running = 1;
+ ret = btrfs_defrag_leaves(trans, root, cacheonly);
+ btrfs_end_transaction(trans, root);
+ mutex_unlock(&info->fs_mutex);
+
+ btrfs_btree_balance_dirty(root);
+ cond_resched();
+
+ mutex_lock(&info->fs_mutex);
+ trans = btrfs_start_transaction(root, 1);
+ if (ret != -EAGAIN)
+ break;
+ }
+ root->defrag_running = 0;
+ radix_tree_tag_clear(&info->fs_roots_radix,
+ (unsigned long)root->root_key.objectid,
+ BTRFS_ROOT_DEFRAG_TAG);
+ btrfs_end_transaction(trans, root);
+ return 0;
+}
+
int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info)
{
struct btrfs_root *gang[1];
struct btrfs_root *root;
- struct btrfs_root *tree_root = info->tree_root;
- struct btrfs_trans_handle *trans;
int i;
int ret;
int err = 0;
u64 last = 0;
- trans = btrfs_start_transaction(tree_root, 1);
while(1) {
ret = radix_tree_gang_lookup_tag(&info->fs_roots_radix,
(void **)gang, last,
@@ -339,37 +368,10 @@ int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info)
for (i = 0; i < ret; i++) {
root = gang[i];
last = root->root_key.objectid + 1;
- radix_tree_tag_clear(&info->fs_roots_radix,
- (unsigned long)root->root_key.objectid,
- BTRFS_ROOT_DEFRAG_TAG);
- if (root->defrag_running)
- continue;
-
- while (1) {
- mutex_lock(&root->fs_info->trans_mutex);
- record_root_in_trans(root);
- mutex_unlock(&root->fs_info->trans_mutex);
-
- root->defrag_running = 1;
- err = btrfs_defrag_leaves(trans, root, 1);
- btrfs_end_transaction(trans, tree_root);
- mutex_unlock(&info->fs_mutex);
-
- btrfs_btree_balance_dirty(root);
- cond_resched();
-
- mutex_lock(&info->fs_mutex);
- trans = btrfs_start_transaction(tree_root, 1);
- if (err != -EAGAIN)
- break;
- }
- root->defrag_running = 0;
- radix_tree_tag_clear(&info->fs_roots_radix,
- (unsigned long)root->root_key.objectid,
- BTRFS_ROOT_DEFRAG_TAG);
+ btrfs_defrag_root(root, 1);
}
}
- btrfs_end_transaction(trans, tree_root);
+ btrfs_defrag_root(info->extent_root, 1);
return err;
}
@@ -527,6 +529,20 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
return ret;
}
+int btrfs_clean_old_snapshots(struct btrfs_root *root)
+{
+ struct list_head dirty_roots;
+ INIT_LIST_HEAD(&dirty_roots);
+
+ mutex_lock(&root->fs_info->trans_mutex);
+ list_splice_init(&root->fs_info->dead_roots, &dirty_roots);
+ mutex_unlock(&root->fs_info->trans_mutex);
+
+ if (!list_empty(&dirty_roots)) {
+ drop_dirty_roots(root, &dirty_roots);
+ }
+ return 0;
+}
void btrfs_transaction_cleaner(struct work_struct *work)
{
struct btrfs_fs_info *fs_info = container_of(work,
@@ -536,12 +552,10 @@ void btrfs_transaction_cleaner(struct work_struct *work)
struct btrfs_root *root = fs_info->tree_root;
struct btrfs_transaction *cur;
struct btrfs_trans_handle *trans;
- struct list_head dirty_roots;
unsigned long now;
unsigned long delay = HZ * 30;
int ret;
- INIT_LIST_HEAD(&dirty_roots);
mutex_lock(&root->fs_info->fs_mutex);
mutex_lock(&root->fs_info->trans_mutex);
cur = root->fs_info->running_transaction;
@@ -561,14 +575,7 @@ void btrfs_transaction_cleaner(struct work_struct *work)
ret = btrfs_commit_transaction(trans, root);
out:
mutex_unlock(&root->fs_info->fs_mutex);
-
- mutex_lock(&root->fs_info->trans_mutex);
- list_splice_init(&root->fs_info->dead_roots, &dirty_roots);
- mutex_unlock(&root->fs_info->trans_mutex);
-
- if (!list_empty(&dirty_roots)) {
- drop_dirty_roots(root, &dirty_roots);
- }
+ btrfs_clean_old_snapshots(root);
btrfs_transaction_queue_work(root, delay);
}