btrfs-progs: add btrfs_uuid_tree_remove
It will be used to clear received data on RW snapshots that were received. The function is copied from kernel sources. Signed-off-by: Nikolay Borisov <nborisov@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
97640a5b81
commit
39c6e0b79c
|
@ -2865,6 +2865,8 @@ int btrfs_lookup_uuid_received_subvol_item(int fd, const u8 *uuid,
|
|||
/* uuid-tree.c, interface for unmounte filesystem */
|
||||
int btrfs_uuid_tree_add(struct btrfs_trans_handle *trans, u8 *uuid, u8 type,
|
||||
u64 subvol_id_cpu);
|
||||
int btrfs_uuid_tree_remove(struct btrfs_trans_handle *trans, u8 *uuid, u8 type,
|
||||
u64 subid);
|
||||
|
||||
static inline int is_fstree(u64 rootid)
|
||||
{
|
||||
|
|
|
@ -110,3 +110,84 @@ int btrfs_lookup_uuid_received_subvol_item(int fd, const u8 *uuid,
|
|||
BTRFS_UUID_KEY_RECEIVED_SUBVOL,
|
||||
subvol_id);
|
||||
}
|
||||
|
||||
int btrfs_uuid_tree_remove(struct btrfs_trans_handle *trans, u8 *uuid, u8 type,
|
||||
u64 subid)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = trans->fs_info;
|
||||
struct btrfs_root *uuid_root = fs_info->uuid_root;
|
||||
int ret;
|
||||
struct btrfs_path *path = NULL;
|
||||
struct btrfs_key key;
|
||||
struct extent_buffer *eb;
|
||||
int slot;
|
||||
unsigned long offset;
|
||||
u32 item_size;
|
||||
unsigned long move_dst;
|
||||
unsigned long move_src;
|
||||
unsigned long move_len;
|
||||
|
||||
if (!uuid_root) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
btrfs_uuid_to_key(uuid, &key);
|
||||
key.type = type;
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
if (!path) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = btrfs_search_slot(trans, uuid_root, &key, path, -1, 1);
|
||||
if (ret < 0) {
|
||||
warning("error %d while searching for uuid item!", ret);
|
||||
goto out;
|
||||
}
|
||||
if (ret > 0) {
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
eb = path->nodes[0];
|
||||
slot = path->slots[0];
|
||||
offset = btrfs_item_ptr_offset(eb, slot);
|
||||
item_size = btrfs_item_size_nr(eb, slot);
|
||||
if (!IS_ALIGNED(item_size, sizeof(u64))) {
|
||||
warning("uuid item with illegal size %u!", item_size);
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
while (item_size) {
|
||||
__le64 read_subid;
|
||||
|
||||
read_extent_buffer(eb, &read_subid, offset, sizeof(read_subid));
|
||||
if (le64_to_cpu(read_subid) == subid)
|
||||
break;
|
||||
offset += sizeof(read_subid);
|
||||
item_size -= sizeof(read_subid);
|
||||
}
|
||||
|
||||
if (!item_size) {
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
item_size = btrfs_item_size_nr(eb, slot);
|
||||
if (item_size == sizeof(subid)) {
|
||||
ret = btrfs_del_item(trans, uuid_root, path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
move_dst = offset;
|
||||
move_src = offset + sizeof(subid);
|
||||
move_len = item_size - (move_src - btrfs_item_ptr_offset(eb, slot));
|
||||
memmove_extent_buffer(eb, move_dst, move_src, move_len);
|
||||
btrfs_truncate_item(path, item_size - sizeof(subid), 1);
|
||||
|
||||
out:
|
||||
btrfs_free_path(path);
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue