From: David Sterba Date: Tue, 23 Aug 2016 15:48:29 +0000 (+0200) Subject: btrfs-progs: convert: move link_subvol X-Git-Tag: upstream/4.16.1~1360 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6ffb89577f5ba23f6f89dcc65153ddf21963ba9c;p=platform%2Fupstream%2Fbtrfs-progs.git btrfs-progs: convert: move link_subvol Signed-off-by: David Sterba --- diff --git a/btrfs-convert.c b/btrfs-convert.c index 4545d39..46fd534 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) {