mirror of
https://github.com/kdave/btrfs-progs
synced 2025-01-08 22:49:34 +00:00
btrfs-progs: convert: move link_subvol out of main
link_subvol() is moved to inode.c and renamed as btrfs_mksubvol(). The change cascades down to the callchain. Signed-off-by: Yingyi Luo <yingyil@google.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
8d93d71f6a
commit
8a820b5765
126
convert/main.c
126
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);
|
||||
return new_root;
|
||||
}
|
||||
|
||||
static int create_subvol(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root, u64 root_objectid)
|
||||
{
|
||||
@ -1319,7 +1196,8 @@ static int do_convert(const char *devname, u32 convert_flags, u32 nodesize,
|
||||
task_deinit(ctx.info);
|
||||
}
|
||||
|
||||
image_root = link_subvol(root, subvol_name, CONV_IMAGE_SUBVOL_OBJECTID);
|
||||
image_root = btrfs_mksubvol(root, subvol_name,
|
||||
CONV_IMAGE_SUBVOL_OBJECTID);
|
||||
if (!image_root) {
|
||||
error("unable to link subvolume %s", subvol_name);
|
||||
goto fail;
|
||||
|
2
ctree.h
2
ctree.h
@ -2745,6 +2745,8 @@ int btrfs_add_orphan_item(struct btrfs_trans_handle *trans,
|
||||
u64 ino);
|
||||
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);
|
||||
|
||||
/* file.c */
|
||||
int btrfs_get_extent(struct btrfs_trans_handle *trans,
|
||||
|
124
inode.c
124
inode.c
@ -28,6 +28,7 @@
|
||||
#include "transaction.h"
|
||||
#include "disk-io.h"
|
||||
#include "time.h"
|
||||
#include "messages.h"
|
||||
|
||||
/*
|
||||
* Find a free inode index for later btrfs_add_link().
|
||||
@ -570,3 +571,126 @@ out:
|
||||
*ino = ret_ino;
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct btrfs_root *btrfs_mksubvol(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);
|
||||
return new_root;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user