[PATCH 2/4 v3] btrfs-progs: add a parameter to btrfs_mksubvol

2017-09-15 Thread Yingyi Luo
From: yingyil 

A convert parameter is added as a flag to indicate if btrfs_mksubvol()
is used for btrfs-convert. The change cascades down to the callchain.

Signed-off-by: yingyil 
---
v3: changed the convert flag from int type to bool type.

 convert/main.c |  2 +-
 ctree.h|  4 +++-
 inode.c| 26 --
 3 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/convert/main.c b/convert/main.c
index 0babf0e8..882daf7c 100644
--- a/convert/main.c
+++ b/convert/main.c
@@ -1197,7 +1197,7 @@ static int do_convert(const char *devname, u32 
convert_flags, u32 nodesize,
}
 
image_root = btrfs_mksubvol(root, subvol_name,
-   CONV_IMAGE_SUBVOL_OBJECTID);
+   CONV_IMAGE_SUBVOL_OBJECTID, true);
if (!image_root) {
error("unable to link subvolume %s", subvol_name);
goto fail;
diff --git a/ctree.h b/ctree.h
index 22313576..ae25eed5 100644
--- a/ctree.h
+++ b/ctree.h
@@ -19,6 +19,8 @@
 #ifndef __BTRFS_CTREE_H__
 #define __BTRFS_CTREE_H__
 
+#include 
+
 #if BTRFS_FLAT_INCLUDES
 #include "list.h"
 #include "kerncompat.h"
@@ -2751,7 +2753,7 @@ int btrfs_add_orphan_item(struct btrfs_trans_handle 
*trans,
 int btrfs_mkdir(struct btrfs_trans_handle *trans, struct btrfs_root *root,
char *name, int namelen, u64 parent_ino, u64 *ino, int mode);
 struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root, const char *base,
- u64 root_objectid);
+ u64 root_objectid, bool convert);
 
 /* file.c */
 int btrfs_get_extent(struct btrfs_trans_handle *trans,
diff --git a/inode.c b/inode.c
index 5dd816bf..ea812ce8 100644
--- a/inode.c
+++ b/inode.c
@@ -573,7 +573,8 @@ out:
 }
 
 struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root,
- const char *base, u64 root_objectid)
+ const char *base, u64 root_objectid,
+ bool convert)
 {
struct btrfs_trans_handle *trans;
struct btrfs_fs_info *fs_info = root->fs_info;
@@ -639,16 +640,21 @@ struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root,
key.type = BTRFS_ROOT_ITEM_KEY;
 
memcpy(buf, base, len);
-   for (i = 0; i < 1024; i++) {
-   ret = btrfs_insert_dir_item(trans, root, buf, len,
-   dirid, &key, BTRFS_FT_DIR, index);
-   if (ret != -EEXIST)
-   break;
-   len = snprintf(buf, ARRAY_SIZE(buf), "%s%d", base, i);
-   if (len < 1 || len > BTRFS_NAME_LEN) {
-   ret = -EINVAL;
-   break;
+   if (convert) {
+   for (i = 0; i < 1024; i++) {
+   ret = btrfs_insert_dir_item(trans, root, buf, len,
+   dirid, &key, BTRFS_FT_DIR, index);
+   if (ret != -EEXIST)
+   break;
+   len = snprintf(buf, ARRAY_SIZE(buf), "%s%d", base, i);
+   if (len < 1 || len > BTRFS_NAME_LEN) {
+   ret = -EINVAL;
+   break;
+   }
}
+   } else {
+   ret = btrfs_insert_dir_item(trans, root, buf, len, dirid, &key,
+   BTRFS_FT_DIR, index);
}
if (ret)
goto fail;
-- 
2.14.1.690.gbb1197296e-goog

--
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 1/4 v3] btrfs-progs: convert: move link_subvol out of main

2017-09-15 Thread Yingyi Luo
From: yingyil 

link_subvol() is moved to inode.c and renamed as btrfs_mksubvol().
The change cascades down to the callchain.

Signed-off-by: yingyil 
---
v3: moved link_subvol to inode.c and put its header in ctree.h. The name is
changed to btrfs_mksubvol. Thanks for your comments.

 convert/main.c | 126 +
 ctree.h|   2 +
 inode.c| 124 
 3 files changed, 128 insertions(+), 124 deletions(-)

diff --git a/convert/main.c b/convert/main.c
index 7ec6202d..0babf0e8 100644
--- a/convert/main.c
+++ b/convert/main.c
@@ -838,129 +838,6 @@ out:
return ret;
 }
 
-static struct btrfs_root* link_subvol(struct btrfs_root *root,
-   const char *base, u64 root_objectid)
-{
-   struct btrfs_trans_handle *trans;
-   struct btrfs_fs_info *fs_info = root->fs_info;
-   struct btrfs_root *tree_root = fs_info->tree_root;
-   struct btrfs_root *new_root = NULL;
-   struct btrfs_path path;
-   struct btrfs_inode_item *inode_item;
-   struct extent_buffer *leaf;
-   struct btrfs_key key;
-   u64 dirid = btrfs_root_dirid(&root->root_item);
-   u64 index = 2;
-   char buf[BTRFS_NAME_LEN + 1]; /* for snprintf null */
-   int len;
-   int i;
-   int ret;
-
-   len = strlen(base);
-   if (len == 0 || len > BTRFS_NAME_LEN)
-   return NULL;
-
-   btrfs_init_path(&path);
-   key.objectid = dirid;
-   key.type = BTRFS_DIR_INDEX_KEY;
-   key.offset = (u64)-1;
-
-   ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
-   if (ret <= 0) {
-   error("search for DIR_INDEX dirid %llu failed: %d",
-   (unsigned long long)dirid, ret);
-   goto fail;
-   }
-
-   if (path.slots[0] > 0) {
-   path.slots[0]--;
-   btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]);
-   if (key.objectid == dirid && key.type == BTRFS_DIR_INDEX_KEY)
-   index = key.offset + 1;
-   }
-   btrfs_release_path(&path);
-
-   trans = btrfs_start_transaction(root, 1);
-   if (IS_ERR(trans)) {
-   error("unable to start transaction");
-   goto fail;
-   }
-
-   key.objectid = dirid;
-   key.offset = 0;
-   key.type =  BTRFS_INODE_ITEM_KEY;
-
-   ret = btrfs_lookup_inode(trans, root, &path, &key, 1);
-   if (ret) {
-   error("search for INODE_ITEM %llu failed: %d",
-   (unsigned long long)dirid, ret);
-   goto fail;
-   }
-   leaf = path.nodes[0];
-   inode_item = btrfs_item_ptr(leaf, path.slots[0],
-   struct btrfs_inode_item);
-
-   key.objectid = root_objectid;
-   key.offset = (u64)-1;
-   key.type = BTRFS_ROOT_ITEM_KEY;
-
-   memcpy(buf, base, len);
-   for (i = 0; i < 1024; i++) {
-   ret = btrfs_insert_dir_item(trans, root, buf, len,
-   dirid, &key, BTRFS_FT_DIR, index);
-   if (ret != -EEXIST)
-   break;
-   len = snprintf(buf, ARRAY_SIZE(buf), "%s%d", base, i);
-   if (len < 1 || len > BTRFS_NAME_LEN) {
-   ret = -EINVAL;
-   break;
-   }
-   }
-   if (ret)
-   goto fail;
-
-   btrfs_set_inode_size(leaf, inode_item, len * 2 +
-btrfs_inode_size(leaf, inode_item));
-   btrfs_mark_buffer_dirty(leaf);
-   btrfs_release_path(&path);
-
-   /* add the backref first */
-   ret = btrfs_add_root_ref(trans, tree_root, root_objectid,
-BTRFS_ROOT_BACKREF_KEY,
-root->root_key.objectid,
-dirid, index, buf, len);
-   if (ret) {
-   error("unable to add root backref for %llu: %d",
-   root->root_key.objectid, ret);
-   goto fail;
-   }
-
-   /* now add the forward ref */
-   ret = btrfs_add_root_ref(trans, tree_root, root->root_key.objectid,
-BTRFS_ROOT_REF_KEY, root_objectid,
-dirid, index, buf, len);
-   if (ret) {
-   error("unable to add root ref for %llu: %d",
-   root->root_key.objectid, ret);
-   goto fail;
-   }
-
-   ret = btrfs_commit_transaction(trans, root);
-   if (ret) {
-   error("transaction commit failed: %d", ret);
-   goto fail;
-   }
-
-   new_root = btrfs_read_fs_root(fs_info, &key);
-   if (IS_ERR(new_root)) {
-   error("unable to fs read root: %lu", PTR_ERR(new_root));
-   new_root = NULL;
-   }
-fail:
-   btrfs_init_path(&path);
-   retu

[PATCH 3/4 v2] btrfs-progs: mkfs: refactor create_data_reloc_tree

2017-08-30 Thread Yingyi Luo
From: yingyil 

Add an objectid parameter to make the function a general one for
inserting root items and rename it to create_tree. The change cascades
down to the callchain.

Signed-off-by: yingyil 
---
v2: utilize create_tree() function for creating a subvolume, instead of
create_subvol() in convert/main.c.

 mkfs/main.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/mkfs/main.c b/mkfs/main.c
index afd68bc5..869c11fa 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -320,13 +320,12 @@ static int create_raid_groups(struct btrfs_trans_handle 
*trans,
return ret;
 }
 
-static int create_data_reloc_tree(struct btrfs_trans_handle *trans,
- struct btrfs_root *root)
+static int create_tree(struct btrfs_trans_handle *trans,
+   struct btrfs_root *root, u64 objectid)
 {
struct btrfs_key location;
struct btrfs_root_item root_item;
struct extent_buffer *tmp;
-   u64 objectid = BTRFS_DATA_RELOC_TREE_OBJECTID;
int ret;
 
ret = btrfs_copy_root(trans, root, root->node, &tmp, objectid);
@@ -1846,7 +1845,7 @@ raid_groups:
}
}
 
-   ret = create_data_reloc_tree(trans, root);
+   ret = create_tree(trans, root, BTRFS_DATA_RELOC_TREE_OBJECTID);
if (ret) {
error("unable to create data reloc tree: %d", ret);
goto out;
-- 
2.14.1.342.g6490525c54-goog

--
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 2/4 v2] btrfs-progs: add a parameter to btrfs_link_subvol

2017-08-30 Thread Yingyi Luo
From: yingyil 

A convert parameter is added as a flag to indicate if btrfs_link_subvol()
is used for btrfs-convert. The change cascades down to the callchain.

Signed-off-by: yingyil 
---
v2: Added a flag for btrfs_link_subvol() function so that it can be used in a
more general way. For example, if mkfs calls this function, it will return
directly with an error code if the subvolume creation fails.

 convert/main.c |  2 +-
 utils.c| 25 +++--
 utils.h|  2 +-
 3 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/convert/main.c b/convert/main.c
index 8f7fec25..19a60782 100644
--- a/convert/main.c
+++ b/convert/main.c
@@ -1192,7 +1192,7 @@ static int do_convert(const char *devname, u32 
convert_flags, u32 nodesize,
task_deinit(ctx.info);
}
 
-   image_root = btrfs_link_subvol(root, subvol_name, 
CONV_IMAGE_SUBVOL_OBJECTID);
+   image_root = btrfs_link_subvol(root, subvol_name, 
CONV_IMAGE_SUBVOL_OBJECTID, 1);
if (!image_root) {
error("unable to link subvolume %s", subvol_name);
goto fail;
diff --git a/utils.c b/utils.c
index 32382328..20ea9e74 100644
--- a/utils.c
+++ b/utils.c
@@ -2576,7 +2576,7 @@ void btrfs_config_init(void)
 }
 
 struct btrfs_root *btrfs_link_subvol(struct btrfs_root *root,
-   const char *base, u64 root_objectid)
+   const char *base, u64 root_objectid, int convert)
 {
struct btrfs_trans_handle *trans;
struct btrfs_fs_info *fs_info = root->fs_info;
@@ -2642,16 +2642,21 @@ struct btrfs_root *btrfs_link_subvol(struct btrfs_root 
*root,
key.type = BTRFS_ROOT_ITEM_KEY;
 
memcpy(buf, base, len);
-   for (i = 0; i < 1024; i++) {
-   ret = btrfs_insert_dir_item(trans, root, buf, len, dirid,
-   &key, BTRFS_FT_DIR, index);
-   if (ret != -EEXIST)
-   break;
-   len = snprintf(buf, ARRAY_SIZE(buf), "%s%d", base, i);
-   if (len < 1 || len > BTRFS_NAME_LEN) {
-   ret = -EINVAL;
-   break;
+   if (convert) {
+   for (i = 0; i < 1024; i++) {
+   ret = btrfs_insert_dir_item(trans, root, buf, len, 
dirid,
+   &key, BTRFS_FT_DIR, index);
+   if (ret != -EEXIST)
+   break;
+   len = snprintf(buf, ARRAY_SIZE(buf), "%s%d", base, i);
+   if (len < 1 || len > BTRFS_NAME_LEN) {
+   ret = -EINVAL;
+   break;
+   }
}
+   } else {
+   ret = btrfs_insert_dir_item(trans, root, buf, len, dirid, &key,
+   BTRFS_FT_DIR, index);
}
if (ret)
goto fail;
diff --git a/utils.h b/utils.h
index 886590fd..28aa8373 100644
--- a/utils.h
+++ b/utils.h
@@ -171,6 +171,6 @@ unsigned int rand_range(unsigned int upper);
 void init_rand_seed(u64 seed);
 
 struct btrfs_root *btrfs_link_subvol(struct btrfs_root *root, const char *base,
-u64 root_objectid);
+u64 root_objectid, int convert);
 
 #endif
-- 
2.14.1.342.g6490525c54-goog

--
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);
+ 

[PATCH 1/4 v2] btrfs-progs: convert: move link_subvol out of main

2017-08-30 Thread Yingyi Luo
From: yingyil 

link_subvol() is moved to utils.c and renamed as btrfs_link_subvol().
The change cascades down to the callchain.

Signed-off-by: yingyil 
---
v2: split the original patch to make code movement into a separate patch.

 convert/main.c | 125 +
 utils.c| 123 
 utils.h|   3 ++
 3 files changed, 127 insertions(+), 124 deletions(-)

diff --git a/convert/main.c b/convert/main.c
index 03da9e49..8f7fec25 100644
--- a/convert/main.c
+++ b/convert/main.c
@@ -834,129 +834,6 @@ out:
return ret;
 }
 
-static struct btrfs_root* link_subvol(struct btrfs_root *root,
-   const char *base, u64 root_objectid)
-{
-   struct btrfs_trans_handle *trans;
-   struct btrfs_fs_info *fs_info = root->fs_info;
-   struct btrfs_root *tree_root = fs_info->tree_root;
-   struct btrfs_root *new_root = NULL;
-   struct btrfs_path path;
-   struct btrfs_inode_item *inode_item;
-   struct extent_buffer *leaf;
-   struct btrfs_key key;
-   u64 dirid = btrfs_root_dirid(&root->root_item);
-   u64 index = 2;
-   char buf[BTRFS_NAME_LEN + 1]; /* for snprintf null */
-   int len;
-   int i;
-   int ret;
-
-   len = strlen(base);
-   if (len == 0 || len > BTRFS_NAME_LEN)
-   return NULL;
-
-   btrfs_init_path(&path);
-   key.objectid = dirid;
-   key.type = BTRFS_DIR_INDEX_KEY;
-   key.offset = (u64)-1;
-
-   ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
-   if (ret <= 0) {
-   error("search for DIR_INDEX dirid %llu failed: %d",
-   (unsigned long long)dirid, ret);
-   goto fail;
-   }
-
-   if (path.slots[0] > 0) {
-   path.slots[0]--;
-   btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]);
-   if (key.objectid == dirid && key.type == BTRFS_DIR_INDEX_KEY)
-   index = key.offset + 1;
-   }
-   btrfs_release_path(&path);
-
-   trans = btrfs_start_transaction(root, 1);
-   if (!trans) {
-   error("unable to start transaction");
-   goto fail;
-   }
-
-   key.objectid = dirid;
-   key.offset = 0;
-   key.type =  BTRFS_INODE_ITEM_KEY;
-
-   ret = btrfs_lookup_inode(trans, root, &path, &key, 1);
-   if (ret) {
-   error("search for INODE_ITEM %llu failed: %d",
-   (unsigned long long)dirid, ret);
-   goto fail;
-   }
-   leaf = path.nodes[0];
-   inode_item = btrfs_item_ptr(leaf, path.slots[0],
-   struct btrfs_inode_item);
-
-   key.objectid = root_objectid;
-   key.offset = (u64)-1;
-   key.type = BTRFS_ROOT_ITEM_KEY;
-
-   memcpy(buf, base, len);
-   for (i = 0; i < 1024; i++) {
-   ret = btrfs_insert_dir_item(trans, root, buf, len,
-   dirid, &key, BTRFS_FT_DIR, index);
-   if (ret != -EEXIST)
-   break;
-   len = snprintf(buf, ARRAY_SIZE(buf), "%s%d", base, i);
-   if (len < 1 || len > BTRFS_NAME_LEN) {
-   ret = -EINVAL;
-   break;
-   }
-   }
-   if (ret)
-   goto fail;
-
-   btrfs_set_inode_size(leaf, inode_item, len * 2 +
-btrfs_inode_size(leaf, inode_item));
-   btrfs_mark_buffer_dirty(leaf);
-   btrfs_release_path(&path);
-
-   /* add the backref first */
-   ret = btrfs_add_root_ref(trans, tree_root, root_objectid,
-BTRFS_ROOT_BACKREF_KEY,
-root->root_key.objectid,
-dirid, index, buf, len);
-   if (ret) {
-   error("unable to add root backref for %llu: %d",
-   root->root_key.objectid, ret);
-   goto fail;
-   }
-
-   /* now add the forward ref */
-   ret = btrfs_add_root_ref(trans, tree_root, root->root_key.objectid,
-BTRFS_ROOT_REF_KEY, root_objectid,
-dirid, index, buf, len);
-   if (ret) {
-   error("unable to add root ref for %llu: %d",
-   root->root_key.objectid, ret);
-   goto fail;
-   }
-
-   ret = btrfs_commit_transaction(trans, root);
-   if (ret) {
-   error("transaction commit failed: %d", ret);
-   goto fail;
-   }
-
-   new_root = btrfs_read_fs_root(fs_info, &key);
-   if (IS_ERR(new_root)) {
-   error("unable to fs read root: %lu", PTR_ERR(new_root));
-   new_root = NULL;
-   }
-fail:
-   btrfs_init_path(&path);
-   return new_root;
-}
-
 static int create_subvol(struct btrfs_t

[PATCH 0/4 v2] add subvolume support to mkfs

2017-08-30 Thread Yingyi Luo
From: yingyil 

Hi all,

Thanks for all the comments you gave to me. I really appriciate it. I've
updated the patch, split it into small ones so that it may be easier
for you to see the changes and review.

One use case of this feature is that it allows easier operations on subvolumes,
such as migrating subvolumes across images. With the current btrfs tool, we have
to do this manually by creating an empty subvolume then moving the files over.
This feature which creates a subvolume for a given directory when making btrfs
images simplifies the process and makes the logic cleaner.

Goffredo: Thanks again for you comments and pointing out the bug. It happened
to be that I skipped the error code checking when I tested the functionality.
The error came from a duplicate call of btrfs_make_root_dir() from
make_root_dir() in mkfs/main.c and create_subvol() in convert/main.c.

strdup() is used to get a returnable copy of the literal string.
FYI, parse_label() used strdup() to parse the input string. I think using
strdup() would make it consistent with the current code.

Extending the feature would be a good idea. I'll try to work on it later.

Best regards,
Yingyi

yingyil (4):
  btrfs-progs: convert: move link_subvol out of main
  btrfs-progs: add a parameter to btrfs_link_subvol
  btrfs-progs: mkfs: refactor create_data_reloc_tree
  btrfs-progs: mkfs: add subvolume support to mkfs

 convert/main.c | 125 +--
 mkfs/main.c|  82 
 utils.c| 128 +
 utils.h|   3 ++
 4 files changed, 205 insertions(+), 133 deletions(-)

-- 
2.14.1.342.g6490525c54-goog

--
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 1/1] btrfs-progs: mkfs: add subvolume support to mkfs

2017-08-25 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.

Two functions link_subvol() and create_subvol() are moved from
convert/main.c to utils.c to enable code reuse.

Signed-off-by: yingyil 
---
 convert/main.c | 161 -
 mkfs/main.c|  73 --
 utils.c| 161 +
 utils.h|   5 ++
 4 files changed, 234 insertions(+), 166 deletions(-)

diff --git a/convert/main.c b/convert/main.c
index 0deccd9..93609ed 100644
--- a/convert/main.c
+++ b/convert/main.c
@@ -832,167 +832,6 @@ out:
return ret;
 }
 
-static struct btrfs_root* link_subvol(struct btrfs_root *root,
-   const char *base, u64 root_objectid)
-{
-   struct btrfs_trans_handle *trans;
-   struct btrfs_fs_info *fs_info = root->fs_info;
-   struct btrfs_root *tree_root = fs_info->tree_root;
-   struct btrfs_root *new_root = NULL;
-   struct btrfs_path path;
-   struct btrfs_inode_item *inode_item;
-   struct extent_buffer *leaf;
-   struct btrfs_key key;
-   u64 dirid = btrfs_root_dirid(&root->root_item);
-   u64 index = 2;
-   char buf[BTRFS_NAME_LEN + 1]; /* for snprintf null */
-   int len;
-   int i;
-   int ret;
-
-   len = strlen(base);
-   if (len == 0 || len > BTRFS_NAME_LEN)
-   return NULL;
-
-   btrfs_init_path(&path);
-   key.objectid = dirid;
-   key.type = BTRFS_DIR_INDEX_KEY;
-   key.offset = (u64)-1;
-
-   ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
-   if (ret <= 0) {
-   error("search for DIR_INDEX dirid %llu failed: %d",
-   (unsigned long long)dirid, ret);
-   goto fail;
-   }
-
-   if (path.slots[0] > 0) {
-   path.slots[0]--;
-   btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]);
-   if (key.objectid == dirid && key.type == BTRFS_DIR_INDEX_KEY)
-   index = key.offset + 1;
-   }
-   btrfs_release_path(&path);
-
-   trans = btrfs_start_transaction(root, 1);
-   if (!trans) {
-   error("unable to start transaction");
-   goto fail;
-   }
-
-   key.objectid = dirid;
-   key.offset = 0;
-   key.type =  BTRFS_INODE_ITEM_KEY;
-
-   ret = btrfs_lookup_inode(trans, root, &path, &key, 1);
-   if (ret) {
-   error("search for INODE_ITEM %llu failed: %d",
-   (unsigned long long)dirid, ret);
-   goto fail;
-   }
-   leaf = path.nodes[0];
-   inode_item = btrfs_item_ptr(leaf, path.slots[0],
-   struct btrfs_inode_item);
-
-   key.objectid = root_objectid;
-   key.offset = (u64)-1;
-   key.type = BTRFS_ROOT_ITEM_KEY;
-
-   memcpy(buf, base, len);
-   for (i = 0; i < 1024; i++) {
-   ret = btrfs_insert_dir_item(trans, root, buf, len,
-   dirid, &key, BTRFS_FT_DIR, index);
-   if (ret != -EEXIST)
-   break;
-   len = snprintf(buf, ARRAY_SIZE(buf), "%s%d", base, i);
-   if (len < 1 || len > BTRFS_NAME_LEN) {
-   ret = -EINVAL;
-   break;
-   }
-   }
-   if (ret)
-   goto fail;
-
-   btrfs_set_inode_size(leaf, inode_item, len * 2 +
-btrfs_inode_size(leaf, inode_item));
-   btrfs_mark_buffer_dirty(leaf);
-   btrfs_release_path(&path);
-
-   /* add the backref first */
-   ret = btrfs_add_root_ref(trans, tree_root, root_objectid,
-BTRFS_ROOT_BACKREF_KEY,
-root->root_key.objectid,
-dirid, index, buf, len);
-   if (ret) {
-   error("unable to add root backref for %llu: %d",
-   root->root_key.objectid, ret);
-   goto fail;
-   }
-
-   /* now add the forward ref */
-   ret = btrfs_add_root_ref(trans, tree_root, root->root_key.objectid,
-BTRFS_ROOT_REF_KEY, root_objectid,
-dirid, index, buf, len);
-   if (ret) {
-   error("unable to add root ref for %llu: %d",
-   root->root_key.objectid, ret);
-   goto fail;
-   }
-
-   ret = btrfs_commit_transaction(trans, root);
-   if (ret) {
-   error("transaction commit failed: %d", ret);
-   goto fail;
-   }
-
-   new_root = btrfs_read_fs_root(fs_info, &key);
-   if (IS_ERR(new_root)) {
-   error("unable to fs read root: 

[PATCH 0/1] btrfs-progs: mkfs: add subvolume support to mkfs

2017-08-25 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.

Two functions link_subvol() and create_subvol() are moved from
convert/main.c to utils.c to enable code reuse.

yingyil (1):
  btrfs-progs: mkfs: add subvolume support to mkfs

 convert/main.c | 161 -
 mkfs/main.c|  73 --
 utils.c| 161 +
 utils.h|   5 ++
 4 files changed, 234 insertions(+), 166 deletions(-)

-- 
2.14.1.342.g6490525c54-goog

--
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