From patchwork Fri Jan 29 05:03:22 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 8159031 Return-Path: X-Original-To: patchwork-linux-btrfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id BA75FBEEE5 for ; Fri, 29 Jan 2016 05:18:03 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id AB8D02035D for ; Fri, 29 Jan 2016 05:18:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8C67B20351 for ; Fri, 29 Jan 2016 05:18:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752289AbcA2FR6 (ORCPT ); Fri, 29 Jan 2016 00:17:58 -0500 Received: from cn.fujitsu.com ([222.73.24.84]:31409 "EHLO song.cn.fujitsu.com" rhost-flags-OK-FAIL-OK-OK) by vger.kernel.org with ESMTP id S1751009AbcA2FR6 (ORCPT ); Fri, 29 Jan 2016 00:17:58 -0500 X-IronPort-AV: E=Sophos;i="5.20,367,1444665600"; d="scan'208";a="304667" Received: from unknown (HELO cn.fujitsu.com) ([10.167.250.3]) by song.cn.fujitsu.com with ESMTP; 29 Jan 2016 13:05:46 +0800 Received: from localhost.localdomain (unknown [10.167.226.34]) by cn.fujitsu.com (Postfix) with ESMTP id 3031E405640E; Fri, 29 Jan 2016 13:05:34 +0800 (CST) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: dsterba@suse.cz, David Sterba Subject: [PATCH v3 12/22] btrfs-progs: Introduce function to create convert data chunks Date: Fri, 29 Jan 2016 13:03:22 +0800 Message-Id: <1454043812-7893-13-git-send-email-quwenruo@cn.fujitsu.com> X-Mailer: git-send-email 2.7.0 In-Reply-To: <1454043812-7893-1-git-send-email-quwenruo@cn.fujitsu.com> References: <1454043812-7893-1-git-send-email-quwenruo@cn.fujitsu.com> MIME-Version: 1.0 X-yoursite-MailScanner-ID: 3031E405640E.AAF5E X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: quwenruo@cn.fujitsu.com X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Introduce new function, make_convert_data_chunks(), to build up data chunks for convert. It will call a modified verion of btrfs_alloc_data_chunk() to force data chunks to cover all known ext* data. Signed-off-by: Qu Wenruo Signed-off-by: David Sterba --- btrfs-convert.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ mkfs.c | 2 +- volumes.c | 46 ++++++++++++++++++++++++++++++++++------------ volumes.h | 2 +- 4 files changed, 86 insertions(+), 14 deletions(-) diff --git a/btrfs-convert.c b/btrfs-convert.c index 1573e41..102953a 100644 --- a/btrfs-convert.c +++ b/btrfs-convert.c @@ -1863,6 +1863,56 @@ static int create_subvol(struct btrfs_trans_handle *trans, return 0; } +/* + * New make_btrfs_v2() has handle system and meta chunks quite well. + * So only need to add remaining data chunks. + */ +static int make_convert_data_block_groups(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info, + struct btrfs_mkfs_config *cfg, + struct btrfs_convert_context *cctx) +{ + struct btrfs_root *extent_root = fs_info->extent_root; + struct cache_tree *data_chunks = &cctx->data_chunks; + struct cache_extent *cache; + u64 max_chunk_size; + int ret = 0; + + /* + * Don't create data chunk over 10% of the convert device + * And for single chunk, don't create chunk larger than 1G. + */ + max_chunk_size = cfg->num_bytes / 10; + max_chunk_size = min((u64)(1024 * 1024 * 1024), max_chunk_size); + max_chunk_size = round_down(max_chunk_size, extent_root->sectorsize); + + for (cache = first_cache_extent(data_chunks); cache; + cache = next_cache_extent(cache)) { + u64 cur = cache->start; + + while (cur < cache->start + cache->size) { + u64 len; + u64 cur_backup = cur; + + len = min(max_chunk_size, + cache->start + cache->size - cur); + ret = btrfs_alloc_data_chunk(trans, extent_root, + &cur_backup, len, + BTRFS_BLOCK_GROUP_DATA, 1); + if (ret < 0) + break; + ret = btrfs_make_block_group(trans, extent_root, 0, + BTRFS_BLOCK_GROUP_DATA, + BTRFS_FIRST_CHUNK_TREE_OBJECTID, + cur, len); + if (ret < 0) + break; + cur += len; + } + } + return ret; +} + static int init_btrfs(struct btrfs_root *root) { int ret; diff --git a/mkfs.c b/mkfs.c index 5b77324..2d690cb 100644 --- a/mkfs.c +++ b/mkfs.c @@ -971,7 +971,7 @@ static int create_chunks(struct btrfs_trans_handle *trans, size_of_data = minimum_data_chunk_size; ret = btrfs_alloc_data_chunk(trans, root->fs_info->extent_root, - &chunk_start, size_of_data, data_type); + &chunk_start, size_of_data, data_type, 0); BUG_ON(ret); ret = btrfs_make_block_group(trans, root->fs_info->extent_root, 0, data_type, BTRFS_FIRST_CHUNK_TREE_OBJECTID, diff --git a/volumes.c b/volumes.c index a94be0e..7ce92a0 100644 --- a/volumes.c +++ b/volumes.c @@ -399,7 +399,7 @@ static int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, struct btrfs_device *device, u64 chunk_tree, u64 chunk_objectid, u64 chunk_offset, - u64 num_bytes, u64 *start) + u64 num_bytes, u64 *start, int convert) { int ret; struct btrfs_path *path; @@ -412,9 +412,15 @@ static int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, if (!path) return -ENOMEM; - ret = find_free_dev_extent(trans, device, path, num_bytes, start); - if (ret) { - goto err; + /* + * For convert case, just skip search free dev_extent, as caller + * is responsible to ensure it's free. + */ + if (!convert) { + ret = find_free_dev_extent(trans, device, path, num_bytes, + start); + if (ret) + goto err; } key.objectid = device->devid; @@ -973,7 +979,7 @@ again: ret = btrfs_alloc_dev_extent(trans, device, info->chunk_root->root_key.objectid, BTRFS_FIRST_CHUNK_TREE_OBJECTID, key.offset, - calc_size, &dev_offset); + calc_size, &dev_offset, 0); BUG_ON(ret); device->bytes_used += calc_size; @@ -1029,9 +1035,17 @@ again: return ret; } +/* + * Alloc a DATA chunk with SINGLE profile. + * + * If 'convert' is set, it will alloc a chunk with 1:1 mapping + * (btrfs logical bytenr == on-disk bytenr) + * For that case, caller must ensure the chunk and dev_extent is not + * occupied. + */ int btrfs_alloc_data_chunk(struct btrfs_trans_handle *trans, struct btrfs_root *extent_root, u64 *start, - u64 num_bytes, u64 type) + u64 num_bytes, u64 type, int convert) { u64 dev_offset; struct btrfs_fs_info *info = extent_root->fs_info; @@ -1052,10 +1066,17 @@ int btrfs_alloc_data_chunk(struct btrfs_trans_handle *trans, key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID; key.type = BTRFS_CHUNK_ITEM_KEY; - ret = find_next_chunk(chunk_root, BTRFS_FIRST_CHUNK_TREE_OBJECTID, - &key.offset); - if (ret) - return ret; + if (convert) { + BUG_ON(*start != round_down(*start, extent_root->sectorsize)); + key.offset = *start; + dev_offset = *start; + } else { + ret = find_next_chunk(chunk_root, + BTRFS_FIRST_CHUNK_TREE_OBJECTID, + &key.offset); + if (ret) + return ret; + } chunk = kmalloc(btrfs_chunk_item_size(num_stripes), GFP_NOFS); if (!chunk) @@ -1080,7 +1101,7 @@ int btrfs_alloc_data_chunk(struct btrfs_trans_handle *trans, ret = btrfs_alloc_dev_extent(trans, device, info->chunk_root->root_key.objectid, BTRFS_FIRST_CHUNK_TREE_OBJECTID, key.offset, - calc_size, &dev_offset); + calc_size, &dev_offset, convert); BUG_ON(ret); device->bytes_used += calc_size; @@ -1117,7 +1138,8 @@ int btrfs_alloc_data_chunk(struct btrfs_trans_handle *trans, ret = btrfs_insert_item(trans, chunk_root, &key, chunk, btrfs_chunk_item_size(num_stripes)); BUG_ON(ret); - *start = key.offset; + if (!convert) + *start = key.offset; map->ce.start = key.offset; map->ce.size = num_bytes; diff --git a/volumes.h b/volumes.h index c0007ad..d88e1cf 100644 --- a/volumes.h +++ b/volumes.h @@ -194,7 +194,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, u64 *num_bytes, u64 type); int btrfs_alloc_data_chunk(struct btrfs_trans_handle *trans, struct btrfs_root *extent_root, u64 *start, - u64 num_bytes, u64 type); + u64 num_bytes, u64 type, int convert); int btrfs_read_super_device(struct btrfs_root *root, struct extent_buffer *buf); int btrfs_add_device(struct btrfs_trans_handle *trans, struct btrfs_root *root,