Re: [PATCH 4/4 v2] btrfs-progs: mkfs: add subvolume support to mkfs

2017-09-12 Thread David Sterba
On Wed, Aug 30, 2017 at 10:24:50AM -0700, Yingyi Luo wrote:
> From: yingyil 
> 
> Add -S/--subvol [NAME] option to configure. It enables users to create a
> subvolume under the toplevel volume and populate the created subvolume
> with files from the rootdir specified by -r/--rootdir option.

Sounds good, I think we can achieve more than just subvol + copy of a
directory, with a extension of the command line ui. This should allow to
create multiple subvolumes, nested (or not) with contents of the
directory copied over any pre-created contents from --rootdir.

First, the option --subvol could be specified repeatedly. Each path
component that would not exist will become a directory, the last one
will be subvolume.

With --rootdir among the --subvol options, all existing paths would be
reused (as long files and directories/subvolumes don't clash).

Example, immitating one of used root filesystem layout:

expected result
/
/@ (subvolume
/@/boot (subvolume)
/@/home (subvolume)
/@/var/log (subvolume)
/@/tmp (subvolume)

and over that, same as if some tarball is unpacked, creating /bin,
/etc, /usr, /sbin etc.

would be generated by by something like:

$ mkfs.btrfs -S /@ -S /@/boot -S /@/home -S /@/var/log -S /@/tmp --rootdir 
rootfiles/ /path/to/device

Reusing --rootdir might be a bad idea, so we'd have add a new option
that would specify the target path and the source directory.

Your patchset is a good start and I'm not asking you to implement the
above, but to let you know that the end result might be more general
compared to the usecase that brought you here.
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/4 v2] btrfs-progs: mkfs: add subvolume support to mkfs

2017-08-30 Thread Yingyi Luo
From: yingyil 

Add -S/--subvol [NAME] option to configure. It enables users to create a
subvolume under the toplevel volume and populate the created subvolume
with files from the rootdir specified by -r/--rootdir option.

Signed-off-by: yingyil 
---
v2: Fixed the bug for subvolume creation failure: calling create_tree(), instead
of create_subvol() in convert/main.c since btrfs_make_root_dir() in
create_subvol() is not needed to be called in mkfs.

 mkfs/main.c | 75 -
 1 file changed, 70 insertions(+), 5 deletions(-)

diff --git a/mkfs/main.c b/mkfs/main.c
index 869c11fa..21abc4a4 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -363,6 +363,7 @@ static void print_usage(int ret)
printf("\t-U|--uuid UUID  specify the filesystem UUID (must be 
unique)\n");
printf("  creation:\n");
printf("\t-b|--byte-count SIZEset filesystem size to SIZE (on the 
first device)\n");
+   printf("\t-S|--subvol NAMEcreate a sunvolume with NAME and copy 
files from ROOTDIR to the subvolume\n");
printf("\t-r|--rootdir DIRcopy files from DIR to the image root 
directory\n");
printf("\t-K|--nodiscard  do not perform whole device TRIM\n");
printf("\t-f|--force  force overwrite of existing 
filesystem\n");
@@ -412,6 +413,18 @@ static char *parse_label(const char *input)
return strdup(input);
 }
 
+static char *parse_subvol_name(const char *input)
+{
+   int len = strlen(input);
+
+   if (len >= BTRFS_SUBVOL_NAME_MAX) {
+   error("subvolume name %s is too long (max %d)",
+   input, BTRFS_SUBVOL_NAME_MAX - 1);
+   exit(1);
+   }
+   return strdup(input);
+}
+
 static int add_directory_items(struct btrfs_trans_handle *trans,
   struct btrfs_root *root, u64 objectid,
   ino_t parent_inum, const char *name,
@@ -1418,6 +1431,8 @@ int main(int argc, char **argv)
int discard = 1;
int ssd = 0;
int force_overwrite = 0;
+   char *subvol_name = NULL;
+   int subvol_name_set = 0;
char *source_dir = NULL;
int source_dir_set = 0;
u64 num_of_meta_chunks = 0;
@@ -1444,6 +1459,7 @@ int main(int argc, char **argv)
{ "sectorsize", required_argument, NULL, 's' },
{ "data", required_argument, NULL, 'd' },
{ "version", no_argument, NULL, 'V' },
+   { "subvol", required_argument, NULL, 'S'},
{ "rootdir", required_argument, NULL, 'r' },
{ "nodiscard", no_argument, NULL, 'K' },
{ "features", required_argument, NULL, 'O' },
@@ -1453,7 +1469,7 @@ int main(int argc, char **argv)
{ NULL, 0, NULL, 0}
};
 
-   c = getopt_long(argc, argv, "A:b:fl:n:s:m:d:L:O:r:U:VMKq",
+   c = getopt_long(argc, argv, "A:b:fl:n:s:m:d:L:O:S:r:U:VMKq",
long_options, NULL);
if (c < 0)
break;
@@ -1514,6 +1530,10 @@ int main(int argc, char **argv)
printf("mkfs.btrfs, part of %s\n",
PACKAGE_STRING);
goto success;
+   case 'S':
+   subvol_name = parse_subvol_name(optarg);
+   subvol_name_set = 1;
+   break;
case 'r':
source_dir = optarg;
source_dir_set = 1;
@@ -1534,6 +1554,11 @@ int main(int argc, char **argv)
}
}
 
+   if (subvol_name_set && !source_dir_set) {
+   error("root directory needs to be set");
+   goto error;
+   }
+
if (verbose) {
printf("%s\n", PACKAGE_STRING);
printf("See %s for more information.\n\n", PACKAGE_URL);
@@ -1872,10 +1897,48 @@ raid_groups:
goto out;
}
 
-   ret = make_image(source_dir, root);
-   if (ret) {
-   error("error wihle filling filesystem: %d", ret);
-   goto out;
+   if (subvol_name_set) {
+   u64 dirid, objectid;
+   struct btrfs_root *file_root;
+
+   dirid = 
btrfs_root_dirid(&fs_info->tree_root->root_item);
+   ret = btrfs_find_free_objectid(NULL, 
fs_info->tree_root, dirid, &objectid);
+   if (ret) {
+   error("unable to find a free objectid: %d", 
ret);
+   goto out;
+   }
+   trans = btrfs_start_transaction(root, 1);
+