linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Qu Wenruo <quwenruo.btrfs@gmx.com>
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	[thread overview]
Message-ID: <20170904064110.25951-4-quwenruo.btrfs@gmx.com> (raw)
In-Reply-To: <20170904064110.25951-1-quwenruo.btrfs@gmx.com>

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 <quwenruo.btrfs@gmx.com>
---
 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);
-- 
2.14.1


  parent reply	other threads:[~2017-09-04  6:41 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-04  6:41 [PATCH 0/5] Mkfs: Rework --rootdir to a more generic behavior Qu Wenruo
2017-09-04  6:41 ` [PATCH 1/5] btrfs-progs: Fix one-byte overlap bug in free_block_group_cache Qu Wenruo
2017-09-04  6:41 ` [PATCH 2/5] btrfs-progs: mkfs: Rework rootdir option to avoid custom chunk layout Qu Wenruo
2017-09-04  6:41 ` Qu Wenruo [this message]
2017-09-04  6:41 ` [PATCH 4/5] btrfs-progs: mkfs: Update allocation info before verbose output Qu Wenruo
2017-09-04  6:41 ` [PATCH 5/5] btrfs-progs: Doc/mkfs: Add explanation for rootdir parameter Qu Wenruo
2017-09-04 10:47   ` Duncan
2017-09-04 18:08 ` [PATCH 0/5] Mkfs: Rework --rootdir to a more generic behavior David Sterba
2017-09-05  8:19   ` Qu Wenruo
2017-09-05 19:05     ` Goffredo Baroncelli
2017-09-06  3:20       ` Qu Wenruo
2017-09-06 18:44         ` Goffredo Baroncelli
2017-09-06 11:31       ` Austin S. Hemmelgarn
2017-09-06 16:43         ` Goffredo Baroncelli
2017-09-06 17:16           ` Austin S. Hemmelgarn
2017-09-06 17:48             ` Goffredo Baroncelli
2017-09-06 18:02               ` Austin S. Hemmelgarn
2017-09-06 18:31                 ` Goffredo Baroncelli
2017-09-06 18:46                   ` Austin S. Hemmelgarn

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170904064110.25951-4-quwenruo.btrfs@gmx.com \
    --to=quwenruo.btrfs@gmx.com \
    --cc=dsterba@suse.cz \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).