virDomainFSDefFormat(virBufferPtr buf,
                     virDomainFSDefPtr def,
                     unsigned int flags)
{
    const char *type = virDomainFSTypeToString(def->type);
    const char *accessmode = virDomainFSAccessModeTypeToString(def->accessmode);
    const char *fsdriver = virDomainFSDriverTypeToString(def->fsdriver);
    const char *wrpolicy = virDomainFSWrpolicyTypeToString(def->wrpolicy);
    const char *multidevs = virDomainFSMultidevsTypeToString(def->multidevs);
    const char *src = def->src->path;
    g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER;
    g_auto(virBuffer) driverBuf = VIR_BUFFER_INIT_CHILD(buf);
    g_auto(virBuffer) binaryAttrBuf = VIR_BUFFER_INITIALIZER;
    g_auto(virBuffer) binaryBuf = VIR_BUFFER_INIT_CHILD(buf);

    if (!type) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected filesystem type %d"), def->type);
        return -1;
    }

   if (!accessmode) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected accessmode %d"), def->accessmode);
        return -1;
    }

    if (!multidevs) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected multidevs %d"), def->multidevs);
        return -1;
    }

    virBufferAsprintf(buf,
                      "<filesystem type='%s' accessmode='%s'",
                      type, accessmode);
    if (def->model) {
        virBufferAsprintf(buf, " model='%s'",
                          virDomainFSModelTypeToString(def->model));
    }
    if (def->multidevs)
        virBufferAsprintf(buf, " multidevs='%s'", multidevs);
    virBufferAddLit(buf, ">\n");

    virBufferAdjustIndent(buf, 2);
    virBufferAdjustIndent(&driverBuf, 2);
    virBufferAdjustIndent(&binaryBuf, 2);
    if (def->fsdriver) {
        virBufferAsprintf(&driverAttrBuf, " type='%s'", fsdriver);

        if (def->format)
            virBufferAsprintf(&driverAttrBuf, " format='%s'",
                              virStorageFileFormatTypeToString(def->format));

        /* Don't generate anything if wrpolicy is set to default */
        if (def->wrpolicy)
            virBufferAsprintf(&driverAttrBuf, " wrpolicy='%s'", wrpolicy);

        if (def->queue_size)
            virBufferAsprintf(&driverAttrBuf, " queue='%llu'", def->queue_size);

    }

    if (def->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS) {
        g_auto(virBuffer) lockAttrBuf = VIR_BUFFER_INITIALIZER;
        virBufferEscapeString(&binaryAttrBuf, " path='%s'", def->binary);

        if (def->xattr != VIR_TRISTATE_SWITCH_ABSENT) {
            virBufferAsprintf(&binaryAttrBuf, " xattr='%s'",
                              virTristateSwitchTypeToString(def->xattr));
        }

        if (def->cache != VIR_DOMAIN_FS_CACHE_MODE_DEFAULT) {
            virBufferAsprintf(&binaryBuf, "<cache mode='%s'/>\n",
                              virDomainFSCacheModeTypeToString(def->cache));
        }

        if (def->posix_lock != VIR_TRISTATE_SWITCH_ABSENT) {
            virBufferAsprintf(&lockAttrBuf, " posix='%s'",
                              virTristateSwitchTypeToString(def->posix_lock));
        }

        if (def->flock != VIR_TRISTATE_SWITCH_ABSENT) {
            virBufferAsprintf(&lockAttrBuf, " flock='%s'",
                              virTristateSwitchTypeToString(def->flock));
        }

        virXMLFormatElement(&binaryBuf, "lock", &lockAttrBuf, NULL);
    }

    virDomainVirtioOptionsFormat(&driverAttrBuf, def->virtio);

    virXMLFormatElement(buf, "driver", &driverAttrBuf, &driverBuf);
    virXMLFormatElement(buf, "binary", &binaryAttrBuf, &binaryBuf);

    switch (def->type) {
    case VIR_DOMAIN_FS_TYPE_MOUNT:
    case VIR_DOMAIN_FS_TYPE_BIND:
        virBufferEscapeString(buf, "<source dir='%s'/>\n",
                              src);
        break;

    case VIR_DOMAIN_FS_TYPE_BLOCK:
        virBufferEscapeString(buf, "<source dev='%s'/>\n",
                              src);
        break;

    case VIR_DOMAIN_FS_TYPE_FILE:
        virBufferEscapeString(buf, "<source file='%s'/>\n",
                              src);
        break;

    case VIR_DOMAIN_FS_TYPE_TEMPLATE:
        virBufferEscapeString(buf, "<source name='%s'/>\n",
                              src);
        break;

    case VIR_DOMAIN_FS_TYPE_RAM:
        virBufferAsprintf(buf, "<source usage='%lld' units='KiB'/>\n",
                          def->usage / 1024);
        break;

    case VIR_DOMAIN_FS_TYPE_VOLUME:
        virBufferAddLit(buf, "<source");
        virBufferEscapeString(buf, " pool='%s'", def->src->srcpool->pool);
        virBufferEscapeString(buf, " volume='%s'", def->src->srcpool->volume);
        virBufferAddLit(buf, "/>\n");
        break;
    }

    virBufferEscapeString(buf, "<target dir='%s'/>\n",
                          def->dst);

    if (def->readonly)
        virBufferAddLit(buf, "<readonly/>\n");

    if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0)
        return -1;

    if (def->space_hard_limit)
        virBufferAsprintf(buf, "<space_hard_limit unit='bytes'>"
                          "%llu</space_hard_limit>\n", def->space_hard_limit);
    if (def->space_soft_limit) {
        virBufferAsprintf(buf, "<space_soft_limit unit='bytes'>"
                          "%llu</space_soft_limit>\n", def->space_soft_limit);
    }
    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</filesystem>\n");

    return 0;
}