btrfs_iterate(&iterator) > 0; )
int btrfs_subvol_get_info_fd(int fd, uint64_t subvol_id, BtrfsSubvolInfo *ret) {
- struct btrfs_ioctl_search_args args = {
- /* Tree of tree roots */
- .key.tree_id = BTRFS_ROOT_TREE_OBJECTID,
-
- /* Look precisely for the subvolume items */
- .key.min_type = BTRFS_ROOT_ITEM_KEY,
- .key.max_type = BTRFS_ROOT_ITEM_KEY,
-
- .key.min_offset = 0,
- .key.max_offset = UINT64_MAX,
-
- /* No restrictions on the other components */
- .key.min_transid = 0,
- .key.max_transid = UINT64_MAX,
- };
-
- bool found = false;
int r;
assert(fd >= 0);
if (fd < 0)
return fd;
- if (subvol_id == 0) {
- r = btrfs_subvol_get_id_fd(fd, &subvol_id);
- if (r < 0)
- return r;
- } else {
- r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
- if (r < 0)
- return r;
- if (r == 0)
- return -ENOTTY;
- }
-
- args.key.min_objectid = args.key.max_objectid = subvol_id;
-
- while (btrfs_ioctl_search_args_compare(&args) <= 0) {
- struct btrfs_ioctl_search_header sh;
- const void *body;
-
- args.key.nr_items = 256;
- if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
- return -errno;
-
- if (args.key.nr_items <= 0)
- break;
-
- FOREACH_BTRFS_IOCTL_SEARCH_HEADER(sh, body, args) {
- /* Make sure we start the next search at least from this entry */
- btrfs_ioctl_search_args_set(&args, &sh);
-
- if (sh.objectid != subvol_id)
- continue;
- if (sh.type != BTRFS_ROOT_ITEM_KEY)
- continue;
-
- /* Older versions of the struct lacked the otime setting */
- if (sh.len < offsetof(struct btrfs_root_item, otime) + sizeof(struct btrfs_timespec))
- continue;
+ r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ENOTTY;
- const struct btrfs_root_item *ri = body;
- ret->otime = (usec_t) le64toh(ri->otime.sec) * USEC_PER_SEC +
- (usec_t) le32toh(ri->otime.nsec) / NSEC_PER_USEC;
+ struct btrfs_ioctl_get_subvol_info_args info;
+ if (ioctl(fd, BTRFS_IOC_GET_SUBVOL_INFO, &info) < 0)
+ return -errno;
- ret->subvol_id = subvol_id;
- ret->read_only = le64toh(ri->flags) & BTRFS_ROOT_SUBVOL_RDONLY;
+ *ret = (BtrfsSubvolInfo) {
+ .subvol_id = info.treeid,
+ .otime = info.otime.sec * USEC_PER_SEC + (info.otime.nsec / NSEC_PER_USEC),
+ .read_only = FLAGS_SET(info.flags, BTRFS_SUBVOL_RDONLY),
+ };
- assert_cc(sizeof(ri->uuid) == sizeof(ret->uuid));
- memcpy(&ret->uuid, ri->uuid, sizeof(ret->uuid));
- memcpy(&ret->parent_uuid, ri->parent_uuid, sizeof(ret->parent_uuid));
+ assert_cc(sizeof(info.uuid) == sizeof(sd_id128_t));
+ memcpy(&ret->uuid, info.uuid, sizeof(sd_id128_t));
- found = true;
- goto finish;
- }
+ assert_cc(sizeof(info.parent_uuid) == sizeof(sd_id128_t));
+ memcpy(&ret->parent_uuid, info.parent_uuid, sizeof(sd_id128_t));
- /* Increase search key by one, to read the next item, if we can. */
- if (!btrfs_ioctl_search_args_inc(&args))
- break;
- }
-
-finish:
- return found ? 0 : -ENODATA;
+ return 0;
}
int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *ret) {