+#endif
+
+#define SUBVOL_ID_BATCH 1024
+
+/*
+ * Enumerate all dead subvolumes that exist in the filesystem.
+ * Fill @ids and reallocate to bigger size if needed.
+ */
+static int enumerate_dead_subvols(int fd, u64 **ids)
+{
+ int ret;
+ struct btrfs_ioctl_search_args args;
+ struct btrfs_ioctl_search_key *sk = &args.key;
+ int idx = 0;
+ int count = 0;
+
+ memset(&args, 0, sizeof(args));
+
+ sk->tree_id = BTRFS_ROOT_TREE_OBJECTID;
+ sk->min_objectid = BTRFS_ORPHAN_OBJECTID;
+ sk->max_objectid = BTRFS_ORPHAN_OBJECTID;
+ sk->min_type = BTRFS_ORPHAN_ITEM_KEY;
+ sk->max_type = BTRFS_ORPHAN_ITEM_KEY;
+ sk->min_offset = 0;
+ sk->max_offset = (u64)-1;
+ sk->min_transid = 0;
+ sk->max_transid = (u64)-1;
+ sk->nr_items = 4096;
+
+ *ids = NULL;
+ while (1) {
+ struct btrfs_ioctl_search_header *sh;
+ unsigned long off;
+ int i;
+
+ ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
+ if (ret < 0)
+ return -errno;
+
+ if (!sk->nr_items)
+ return idx;
+
+ off = 0;
+ for (i = 0; i < sk->nr_items; i++) {
+ sh = (struct btrfs_ioctl_search_header*)(args.buf + off);
+ off += sizeof(*sh);
+
+ if (btrfs_search_header_type(sh)
+ == BTRFS_ORPHAN_ITEM_KEY) {
+ if (idx >= count) {
+ u64 *newids;
+
+ count += SUBVOL_ID_BATCH;
+ newids = (u64*)realloc(*ids,
+ count * sizeof(u64));
+ if (!newids)
+ return -ENOMEM;
+ *ids = newids;
+ }
+ (*ids)[idx] = btrfs_search_header_offset(sh);
+ idx++;
+ }
+ off += btrfs_search_header_len(sh);
+
+ sk->min_objectid = btrfs_search_header_objectid(sh);
+ sk->min_type = btrfs_search_header_type(sh);
+ sk->min_offset = btrfs_search_header_offset(sh);
+ }
+ if (sk->min_offset < (u64)-1)
+ sk->min_offset++;
+ else
+ break;
+ if (sk->min_type != BTRFS_ORPHAN_ITEM_KEY)
+ break;
+ if (sk->min_objectid != BTRFS_ORPHAN_OBJECTID)
+ break;
+ }
+
+ return idx;
+}