Skip to content

Commit

Permalink
Btrfs: make ordered operations be handled by multi-task
Browse files Browse the repository at this point in the history
The process of the ordered operations is similar to the delalloc inode flush, so
we handle them by flush workers.

Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
  • Loading branch information
Miao Xie authored and Josef Bacik committed Dec 11, 2012
1 parent 8ccf6f1 commit 25287e0
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 21 deletions.
46 changes: 30 additions & 16 deletions fs/btrfs/ordered-data.c
Original file line number Diff line number Diff line change
Expand Up @@ -519,20 +519,25 @@ void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput)
* extra check to make sure the ordered operation list really is empty
* before we return
*/
void btrfs_run_ordered_operations(struct btrfs_root *root, int wait)
int btrfs_run_ordered_operations(struct btrfs_root *root, int wait)
{
struct btrfs_inode *btrfs_inode;
struct inode *inode;
struct list_head splice;
struct list_head works;
struct btrfs_delalloc_work *work, *next;
int ret = 0;

INIT_LIST_HEAD(&splice);
INIT_LIST_HEAD(&works);

mutex_lock(&root->fs_info->ordered_operations_mutex);
spin_lock(&root->fs_info->ordered_extent_lock);
again:
list_splice_init(&root->fs_info->ordered_operations, &splice);

while (!list_empty(&splice)) {

btrfs_inode = list_entry(splice.next, struct btrfs_inode,
ordered_operations);

Expand All @@ -549,15 +554,26 @@ void btrfs_run_ordered_operations(struct btrfs_root *root, int wait)
list_add_tail(&BTRFS_I(inode)->ordered_operations,
&root->fs_info->ordered_operations);
}

if (!inode)
continue;
spin_unlock(&root->fs_info->ordered_extent_lock);

if (inode) {
if (wait)
btrfs_wait_ordered_range(inode, 0, (u64)-1);
else
filemap_flush(inode->i_mapping);
btrfs_add_delayed_iput(inode);
work = btrfs_alloc_delalloc_work(inode, wait, 1);
if (!work) {
if (list_empty(&BTRFS_I(inode)->ordered_operations))
list_add_tail(&btrfs_inode->ordered_operations,
&splice);
spin_lock(&root->fs_info->ordered_extent_lock);
list_splice_tail(&splice,
&root->fs_info->ordered_operations);
spin_unlock(&root->fs_info->ordered_extent_lock);
ret = -ENOMEM;
goto out;
}
list_add_tail(&work->list, &works);
btrfs_queue_worker(&root->fs_info->flush_workers,
&work->work);

cond_resched();
spin_lock(&root->fs_info->ordered_extent_lock);
Expand All @@ -566,7 +582,13 @@ void btrfs_run_ordered_operations(struct btrfs_root *root, int wait)
goto again;

spin_unlock(&root->fs_info->ordered_extent_lock);
out:
list_for_each_entry_safe(work, next, &works, list) {
list_del_init(&work->list);
btrfs_wait_and_free_delalloc_work(work);
}
mutex_unlock(&root->fs_info->ordered_operations_mutex);
return ret;
}

/*
Expand Down Expand Up @@ -934,15 +956,6 @@ void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans,
if (last_mod < root->fs_info->last_trans_committed)
return;

/*
* the transaction is already committing. Just start the IO and
* don't bother with all of this list nonsense
*/
if (trans && root->fs_info->running_transaction->blocked) {
btrfs_wait_ordered_range(inode, 0, (u64)-1);
return;
}

spin_lock(&root->fs_info->ordered_extent_lock);
if (list_empty(&BTRFS_I(inode)->ordered_operations)) {
list_add_tail(&BTRFS_I(inode)->ordered_operations,
Expand All @@ -959,6 +972,7 @@ int __init ordered_data_init(void)
NULL);
if (!btrfs_ordered_extent_cache)
return -ENOMEM;

return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion fs/btrfs/ordered-data.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ struct btrfs_ordered_extent *btrfs_lookup_ordered_range(struct inode *inode,
int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
struct btrfs_ordered_extent *ordered);
int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, u32 *sum);
void btrfs_run_ordered_operations(struct btrfs_root *root, int wait);
int btrfs_run_ordered_operations(struct btrfs_root *root, int wait);
void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct inode *inode);
Expand Down
18 changes: 14 additions & 4 deletions fs/btrfs/transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -1412,15 +1412,21 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
struct btrfs_transaction *cur_trans = trans->transaction;
struct btrfs_transaction *prev_trans = NULL;
DEFINE_WAIT(wait);
int ret = -EIO;
int ret;
int should_grow = 0;
unsigned long now = get_seconds();
int flush_on_commit = btrfs_test_opt(root, FLUSHONCOMMIT);

btrfs_run_ordered_operations(root, 0);
ret = btrfs_run_ordered_operations(root, 0);
if (ret) {
btrfs_abort_transaction(trans, root, ret);
goto cleanup_transaction;
}

if (cur_trans->aborted)
if (cur_trans->aborted) {
ret = cur_trans->aborted;
goto cleanup_transaction;
}

/* make a pass through all the delayed refs we have so far
* any runnings procs may add more while we are here
Expand Down Expand Up @@ -1523,7 +1529,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
* it here and no for sure that nothing new will be added
* to the list
*/
btrfs_run_ordered_operations(root, 1);
ret = btrfs_run_ordered_operations(root, 1);
if (ret) {
btrfs_abort_transaction(trans, root, ret);
goto cleanup_transaction;
}

prepare_to_wait(&cur_trans->writer_wait, &wait,
TASK_UNINTERRUPTIBLE);
Expand Down

0 comments on commit 25287e0

Please sign in to comment.