All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] Remaining part of mkfs --rootdir rework
@ 2017-11-29  9:15 Qu Wenruo
  2017-11-29  9:15 ` [PATCH 1/9] btrfs-progs: mkfs: Cleanup temporary chunks before filling rootdir Qu Wenruo
                   ` (9 more replies)
  0 siblings, 10 replies; 12+ messages in thread
From: Qu Wenruo @ 2017-11-29  9:15 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

Can be fetched from my github repo:
https://github.com/adam900710/btrfs-progs/tree/mkfs_rootdir_rework

Based on the following commit head of David's devel branch:
------
 commit af322ba5aa1dd0b2a3422e1c4acd8082948efa7b (david/devel)
 Author: Su Yue <suy.fnst@cn.fujitsu.com>
 Date:   Tue Nov 28 17:14:48 2017 +0800

    btrfs-progs: fi defrag: clean up duplicate code if find errors
    
    In function cmd_filesystem_defrag(), lines of code for error handling
    are duplicate and hard to expand in further.
    
    Create a jump label for errors.
    
    Signed-off-by: Su Yue <suy.fnst@cn.fujitsu.com>
    Signed-off-by: David Sterba <dsterba@suse.com>
------

Patch 1 is split from original patch.
Patch 2~5 are the patches rebased. Only minor conflicts.

Patch 6~7 are regression fix and its test case. Which prohibits
mkfs.btrfs --rootdir from creating new file.

Patch 8~9 are fix and test case for incorrect shrink behavior, which
will shrink the fs even --shrink is not specified.

Qu Wenruo (9):
  btrfs-progs: mkfs: Cleanup temporary chunks before filling rootdir
  btrfs-progs: mkfs: Don't use custom chunk allocator for rootdir
  btrfs-progs: mkfs/rootdir: Use over-reserve method to make size
    estimate easier
  btrfs-progs: mkfs/rootdir: Shrink fs for rootdir option
  btrfs-progs: mkfs: Separate shrink from rootdir
  btrfs-progs: mkfs: Fix regression preventing --rootdir to create file
  btrfs-progs: tests/mkfs: Introduce test case to check if mkfs rootdir
    can create new file
  btrfs-progs: mkfs: Use the whole file or block device to mkfs for
    rootdir
  btrfs-progs: tests/mkfs: Introduce test case to verify if mkfs.btrfs
    rootdir shrink behaves correctly

 Documentation/mkfs.btrfs.asciidoc                |  11 +
 mkfs/main.c                                      | 231 ++++++++++-----------
 mkfs/rootdir.c                                   | 249 +++++++++++++++++++----
 mkfs/rootdir.h                                   |   7 +-
 tests/mkfs-tests/011-rootdir-create-file/test.sh |  14 ++
 tests/mkfs-tests/012-rootdir-no-shrink/test.sh   |  38 ++++
 utils.c                                          |  17 +-
 utils.h                                          |   2 +
 8 files changed, 402 insertions(+), 167 deletions(-)
 create mode 100755 tests/mkfs-tests/011-rootdir-create-file/test.sh
 create mode 100755 tests/mkfs-tests/012-rootdir-no-shrink/test.sh

-- 
2.15.0


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/9] btrfs-progs: mkfs: Cleanup temporary chunks before filling rootdir
  2017-11-29  9:15 [PATCH 0/9] Remaining part of mkfs --rootdir rework Qu Wenruo
@ 2017-11-29  9:15 ` Qu Wenruo
  2017-11-29  9:15 ` [PATCH 2/9] btrfs-progs: mkfs: Don't use custom chunk allocator for rootdir Qu Wenruo
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Qu Wenruo @ 2017-11-29  9:15 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

Cleanup those temporary chunks should be as soon as possible, and it
should be especially before doing large tree operations, like filling
rootdir.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 mkfs/main.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/mkfs/main.c b/mkfs/main.c
index 2da38cb9490e..a81718d1517d 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -1248,6 +1248,13 @@ raid_groups:
 		goto out;
 	}
 
+	ret = cleanup_temp_chunks(fs_info, &allocation, data_profile,
+				  metadata_profile, metadata_profile);
+	if (ret < 0) {
+		error("failed to cleanup temporary chunks: %d", ret);
+		goto out;
+	}
+
 	if (source_dir_set) {
 		trans = btrfs_start_transaction(root, 1);
 		BUG_ON(IS_ERR(trans));
@@ -1311,12 +1318,6 @@ raid_groups:
 			}
 		}
 	}
-	ret = cleanup_temp_chunks(fs_info, &allocation, data_profile,
-				  metadata_profile, metadata_profile);
-	if (ret < 0) {
-		error("failed to cleanup temporary chunks: %d", ret);
-		goto out;
-	}
 
 	if (verbose) {
 		char features_buf[64];
-- 
2.15.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/9] btrfs-progs: mkfs: Don't use custom chunk allocator for rootdir
  2017-11-29  9:15 [PATCH 0/9] Remaining part of mkfs --rootdir rework Qu Wenruo
  2017-11-29  9:15 ` [PATCH 1/9] btrfs-progs: mkfs: Cleanup temporary chunks before filling rootdir Qu Wenruo
@ 2017-11-29  9:15 ` Qu Wenruo
  2017-11-29  9:15 ` [PATCH 3/9] btrfs-progs: mkfs/rootdir: Use over-reserve method to make size estimate easier Qu Wenruo
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Qu Wenruo @ 2017-11-29  9:15 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

Remove these custom chunk allocator for mkfs.
Use generic btrfs chunk allocator instead.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 mkfs/main.c | 62 -------------------------------------------------------------
 1 file changed, 62 deletions(-)

diff --git a/mkfs/main.c b/mkfs/main.c
index a81718d1517d..716395c4b6b4 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -413,53 +413,6 @@ static char *parse_subvol_name(const char *input)
 	return strdup(input);
 }
 
-static int create_chunks(struct btrfs_trans_handle *trans,
-			 struct btrfs_root *root, u64 num_of_meta_chunks,
-			 u64 size_of_data,
-			 struct mkfs_allocation *allocation)
-{
-	struct btrfs_fs_info *fs_info = root->fs_info;
-	u64 chunk_start;
-	u64 chunk_size;
-	u64 meta_type = BTRFS_BLOCK_GROUP_METADATA;
-	u64 data_type = BTRFS_BLOCK_GROUP_DATA;
-	u64 minimum_data_chunk_size = SZ_8M;
-	u64 i;
-	int ret;
-
-	for (i = 0; i < num_of_meta_chunks; i++) {
-		ret = btrfs_alloc_chunk(trans, fs_info,
-					&chunk_start, &chunk_size, meta_type);
-		if (ret)
-			return ret;
-		ret = btrfs_make_block_group(trans, fs_info, 0,
-					     meta_type, BTRFS_FIRST_CHUNK_TREE_OBJECTID,
-					     chunk_start, chunk_size);
-		allocation->metadata += chunk_size;
-		if (ret)
-			return ret;
-		set_extent_dirty(&root->fs_info->free_space_cache,
-				 chunk_start, chunk_start + chunk_size - 1);
-	}
-
-	if (size_of_data < minimum_data_chunk_size)
-		size_of_data = minimum_data_chunk_size;
-
-	ret = btrfs_alloc_data_chunk(trans, fs_info,
-				     &chunk_start, size_of_data, data_type, 0);
-	if (ret)
-		return ret;
-	ret = btrfs_make_block_group(trans, fs_info, 0,
-				     data_type, BTRFS_FIRST_CHUNK_TREE_OBJECTID,
-				     chunk_start, size_of_data);
-	allocation->data += size_of_data;
-	if (ret)
-		return ret;
-	set_extent_dirty(&root->fs_info->free_space_cache,
-			 chunk_start, chunk_start + size_of_data - 1);
-	return ret;
-}
-
 static int zero_output_file(int out_fd, u64 size)
 {
 	int loop_num;
@@ -1256,21 +1209,6 @@ raid_groups:
 	}
 
 	if (source_dir_set) {
-		trans = btrfs_start_transaction(root, 1);
-		BUG_ON(IS_ERR(trans));
-		ret = create_chunks(trans, root,
-				    num_of_meta_chunks, size_of_data,
-				    &allocation);
-		if (ret) {
-			error("unable to create chunks: %d", ret);
-			goto out;
-		}
-		ret = btrfs_commit_transaction(trans, root);
-		if (ret) {
-			error("transaction commit failed: %d", ret);
-			goto out;
-		}
-
 		if (subvol_name_set) {
 			u64 dirid, objectid;
 			struct btrfs_root *file_root;
-- 
2.15.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/9] btrfs-progs: mkfs/rootdir: Use over-reserve method to make size estimate easier
  2017-11-29  9:15 [PATCH 0/9] Remaining part of mkfs --rootdir rework Qu Wenruo
  2017-11-29  9:15 ` [PATCH 1/9] btrfs-progs: mkfs: Cleanup temporary chunks before filling rootdir Qu Wenruo
  2017-11-29  9:15 ` [PATCH 2/9] btrfs-progs: mkfs: Don't use custom chunk allocator for rootdir Qu Wenruo
@ 2017-11-29  9:15 ` Qu Wenruo
  2017-11-29  9:15 ` [PATCH 4/9] btrfs-progs: mkfs/rootdir: Shrink fs for rootdir option Qu Wenruo
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Qu Wenruo @ 2017-11-29  9:15 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

Use an easier method to calculate the estimate device for mkfs.btrfs
--rootdir.

The new method will over-estimate, but should ensure we won't encounter
ENOSPC.

It relies on the following data to estimate:
1) number of inodes
   for metadata chunk size
2) rounded up data size of each regular inode
   for data chunk size.

Total meta chunk size = round_up(nr_inode * (PATH_MAX * 3 + sectorsize),
min_chunk_size) * profile_multiplier

PATH_MAX is the maximum size possible for INODE_REF/DIR_INDEX/DIR_ITEM.
Sectorsize is the maximum size possible for inline extent.
min_chunk_size is 8M for SINGLE, and 32M for DUP, get from
btrfs_alloc_chunk().
profile_multiplier is 1 for Single, 2 for DUP.

Total data chunk size is much easier.
Total data chunk size = round_up(total_data_usage, min_chunk_size) *
profile_multiplier

Total_data_usage is the sum of *rounded up* size of each regular inode
use.
min_chunk_size is 8M for SINGLE, 64M for DUP, get from
btrfS_alloc_chunk().
Same profile_multiplier for meta.

This over-estimate calculate is, of course, over-estimate.
But since we will later shrink the fs to its real usage, it doesn't
matter much now.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 mkfs/main.c    | 109 ++++++++++++++++++++++++++--------------------------
 mkfs/rootdir.c | 119 +++++++++++++++++++++++++++++++++++++++------------------
 mkfs/rootdir.h |   5 +--
 3 files changed, 139 insertions(+), 94 deletions(-)

diff --git a/mkfs/main.c b/mkfs/main.c
index 716395c4b6b4..eb49182ebe81 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -747,8 +747,6 @@ int main(int argc, char **argv)
 	int subvol_name_set = 0;
 	char *source_dir = NULL;
 	int source_dir_set = 0;
-	u64 num_of_meta_chunks = 0;
-	u64 size_of_data = 0;
 	u64 source_dir_size = 0;
 	u64 min_dev_size;
 	int dev_cnt = 0;
@@ -977,6 +975,34 @@ int main(int argc, char **argv)
 
 	min_dev_size = btrfs_min_dev_size(nodesize, mixed, metadata_profile,
 					  data_profile);
+	/*
+	 * Enlarge the destination file or create new one, using the
+	 * size calculated from source dir.
+	 *
+	 * This must be done before minimal device size check.
+	 */
+	if (source_dir_set) {
+		fd = open(file, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP |
+			  S_IWGRP | S_IROTH);
+		if (fd < 0) {
+			error("unable to open %s: %s", file, strerror(errno));
+			goto error;
+		}
+
+		source_dir_size = btrfs_mkfs_size_dir(source_dir, sectorsize,
+				min_dev_size, metadata_profile, data_profile);
+		if (block_count < source_dir_size)
+			block_count = source_dir_size;
+		ret = zero_output_file(fd, block_count);
+		if (ret) {
+			error("unable to zero the output file");
+			close(fd);
+			goto error;
+		}
+		/* our "device" is the new image file */
+		dev_block_count = block_count;
+		close(fd);
+	}
 	/* Check device/block_count after the nodesize is determined */
 	if (block_count && block_count < min_dev_size) {
 		error("size %llu is too small to make a usable filesystem",
@@ -1010,51 +1036,28 @@ int main(int argc, char **argv)
 
 	dev_cnt--;
 
-	if (!source_dir_set) {
-		/*
-		 * open without O_EXCL so that the problem should not
-		 * occur by the following processing.
-		 * (btrfs_register_one_device() fails if O_EXCL is on)
-		 */
-		fd = open(file, O_RDWR);
-		if (fd < 0) {
-			error("unable to open %s: %s", file, strerror(errno));
-			goto error;
-		}
-		ret = btrfs_prepare_device(fd, file, &dev_block_count,
-				block_count,
-				(zero_end ? PREP_DEVICE_ZERO_END : 0) |
-				(discard ? PREP_DEVICE_DISCARD : 0) |
-				(verbose ? PREP_DEVICE_VERBOSE : 0));
-		if (ret) {
-			goto error;
-		}
-		if (block_count && block_count > dev_block_count) {
-			error("%s is smaller than requested size, expected %llu, found %llu",
-					file,
-					(unsigned long long)block_count,
-					(unsigned long long)dev_block_count);
-			goto error;
-		}
-	} else {
-		fd = open(file, O_CREAT | O_RDWR,
-				S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
-		if (fd < 0) {
-			error("unable to open %s: %s", file, strerror(errno));
-			goto error;
-		}
-
-		source_dir_size = btrfs_mkfs_size_dir(source_dir, sectorsize,
-					&num_of_meta_chunks, &size_of_data);
-		if(block_count < source_dir_size)
-			block_count = source_dir_size;
-		ret = zero_output_file(fd, block_count);
-		if (ret) {
-			error("unable to zero the output file");
-			goto error;
-		}
-		/* our "device" is the new image file */
-		dev_block_count = block_count;
+	/*
+	 * open without O_EXCL so that the problem should not
+	 * occur by the following processing.
+	 * (btrfs_register_one_device() fails if O_EXCL is on)
+	 */
+	fd = open(file, O_RDWR);
+	if (fd < 0) {
+		error("unable to open %s: %s", file, strerror(errno));
+		goto error;
+	}
+	ret = btrfs_prepare_device(fd, file, &dev_block_count,
+			block_count,
+			(zero_end ? PREP_DEVICE_ZERO_END : 0) |
+			(discard ? PREP_DEVICE_DISCARD : 0) |
+			(verbose ? PREP_DEVICE_VERBOSE : 0));
+	if (ret)
+		goto error;
+	if (block_count && block_count > dev_block_count) {
+		error("%s is smaller than requested size, expected %llu, found %llu",
+		      file, (unsigned long long)block_count,
+		      (unsigned long long)dev_block_count);
+		goto error;
 	}
 
 	/* To create the first block group and chunk 0 in make_btrfs */
@@ -1180,13 +1183,11 @@ int main(int argc, char **argv)
 	}
 
 raid_groups:
-	if (!source_dir_set) {
-		ret = create_raid_groups(trans, root, data_profile,
-				 metadata_profile, mixed, &allocation);
-		if (ret) {
-			error("unable to create raid groups: %d", ret);
-			goto out;
-		}
+	ret = create_raid_groups(trans, root, data_profile,
+			 metadata_profile, mixed, &allocation);
+	if (ret) {
+		error("unable to create raid groups: %d", ret);
+		goto out;
 	}
 
 	ret = create_tree(trans, root, BTRFS_DATA_RELOC_TREE_OBJECTID);
diff --git a/mkfs/rootdir.c b/mkfs/rootdir.c
index 0eb3f8f26139..f8cff44d06eb 100644
--- a/mkfs/rootdir.c
+++ b/mkfs/rootdir.c
@@ -33,19 +33,29 @@
 #include "transaction.h"
 #include "utils.h"
 #include "mkfs/rootdir.h"
+#include "mkfs/common.h"
 #include "send-utils.h"
 
-/*
- * This ignores symlinks with unreadable targets and subdirs that can't
- * be read.  It's a best-effort to give a rough estimate of the size of
- * a subdir.  It doesn't guarantee that prepopulating btrfs from this
- * tree won't still run out of space.
- */
-static u64 global_total_size;
-static u64 fs_block_size;
+static u32 fs_block_size;
 
 static u64 index_cnt = 2;
 
+/*
+ * Size estimate will be done using the following data:
+ * 1) Number of inodes
+ *    Since we will later shrink the fs, over-estimate is completely fine here
+ *    as long as our estimate ensure we can populate the image without ENOSPC.
+ *    So we only records how many inodes there is, and use the maximum space
+ *    usage for every inode.
+ *
+ * 2) Data space each (regular) inode uses
+ *    To estimate data chunk size.
+ *    Don't care if it can fit as inline extent.
+ *    Always round them up to sectorsize.
+ */
+static u64 ftw_meta_nr_inode;
+static u64 ftw_data_size;
+
 static int add_directory_items(struct btrfs_trans_handle *trans,
 			       struct btrfs_root *root, u64 objectid,
 			       ino_t parent_inum, const char *name,
@@ -685,53 +695,88 @@ out:
 static int ftw_add_entry_size(const char *fpath, const struct stat *st,
 			      int type)
 {
-	if (type == FTW_F || type == FTW_D)
-		global_total_size += round_up(st->st_size, fs_block_size);
+	/*
+	 * Failed to read dir, mostly due to EPERM.
+	 * Abort ASAP, so we don't need to populate the fs
+	 */
+	if (type == FTW_DNR || type == FTW_NS)
+		return -EPERM;
+
+	if (S_ISREG(st->st_mode))
+		ftw_data_size += round_up(st->st_size, fs_block_size);
+	ftw_meta_nr_inode++;
 
 	return 0;
 }
 
-u64 btrfs_mkfs_size_dir(const char *dir_name, u64 sectorsize,
-			u64 *num_of_meta_chunks_ret, u64 *size_of_data_ret)
+u64 btrfs_mkfs_size_dir(const char *dir_name, u32 sectorsize, u64 min_dev_size,
+			u64 meta_profile, u64 data_profile)
 {
-	u64 dir_size = 0;
 	u64 total_size = 0;
 	int ret;
-	u64 default_chunk_size = SZ_8M;
-	u64 allocated_meta_size = SZ_8M;
-	u64 allocated_total_size = 20 * SZ_1M;	/* 20MB */
-	u64 num_of_meta_chunks = 0;
-	u64 num_of_data_chunks = 0;
-	u64 num_of_allocated_meta_chunks =
-			allocated_meta_size / default_chunk_size;
-
-	global_total_size = 0;
+
+	u64 meta_size = 0;	/* Based on @ftw_meta_nr_inode */
+	u64 meta_chunk_size = 0;/* Based on @meta_size */
+	u64 data_chunk_size = 0;/* Based on @ftw_data_size */
+
+	u64 meta_threshold = SZ_8M;
+	u64 data_threshold = SZ_8M;
+
+	float data_multipler = 1;
+	float meta_multipler = 1;
+
 	fs_block_size = sectorsize;
+	ftw_data_size = 0;
+	ftw_meta_nr_inode = 0;
 	ret = ftw(dir_name, ftw_add_entry_size, 10);
-	dir_size = global_total_size;
 	if (ret < 0) {
 		error("ftw subdir walk of %s failed: %s", dir_name,
 			strerror(errno));
 		exit(1);
 	}
 
-	num_of_data_chunks = (dir_size + default_chunk_size - 1) /
-		default_chunk_size;
 
-	num_of_meta_chunks = (dir_size / 2) / default_chunk_size;
-	if (((dir_size / 2) % default_chunk_size) != 0)
-		num_of_meta_chunks++;
-	if (num_of_meta_chunks <= num_of_allocated_meta_chunks)
-		num_of_meta_chunks = 0;
-	else
-		num_of_meta_chunks -= num_of_allocated_meta_chunks;
+	/*
+	 * Maximum metadata useage for every inode, which will be PATH_MAX
+	 * for the following items:
+	 * 1) DIR_ITEM
+	 * 2) DIR_INDEX
+	 * 3) INODE_REF
+	 *
+	 * Plus possible inline extent size, which is sectorsize.
+	 *
+	 * And finally, allow metadata usage to increase with data size.
+	 * Follow the old kernel 8:1 data:meta ratio.
+	 * This is especially important for --rootdir, as the file extent size
+	 * up limit is 1M, instead of 128M in kernel.
+	 * This can bump meta usage easily.
+	 */
+	meta_size = ftw_meta_nr_inode * (PATH_MAX * 3 + sectorsize) +
+		    ftw_data_size / 8;
 
-	total_size = allocated_total_size +
-		     (num_of_data_chunks * default_chunk_size) +
-		     (num_of_meta_chunks * default_chunk_size);
+	/* Minimal chunk size from btrfs_alloc_chunk(). */
+	if (meta_profile & BTRFS_BLOCK_GROUP_DUP) {
+		meta_threshold = SZ_32M;
+		meta_multipler = 2;
+	}
+	if (data_profile & BTRFS_BLOCK_GROUP_DUP) {
+		data_threshold = SZ_64M;
+		data_multipler = 2;
+	}
 
-	*num_of_meta_chunks_ret = num_of_meta_chunks;
-	*size_of_data_ret = num_of_data_chunks * default_chunk_size;
+	/*
+	 * Only when the usage is larger than the minimal chunk size (threshold)
+	 * we need to allocate new chunk, or the initial chunk in the image is
+	 * large enough.
+	 */
+	if (meta_size > meta_threshold)
+		meta_chunk_size = (round_up(meta_size, meta_threshold) -
+				   meta_threshold) * meta_multipler;
+	if (ftw_data_size > data_threshold)
+		data_chunk_size = (round_up(ftw_data_size, data_threshold) -
+				   data_threshold) * data_multipler;
+
+	total_size = data_chunk_size + meta_chunk_size + min_dev_size;
 	return total_size;
 }
 
diff --git a/mkfs/rootdir.h b/mkfs/rootdir.h
index c4b120c5d1e4..ada50ccb6ac4 100644
--- a/mkfs/rootdir.h
+++ b/mkfs/rootdir.h
@@ -30,7 +30,6 @@ struct directory_name_entry {
 
 int btrfs_mkfs_fill_dir(const char *source_dir, struct btrfs_root *root,
 			bool verbose);
-u64 btrfs_mkfs_size_dir(const char *dir_name, u64 sectorsize,
-			u64 *num_of_meta_chunks_ret, u64 *size_of_data_ret);
-
+u64 btrfs_mkfs_size_dir(const char *dir_name, u32 sectorsize, u64 min_dev_size,
+			u64 meta_profile, u64 data_profile);
 #endif
-- 
2.15.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/9] btrfs-progs: mkfs/rootdir: Shrink fs for rootdir option
  2017-11-29  9:15 [PATCH 0/9] Remaining part of mkfs --rootdir rework Qu Wenruo
                   ` (2 preceding siblings ...)
  2017-11-29  9:15 ` [PATCH 3/9] btrfs-progs: mkfs/rootdir: Use over-reserve method to make size estimate easier Qu Wenruo
@ 2017-11-29  9:15 ` Qu Wenruo
  2017-11-29  9:16 ` [PATCH 5/9] btrfs-progs: mkfs: Separate shrink from rootdir Qu Wenruo
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Qu Wenruo @ 2017-11-29  9:15 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

Use the new dev extent based shrink method for rootdir option.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 mkfs/main.c    |   5 +++
 mkfs/rootdir.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 mkfs/rootdir.h |   1 +
 3 files changed, 117 insertions(+)

diff --git a/mkfs/main.c b/mkfs/main.c
index eb49182ebe81..eb3e5bb1f92e 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -1256,6 +1256,11 @@ raid_groups:
 				goto out;
 			}
 		}
+		ret = btrfs_mkfs_shrink_fs(fs_info, NULL);
+		if (ret < 0) {
+			error("error while shrinking filesystem: %d", ret);
+			goto out;
+		}
 	}
 
 	if (verbose) {
diff --git a/mkfs/rootdir.c b/mkfs/rootdir.c
index f8cff44d06eb..271167fe0c02 100644
--- a/mkfs/rootdir.c
+++ b/mkfs/rootdir.c
@@ -822,3 +822,114 @@ out:
 
 	return ret;
 }
+
+/*
+ * Set device size to @new_size.
+ *
+ * Only used for --rootdir option.
+ * We will need to reset the following values:
+ * 1) dev item in chunk tree
+ * 2) super->dev_item
+ * 3) super->total_bytes
+ */
+static int set_device_size(struct btrfs_fs_info *fs_info,
+			   struct btrfs_device *device, u64 new_size)
+{
+	struct btrfs_root *chunk_root = fs_info->chunk_root;
+	struct btrfs_trans_handle *trans;
+	struct btrfs_dev_item *di;
+	struct btrfs_path path;
+	struct btrfs_key key;
+	int ret;
+
+	/*
+	 * Update in-meory device->total_bytes, so that at trans commit time,
+	 * it super->dev_item will also get updated
+	 */
+	device->total_bytes = new_size;
+	btrfs_init_path(&path);
+
+	/* Update device item in chunk tree */
+	trans = btrfs_start_transaction(chunk_root, 1);
+	if (IS_ERR(trans)) {
+		ret = PTR_ERR(trans);
+		error("failed to start transaction: %d (%s)", ret,
+			strerror(-ret));
+		return ret;
+	}
+	key.objectid = BTRFS_DEV_ITEMS_OBJECTID;
+	key.type = BTRFS_DEV_ITEM_KEY;
+	key.offset = device->devid;
+
+	ret = btrfs_search_slot(trans, chunk_root, &key, &path, 0, 1);
+	if (ret < 0)
+		goto err;
+	if (ret > 0)
+		ret = -ENOENT;
+	di = btrfs_item_ptr(path.nodes[0], path.slots[0],
+			    struct btrfs_dev_item);
+	btrfs_set_device_total_bytes(path.nodes[0], di, new_size);
+	btrfs_mark_buffer_dirty(path.nodes[0]);
+
+	/*
+	 * Update super->total_bytes, since it's only used for --rootdir,
+	 * there is only one device, just use the @new_size.
+	 */
+	btrfs_set_super_total_bytes(fs_info->super_copy, new_size);
+
+	/*
+	 * Commit transaction to reflect the updated super->total_bytes and
+	 * super->dev_item
+	 */
+	ret = btrfs_commit_transaction(trans, chunk_root);
+	if (ret < 0)
+		error("failed to commit current transaction: %d (%s)",
+			ret, strerror(-ret));
+	btrfs_release_path(&path);
+	return ret;
+
+err:
+	btrfs_release_path(&path);
+	/*
+	 * Commit trans here won't cause problem since the fs still has
+	 * bad magic, and something wrong already happened, we don't
+	 * care the return value anyway.
+	 */
+	btrfs_commit_transaction(trans, chunk_root);
+	return ret;
+}
+
+int btrfs_mkfs_shrink_fs(struct btrfs_fs_info *fs_info, u64 *new_size_ret)
+{
+	u64 new_size;
+	struct btrfs_device *device;
+	struct list_head *cur;
+	int nr_devs = 0;
+	int ret;
+
+	list_for_each(cur, &fs_info->fs_devices->devices)
+		nr_devs++;
+
+	if (nr_devs > 1) {
+		error("cannot shrink fs with more than 1 device");
+		return -ENOTTY;
+	}
+
+	ret = get_device_extent_end(fs_info, 1, &new_size);
+	if (ret < 0) {
+		error("failed to get minimal device size: %d (%s)",
+			ret, strerror(-ret));
+		return ret;
+	}
+
+	BUG_ON(!IS_ALIGNED(new_size, fs_info->sectorsize));
+
+	device = list_entry(fs_info->fs_devices->devices.next,
+			   struct btrfs_device, dev_list);
+	ret = set_device_size(fs_info, device, new_size);
+	if (ret < 0)
+		return ret;
+	if (new_size_ret)
+		*new_size_ret = new_size;
+	return ret;
+}
diff --git a/mkfs/rootdir.h b/mkfs/rootdir.h
index ada50ccb6ac4..91bebc507f02 100644
--- a/mkfs/rootdir.h
+++ b/mkfs/rootdir.h
@@ -32,4 +32,5 @@ int btrfs_mkfs_fill_dir(const char *source_dir, struct btrfs_root *root,
 			bool verbose);
 u64 btrfs_mkfs_size_dir(const char *dir_name, u32 sectorsize, u64 min_dev_size,
 			u64 meta_profile, u64 data_profile);
+int btrfs_mkfs_shrink_fs(struct btrfs_fs_info *fs_info, u64 *new_size_ret);
 #endif
-- 
2.15.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 5/9] btrfs-progs: mkfs: Separate shrink from rootdir
  2017-11-29  9:15 [PATCH 0/9] Remaining part of mkfs --rootdir rework Qu Wenruo
                   ` (3 preceding siblings ...)
  2017-11-29  9:15 ` [PATCH 4/9] btrfs-progs: mkfs/rootdir: Shrink fs for rootdir option Qu Wenruo
@ 2017-11-29  9:16 ` Qu Wenruo
  2017-11-29  9:16 ` [PATCH 6/9] btrfs-progs: mkfs: Fix regression preventing --rootdir to create file Qu Wenruo
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Qu Wenruo @ 2017-11-29  9:16 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

Make --shrink a separate option for --rootdir, and make it default to
off.
So this will cause less confusion.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 Documentation/mkfs.btrfs.asciidoc | 11 +++++++++++
 mkfs/main.c                       | 26 ++++++++++++++++++++------
 mkfs/rootdir.c                    | 21 ++++++++++++++++++++-
 mkfs/rootdir.h                    |  3 ++-
 4 files changed, 53 insertions(+), 8 deletions(-)

diff --git a/Documentation/mkfs.btrfs.asciidoc b/Documentation/mkfs.btrfs.asciidoc
index 62f5a5bebaee..ded798216a5b 100644
--- a/Documentation/mkfs.btrfs.asciidoc
+++ b/Documentation/mkfs.btrfs.asciidoc
@@ -106,6 +106,17 @@ Please see the mount option 'discard' for that in `btrfs`(5).
 *-r|--rootdir <rootdir>*::
 Populate the toplevel subvolume with files from 'rootdir'.  This does not
 require root permissions and does not mount the filesystem.
++
+NOTE: This option may enlarge the image or file to ensure it's large enough to
+contain the files from 'rootdir'.
+
+*--shrink*:
+Shrink the filesystem to its minimal size, only works with *-r|--rootdir*
+option.
++
+NOTE: If the destination is regular file, this option will also reduce the
+file size. Or it will only reduce the filesystem available space.
+Extra space will not be usable unless resized using 'btrfs filesystem resize'.
 
 *-O|--features <feature1>[,<feature2>...]*::
 A list of filesystem features turned on at mkfs time. Not all features are
diff --git a/mkfs/main.c b/mkfs/main.c
index eb3e5bb1f92e..64cf03289188 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -746,9 +746,11 @@ int main(int argc, char **argv)
 	char *subvol_name = NULL;
 	int subvol_name_set = 0;
 	char *source_dir = NULL;
-	int source_dir_set = 0;
+	bool source_dir_set = false;
+	bool shrink_rootdir = false;
 	u64 source_dir_size = 0;
 	u64 min_dev_size;
+	u64 shrink_size;
 	int dev_cnt = 0;
 	int saved_optind;
 	char fs_uuid[BTRFS_UUID_UNPARSED_SIZE] = { 0 };
@@ -758,6 +760,7 @@ int main(int argc, char **argv)
 
 	while(1) {
 		int c;
+		enum { GETOPT_VAL_SHRINK = 257 };
 		static const struct option long_options[] = {
 			{ "alloc-start", required_argument, NULL, 'A'},
 			{ "byte-count", required_argument, NULL, 'b' },
@@ -776,6 +779,7 @@ int main(int argc, char **argv)
 			{ "features", required_argument, NULL, 'O' },
 			{ "uuid", required_argument, NULL, 'U' },
 			{ "quiet", 0, NULL, 'q' },
+			{ "shrink", no_argument, NULL, GETOPT_VAL_SHRINK },
 			{ "help", no_argument, NULL, GETOPT_VAL_HELP },
 			{ NULL, 0, NULL, 0}
 		};
@@ -847,7 +851,7 @@ int main(int argc, char **argv)
 				break;
 			case 'r':
 				source_dir = optarg;
-				source_dir_set = 1;
+				source_dir_set = true;
 				break;
 			case 'U':
 				strncpy(fs_uuid, optarg,
@@ -859,6 +863,9 @@ int main(int argc, char **argv)
 			case 'q':
 				verbose = 0;
 				break;
+			case GETOPT_VAL_SHRINK:
+				shrink_rootdir = true;
+				break;
 			case GETOPT_VAL_HELP:
 			default:
 				print_usage(c != GETOPT_VAL_HELP);
@@ -886,6 +893,10 @@ int main(int argc, char **argv)
 		error("the option -r is limited to a single device");
 		goto error;
 	}
+	if (shrink_rootdir && !source_dir_set) {
+		error("the option --shrink can only be paired with -r");
+		goto error;
+	}
 
 	if (*fs_uuid) {
 		uuid_t dummy_uuid;
@@ -1256,10 +1267,13 @@ raid_groups:
 				goto out;
 			}
 		}
-		ret = btrfs_mkfs_shrink_fs(fs_info, NULL);
-		if (ret < 0) {
-			error("error while shrinking filesystem: %d", ret);
-			goto out;
+		if (shrink_rootdir) {
+			ret = btrfs_mkfs_shrink_fs(fs_info, &shrink_size,
+						   shrink_rootdir);
+			if (ret < 0) {
+				error("error while shrinking filesystem: %d", ret);
+				goto out;
+			}
 		}
 	}
 
diff --git a/mkfs/rootdir.c b/mkfs/rootdir.c
index 271167fe0c02..b91900834316 100644
--- a/mkfs/rootdir.c
+++ b/mkfs/rootdir.c
@@ -899,11 +899,13 @@ err:
 	return ret;
 }
 
-int btrfs_mkfs_shrink_fs(struct btrfs_fs_info *fs_info, u64 *new_size_ret)
+int btrfs_mkfs_shrink_fs(struct btrfs_fs_info *fs_info, u64 *new_size_ret,
+			 bool shrink_file_size)
 {
 	u64 new_size;
 	struct btrfs_device *device;
 	struct list_head *cur;
+	struct stat64 file_stat;
 	int nr_devs = 0;
 	int ret;
 
@@ -931,5 +933,22 @@ int btrfs_mkfs_shrink_fs(struct btrfs_fs_info *fs_info, u64 *new_size_ret)
 		return ret;
 	if (new_size_ret)
 		*new_size_ret = new_size;
+
+	if (shrink_file_size) {
+		ret = fstat64(device->fd, &file_stat);
+		if (ret < 0) {
+			error("failed to stat devid %llu: %s", device->devid,
+				strerror(errno));
+			return ret;
+		}
+		if (!S_ISREG(file_stat.st_mode))
+			return ret;
+		ret = ftruncate64(device->fd, new_size);
+		if (ret < 0) {
+			error("failed to truncate device file of devid %llu: %s",
+				device->devid, strerror(errno));
+			return ret;
+		}
+	}
 	return ret;
 }
diff --git a/mkfs/rootdir.h b/mkfs/rootdir.h
index 91bebc507f02..7ab53c292c9d 100644
--- a/mkfs/rootdir.h
+++ b/mkfs/rootdir.h
@@ -32,5 +32,6 @@ int btrfs_mkfs_fill_dir(const char *source_dir, struct btrfs_root *root,
 			bool verbose);
 u64 btrfs_mkfs_size_dir(const char *dir_name, u32 sectorsize, u64 min_dev_size,
 			u64 meta_profile, u64 data_profile);
-int btrfs_mkfs_shrink_fs(struct btrfs_fs_info *fs_info, u64 *new_size_ret);
+int btrfs_mkfs_shrink_fs(struct btrfs_fs_info *fs_info, u64 *new_size_ret,
+			 bool shrink_file_size);
 #endif
-- 
2.15.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 6/9] btrfs-progs: mkfs: Fix regression preventing --rootdir to create file
  2017-11-29  9:15 [PATCH 0/9] Remaining part of mkfs --rootdir rework Qu Wenruo
                   ` (4 preceding siblings ...)
  2017-11-29  9:16 ` [PATCH 5/9] btrfs-progs: mkfs: Separate shrink from rootdir Qu Wenruo
@ 2017-11-29  9:16 ` Qu Wenruo
  2017-11-30  5:16   ` Misono, Tomohiro
  2017-11-29  9:16 ` [PATCH 7/9] btrfs-progs: tests/mkfs: Introduce test case to check if mkfs rootdir can create new file Qu Wenruo
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 12+ messages in thread
From: Qu Wenruo @ 2017-11-29  9:16 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

Commit 460e93f25754 ("btrfs-progs: mkfs: check the status of file at mkfs")
will try to check the file state before creating fs on it.

The check is mostly fine for normal mkfs case, while for --rootdir
option, it's allowed to create new file if destination file doesn't
exist.

Fix it by allowing non-existing file if --rootdir is specified.

Fixes: 460e93f25754 ("btrfs-progs: mkfs: check the status of file at mkfs")
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 mkfs/main.c |  6 ++++--
 utils.c     | 15 +++++++++++++++
 utils.h     |  1 +
 3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/mkfs/main.c b/mkfs/main.c
index 64cf03289188..a34b73bfb845 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -733,7 +733,7 @@ int main(int argc, char **argv)
 	u32 stripesize = 4096;
 	int zero_end = 1;
 	int fd = -1;
-	int ret;
+	int ret = 0;
 	int close_ret;
 	int i;
 	int mixed = 0;
@@ -913,7 +913,9 @@ int main(int argc, char **argv)
 
 	while (dev_cnt-- > 0) {
 		file = argv[optind++];
-		if (is_block_device(file) == 1)
+		if (source_dir_set && is_path_exist(file) == 0)
+			ret = 0;
+		else if (is_block_device(file) == 1)
 			ret = test_dev_for_mkfs(file, force_overwrite);
 		else
 			ret = test_status_for_mkfs(file, force_overwrite);
diff --git a/utils.c b/utils.c
index 524f463d3140..22c137514592 100644
--- a/utils.c
+++ b/utils.c
@@ -456,6 +456,21 @@ static int is_reg_file(const char *path)
 	return S_ISREG(statbuf.st_mode);
 }
 
+int is_path_exist(const char *path)
+{
+	struct stat statbuf;
+	int ret;
+
+	ret = stat(path, &statbuf);
+	if (ret < 0) {
+		if (errno == ENOENT)
+			return 0;
+		else
+			return -errno;
+	}
+	return 1;
+}
+
 /*
  * This function checks if the given input parameter is
  * an uuid or a path
diff --git a/utils.h b/utils.h
index a82d46f6d7cc..860c25d3cdba 100644
--- a/utils.h
+++ b/utils.h
@@ -122,6 +122,7 @@ int set_label(const char *btrfs_dev, const char *label);
 char *__strncpy_null(char *dest, const char *src, size_t n);
 int is_block_device(const char *file);
 int is_mount_point(const char *file);
+int is_path_exist(const char *file);
 int check_arg_type(const char *input);
 int open_path_or_dev_mnt(const char *path, DIR **dirstream, int verbose);
 int btrfs_open(const char *path, DIR **dirstream, int verbose, int dir_only);
-- 
2.15.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 7/9] btrfs-progs: tests/mkfs: Introduce test case to check if mkfs rootdir can create new file
  2017-11-29  9:15 [PATCH 0/9] Remaining part of mkfs --rootdir rework Qu Wenruo
                   ` (5 preceding siblings ...)
  2017-11-29  9:16 ` [PATCH 6/9] btrfs-progs: mkfs: Fix regression preventing --rootdir to create file Qu Wenruo
@ 2017-11-29  9:16 ` Qu Wenruo
  2017-11-29  9:16 ` [PATCH 8/9] btrfs-progs: mkfs: Use the whole file or block device to mkfs for rootdir Qu Wenruo
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Qu Wenruo @ 2017-11-29  9:16 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

To test regression 460e93f25754 ("btrfs-progs: mkfs: check the status of file at
mkfs").

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 tests/mkfs-tests/011-rootdir-create-file/test.sh | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
 create mode 100755 tests/mkfs-tests/011-rootdir-create-file/test.sh

diff --git a/tests/mkfs-tests/011-rootdir-create-file/test.sh b/tests/mkfs-tests/011-rootdir-create-file/test.sh
new file mode 100755
index 000000000000..c6f3d74da885
--- /dev/null
+++ b/tests/mkfs-tests/011-rootdir-create-file/test.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+# Regression test for mkfs.btrfs --rootdir on non-exist file
+# Designed behavior is, it should create a new file if destination doesn't exist
+# Regression 460e93f25754 ("btrfs-progs: mkfs: check the status of file at mkfs")
+
+
+source "$TOP/tests/common"
+
+check_prereq mkfs.btrfs
+
+tmp=$(mktemp -d --tmpdir btrfs-progs-mkfs.rootdirXXXXXXX)
+run_check "$TOP/mkfs.btrfs" -f -r "$TOP/Documentation/" $tmp/new_file
+
+rm -rf -- "$tmp"
-- 
2.15.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 8/9] btrfs-progs: mkfs: Use the whole file or block device to mkfs for rootdir
  2017-11-29  9:15 [PATCH 0/9] Remaining part of mkfs --rootdir rework Qu Wenruo
                   ` (6 preceding siblings ...)
  2017-11-29  9:16 ` [PATCH 7/9] btrfs-progs: tests/mkfs: Introduce test case to check if mkfs rootdir can create new file Qu Wenruo
@ 2017-11-29  9:16 ` Qu Wenruo
  2017-11-29  9:16 ` [PATCH 9/9] btrfs-progs: tests/mkfs: Introduce test case to verify if mkfs.btrfs rootdir shrink behaves correctly Qu Wenruo
  2017-12-07 19:06 ` [PATCH 0/9] Remaining part of mkfs --rootdir rework David Sterba
  9 siblings, 0 replies; 12+ messages in thread
From: Qu Wenruo @ 2017-11-29  9:16 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

For --rootdir, even for large existing file or block device, it will
always shrink the result filesystem.

The problem is, mkfs.btrfs will try to calculate the dir size, and use
it as @block_count to mkfs, which makes the result filesystem shrinked.

Fix by trying to get the original block device or file size as
@block_count, so mkfs.btrfs can use the full file/block device for
--rootdir option.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 mkfs/main.c | 22 ++++++++++++++++++++--
 utils.c     |  2 +-
 utils.h     |  1 +
 3 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/mkfs/main.c b/mkfs/main.c
index a34b73bfb845..eeeba9292856 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -995,13 +995,31 @@ int main(int argc, char **argv)
 	 * This must be done before minimal device size check.
 	 */
 	if (source_dir_set) {
-		fd = open(file, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP |
-			  S_IWGRP | S_IROTH);
+		int oflags = O_RDWR;
+		struct stat statbuf;
+
+		if (is_path_exist(file) == 0)
+			oflags |= O_CREAT;
+
+		fd = open(file, oflags , S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
+					 S_IROTH);
 		if (fd < 0) {
 			error("unable to open %s: %s", file, strerror(errno));
 			goto error;
 		}
+		ret = fstat(fd, &statbuf);
+		if (ret < 0) {
+			error("unable to stat %s: %s", file, strerror(errno));
+			ret = -errno;
+			goto error;
+		}
 
+		/*
+		 * Block_count not specified, use file/dev size first.
+		 * Or we will always use source_dir_size calculated for mkfs.
+		 */
+		if (!block_count)
+			block_count = btrfs_device_size(fd, &statbuf);
 		source_dir_size = btrfs_mkfs_size_dir(source_dir, sectorsize,
 				min_dev_size, metadata_profile, data_profile);
 		if (block_count < source_dir_size)
diff --git a/utils.c b/utils.c
index 22c137514592..80071e23fe2b 100644
--- a/utils.c
+++ b/utils.c
@@ -447,7 +447,7 @@ int is_mount_point(const char *path)
 	return ret;
 }
 
-static int is_reg_file(const char *path)
+int is_reg_file(const char *path)
 {
 	struct stat statbuf;
 
diff --git a/utils.h b/utils.h
index 860c25d3cdba..bd7484fd3620 100644
--- a/utils.h
+++ b/utils.h
@@ -123,6 +123,7 @@ char *__strncpy_null(char *dest, const char *src, size_t n);
 int is_block_device(const char *file);
 int is_mount_point(const char *file);
 int is_path_exist(const char *file);
+int is_reg_file(const char *path);
 int check_arg_type(const char *input);
 int open_path_or_dev_mnt(const char *path, DIR **dirstream, int verbose);
 int btrfs_open(const char *path, DIR **dirstream, int verbose, int dir_only);
-- 
2.15.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 9/9] btrfs-progs: tests/mkfs: Introduce test case to verify if mkfs.btrfs rootdir shrink behaves correctly
  2017-11-29  9:15 [PATCH 0/9] Remaining part of mkfs --rootdir rework Qu Wenruo
                   ` (7 preceding siblings ...)
  2017-11-29  9:16 ` [PATCH 8/9] btrfs-progs: mkfs: Use the whole file or block device to mkfs for rootdir Qu Wenruo
@ 2017-11-29  9:16 ` Qu Wenruo
  2017-12-07 19:06 ` [PATCH 0/9] Remaining part of mkfs --rootdir rework David Sterba
  9 siblings, 0 replies; 12+ messages in thread
From: Qu Wenruo @ 2017-11-29  9:16 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 tests/mkfs-tests/012-rootdir-no-shrink/test.sh | 38 ++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)
 create mode 100755 tests/mkfs-tests/012-rootdir-no-shrink/test.sh

diff --git a/tests/mkfs-tests/012-rootdir-no-shrink/test.sh b/tests/mkfs-tests/012-rootdir-no-shrink/test.sh
new file mode 100755
index 000000000000..1dfa55b376f6
--- /dev/null
+++ b/tests/mkfs-tests/012-rootdir-no-shrink/test.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# Test if mkfs.btrfs --rootdir will skip shrinking correctly
+
+source "$TOP/tests/common"
+
+check_prereq mkfs.btrfs
+
+setup_root_helper
+
+fs_size=$((512 * 1024 * 1024))
+bs=$((1024 * 1024))
+tmp=$(mktemp -d --tmpdir btrfs-progs-mkfs.rootdirXXXXXXX)
+
+prepare_test_dev $fs_size
+
+### no shrink case ###
+
+run_check "$TOP/mkfs.btrfs" -f -r $tmp "$TEST_DEV"
+run_check_mount_test_dev
+
+# We should be able to write at least half of the fs size data since
+# the fs is not shrunk
+run_check $SUDO_HELPER dd if=/dev/zero bs=$bs count=$(($fs_size / $bs / 2)) \
+	of="$TEST_MNT/file"
+
+run_check_umount_test_dev
+
+### shrink case ###
+run_check "$TOP/mkfs.btrfs" -f -r $tmp --shrink "$TEST_DEV"
+run_check_mount_test_dev
+
+run_mustfail "mkfs.btrfs for shrink rootdir" \
+	$SUDO_HELPER dd if=/dev/zero bs=$bs count=$(($fs_size / $bs / 2)) \
+	of="$TEST_MNT/file"
+
+run_check_umount_test_dev
+
+rm -rf -- "$tmp"
-- 
2.15.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 6/9] btrfs-progs: mkfs: Fix regression preventing --rootdir to create file
  2017-11-29  9:16 ` [PATCH 6/9] btrfs-progs: mkfs: Fix regression preventing --rootdir to create file Qu Wenruo
@ 2017-11-30  5:16   ` Misono, Tomohiro
  0 siblings, 0 replies; 12+ messages in thread
From: Misono, Tomohiro @ 2017-11-30  5:16 UTC (permalink / raw)
  To: Qu Wenruo, linux-btrfs; +Cc: dsterba

On 2017/11/29 18:16, Qu Wenruo wrote:
> Commit 460e93f25754 ("btrfs-progs: mkfs: check the status of file at mkfs")
> will try to check the file state before creating fs on it.
> 
> The check is mostly fine for normal mkfs case, while for --rootdir
> option, it's allowed to create new file if destination file doesn't
> exist.
> 
> Fix it by allowing non-existing file if --rootdir is specified.
> 
> Fixes: 460e93f25754 ("btrfs-progs: mkfs: check the status of file at mkfs")
> Signed-off-by: Qu Wenruo <wqu@suse.com>

Sorry, I didn't notice that. Thanks.
Reviewed-by: Tomohiro Misono <misono.tomohiro@jp.fujitsu.com>

> ---
>  mkfs/main.c |  6 ++++--
>  utils.c     | 15 +++++++++++++++
>  utils.h     |  1 +
>  3 files changed, 20 insertions(+), 2 deletions(-)
> 
> diff --git a/mkfs/main.c b/mkfs/main.c
> index 64cf03289188..a34b73bfb845 100644
> --- a/mkfs/main.c
> +++ b/mkfs/main.c
> @@ -733,7 +733,7 @@ int main(int argc, char **argv)
>  	u32 stripesize = 4096;
>  	int zero_end = 1;
>  	int fd = -1;
> -	int ret;
> +	int ret = 0;
>  	int close_ret;
>  	int i;
>  	int mixed = 0;
> @@ -913,7 +913,9 @@ int main(int argc, char **argv)
>  
>  	while (dev_cnt-- > 0) {
>  		file = argv[optind++];
> -		if (is_block_device(file) == 1)
> +		if (source_dir_set && is_path_exist(file) == 0)
> +			ret = 0;
> +		else if (is_block_device(file) == 1)
>  			ret = test_dev_for_mkfs(file, force_overwrite);
>  		else
>  			ret = test_status_for_mkfs(file, force_overwrite);
> diff --git a/utils.c b/utils.c
> index 524f463d3140..22c137514592 100644
> --- a/utils.c
> +++ b/utils.c
> @@ -456,6 +456,21 @@ static int is_reg_file(const char *path)
>  	return S_ISREG(statbuf.st_mode);
>  }
>  
> +int is_path_exist(const char *path)
> +{
> +	struct stat statbuf;
> +	int ret;
> +
> +	ret = stat(path, &statbuf);
> +	if (ret < 0) {
> +		if (errno == ENOENT)
> +			return 0;
> +		else
> +			return -errno;
> +	}
> +	return 1;
> +}
> +
>  /*
>   * This function checks if the given input parameter is
>   * an uuid or a path
> diff --git a/utils.h b/utils.h
> index a82d46f6d7cc..860c25d3cdba 100644
> --- a/utils.h
> +++ b/utils.h
> @@ -122,6 +122,7 @@ int set_label(const char *btrfs_dev, const char *label);
>  char *__strncpy_null(char *dest, const char *src, size_t n);
>  int is_block_device(const char *file);
>  int is_mount_point(const char *file);
> +int is_path_exist(const char *file);
>  int check_arg_type(const char *input);
>  int open_path_or_dev_mnt(const char *path, DIR **dirstream, int verbose);
>  int btrfs_open(const char *path, DIR **dirstream, int verbose, int dir_only);
> 


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/9] Remaining part of mkfs --rootdir rework
  2017-11-29  9:15 [PATCH 0/9] Remaining part of mkfs --rootdir rework Qu Wenruo
                   ` (8 preceding siblings ...)
  2017-11-29  9:16 ` [PATCH 9/9] btrfs-progs: tests/mkfs: Introduce test case to verify if mkfs.btrfs rootdir shrink behaves correctly Qu Wenruo
@ 2017-12-07 19:06 ` David Sterba
  9 siblings, 0 replies; 12+ messages in thread
From: David Sterba @ 2017-12-07 19:06 UTC (permalink / raw)
  To: Qu Wenruo; +Cc: linux-btrfs, dsterba, ahferroin7

On Wed, Nov 29, 2017 at 05:15:55PM +0800, Qu Wenruo wrote:
> Qu Wenruo (9):
>   btrfs-progs: mkfs: Cleanup temporary chunks before filling rootdir
>   btrfs-progs: mkfs: Don't use custom chunk allocator for rootdir
>   btrfs-progs: mkfs/rootdir: Use over-reserve method to make size
>     estimate easier
>   btrfs-progs: mkfs/rootdir: Shrink fs for rootdir option
>   btrfs-progs: mkfs: Separate shrink from rootdir
>   btrfs-progs: mkfs: Fix regression preventing --rootdir to create file
>   btrfs-progs: tests/mkfs: Introduce test case to check if mkfs rootdir
>     can create new file
>   btrfs-progs: mkfs: Use the whole file or block device to mkfs for
>     rootdir
>   btrfs-progs: tests/mkfs: Introduce test case to verify if mkfs.btrfs
>     rootdir shrink behaves correctly

Patches reviewed and merged. The basic test coverage is there, I'm CCing
Austin: we'd appreciate if you could also test it for your usecase.
Thanks.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2017-12-07 19:08 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-29  9:15 [PATCH 0/9] Remaining part of mkfs --rootdir rework Qu Wenruo
2017-11-29  9:15 ` [PATCH 1/9] btrfs-progs: mkfs: Cleanup temporary chunks before filling rootdir Qu Wenruo
2017-11-29  9:15 ` [PATCH 2/9] btrfs-progs: mkfs: Don't use custom chunk allocator for rootdir Qu Wenruo
2017-11-29  9:15 ` [PATCH 3/9] btrfs-progs: mkfs/rootdir: Use over-reserve method to make size estimate easier Qu Wenruo
2017-11-29  9:15 ` [PATCH 4/9] btrfs-progs: mkfs/rootdir: Shrink fs for rootdir option Qu Wenruo
2017-11-29  9:16 ` [PATCH 5/9] btrfs-progs: mkfs: Separate shrink from rootdir Qu Wenruo
2017-11-29  9:16 ` [PATCH 6/9] btrfs-progs: mkfs: Fix regression preventing --rootdir to create file Qu Wenruo
2017-11-30  5:16   ` Misono, Tomohiro
2017-11-29  9:16 ` [PATCH 7/9] btrfs-progs: tests/mkfs: Introduce test case to check if mkfs rootdir can create new file Qu Wenruo
2017-11-29  9:16 ` [PATCH 8/9] btrfs-progs: mkfs: Use the whole file or block device to mkfs for rootdir Qu Wenruo
2017-11-29  9:16 ` [PATCH 9/9] btrfs-progs: tests/mkfs: Introduce test case to verify if mkfs.btrfs rootdir shrink behaves correctly Qu Wenruo
2017-12-07 19:06 ` [PATCH 0/9] Remaining part of mkfs --rootdir rework David Sterba

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.