btrfs-progs: convert: move link_subvol

Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
David Sterba 2016-08-23 17:48:29 +02:00
parent c946c415dd
commit 6ffb89577f

View File

@ -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)
{