On wed, 6 Mar 2013 09:53:28 -0500, Chris Mason wrote:
[SNIP]
> static int btrfs_wq_run_delayed_node(struct btrfs_delayed_root *delayed_root,
> - struct btrfs_root *root, int all)
> + struct btrfs_root *root, int nr)
> {
> - struct btrfs_async_delayed_node *async_node;
> - struct btrfs_delayed_node *curr;
> - int count = 0;
> + struct btrfs_async_delayed_work *async_work;
>
> -again:
> - curr = btrfs_first_prepared_delayed_node(delayed_root);
> - if (!curr)
> + if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND)
> return 0;
>
> - async_node = kmalloc(sizeof(*async_node), GFP_NOFS);
> - if (!async_node) {
> - btrfs_release_prepared_delayed_node(curr);
> + async_work = kmalloc(sizeof(*async_work), GFP_NOFS);
> + if (!async_work)
> return -ENOMEM;
> - }
> -
> - async_node->root = root;
> - async_node->delayed_node = curr;
> -
> - async_node->work.func = btrfs_async_run_delayed_node_done;
> - async_node->work.flags = 0;
> -
> - btrfs_queue_worker(&root->fs_info->delayed_workers, &async_node->work);
> - count++;
>
> - if (all || count < 4)
> - goto again;
> + async_work->delayed_root = delayed_root;
> + async_work->work.func = btrfs_async_run_delayed_root;
> + async_work->work.flags = 0;
> + if (nr)
> + async_work->nr = 0;
> + else
> + async_work->nr = nr;
the code here is wrong.
the argument nr is the number we want to deal with, if it is 0, we will deal with all.
so
- if (nr)
- async_work->nr = 0;
- else
- async_work->nr = nr;
+ async_work->nr = nr;
>
> + btrfs_queue_worker(&root->fs_info->delayed_workers, &async_work->work);
> return 0;
> }
>
> @@ -1424,30 +1431,55 @@ void btrfs_assert_delayed_root_empty(struct btrfs_root *root)
> WARN_ON(btrfs_first_delayed_node(delayed_root));
> }
>
> +static int refs_newer(struct btrfs_delayed_root *delayed_root,
> + int seq, int count)
> +{
> + int val = atomic_read(&delayed_root->items_seq);
> +
> + if (val < seq || val >= seq + count)
> + return 1;
> + return 0;
> +}
> +
> void btrfs_balance_delayed_items(struct btrfs_root *root)
> {
> struct btrfs_delayed_root *delayed_root;
> + int seq;
>
> delayed_root = btrfs_get_delayed_root(root);
>
> if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND)
> return;
>
> + seq = atomic_read(&delayed_root->items_seq);
> +
> if (atomic_read(&delayed_root->items) >= BTRFS_DELAYED_WRITEBACK) {
> int ret;
> + DEFINE_WAIT(__wait);
> +
> ret = btrfs_wq_run_delayed_node(delayed_root, root, 1);
here
- ret = btrfs_wq_run_delayed_node(delayed_root, root, 1);
+ ret = btrfs_wq_run_delayed_node(delayed_root, root, 0);
> if (ret)
> return;
>
> - wait_event_interruptible_timeout(
> - delayed_root->wait,
> - (atomic_read(&delayed_root->items) <
> - BTRFS_DELAYED_BACKGROUND),
> - HZ);
> - return;
> + while (1) {
> + prepare_to_wait(&delayed_root->wait, &__wait,
> + TASK_INTERRUPTIBLE);
> +
> + if (refs_newer(delayed_root, seq,
> + BTRFS_DELAYED_BATCH) ||
> + atomic_read(&delayed_root->items) <
> + BTRFS_DELAYED_BACKGROUND) {
> + break;
> + }
> + if (!signal_pending(current))
> + schedule();
> + else
> + break;
> + }
> + finish_wait(&delayed_root->wait, &__wait);
> }
>
> - btrfs_wq_run_delayed_node(delayed_root, root, 0);
> + btrfs_wq_run_delayed_node(delayed_root, root, BTRFS_DELAYED_BATCH);
> }
There is a problem that we may introduce lots of btrfs_works, we need avoid
it.
Thanks
Miao
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html