> diff --git a/cmds-subvolume.c b/cmds-subvolume.c
> index de246ab..0f36cde 100644
> --- a/cmds-subvolume.c
> +++ b/cmds-subvolume.c
> @@ -809,6 +809,7 @@ static int cmd_subvol_show(int argc, char **argv)
>       int fd = -1, mntfd = -1;
>       int ret = 1;
>       DIR *dirstream1 = NULL, *dirstream2 = NULL;
> +     u64 freeable_bytes;
>  
>       if (check_argc_exact(argc, 2))
>               usage(cmd_subvol_show_usage);
> @@ -878,6 +879,8 @@ static int cmd_subvol_show(int argc, char **argv)
>               goto out;
>       }
>  
> +     freeable_bytes = get_subvol_freeable_bytes(fd);
> +
>       ret = 0;
>       /* print the info */
>       printf("%s\n", fullpath);
> @@ -915,6 +918,8 @@ static int cmd_subvol_show(int argc, char **argv)
>       else
>               printf("\tFlags: \t\t\t-\n");
>  
> +     printf("\tUnshared space: \t%s\n",
> +             pretty_size(freeable_bytes));

There's no reason to have a local variable:

        printf("\tUnshared space: \t%s\n",
                pretty_size(get_subvol_freeable_bytes(fd));


>       printf("\tSnapshot(s):\n");
>       filter_set = btrfs_list_alloc_filter_set();
> diff --git a/utils.c b/utils.c
> index ccb5199..ca30485 100644
> --- a/utils.c
> +++ b/utils.c
> @@ -2062,3 +2062,157 @@ int lookup_ino_rootid(int fd, u64 *rootid)
>  
>       return 0;
>  }
> +
> +/* gets the ref count for given extent
> + * 0 = didn't find the item
> + * n = number of references
> +*/
> +u64 get_extent_refcnt(int fd, u64 disk_blk)
> +{
> +     int ret = 0, i, e;
> +     struct btrfs_ioctl_search_args args;
> +     struct btrfs_ioctl_search_key *sk = &args.key;
> +     struct btrfs_ioctl_search_header sh;
> +     unsigned long off = 0;
> +
> +     memset(&args, 0, sizeof(args));
> +
> +     sk->tree_id = BTRFS_EXTENT_TREE_OBJECTID;
> +
> +     sk->min_type = BTRFS_EXTENT_ITEM_KEY;
> +     sk->max_type = BTRFS_EXTENT_ITEM_KEY;
> +
> +     sk->min_objectid = disk_blk;
> +     sk->max_objectid = disk_blk;
> +
> +     sk->max_offset = (u64)-1;
> +     sk->max_transid = (u64)-1;
> +
> +     while (1) {
> +             sk->nr_items = 4096;
> +
> +             ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
> +             e = errno;
> +             if (ret < 0) {
> +                     fprintf(stderr, "ERROR: search failed - %s\n",
> +                             strerror(e));
> +                     return 0;
> +             }
> +             if (sk->nr_items == 0)
> +                     break;
> +
> +             off = 0;
> +             for (i = 0; i < sk->nr_items; i++) {
> +                     struct btrfs_extent_item *ei;
> +                     u64 ref;
> +
> +                     memcpy(&sh, args.buf + off, sizeof(sh));
> +                     off += sizeof(sh);
> +
> +                     if (sh.type != BTRFS_EXTENT_ITEM_KEY) {
> +                             off += sh.len;
> +                             continue;
> +                     }
> +
> +                     ei = (struct btrfs_extent_item *)(args.buf + off);
> +                     ref = btrfs_stack_extent_refs(ei);
> +                     return ref;
> +             }
> +             sk->min_objectid = sh.objectid;
> +             sk->min_offset = sh.offset;
> +             sk->min_type = sh.type;
> +             if (sk->min_offset < (u64)-1)
> +                     sk->min_offset++;
> +             else if (sk->min_objectid < (u64)-1) {
> +                     sk->min_objectid++;
> +                     sk->min_offset = 0;
> +                     sk->min_type = 0;
> +             } else
> +                     break;
> +     }
> +     return 0;
> +}

These two fiddly functions only differ in the tree search and what they
do with each item.  So replace them with a function that takes a
description of the search and calls the caller's callback for each item.

typedef void (*item_func_t)(struct btrfs_key *key, void *data, void *arg);

int btrfs_for_each_item(int fd, min and max and junk,
                        item_func_t func, void *arg);

u64 get_subvol_freeable_bytes(int fd)
{
        u64 size_bytes = 0;

        btrfs_for_each_item(fd, ...., sum_extents, &size_bytes);

        return size_bytes;
}

Etc.  You get the idea.

- z
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to