summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--btrfs-convert.c200
1 files changed, 100 insertions, 100 deletions
diff --git a/btrfs-convert.c b/btrfs-convert.c
index 4545d394..46fd534e 100644
--- a/btrfs-convert.c
+++ b/btrfs-convert.c
@@ -1052,6 +1052,106 @@ 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;
+
+ path = btrfs_alloc_path();
+ BUG_ON(!path);
+
+ key.objectid = dirid;
+ key.type = BTRFS_DIR_INDEX_KEY;
+ key.offset = (u64)-1;
+
+ ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+ BUG_ON(ret <= 0);
+
+ 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);
+ BUG_ON(!trans);
+
+ key.objectid = dirid;
+ key.offset = 0;
+ key.type = BTRFS_INODE_ITEM_KEY;
+
+ ret = btrfs_lookup_inode(trans, root, path, &key, 1);
+ BUG_ON(ret);
+ 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);
+ BUG_ON(ret);
+
+ /* 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);
+
+ ret = btrfs_commit_transaction(trans, root);
+ BUG_ON(ret);
+
+ new_root = btrfs_read_fs_root(fs_info, &key);
+ if (IS_ERR(new_root))
+ new_root = NULL;
+fail:
+ btrfs_free_path(path);
+ return new_root;
+}
+
/*
* Open Ext2fs in readonly mode, read block allocation bitmap and
* inode bitmap into memory.
@@ -1901,106 +2001,6 @@ static int ext2_copy_inodes(struct btrfs_convert_context *cctx,
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;
-
- path = btrfs_alloc_path();
- BUG_ON(!path);
-
- key.objectid = dirid;
- key.type = BTRFS_DIR_INDEX_KEY;
- key.offset = (u64)-1;
-
- ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
- BUG_ON(ret <= 0);
-
- 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);
- BUG_ON(!trans);
-
- key.objectid = dirid;
- key.offset = 0;
- key.type = BTRFS_INODE_ITEM_KEY;
-
- ret = btrfs_lookup_inode(trans, root, path, &key, 1);
- BUG_ON(ret);
- 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);
- BUG_ON(ret);
-
- /* 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);
-
- ret = btrfs_commit_transaction(trans, root);
- BUG_ON(ret);
-
- new_root = btrfs_read_fs_root(fs_info, &key);
- if (IS_ERR(new_root))
- new_root = NULL;
-fail:
- btrfs_free_path(path);
- return new_root;
-}
-
static int create_subvol(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 root_objectid)
{