From: Josef Bacik <josef@redhat.com>
To: Hugo Mills <hugo@carfax.org.uk>
Cc: linux-btrfs@vger.kernel.org, chris.mason@oracle.com
Subject: Re: [PATCH v4 3/8] btrfs: Factor out enumeration of chunks to a separate function
Date: Thu, 07 Apr 2011 14:00:38 -0400 [thread overview]
Message-ID: <4D9DFBC6.5010505@redhat.com> (raw)
In-Reply-To: <1302195975-3088-4-git-send-email-hugo@carfax.org.uk>
On 04/07/2011 01:06 PM, Hugo Mills wrote:
> The main balance function has two loops which are functionally
> identical in their looping mechanism, but which perform a different
> operation on the chunks they loop over. To avoid repeating code more
> than necessary, factor this loop out into a separate iterator function
> which takes a function parameter for the action to be performed.
>
> Signed-off-by: Hugo Mills<hugo@carfax.org.uk>
> ---
> fs/btrfs/volumes.c | 179 +++++++++++++++++++++++++++++-----------------------
> 1 files changed, 99 insertions(+), 80 deletions(-)
>
> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
> index 5378b94..ffba817 100644
> --- a/fs/btrfs/volumes.c
> +++ b/fs/btrfs/volumes.c
> @@ -2029,6 +2029,97 @@ static u64 div_factor(u64 num, int factor)
> return num;
> }
>
> +/* Define a type, and two functions which can be used for the two
> + * phases of the balance operation: one for counting chunks, and one
> + * for actually moving them. */
> +typedef void (*balance_iterator_function)(struct btrfs_root *,
> + struct btrfs_balance_info *,
> + struct btrfs_path *,
> + struct btrfs_key *);
> +
> +void balance_count_chunks(struct btrfs_root *chunk_root,
> + struct btrfs_balance_info *bal_info,
> + struct btrfs_path *path,
> + struct btrfs_key *key)
> +{
> + spin_lock(&chunk_root->fs_info->balance_info_lock);
> + bal_info->expected++;
> + spin_unlock(&chunk_root->fs_info->balance_info_lock);
> +}
> +
> +void balance_move_chunks(struct btrfs_root *chunk_root,
> + struct btrfs_balance_info *bal_info,
> + struct btrfs_path *path,
> + struct btrfs_key *key)
> +{
> + int ret;
> +
> + ret = btrfs_relocate_chunk(chunk_root,
> + chunk_root->root_key.objectid,
> + key->objectid,
> + key->offset);
> + BUG_ON(ret&& ret != -ENOSPC);
> + spin_lock(&chunk_root->fs_info->balance_info_lock);
> + bal_info->completed++;
> + spin_unlock(&chunk_root->fs_info->balance_info_lock);
> + printk(KERN_INFO "btrfs: balance: %llu/%llu block groups completed\n",
> + bal_info->completed, bal_info->expected);
> +}
> +
> +/* Iterate through all chunks, performing some function on each one. */
> +int balance_iterate_chunks(struct btrfs_root *chunk_root,
> + struct btrfs_balance_info *bal_info,
> + balance_iterator_function fn)
> +{
> + int ret;
> + struct btrfs_path *path;
> + struct btrfs_key key;
> + struct btrfs_key found_key;
> +
> + path = btrfs_alloc_path();
> + if (!path)
> + return -ENOSPC;
Return ENOMEM, we're out of memory not space.
> +
> + key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
> + key.offset = (u64)-1;
> + key.type = BTRFS_CHUNK_ITEM_KEY;
> +
> + while (!bal_info->cancel_pending) {
> + ret = btrfs_search_slot(NULL, chunk_root,&key, path, 0, 0);
> + if (ret< 0)
> + break;
> + /*
> + * this shouldn't happen, it means the last relocate
> + * failed
> + */
> + if (ret == 0)
> + break;
> +
> + ret = btrfs_previous_item(chunk_root, path, 0,
> + BTRFS_CHUNK_ITEM_KEY);
> + if (ret)
> + break;
> +
> + btrfs_item_key_to_cpu(path->nodes[0],&found_key,
> + path->slots[0]);
> + if (found_key.objectid != key.objectid)
> + break;
> +
> + /* chunk zero is special */
> + if (found_key.offset == 0)
> + break;
> +
> + /* Call the function to do the work for this chunk */
> + btrfs_release_path(chunk_root, path);
> + fn(chunk_root, bal_info, path,&found_key);
> +
> + key.offset = found_key.offset - 1;
> + }
> +
> + btrfs_free_path(path);
> + return ret;
> +}
> +
> int btrfs_balance(struct btrfs_root *dev_root)
> {
> int ret;
> @@ -2036,11 +2127,8 @@ int btrfs_balance(struct btrfs_root *dev_root)
> struct btrfs_device *device;
> u64 old_size;
> u64 size_to_free;
> - struct btrfs_path *path;
> - struct btrfs_key key;
> struct btrfs_root *chunk_root = dev_root->fs_info->chunk_root;
> struct btrfs_trans_handle *trans;
> - struct btrfs_key found_key;
> struct btrfs_balance_info *bal_info;
>
> if (dev_root->fs_info->sb->s_flags& MS_RDONLY)
> @@ -2061,8 +2149,7 @@ int btrfs_balance(struct btrfs_root *dev_root)
> }
> spin_lock(&dev_root->fs_info->balance_info_lock);
> dev_root->fs_info->balance_info = bal_info;
> - bal_info->expected = -1; /* One less than actually counted,
> - because chunk 0 is special */
> + bal_info->expected = 0;
> bal_info->completed = 0;
> bal_info->cancel_pending = 0;
> spin_unlock(&dev_root->fs_info->balance_info_lock);
> @@ -2091,91 +2178,23 @@ int btrfs_balance(struct btrfs_root *dev_root)
> }
>
> /* step two, count the chunks */
> - path = btrfs_alloc_path();
> - if (!path) {
> - ret = -ENOSPC;
> - goto error;
> - }
> -
> - key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
> - key.offset = (u64)-1;
> - key.type = BTRFS_CHUNK_ITEM_KEY;
> -
> - ret = btrfs_search_slot(NULL, chunk_root,&key, path, 0, 0);
> - if (ret<= 0) {
> - printk(KERN_ERR "btrfs: Failed to find the last chunk.\n");
> - BUG();
> - }
> -
> - while (1) {
> - ret = btrfs_previous_item(chunk_root, path, 0,
> - BTRFS_CHUNK_ITEM_KEY);
> - if (ret)
> - break;
> -
> - spin_lock(&dev_root->fs_info->balance_info_lock);
> - bal_info->expected++;
> - spin_unlock(&dev_root->fs_info->balance_info_lock);
> - }
> -
> - btrfs_free_path(path);
> - path = btrfs_alloc_path();
> - if (!path) {
> - ret = -ENOSPC;
> + ret = balance_iterate_chunks(chunk_root, bal_info,
> + balance_count_chunks);
> + if (ret)
> goto error;
> - }
>
> /* step three, relocate all the chunks */
> - key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
> - key.offset = (u64)-1;
> - key.type = BTRFS_CHUNK_ITEM_KEY;
> -
> - while (!bal_info->cancel_pending) {
> - ret = btrfs_search_slot(NULL, chunk_root,&key, path, 0, 0);
> - if (ret< 0)
> - goto error;
> -
> - /*
> - * this shouldn't happen, it means the last relocate
> - * failed
> - */
> - if (ret == 0)
> - break;
> -
> - ret = btrfs_previous_item(chunk_root, path, 0,
> - BTRFS_CHUNK_ITEM_KEY);
> - if (ret)
> - break;
> -
> - btrfs_item_key_to_cpu(path->nodes[0],&found_key,
> - path->slots[0]);
> - if (found_key.objectid != key.objectid)
> - break;
> -
> - /* chunk zero is special */
> - if (found_key.offset == 0)
> - break;
> + ret = balance_iterate_chunks(chunk_root, bal_info,
> + balance_move_chunks);
> + if (ret)
> + goto error;
>
> - btrfs_release_path(chunk_root, path);
> - ret = btrfs_relocate_chunk(chunk_root,
> - chunk_root->root_key.objectid,
> - found_key.objectid,
> - found_key.offset);
> - BUG_ON(ret&& ret != -ENOSPC);
> - key.offset = found_key.offset - 1;
> - spin_lock(&dev_root->fs_info->balance_info_lock);
> - bal_info->completed++;
> - spin_unlock(&dev_root->fs_info->balance_info_lock);
> - printk(KERN_INFO "btrfs: balance: %llu/%llu block groups completed\n",
> - bal_info->completed, bal_info->expected);
> - }
> ret = 0;
> if (bal_info->cancel_pending) {
> printk(KERN_INFO "btrfs: balance cancelled\n");
> ret = -EINTR;
> }
> error:
> - btrfs_free_path(path);
> spin_lock(&dev_root->fs_info->balance_info_lock);
> kfree(dev_root->fs_info->balance_info);
> dev_root->fs_info->balance_info = NULL;
next prev parent reply other threads:[~2011-04-07 18:00 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-04-07 17:06 [PATCH v4 0/8] Balance management Hugo Mills
2011-04-07 17:06 ` [PATCH v4 1/8] btrfs: Balance progress monitoring Hugo Mills
2011-04-07 17:26 ` Josef Bacik
2011-04-08 2:26 ` Li Zefan
2011-04-08 13:43 ` Hugo Mills
2011-04-08 13:12 ` David Sterba
2011-04-08 16:00 ` David Sterba
2011-04-08 13:37 ` David Sterba
2011-04-08 14:07 ` Hugo Mills
2011-04-07 17:06 ` [PATCH v4 2/8] btrfs: Cancel filesystem balance Hugo Mills
2011-04-07 17:06 ` [PATCH v4 3/8] btrfs: Factor out enumeration of chunks to a separate function Hugo Mills
2011-04-07 18:00 ` Josef Bacik [this message]
2011-04-07 17:06 ` [PATCH v4 4/8] btrfs: Implement filtered balance ioctl Hugo Mills
2011-04-07 17:06 ` [PATCH v4 5/8] btrfs: Balance filter for device ID Hugo Mills
2011-04-07 17:06 ` [PATCH v4 6/8] btrfs: Balance filter for virtual address ranges Hugo Mills
2011-04-07 17:06 ` [PATCH v4 7/8] btrfs: Replication-type information Hugo Mills
2011-04-07 17:06 ` [PATCH v4 8/8] btrfs: Balance filter for physical device address Hugo Mills
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4D9DFBC6.5010505@redhat.com \
--to=josef@redhat.com \
--cc=chris.mason@oracle.com \
--cc=hugo@carfax.org.uk \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).