From patchwork Wed Dec 24 01:55:13 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 5535971 Return-Path: X-Original-To: patchwork-linux-btrfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 7BB0E9F1CD for ; Wed, 24 Dec 2014 01:55:30 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5BC5B201C0 for ; Wed, 24 Dec 2014 01:55:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3782A201B9 for ; Wed, 24 Dec 2014 01:55:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750934AbaLXBzT (ORCPT ); Tue, 23 Dec 2014 20:55:19 -0500 Received: from cn.fujitsu.com ([59.151.112.132]:54299 "EHLO heian.cn.fujitsu.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1750740AbaLXBzS (ORCPT ); Tue, 23 Dec 2014 20:55:18 -0500 X-IronPort-AV: E=Sophos;i="5.04,848,1406563200"; d="scan'208";a="46085473" Received: from unknown (HELO edo.cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 24 Dec 2014 09:51:55 +0800 Received: from G08CNEXCHPEKD02.g08.fujitsu.local (localhost.localdomain [127.0.0.1]) by edo.cn.fujitsu.com (8.14.3/8.13.1) with ESMTP id sBO1snKS023062 for ; Wed, 24 Dec 2014 09:54:49 +0800 Received: from localhost.localdomain (10.167.226.33) by G08CNEXCHPEKD02.g08.fujitsu.local (10.167.33.89) with Microsoft SMTP Server (TLS) id 14.3.181.6; Wed, 24 Dec 2014 09:55:21 +0800 From: Qu Wenruo To: Subject: [PATCH 1/2] btrfs: Make the chunk size limit on on-disk/logical more clean. Date: Wed, 24 Dec 2014 09:55:13 +0800 Message-ID: <1419386114-21703-1-git-send-email-quwenruo@cn.fujitsu.com> X-Mailer: git-send-email 2.2.1 MIME-Version: 1.0 X-Originating-IP: [10.167.226.33] Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Original __btrfs_alloc_chunk() use max_chunk_size to limit chunk size, however it mixed the on-disk space with logical space. When comes to 10% of writable space, max_chunk_size is used with on-disk size, but it is also used as logical space size limit, so it is very confusing and causing inconsistence in different profile. For example: on M single, D single 5G btrfs single device, data chunk is limited to 512M due to 10% limit. on M RAID1, D RAID1 10Gx2 btrfs 2 devices, data chunk is limited to 2G due to 10% limit is mixed with on-disk space, causing the logical chunk space to 1G, twice than single device. This patch will make the logical and on-disk space limit independent and clear and solve the above inconsistence. Signed-off-by: Qu Wenruo --- changelog: v2: Newly introduced. --- fs/btrfs/volumes.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 0144790..8e74b34 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -4235,10 +4235,12 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, int ncopies; /* how many copies to data has */ int ret; u64 max_stripe_size; - u64 max_chunk_size; + u64 max_logical_size; /* Up limit on chunk's logical size */ + u64 max_physical_size; /* Up limit on a chunk's on-disk size */ u64 stripe_size; u64 num_bytes; u64 raid_stripe_len = BTRFS_STRIPE_LEN; + int need_bump = 0; int ndevs; int i; int j; @@ -4260,7 +4262,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, if (type & BTRFS_BLOCK_GROUP_DATA) { max_stripe_size = 1024 * 1024 * 1024; - max_chunk_size = 10 * max_stripe_size; + max_logical_size = 10 * max_stripe_size; if (!devs_max) devs_max = BTRFS_MAX_DEVS(info->chunk_root); } else if (type & BTRFS_BLOCK_GROUP_METADATA) { @@ -4269,12 +4271,12 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, max_stripe_size = 1024 * 1024 * 1024; else max_stripe_size = 256 * 1024 * 1024; - max_chunk_size = max_stripe_size; + max_logical_size = max_stripe_size; if (!devs_max) devs_max = BTRFS_MAX_DEVS(info->chunk_root); } else if (type & BTRFS_BLOCK_GROUP_SYSTEM) { max_stripe_size = 32 * 1024 * 1024; - max_chunk_size = 2 * max_stripe_size; + max_logical_size = 2 * max_stripe_size; if (!devs_max) devs_max = BTRFS_MAX_DEVS_SYS_CHUNK; } else { @@ -4284,8 +4286,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, } /* we don't want a chunk larger than 10% of writeable space */ - max_chunk_size = min(div_factor(fs_devices->total_rw_bytes, 1), - max_chunk_size); + max_physical_size = div_factor(fs_devices->total_rw_bytes, 1); devices_info = kzalloc(sizeof(*devices_info) * fs_devices->rw_devices, GFP_NOFS); @@ -4391,15 +4392,21 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, data_stripes = num_stripes - 2; } - /* - * Use the number of data stripes to figure out how big this chunk - * is really going to be in terms of logical address space, - * and compare that answer with the max chunk size - */ - if (stripe_size * data_stripes > max_chunk_size) { - u64 mask = (1ULL << 24) - 1; - stripe_size = max_chunk_size; + /* Restrict on-disk chunk size */ + if (stripe_size * num_stripes > max_physical_size) { + stripe_size = max_physical_size; + do_div(stripe_size, num_stripes); + need_bump = 1; + } + /* restrict logical chunk size */ + if (stripe_size * data_stripes > max_logical_size) { + stripe_size = max_logical_size; do_div(stripe_size, data_stripes); + need_bump = 1; + } + + if (need_bump) { + u64 mask = (1ULL << 24) - 1; /* bump the answer up to a 16MB boundary */ stripe_size = (stripe_size + mask) & ~mask; @@ -4411,6 +4418,11 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, stripe_size = devices_info[ndevs-1].max_avail; } + /* + * Special handle for DUP, since stripe_size is the largest free extent + * we found, DUP can only use half of it. Other profile's dev_stripes + * is always 1. + */ do_div(stripe_size, dev_stripes); /* align to BTRFS_STRIPE_LEN */