On Tue, Aug 23, 2011 at 11:01:48PM +0300, Ilya Dryomov wrote:
> This allows to have a separate set of filters for each chunk type
> (data,meta,sys). The code however is generic and switch on chunk type
> is only done once.
>
> This commit also adds a type filter: it allows to balance for example
> meta and system chunks w/o touching data ones.
>
> Signed-off-by: Ilya Dryomov <idryomov@xxxxxxxxx>
> ---
> fs/btrfs/volumes.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++--
> fs/btrfs/volumes.h | 12 +++++++++
> 2 files changed, 76 insertions(+), 3 deletions(-)
>
> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
> index 0e4a276..95c6310 100644
> --- a/fs/btrfs/volumes.c
> +++ b/fs/btrfs/volumes.c
> @@ -2175,6 +2175,30 @@ static void unset_restripe_control(struct btrfs_fs_info *fs_info)
> kfree(rctl);
> }
>
> +static int should_restripe_chunk(struct btrfs_root *root,
> + struct extent_buffer *leaf,
> + struct btrfs_chunk *chunk, u64 chunk_offset)
> +{
> + struct restripe_control *rctl = root->fs_info->restripe_ctl;
> + u64 chunk_type = btrfs_chunk_type(leaf, chunk);
> + struct btrfs_restripe_args *rargs = NULL;
> +
> + /* type filter */
> + if (!((chunk_type & BTRFS_BLOCK_GROUP_TYPE_MASK) &
> + (rctl->flags & BTRFS_RESTRIPE_TYPE_MASK))) {
> + return 0;
> + }
> +
> + if (chunk_type & BTRFS_BLOCK_GROUP_DATA)
> + rargs = &rctl->data;
> + else if (chunk_type & BTRFS_BLOCK_GROUP_SYSTEM)
> + rargs = &rctl->sys;
> + else if (chunk_type & BTRFS_BLOCK_GROUP_METADATA)
> + rargs = &rctl->meta;
what's the point of setting local variable 'rargs' without using or
returning it?
> +
> + return 1;
> +}
> +
> static int __btrfs_restripe(struct btrfs_root *dev_root)
> {
> struct list_head *devices;
> @@ -2182,10 +2206,13 @@ static int __btrfs_restripe(struct btrfs_root *dev_root)
> u64 old_size;
> u64 size_to_free;
> struct btrfs_root *chunk_root = dev_root->fs_info->chunk_root;
> + struct btrfs_chunk *chunk;
> struct btrfs_path *path;
> struct btrfs_key key;
> struct btrfs_key found_key;
> struct btrfs_trans_handle *trans;
> + struct extent_buffer *leaf;
> + int slot;
> int ret;
> int enospc_errors = 0;
>
> @@ -2241,8 +2268,10 @@ static int __btrfs_restripe(struct btrfs_root *dev_root)
> if (ret)
> BUG_ON(1); /* DIS - break ? */
>
> - btrfs_item_key_to_cpu(path->nodes[0], &found_key,
> - path->slots[0]);
> + leaf = path->nodes[0];
> + slot = path->slots[0];
> + btrfs_item_key_to_cpu(leaf, &found_key, slot);
> +
> if (found_key.objectid != key.objectid)
> break;
>
> @@ -2250,6 +2279,14 @@ static int __btrfs_restripe(struct btrfs_root *dev_root)
> if (found_key.offset == 0)
> break;
>
> + chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
> +
> + if (!should_restripe_chunk(chunk_root, leaf, chunk,
> + found_key.offset)) {
> + btrfs_release_path(path);
> + goto loop;
> + }
> +
> btrfs_release_path(path);
> ret = btrfs_relocate_chunk(chunk_root,
> chunk_root->root_key.objectid,
> @@ -2259,6 +2296,7 @@ static int __btrfs_restripe(struct btrfs_root *dev_root)
> goto error;
> if (ret == -ENOSPC)
> enospc_errors++;
> +loop:
> key.offset = found_key.offset - 1;
> }
>
> @@ -2285,8 +2323,30 @@ int btrfs_restripe(struct restripe_control *rctl)
> mutex_lock(&fs_info->volume_mutex);
>
> /*
> - * Profile changing sanity checks
> + * In case of mixed groups both data and meta should be picked,
> + * and identical options should be given for both of them.
> */
> + allowed = btrfs_super_incompat_flags(&fs_info->super_copy);
> + if ((allowed & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) &&
> + (rctl->flags & (BTRFS_RESTRIPE_DATA | BTRFS_RESTRIPE_METADATA))) {
> + if (!(rctl->flags & BTRFS_RESTRIPE_DATA) ||
> + !(rctl->flags & BTRFS_RESTRIPE_METADATA) ||
> + memcmp(&rctl->data, &rctl->meta, sizeof(rctl->data))) {
> + printk(KERN_ERR "btrfs: with mixed groups data and "
> + "metadata restripe options must be the same\n");
> + ret = -EINVAL;
> + goto out;
> + }
> + }
> +
> + /*
> + * Profile changing sanity checks. Skip them if a simple
> + * balance is requested.
> + */
> + if (!((rctl->data.flags | rctl->sys.flags | rctl->meta.flags) &
> + BTRFS_RESTRIPE_ARGS_CONVERT))
> + goto do_restripe;
> +
> allowed = BTRFS_AVAIL_ALLOC_BIT_SINGLE;
> if (fs_info->fs_devices->num_devices == 1)
> allowed |= BTRFS_BLOCK_GROUP_DUP;
> @@ -2344,6 +2404,7 @@ int btrfs_restripe(struct restripe_control *rctl)
> }
> }
>
> +do_restripe:
> set_restripe_control(rctl);
> mutex_unlock(&fs_info->volume_mutex);
>
> diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
> index 8804c5c..f40227e 100644
> --- a/fs/btrfs/volumes.h
> +++ b/fs/btrfs/volumes.h
> @@ -168,6 +168,18 @@ struct map_lookup {
> #define map_lookup_size(n) (sizeof(struct map_lookup) + \
> (sizeof(struct btrfs_bio_stripe) * (n)))
>
> +/*
> + * Restriper's general "type" filter. Shares bits with chunk type for
> + * simplicity, RESTRIPE prefix is used to avoid confusion.
> + */
> +#define BTRFS_RESTRIPE_DATA (1ULL << 0)
> +#define BTRFS_RESTRIPE_SYSTEM (1ULL << 1)
> +#define BTRFS_RESTRIPE_METADATA (1ULL << 2)
> +
> +#define BTRFS_RESTRIPE_TYPE_MASK (BTRFS_RESTRIPE_DATA | \
> + BTRFS_RESTRIPE_SYSTEM | \
> + BTRFS_RESTRIPE_METADATA)
> +
> #define BTRFS_RESTRIPE_FORCE (1ULL << 3)
>
> /*
> --
--
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