From patchwork Mon Sep 4 06:41:08 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 9936725 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 7D48E60237 for ; Mon, 4 Sep 2017 06:41:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6EB712871E for ; Mon, 4 Sep 2017 06:41:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 63CB02872D; Mon, 4 Sep 2017 06:41:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.4 required=2.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_HI,RCVD_IN_SORBS_SPAM autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F33312871E for ; Mon, 4 Sep 2017 06:41:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753257AbdIDGlY (ORCPT ); Mon, 4 Sep 2017 02:41:24 -0400 Received: from mout.gmx.net ([212.227.15.15]:51860 "EHLO mout.gmx.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752064AbdIDGlW (ORCPT ); Mon, 4 Sep 2017 02:41:22 -0400 Received: from localhost.localdomain ([45.32.39.184]) by mail.gmx.com (mrgmx002 [212.227.17.184]) with ESMTPSA (Nemesis) id 0Lz3rc-1dSVAd2T2G-014Ayl; Mon, 04 Sep 2017 08:41:20 +0200 From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: dsterba@suse.cz Subject: [PATCH 3/5] btrfs-progs: mkfs: Shrink the image for rootdir to minimal size Date: Mon, 4 Sep 2017 15:41:08 +0900 Message-Id: <20170904064110.25951-4-quwenruo.btrfs@gmx.com> X-Mailer: git-send-email 2.13.3 In-Reply-To: <20170904064110.25951-1-quwenruo.btrfs@gmx.com> References: <20170904064110.25951-1-quwenruo.btrfs@gmx.com> X-Provags-ID: V03:K0:vaUHYVKbulFtgAZj5y8QbWOsfhuoG5ZKGHxEe/IK937HAxOfpOv hYLjuOcJHs8//Fgp1td/Zdi35+S3AAOi1fBgkhgoRfias+NFWZGZ4pyY9MM53q+8Z3m/lEM rbnKeSN/Q9Uv+zogyxRmAwSqnwmRBde4cfaiM/N311+prO34QJbYwyewMp4S/f0naeH2Cy+ 4yhstctLpUlkNm/kcBTNg== X-UI-Out-Filterresults: notjunk:1; V01:K0:IYRzBhsPwLY=:LaWHmZ+/plCBAQac+7JrQo XMcdnDagSSqYTdjHXG5SZDSHpLTUlOyYpbe4dVrz1CrzKbKQn5vxxVskluA3BRbDt1A7dVJGr IISanslAboYg5ajQ1ZC9z0ZnP5I7kT5WVt5HCujtWvl/D5q4ALg1MfgyeBlQuGOAOMIgxdCMm b6Me6ojXWbhD2+yF2eLj3LSrI82QPMgOkd7MuH+62Wr9PAHzX0JMdW53r0tMqkHS3xZfJnbxp wlP9h/WX0ugoQSQq3+bD/ac0aVnhCFAPkHC3g86rutSjt3LODFMBdRMUpPlamN82Pjy7GFgDL CVh687o4jKLORTXLZo8IiqkWcFT9oCNAkcQDEh/owsG/Bjlp8PwkLIeuvdin6EpK2UrJRYyRt uhvm9/RuMZyTFUas0yOdh2MLU3h9v20Z1TGDyoswVsZacFPhZa7hDq2y4zcuyCPpDIR8HXw4l op8wl08SMn10sl31j/WeD9N+fB21UIxd67J0IZpwBFJP+05jAq41sQglwJVC26+nu+iQleLsd bxjwXWaTerr9SaZ7ymYSB9ZpcQXwdDpzSX6fPnIBeis0k0WAvOniChqVYR7bdMkSE/1aSdvrS 8ECmrmlI6xgvRu0pra9RNGZRXOSJv5E77jmNl9tOz8y7seotc6JBEq9tmI3eBGNHj/NlesBVw myL5rnkliqSJHUPo72gpyuDw7yzLJgDTpM6ZK6mW3reqGFw7aGjLH0DapimwyXKXoDlwLsYVE fRjIbCdXlgbAAyw9AZ96NZRG0nsMtigINOLPjyomhPNjYmELln74MU18lzCdhhjM7Ory4rxnI zCRs7sjzUkRRyUXt7CA2byQ+et/XQ== Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Follow the original rootdir behavior to shrink the device size to minimal. The shrink itself is very simple, since dev extent is allocated on demand, we just need to shrink the device size to the device extent end position. Signed-off-by: Qu Wenruo --- mkfs/main.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/mkfs/main.c b/mkfs/main.c index bca836b5..c43ce18d 100644 --- a/mkfs/main.c +++ b/mkfs/main.c @@ -990,6 +990,107 @@ fail_no_dir: goto out; } +/* + * Shrink the image to its minimal size. + * + * The work is quite easy, as btrfs only allocates dev extent/chunk on demand. + * So we only need to do: + * 1) Determine the minimal image size + * By checking the device extent end + * 2) Modify in-memory device size + * 3) Modify device item + * 4) Modify superblock + */ +static int shrink_image(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info) +{ + struct btrfs_root *dev_root = fs_info->dev_root; + struct btrfs_root *chunk_root = fs_info->chunk_root; + struct btrfs_path path; + struct btrfs_key key; + struct btrfs_dev_extent *de; + struct btrfs_dev_item *di; + struct btrfs_device *dev; + u64 min_size; + int ret = 0; + + /* + * New rootdir can support multi device easily, but since only one + * device is supported, devid is fixed to 1. + */ + key.objectid = 1; + key.type = BTRFS_DEV_EXTENT_KEY; + key.offset = (u64)-1; + btrfs_init_path(&path); + + /* + * Determine minimal fs size by find the end position of last dev extent + */ + ret = btrfs_search_slot(NULL, dev_root, &key, &path, 0, 0); + if (ret == 0) { + WARN_ON(1); + ret = -EIO; + goto out_release; + } + if (ret < 0) + goto out_release; + + ret = btrfs_previous_item(dev_root, &path, key.objectid, + BTRFS_DEV_EXTENT_KEY); + if (ret < 0) + goto out_release; + if (ret > 0) { + ret = -ENOENT; + goto out_release; + } + btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]); + de = btrfs_item_ptr(path.nodes[0], path.slots[0], + struct btrfs_dev_extent); + min_size = key.offset + btrfs_dev_extent_length(path.nodes[0], de); + btrfs_release_path(&path); + + /* + * Modify btrfs_device size + */ + dev = list_entry(fs_info->fs_devices->devices.next, + struct btrfs_device, dev_list); + if (!dev) { + WARN_ON(1); + ret = -ENOENT; + goto out; + } + dev->total_bytes = min_size; + + /* + * Modify dev item size + */ + key.objectid = BTRFS_DEV_ITEMS_OBJECTID; + key.type = BTRFS_DEV_ITEM_KEY; + key.offset = 1; + + ret = btrfs_search_slot(trans, chunk_root, &key, &path, 0, 1); + if (ret > 0) { + ret = -ENOENT; + goto out_release; + } + if (ret < 0) + goto out_release; + di = btrfs_item_ptr(path.nodes[0], path.slots[0], + struct btrfs_dev_item); + btrfs_set_device_total_bytes(path.nodes[0], di, min_size); + btrfs_release_path(&path); + + /* + * Modify superblock size + */ + btrfs_set_super_total_bytes(fs_info->super_copy, min_size); + +out_release: + btrfs_release_path(&path); +out: + return ret; +} + static int make_image(const char *source_dir, struct btrfs_root *root) { int ret; @@ -1013,6 +1114,12 @@ static int make_image(const char *source_dir, struct btrfs_root *root) error("unable to traverse directory %s: %d", source_dir, ret); goto fail; } + + ret = shrink_image(trans, root->fs_info); + if (ret < 0) { + error("failed to shrink image: %d", ret); + goto out; + } ret = btrfs_commit_transaction(trans, root); if (ret) { error("transaction commit failed: %d", ret);