From patchwork Tue Aug 23 20:01:48 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilya Dryomov X-Patchwork-Id: 1089632 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p7NK2MXV006866 for ; Tue, 23 Aug 2011 20:02:22 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756075Ab1HWUCT (ORCPT ); Tue, 23 Aug 2011 16:02:19 -0400 Received: from mail-bw0-f46.google.com ([209.85.214.46]:56659 "EHLO mail-bw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756054Ab1HWUCR (ORCPT ); Tue, 23 Aug 2011 16:02:17 -0400 Received: by mail-bw0-f46.google.com with SMTP id 11so372435bke.19 for ; Tue, 23 Aug 2011 13:02:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=6CCRDFbFyJAARnofFspQOxnv6yWXOAe5Nr0JN0xx1XI=; b=SzV/H8aUjpg3j8vXZpTyn/cqiJ7ydUfD+nKvgUc0lcTYXVDIA6kHA+za3rYdU0JwbR lxMEUg2qmX3fJKsJhfi8+4Ox778mw8oDAvvHQgnKZBbuUgY+bMI+RX7Suu1HmHKmLnv/ nolF94svfr1+isHlnWJ23C5NAgQMsRQqrCFgA= Received: by 10.204.135.154 with SMTP id n26mr1826658bkt.157.1314129737161; Tue, 23 Aug 2011 13:02:17 -0700 (PDT) Received: from localhost ([31.28.235.172]) by mx.google.com with ESMTPS id s10sm82242bka.31.2011.08.23.13.02.15 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 23 Aug 2011 13:02:16 -0700 (PDT) From: Ilya Dryomov To: linux-btrfs@vger.kernel.org Cc: Chris Mason , Hugo Mills , idryomov@gmail.com Subject: [PATCH 07/21] Btrfs: add basic infrastructure for selective balancing Date: Tue, 23 Aug 2011 23:01:48 +0300 Message-Id: <1314129722-31601-8-git-send-email-idryomov@gmail.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1314129722-31601-1-git-send-email-idryomov@gmail.com> References: <1314129722-31601-1-git-send-email-idryomov@gmail.com> Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Tue, 23 Aug 2011 20:02:22 +0000 (UTC) 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 --- 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; + + 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) /*