static int
virStorageBackendZFSCreateVol(virConnectPtr conn ATTRIBUTE_UNUSED,
                              virStoragePoolObjPtr pool,
                              virStorageVolDefPtr vol)
{
    virCommandPtr cmd = NULL;
    int ret = -1;

    vol->type = VIR_STORAGE_VOL_BLOCK;

    if (vol->target.path != NULL) {
        /* A target path passed to CreateVol has no meaning */
        VIR_FREE(vol->target.path);
    }

    if (virAsprintf(&vol->target.path, "%s/%s",
                    pool->def->target.path, vol->name) == -1)
        return -1;

    if (VIR_STRDUP(vol->key, vol->target.path) < 0)
        goto cleanup;

    /**
     * $ zfs create -o volmode=dev -V 10240K test/volname
     *
     * -o volmode=dev -- we want to get volumes exposed as cdev
     *                   devices. If we don't specify that zfs
     *                   will lookup vfs.zfs.vol.mode sysctl value
     * -V -- tells to create a volume with the specified size
     */
    cmd = virCommandNewArgList(ZFS, "create", "-o", "volmode=dev",
                               "-V", NULL);
    virCommandAddArgFormat(cmd, "%lluK",
                           VIR_DIV_UP(vol->target.capacity, 1024));
    virCommandAddArgFormat(cmd, "%s/%s",
                           pool->def->source.name, vol->name);

    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    if (virStorageBackendZFSFindVols(pool, vol) < 0)
        goto cleanup;

    ret = 0;
 cleanup:
    virCommandFree(cmd);
    return ret;

}
static int
virStorageBackendZFSCreateVol(virConnectPtr conn ATTRIBUTE_UNUSED,
                              virStoragePoolObjPtr pool,
                              virStorageVolDefPtr vol)
{
    virCommandPtr cmd = NULL;
    int ret = -1;
    int volmode_needed = -1;

    if (vol->target.format != VIR_STORAGE_FILE_RAW) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("only RAW volumes are supported by this storage pool"));
        return -1;
    }

    if (vol->target.encryption != NULL) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       "%s", _("storage pool does not support encrypted "
                               "volumes"));
        return -1;
    }

    vol->type = VIR_STORAGE_VOL_BLOCK;

    VIR_FREE(vol->target.path);
    if (virAsprintf(&vol->target.path, "%s/%s",
                    pool->def->target.path, vol->name) == -1)
        return -1;

    if (VIR_STRDUP(vol->key, vol->target.path) < 0)
        goto cleanup;

    volmode_needed = virStorageBackendZFSVolModeNeeded();
    if (volmode_needed < 0)
        goto cleanup;
    /**
     * $ zfs create -o volmode=dev -V 10240K test/volname
     *
     * -o volmode=dev -- we want to get volumes exposed as cdev
     *                   devices. If we don't specify that zfs
     *                   will lookup vfs.zfs.vol.mode sysctl value
     * -V -- tells to create a volume with the specified size
     */
    cmd = virCommandNewArgList(ZFS, "create", NULL);
    if (volmode_needed)
        virCommandAddArgList(cmd, "-o", "volmode=dev", NULL);
    virCommandAddArg(cmd, "-V");
    virCommandAddArgFormat(cmd, "%lluK",
                           VIR_DIV_UP(vol->target.capacity, 1024));
    virCommandAddArgFormat(cmd, "%s/%s",
                           pool->def->source.name, vol->name);

    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    if (virStorageBackendZFSFindVols(pool, vol) < 0)
        goto cleanup;

    ret = 0;
 cleanup:
    virCommandFree(cmd);
    return ret;

}
static int
virStorageBackendZFSRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
                                virStoragePoolObjPtr pool ATTRIBUTE_UNUSED)
{
    virCommandPtr cmd = NULL;
    char *zpool_props = NULL;
    char **lines = NULL;
    char **tokens = NULL;
    size_t i;

    /**
     * $ zpool get -Hp health,size,free,allocated test
     * test    health  ONLINE  -
     * test    size    199715979264    -
     * test    free    198899976704    -
     * test    allocated       816002560       -
     * $
     *
     * Here we just provide a list of properties we want to see
     */
    cmd = virCommandNewArgList(ZPOOL,
                               "get", "-Hp",
                               "health,size,free,allocated",
                               pool->def->source.name,
                               NULL);
    virCommandSetOutputBuffer(cmd, &zpool_props);
    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    if (!(lines = virStringSplit(zpool_props, "\n", 0)))
        goto cleanup;

    for (i = 0; lines[i]; i++) {
        size_t count;
        char *prop_name;

        if (STREQ(lines[i], ""))
            continue;

        virStringFreeList(tokens);
        if (!(tokens = virStringSplitCount(lines[i], "\t", 0, &count)))
            goto cleanup;

        if (count != 4)
            continue;

        prop_name = tokens[1];

        if (STREQ(prop_name, "free") || STREQ(prop_name, "size") ||
            STREQ(prop_name, "allocated")) {
            unsigned long long value;
            if (virStrToLong_ull(tokens[2], NULL, 10, &value) < 0)
                goto cleanup;

            if (STREQ(prop_name, "free"))
                pool->def->available = value;
            else if (STREQ(prop_name, "size"))
                pool->def->capacity = value;
            else if (STREQ(prop_name, "allocated"))
                pool->def->allocation = value;
        }
    }

    /* Obtain a list of volumes */
    if (virStorageBackendZFSFindVols(pool, NULL) < 0)
        goto cleanup;

 cleanup:
    virCommandFree(cmd);
    virStringFreeList(lines);
    virStringFreeList(tokens);
    VIR_FREE(zpool_props);

    return 0;
}