btrfs-progs: Remove deprecated btrfs-zero-log standalone tool
[platform/upstream/btrfs-progs.git] / cmds-subvolume.c
index e5dcdea..45363a5 100644 (file)
@@ -14,6 +14,7 @@
  * Boston, MA 021110-1307, USA.
  */
 
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "utils.h"
 #include "help.h"
 
-static int is_subvolume_cleaned(int fd, u64 subvolid)
+static int wait_for_subvolume_cleaning(int fd, size_t count, uint64_t *ids,
+                                      int sleep_interval)
 {
-       int ret;
-       struct btrfs_ioctl_search_args args;
-       struct btrfs_ioctl_search_key *sk = &args.key;
-
-       sk->tree_id = BTRFS_ROOT_TREE_OBJECTID;
-       sk->min_objectid = subvolid;
-       sk->max_objectid = subvolid;
-       sk->min_type = BTRFS_ROOT_ITEM_KEY;
-       sk->max_type = BTRFS_ROOT_ITEM_KEY;
-       sk->min_offset = 0;
-       sk->max_offset = (u64)-1;
-       sk->min_transid = 0;
-       sk->max_transid = (u64)-1;
-       sk->nr_items = 1;
-
-       ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
-       if (ret < 0)
-               return -errno;
-
-       if (sk->nr_items == 0)
-               return 1;
-
-       return 0;
-}
-
-static int wait_for_subvolume_cleaning(int fd, int count, u64 *ids,
-               int sleep_interval)
-{
-       int ret;
-       int i;
+       size_t i;
+       enum btrfs_util_error err;
 
        while (1) {
                int clean = 1;
@@ -80,16 +54,14 @@ static int wait_for_subvolume_cleaning(int fd, int count, u64 *ids,
                for (i = 0; i < count; i++) {
                        if (!ids[i])
                                continue;
-                       ret = is_subvolume_cleaned(fd, ids[i]);
-                       if (ret < 0) {
-                               error(
-                           "cannot read status of dead subvolume %llu: %s",
-                                       (unsigned long long)ids[i], strerror(-ret));
-                               return ret;
-                       }
-                       if (ret) {
-                               printf("Subvolume id %llu is gone\n", ids[i]);
+                       err = btrfs_util_subvolume_info_fd(fd, ids[i], NULL);
+                       if (err == BTRFS_UTIL_ERROR_SUBVOLUME_NOT_FOUND) {
+                               printf("Subvolume id %" PRIu64 " is gone\n",
+                                      ids[i]);
                                ids[i] = 0;
+                       } else if (err) {
+                               error_btrfs_util(err);
+                               return -errno;
                        } else {
                                clean = 0;
                        }
@@ -263,7 +235,6 @@ static int cmd_subvol_delete(int argc, char **argv)
        int res, ret = 0;
        int cnt;
        int fd = -1;
-       struct btrfs_ioctl_vol_args     args;
        char    *dname, *vname, *cpath;
        char    *dupdname = NULL;
        char    *dupvname = NULL;
@@ -275,6 +246,7 @@ static int cmd_subvol_delete(int argc, char **argv)
        char uuidbuf[BTRFS_UUID_UNPARSED_SIZE];
        struct seen_fsid *seen_fsid_hash[SEEN_FSID_HASH_SIZE] = { NULL, };
        enum { COMMIT_AFTER = 1, COMMIT_EACH = 2 };
+       enum btrfs_util_error err;
 
        while (1) {
                int c;
@@ -318,14 +290,9 @@ static int cmd_subvol_delete(int argc, char **argv)
 again:
        path = argv[cnt];
 
-       res = test_issubvolume(path);
-       if (res < 0) {
-               error("cannot access subvolume %s: %s", path, strerror(-res));
-               ret = 1;
-               goto out;
-       }
-       if (!res) {
-               error("not a subvolume: %s", path);
+       err = btrfs_util_is_subvolume(path);
+       if (err) {
+               error_btrfs_util(err);
                ret = 1;
                goto out;
        }
@@ -351,11 +318,10 @@ again:
        printf("Delete subvolume (%s): '%s/%s'\n",
                commit_mode == COMMIT_EACH || (commit_mode == COMMIT_AFTER && cnt + 1 == argc)
                ? "commit" : "no-commit", dname, vname);
-       memset(&args, 0, sizeof(args));
-       strncpy_null(args.name, vname);
-       res = ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &args);
-       if(res < 0 ){
-               error("cannot delete '%s/%s': %m", dname, vname);
+
+       err = btrfs_util_delete_subvolume_fd(fd, vname, 0);
+       if (err) {
+               error_btrfs_util(err);
                ret = 1;
                goto out;
        }
@@ -372,7 +338,7 @@ again:
                        error("unable to get fsid for '%s': %s",
                                path, strerror(-res));
                        error(
-                       "delete suceeded but commit may not be done in the end");
+                       "delete succeeded but commit may not be done in the end");
                        ret = 1;
                        goto out;
                }
@@ -664,6 +630,7 @@ static int cmd_subvol_snapshot(int argc, char **argv)
        char    *dupdir = NULL;
        char    *newname;
        char    *dstdir;
+       enum btrfs_util_error err;
        struct btrfs_ioctl_vol_args_v2  args;
        struct btrfs_qgroup_inherit *inherit = NULL;
        DIR *dirstream1 = NULL, *dirstream2 = NULL;
@@ -711,13 +678,9 @@ static int cmd_subvol_snapshot(int argc, char **argv)
        dst = argv[optind + 1];
 
        retval = 1;     /* failure */
-       res = test_issubvolume(subvol);
-       if (res < 0) {
-               error("cannot access subvolume %s: %s", subvol, strerror(-res));
-               goto out;
-       }
-       if (!res) {
-               error("not a subvolume: %s", subvol);
+       err = btrfs_util_is_subvolume(subvol);
+       if (err) {
+               error_btrfs_util(err);
                goto out;
        }
 
@@ -806,31 +769,25 @@ static const char * const cmd_subvol_get_default_usage[] = {
 static int cmd_subvol_get_default(int argc, char **argv)
 {
        int fd = -1;
-       int ret;
-       char *subvol;
-       struct btrfs_list_filter_set *filter_set;
-       u64 default_id;
+       int ret = 1;
+       uint64_t default_id;
        DIR *dirstream = NULL;
+       enum btrfs_util_error err;
+       struct btrfs_util_subvolume_info subvol;
+       char *path;
 
        clean_args_no_options(argc, argv, cmd_subvol_get_default_usage);
 
        if (check_argc_exact(argc - optind, 1))
                usage(cmd_subvol_get_default_usage);
 
-       subvol = argv[1];
-       fd = btrfs_open_dir(subvol, &dirstream, 1);
+       fd = btrfs_open_dir(argv[1], &dirstream, 1);
        if (fd < 0)
                return 1;
 
-       ret = btrfs_list_get_default_subvolume(fd, &default_id);
-       if (ret) {
-               error("failed to look up default subvolume: %m");
-               goto out;
-       }
-
-       ret = 1;
-       if (default_id == 0) {
-               error("'default' dir item not found");
+       err = btrfs_util_get_default_subvolume_fd(fd, &default_id);
+       if (err) {
+               error_btrfs_util(err);
                goto out;
        }
 
@@ -841,24 +798,27 @@ static int cmd_subvol_get_default(int argc, char **argv)
                goto out;
        }
 
-       filter_set = btrfs_list_alloc_filter_set();
-       btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_ROOTID,
-                               default_id);
+       err = btrfs_util_subvolume_info_fd(fd, default_id, &subvol);
+       if (err) {
+               error_btrfs_util(err);
+               goto out;
+       }
 
-       /* by default we shall print the following columns*/
-       btrfs_list_setup_print_column(BTRFS_LIST_OBJECTID);
-       btrfs_list_setup_print_column(BTRFS_LIST_GENERATION);
-       btrfs_list_setup_print_column(BTRFS_LIST_TOP_LEVEL);
-       btrfs_list_setup_print_column(BTRFS_LIST_PATH);
+       err = btrfs_util_subvolume_path_fd(fd, default_id, &path);
+       if (err) {
+               error_btrfs_util(err);
+               goto out;
+       }
 
-       ret = btrfs_list_subvols_print(fd, filter_set, NULL,
-               BTRFS_LIST_LAYOUT_DEFAULT, 1, NULL);
+       printf("ID %" PRIu64 " gen %" PRIu64 " top level %" PRIu64 " path %s\n",
+              subvol.id, subvol.generation, subvol.parent_id, path);
 
-       if (filter_set)
-               free(filter_set);
+       free(path);
+
+       ret = 0;
 out:
        close_file_or_dir(fd, dirstream);
-       return !!ret;
+       return ret;
 }
 
 static const char * const cmd_subvol_set_default_usage[] = {
@@ -872,11 +832,9 @@ static const char * const cmd_subvol_set_default_usage[] = {
 
 static int cmd_subvol_set_default(int argc, char **argv)
 {
-       int     ret=0, fd;
-       u64     objectid;
-       char    *path;
-       char    *subvolid;
-       DIR     *dirstream = NULL;
+       u64 objectid;
+       char *path;
+       enum btrfs_util_error err;
 
        clean_args_no_options(argc, argv, cmd_subvol_set_default_usage);
 
@@ -886,42 +844,17 @@ static int cmd_subvol_set_default(int argc, char **argv)
 
        if (argc - optind == 1) {
                /* path to the subvolume is specified */
+               objectid = 0;
                path = argv[optind];
-
-               ret = test_issubvolume(path);
-               if (ret < 0) {
-                       error("stat error: %s", strerror(-ret));
-                       return 1;
-               } else if (!ret) {
-                       error("'%s' is not a subvolume", path);
-                       return 1;
-               }
-
-               fd = btrfs_open_dir(path, &dirstream, 1);
-               if (fd < 0)
-                       return 1;
-
-               ret = lookup_path_rootid(fd, &objectid);
-               if (ret) {
-                       error("unable to get subvol id: %s", strerror(-ret));
-                       close_file_or_dir(fd, dirstream);
-                       return 1;
-               }
        } else {
                /* subvol id and path to the filesystem are specified */
-               subvolid = argv[optind];
+               objectid = arg_strtou64(argv[optind]);
                path = argv[optind + 1];
-               objectid = arg_strtou64(subvolid);
-
-               fd = btrfs_open_dir(path, &dirstream, 1);
-               if (fd < 0)
-                       return 1;
        }
 
-       ret = ioctl(fd, BTRFS_IOC_DEFAULT_SUBVOL, &objectid);
-       close_file_or_dir(fd, dirstream);
-       if (ret < 0) {
-               error("unable to set a new default subvolume: %m");
+       err = btrfs_util_set_default_subvolume(path, objectid);
+       if (err) {
+               error_btrfs_util(err);
                return 1;
        }
        return 0;
@@ -950,13 +883,9 @@ static int cmd_subvol_find_new(int argc, char **argv)
        subvol = argv[optind];
        last_gen = arg_strtou64(argv[optind + 1]);
 
-       ret = test_issubvolume(subvol);
-       if (ret < 0) {
-               error("cannot access subvolume %s: %s", subvol, strerror(-ret));
-               return 1;
-       }
-       if (!ret) {
-               error("not a subvolume: %s", subvol);
+       err = btrfs_util_is_subvolume(subvol);
+       if (err) {
+               error_btrfs_util(err);
                return 1;
        }
 
@@ -989,19 +918,20 @@ static const char * const cmd_subvol_show_usage[] = {
 
 static int cmd_subvol_show(int argc, char **argv)
 {
-       struct root_info get_ri;
-       struct btrfs_list_filter_set *filter_set = NULL;
        char tstr[256];
        char uuidparse[BTRFS_UUID_UNPARSED_SIZE];
        char *fullpath = NULL;
-       char raw_prefix[] = "\t\t\t\t";
        int fd = -1;
        int ret = 1;
        DIR *dirstream1 = NULL;
        int by_rootid = 0;
        int by_uuid = 0;
-       u64 rootid_arg;
+       u64 rootid_arg = 0;
        u8 uuid_arg[BTRFS_UUID_SIZE];
+       struct btrfs_util_subvolume_iterator *iter;
+       struct btrfs_util_subvolume_info subvol;
+       char *subvol_path = NULL;
+       enum btrfs_util_error err;
 
        while (1) {
                int c;
@@ -1038,96 +968,142 @@ static int cmd_subvol_show(int argc, char **argv)
                usage(cmd_subvol_show_usage);
        }
 
-       memset(&get_ri, 0, sizeof(get_ri));
        fullpath = realpath(argv[optind], NULL);
        if (!fullpath) {
                error("cannot find real path for '%s': %m", argv[optind]);
                goto out;
        }
 
-       if (by_rootid) {
-               ret = get_subvol_info_by_rootid(fullpath, &get_ri, rootid_arg);
-       } else if (by_uuid) {
-               ret = get_subvol_info_by_uuid(fullpath, &get_ri, uuid_arg);
-       } else {
-               ret = get_subvol_info(fullpath, &get_ri);
+       fd = open_file_or_dir(fullpath, &dirstream1);
+       if (fd < 0) {
+               error("can't access '%s'", fullpath);
+               goto out;
        }
 
-       if (ret) {
-               if (ret < 0) {
-                       error("Failed to get subvol info %s: %s",
-                                       fullpath, strerror(-ret));
-               } else {
-                       error("Failed to get subvol info %s: %d",
-                                       fullpath, ret);
+       if (by_uuid) {
+               err = btrfs_util_create_subvolume_iterator_fd(fd,
+                                                             BTRFS_FS_TREE_OBJECTID,
+                                                             0, &iter);
+               if (err) {
+                       error_btrfs_util(err);
+                       goto out;
+               }
+
+               for (;;) {
+                       err = btrfs_util_subvolume_iterator_next_info(iter,
+                                                                     &subvol_path,
+                                                                     &subvol);
+                       if (err == BTRFS_UTIL_ERROR_STOP_ITERATION) {
+                               uuid_unparse(uuid_arg, uuidparse);
+                               error("can't find uuid '%s' on '%s'", uuidparse,
+                                     fullpath);
+                               btrfs_util_destroy_subvolume_iterator(iter);
+                               goto out;
+                       } else if (err) {
+                               error_btrfs_util(err);
+                               btrfs_util_destroy_subvolume_iterator(iter);
+                               goto out;
+                       }
+
+                       if (uuid_compare(subvol.uuid, uuid_arg) == 0)
+                               break;
+
+                       free(subvol_path);
                }
-               return ret;
+               btrfs_util_destroy_subvolume_iterator(iter);
+       } else {
+               /*
+                * If !by_rootid, rootid_arg = 0, which means find the
+                * subvolume ID of the fd and use that.
+                */
+               err = btrfs_util_subvolume_info_fd(fd, rootid_arg, &subvol);
+               if (err) {
+                       error_btrfs_util(err);
+                       goto out;
+               }
+
+               err = btrfs_util_subvolume_path_fd(fd, subvol.id, &subvol_path);
+               if (err) {
+                       error_btrfs_util(err);
+                       goto out;
+               }
+
        }
 
        /* print the info */
-       printf("%s\n", get_ri.full_path);
-       printf("\tName: \t\t\t%s\n", get_ri.name);
+       printf("%s\n", subvol.id == BTRFS_FS_TREE_OBJECTID ? "/" : subvol_path);
+       printf("\tName: \t\t\t%s\n",
+              (subvol.id == BTRFS_FS_TREE_OBJECTID ? "<FS_TREE>" :
+               basename(subvol_path)));
 
-       if (uuid_is_null(get_ri.uuid))
+       if (uuid_is_null(subvol.uuid))
                strcpy(uuidparse, "-");
        else
-               uuid_unparse(get_ri.uuid, uuidparse);
+               uuid_unparse(subvol.uuid, uuidparse);
        printf("\tUUID: \t\t\t%s\n", uuidparse);
 
-       if (uuid_is_null(get_ri.puuid))
+       if (uuid_is_null(subvol.parent_uuid))
                strcpy(uuidparse, "-");
        else
-               uuid_unparse(get_ri.puuid, uuidparse);
+               uuid_unparse(subvol.parent_uuid, uuidparse);
        printf("\tParent UUID: \t\t%s\n", uuidparse);
 
-       if (uuid_is_null(get_ri.ruuid))
+       if (uuid_is_null(subvol.received_uuid))
                strcpy(uuidparse, "-");
        else
-               uuid_unparse(get_ri.ruuid, uuidparse);
+               uuid_unparse(subvol.received_uuid, uuidparse);
        printf("\tReceived UUID: \t\t%s\n", uuidparse);
 
-       if (get_ri.otime) {
+       if (subvol.otime.tv_sec) {
                struct tm tm;
 
-               localtime_r(&get_ri.otime, &tm);
+               localtime_r(&subvol.otime.tv_sec, &tm);
                strftime(tstr, 256, "%Y-%m-%d %X %z", &tm);
        } else
                strcpy(tstr, "-");
        printf("\tCreation time: \t\t%s\n", tstr);
 
-       printf("\tSubvolume ID: \t\t%llu\n", get_ri.root_id);
-       printf("\tGeneration: \t\t%llu\n", get_ri.gen);
-       printf("\tGen at creation: \t%llu\n", get_ri.ogen);
-       printf("\tParent ID: \t\t%llu\n", get_ri.ref_tree);
-       printf("\tTop level ID: \t\t%llu\n", get_ri.top_id);
+       printf("\tSubvolume ID: \t\t%" PRIu64 "\n", subvol.id);
+       printf("\tGeneration: \t\t%" PRIu64 "\n", subvol.generation);
+       printf("\tGen at creation: \t%" PRIu64 "\n", subvol.otransid);
+       printf("\tParent ID: \t\t%" PRIu64 "\n", subvol.parent_id);
+       printf("\tTop level ID: \t\t%" PRIu64 "\n", subvol.parent_id);
 
-       if (get_ri.flags & BTRFS_ROOT_SUBVOL_RDONLY)
+       if (subvol.flags & BTRFS_ROOT_SUBVOL_RDONLY)
                printf("\tFlags: \t\t\treadonly\n");
        else
                printf("\tFlags: \t\t\t-\n");
 
        /* print the snapshots of the given subvol if any*/
        printf("\tSnapshot(s):\n");
-       filter_set = btrfs_list_alloc_filter_set();
-       btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_BY_PARENT,
-                               (u64)(unsigned long)get_ri.uuid);
-       btrfs_list_setup_print_column(BTRFS_LIST_PATH);
 
-       fd = open_file_or_dir(fullpath, &dirstream1);
-       if (fd < 0) {
-               fprintf(stderr, "ERROR: can't access '%s'\n", fullpath);
-               goto out;
+       err = btrfs_util_create_subvolume_iterator_fd(fd,
+                                                     BTRFS_FS_TREE_OBJECTID, 0,
+                                                     &iter);
+
+       for (;;) {
+               struct btrfs_util_subvolume_info subvol2;
+               char *path;
+
+               err = btrfs_util_subvolume_iterator_next_info(iter, &path, &subvol2);
+               if (err == BTRFS_UTIL_ERROR_STOP_ITERATION) {
+                       break;
+               } else if (err) {
+                       error_btrfs_util(err);
+                       btrfs_util_destroy_subvolume_iterator(iter);
+                       goto out;
+               }
+
+               if (uuid_compare(subvol2.parent_uuid, subvol.uuid) == 0)
+                       printf("\t\t\t\t%s\n", path);
+
+               free(path);
        }
-       btrfs_list_subvols_print(fd, filter_set, NULL, BTRFS_LIST_LAYOUT_RAW,
-                       1, raw_prefix);
+       btrfs_util_destroy_subvolume_iterator(iter);
 
+       ret = 0;
 out:
-       /* clean up */
-       free(get_ri.path);
-       free(get_ri.name);
-       free(get_ri.full_path);
-       free(filter_set);
-
+       free(subvol_path);
        close_file_or_dir(fd, dirstream1);
        free(fullpath);
        return !!ret;
@@ -1146,160 +1122,15 @@ static const char * const cmd_subvol_sync_usage[] = {
        NULL
 };
 
-#if 0
-/*
- * If we're looking for any dead subvolume, take a shortcut and look
- * for any ORPHAN_ITEMs in the tree root
- */
-static int fs_has_dead_subvolumes(int fd)
-{
-       int ret;
-       struct btrfs_ioctl_search_args args;
-       struct btrfs_ioctl_search_key *sk = &args.key;
-       struct btrfs_ioctl_search_header sh;
-       u64 min_subvolid = 0;
-
-again:
-       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 = min_subvolid;
-       sk->max_offset = (u64)-1;
-       sk->min_transid = 0;
-       sk->max_transid = (u64)-1;
-       sk->nr_items = 1;
-
-       ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
-       if (ret < 0)
-               return -errno;
-
-       if (!sk->nr_items)
-               return 0;
-
-       memcpy(&sh, args.buf, sizeof(sh));
-       min_subvolid = sh.offset;
-
-       /*
-        * Verify that the root item is really there and we haven't hit
-        * a stale orphan
-        */
-       sk->tree_id = BTRFS_ROOT_TREE_OBJECTID;
-       sk->min_objectid = min_subvolid;
-       sk->max_objectid = min_subvolid;
-       sk->min_type = BTRFS_ROOT_ITEM_KEY;
-       sk->max_type = BTRFS_ROOT_ITEM_KEY;
-       sk->min_offset = 0;
-       sk->max_offset = (u64)-1;
-       sk->min_transid = 0;
-       sk->max_transid = (u64)-1;
-       sk->nr_items = 1;
-
-       ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
-       if (ret < 0)
-               return -errno;
-
-       /*
-        * Stale orphan, try the next one
-        */
-       if (!sk->nr_items) {
-               min_subvolid++;
-               goto again;
-       }
-
-       return 1;
-}
-#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;
-}
-
 static int cmd_subvol_sync(int argc, char **argv)
 {
        int fd = -1;
-       int i;
        int ret = 1;
        DIR *dirstream = NULL;
-       u64 *ids = NULL;
-       int id_count;
+       uint64_t *ids = NULL;
+       size_t id_count, i;
        int sleep_interval = 1;
+       enum btrfs_util_error err;
 
        while (1) {
                int c = getopt(argc, argv, "s:");
@@ -1333,10 +1164,9 @@ static int cmd_subvol_sync(int argc, char **argv)
 
        id_count = argc - optind;
        if (!id_count) {
-               id_count = enumerate_dead_subvols(fd, &ids);
-               if (id_count < 0) {
-                       error("can't enumerate dead subvolumes: %s",
-                                       strerror(-id_count));
+               err = btrfs_util_deleted_subvolumes_fd(fd, &ids, &id_count);
+               if (err) {
+                       error_btrfs_util(err);
                        ret = 1;
                        goto out;
                }
@@ -1345,7 +1175,7 @@ static int cmd_subvol_sync(int argc, char **argv)
                        goto out;
                }
        } else {
-               ids = (u64*)malloc(id_count * sizeof(u64));
+               ids = malloc(id_count * sizeof(uint64_t));
                if (!ids) {
                        error("not enough memory");
                        ret = 1;
@@ -1359,13 +1189,13 @@ static int cmd_subvol_sync(int argc, char **argv)
                        arg = argv[optind + i];
                        errno = 0;
                        id = strtoull(arg, NULL, 10);
-                       if (errno < 0) {
+                       if (errno) {
                                error("unrecognized subvolume id %s", arg);
                                ret = 1;
                                goto out;
                        }
-                       if (id < BTRFS_FIRST_FREE_OBJECTID
-                                       || id > BTRFS_LAST_FREE_OBJECTID) {
+                       if (id < BTRFS_FIRST_FREE_OBJECTID ||
+                           id > BTRFS_LAST_FREE_OBJECTID) {
                                error("subvolume id %s out of range", arg);
                                ret = 1;
                                goto out;