diff options
Diffstat (limited to 'uuid-tree.c')
-rw-r--r-- | uuid-tree.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/uuid-tree.c b/uuid-tree.c new file mode 100644 index 00000000..8d0b9173 --- /dev/null +++ b/uuid-tree.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) STRATO AG 2013. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ +#include <stdio.h> +#include <stdlib.h> +#include <uuid/uuid.h> +#include <sys/ioctl.h> +#include "ctree.h" +#include "transaction.h" +#include "disk-io.h" +#include "print-tree.h" + + +static void btrfs_uuid_to_key(const u8 *uuid, u64 *key_objectid, + u64 *key_offset) +{ + *key_objectid = get_unaligned_le64(uuid); + *key_offset = get_unaligned_le64(uuid + sizeof(u64)); +} + + +/* return -ENOENT for !found, < 0 for errors, or 0 if an item was found */ +static int btrfs_uuid_tree_lookup_any(int fd, const u8 *uuid, u8 type, + u64 *subid) +{ + int ret; + u64 key_objectid = 0; + u64 key_offset; + struct btrfs_ioctl_search_args search_arg; + struct btrfs_ioctl_search_header *search_header; + u32 item_size; + __le64 lesubid; + + btrfs_uuid_to_key(uuid, &key_objectid, &key_offset); + + memset(&search_arg, 0, sizeof(search_arg)); + search_arg.key.tree_id = BTRFS_UUID_TREE_OBJECTID; + search_arg.key.min_objectid = key_objectid; + search_arg.key.max_objectid = key_objectid; + search_arg.key.min_type = type; + search_arg.key.max_type = type; + search_arg.key.min_offset = key_offset; + search_arg.key.max_offset = key_offset; + search_arg.key.max_transid = (u64)-1; + search_arg.key.nr_items = 1; + ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &search_arg); + if (ret < 0) { + fprintf(stderr, + "ioctl(BTRFS_IOC_TREE_SEARCH, uuid, key %016llx, UUID_KEY, %016llx) ret=%d, error: %s\n", + (unsigned long long)key_objectid, + (unsigned long long)key_offset, ret, strerror(errno)); + ret = -ENOENT; + goto out; + } + + if (search_arg.key.nr_items < 1) { + ret = -ENOENT; + goto out; + } + search_header = (struct btrfs_ioctl_search_header *)(search_arg.buf); + item_size = btrfs_search_header_len(search_header); + if ((item_size & (sizeof(u64) - 1)) || item_size == 0) { + printf("btrfs: uuid item with illegal size %lu!\n", + (unsigned long)item_size); + ret = -ENOENT; + goto out; + } else { + ret = 0; + } + + /* return first stored id */ + memcpy(&lesubid, search_header + 1, sizeof(lesubid)); + *subid = le64_to_cpu(lesubid); + +out: + return ret; +} + +int btrfs_lookup_uuid_subvol_item(int fd, const u8 *uuid, u64 *subvol_id) +{ + return btrfs_uuid_tree_lookup_any(fd, uuid, BTRFS_UUID_KEY_SUBVOL, + subvol_id); +} + +int btrfs_lookup_uuid_received_subvol_item(int fd, const u8 *uuid, + u64 *subvol_id) +{ + return btrfs_uuid_tree_lookup_any(fd, uuid, + BTRFS_UUID_KEY_RECEIVED_SUBVOL, + subvol_id); +} |