virDomainDiskDefParseValidate(const virDomainDiskDef *def)

{
    virStorageSourcePtr next;

    if (def->bus != VIR_DOMAIN_DISK_BUS_VIRTIO) {
        if (def->event_idx != VIR_TRISTATE_SWITCH_ABSENT) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("disk event_idx mode supported only for virtio bus"));
            return -1;
        }

        if (def->ioeventfd != VIR_TRISTATE_SWITCH_ABSENT) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("disk ioeventfd mode supported only for virtio bus"));
            return -1;
        }
    }

    if (def->device != VIR_DOMAIN_DISK_DEVICE_LUN) {
        if (def->rawio != VIR_TRISTATE_BOOL_ABSENT) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("rawio can be used only with device='lun'"));
            return -1;
        }

        if (def->sgio != VIR_DOMAIN_DEVICE_SGIO_DEFAULT) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("sgio can be used only with device='lun'"));
            return -1;
        }
    }

    if (def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
        def->bus != VIR_DOMAIN_DISK_BUS_FDC) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Invalid bus type '%s' for floppy disk"),
                       virDomainDiskBusTypeToString(def->bus));
        return -1;
    }

    if (def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
        def->bus == VIR_DOMAIN_DISK_BUS_FDC) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Invalid bus type '%s' for disk"),
                       virDomainDiskBusTypeToString(def->bus));
        return -1;
    }

    if (def->removable != VIR_TRISTATE_SWITCH_ABSENT &&
        def->bus != VIR_DOMAIN_DISK_BUS_USB) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("removable is only valid for usb disks"));
        return -1;
    }

    if (def->startupPolicy != VIR_DOMAIN_STARTUP_POLICY_DEFAULT) {
        if (def->src->type == VIR_STORAGE_TYPE_NETWORK) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("Setting disk %s is not allowed for "
                             "disk of network type"),
                           virDomainStartupPolicyTypeToString(def->startupPolicy));
            return -1;
        }

        if (def->device != VIR_DOMAIN_DISK_DEVICE_CDROM &&
            def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
            def->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_REQUISITE) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("Setting disk 'requisite' is allowed only for "
                             "cdrom or floppy"));
            return -1;
        }
    }

    for (next = def->src; next; next = next->backingStore) {
        if (virDomainDiskSourceDefParseAuthValidate(next) < 0)
            return -1;

        if (next->encryption) {
            virStorageEncryptionPtr encryption = next->encryption;

            if (encryption->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS &&
                encryption->encinfo.cipher_name) {

                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("supplying <cipher> for domain disk definition "
                                 "is unnecessary"));
                return -1;
            }
        }
    }

    return 0;
}