2009-09-25 13:20:13 +00:00
|
|
|
/*
|
2012-12-13 15:25:48 +00:00
|
|
|
* virstoragefile.c: file utility functions for FS storage backend
|
2009-09-25 13:20:13 +00:00
|
|
|
*
|
conf: split network host structs to util/
Continuing the refactoring of host-side storage descriptions out
of conf/domain_conf and into util/virstoragefile, this patch
focuses on details about a host name/port/transport as used by
a network storage volume.
* src/conf/domain_conf.h (virDomainDiskProtocolTransport)
(virDomainDiskHostDef, virDomainDiskHostDefClear)
(virDomainDiskHostDefFree, virDomainDiskHostDefCopy): Move...
* src/util/virstoragefile.h (virStorageNetHostTransport)
(virStorageNetHostDef, virStorageNetHostDefClear)
(virStorageNetHostDefFree, virStorageNetHostDefCopy): ...here,
with better names.
* src/util/virstoragefile.c (virStorageNetHostDefClear)
(virStorageNetHostDefFree, virStorageNetHostDefCopy): Moved from...
* src/conf/domain_conf.c (virDomainDiskHostDefClear)
(virDomainDiskHostDefFree, virDomainDiskHostDefCopy): ...here.
(virDomainDiskSourceDefClear, virDomainDiskSourceDefParse)
(virDomainDiskSourceDefFormatInternal): Adjust callers.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefClear):
Likewise.
* src/qemu/qemu_command.c (qemuAddRBDHost)
(qemuParseDriveURIString, qemuParseNBDString)
(qemuBuildNetworkDriveURI, qemuParseCommandLineDisk)
(qemuParseCommandLine, qemuGetDriveSourceString): Likewise.
* src/qemu/qemu_command.h: Likewise.
* src/qemu/qemu_conf.c (qemuAddISCSIPoolSourceHost)
(qemuTranslateDiskSourcePool): Likewise.
* src/qemu/qemu_driver.c
(qemuDomainSnapshotCreateSingleDiskActive)
(qemuDomainSnapshotUndoSingleDiskActive): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGlusterInit): Likewise.
* src/storage/storage_driver.c (virStorageFileFree)
(virStorageFileInitInternal): Likewise.
* src/storage/storage_driver.h (_virStorageFile): Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-26 22:33:08 +00:00
|
|
|
* Copyright (C) 2007-2014 Red Hat, Inc.
|
2009-09-25 13:20:13 +00:00
|
|
|
* Copyright (C) 2007-2008 Daniel P. Berrange
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2009-09-25 13:20:13 +00:00
|
|
|
*
|
|
|
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
2012-12-13 15:25:48 +00:00
|
|
|
#include "virstoragefile.h"
|
2009-09-25 13:20:13 +00:00
|
|
|
|
2011-05-26 18:05:32 +00:00
|
|
|
#include <sys/stat.h>
|
2009-09-29 08:34:48 +00:00
|
|
|
#include <unistd.h>
|
2009-09-29 08:41:23 +00:00
|
|
|
#include <fcntl.h>
|
2012-10-09 23:47:42 +00:00
|
|
|
#include <stdlib.h>
|
2010-02-04 15:55:57 +00:00
|
|
|
#include "dirname.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2011-07-20 09:40:53 +00:00
|
|
|
#include "c-ctype.h"
|
2012-12-12 16:27:01 +00:00
|
|
|
#include "vircommand.h"
|
2012-10-13 16:47:15 +00:00
|
|
|
#include "virhash.h"
|
2013-02-07 01:57:13 +00:00
|
|
|
#include "virendian.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
|
|
|
#include "virutil.h"
|
2013-05-31 05:16:14 +00:00
|
|
|
#if HAVE_SYS_SYSCALL_H
|
|
|
|
# include <sys/syscall.h>
|
|
|
|
#endif
|
2009-09-29 08:34:48 +00:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_STORAGE
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("util.storagefile");
|
|
|
|
|
conf: move host disk type to util/
A continuation of the migration of disk details to virstoragefile.
This patch moves a single enum, but converting the name has quite
a bit of fallout.
* src/conf/domain_conf.h (virDomainDiskType): Move...
* src/util/virstoragefile.h (virStorageType): ...and rename.
* src/bhyve/bhyve_command.c (bhyveBuildDiskArgStr)
(virBhyveProcessBuildLoadCmd): Update clients.
* src/conf/domain_conf.c (virDomainDiskSourceDefParse)
(virDomainDiskDefParseXML, virDomainDiskSourceDefFormatInternal)
(virDomainDiskDefFormat, virDomainDiskGetActualType)
(virDomainDiskDefForeachPath, virDomainDiskSourceIsBlockType):
Likewise.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefParseXML)
(virDomainSnapshotAlignDisks, virDomainSnapshotDiskDefFormat):
Likewise.
* src/esx/esx_driver.c (esxAutodetectSCSIControllerModel)
(esxDomainDefineXML): Likewise.
* src/locking/domain_lock.c (virDomainLockManagerAddDisk):
Likewise.
* src/lxc/lxc_controller.c
(virLXCControllerSetupLoopDeviceDisk)
(virLXCControllerSetupNBDDeviceDisk)
(virLXCControllerSetupLoopDevices, virLXCControllerSetupDisk):
Likewise.
* src/parallels/parallels_driver.c (parallelsGetHddInfo):
Likewise.
* src/phyp/phyp_driver.c (phypDiskType): Likewise.
* src/qemu/qemu_command.c (qemuGetDriveSourceString)
(qemuDomainDiskGetSourceString, qemuBuildDriveStr)
(qemuBuildCommandLine, qemuParseCommandLineDisk)
(qemuParseCommandLine): Likewise.
* src/qemu/qemu_conf.c (qemuCheckSharedDevice)
(qemuTranslateDiskSourcePool)
(qemuTranslateSnapshotDiskSourcePool): Likewise.
* src/qemu/qemu_domain.c (qemuDomainDeviceDefPostParse)
(qemuDomainDetermineDiskChain): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo)
(qemuDomainSnapshotPrepareDiskExternalBackingInactive)
(qemuDomainSnapshotPrepareDiskExternalBackingActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayInactive)
(qemuDomainSnapshotPrepareDiskInternal)
(qemuDomainSnapshotPrepare)
(qemuDomainSnapshotCreateSingleDiskActive): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainChangeEjectableMedia):
Likewise.
* src/qemu/qemu_migration.c (qemuMigrationIsSafe): Likewise.
* src/security/security_apparmor.c
(AppArmorRestoreSecurityImageLabel)
(AppArmorSetSecurityImageLabel): Likewise.
* src/security/security_dac.c (virSecurityDACSetSecurityImageLabel)
(virSecurityDACRestoreSecurityImageLabelInt)
(virSecurityDACSetSecurityAllLabel): Likewise.
* src/security/security_selinux.c
(virSecuritySELinuxRestoreSecurityImageLabelInt)
(virSecuritySELinuxSetSecurityImageLabel)
(virSecuritySELinuxSetSecurityAllLabel): Likewise.
* src/storage/storage_backend.c (virStorageFileBackendForType):
Likewise.
* src/storage/storage_backend_fs.c (virStorageFileBackendFile)
(virStorageFileBackendBlock): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGluster): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainGetXMLDesc, vboxAttachDrives)
(vboxDomainAttachDeviceImpl, vboxDomainDetachDevice): Likewise.
* src/vmware/vmware_conf.c (vmwareVmxPath): Likewise.
* src/vmx/vmx.c (virVMXParseDisk, virVMXFormatDisk)
(virVMXFormatFloppy): Likewise.
* src/xenxs/xen_sxpr.c (xenParseSxprDisks, xenParseSxpr)
(xenFormatSxprDisk): Likewise.
* src/xenxs/xen_xm.c (xenParseXM, xenFormatXMDisk): Likewise.
* tests/securityselinuxlabeltest.c (testSELinuxLoadDef):
Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-27 21:57:49 +00:00
|
|
|
VIR_ENUM_IMPL(virStorage, VIR_STORAGE_TYPE_LAST,
|
2014-04-02 19:01:46 +00:00
|
|
|
"none",
|
conf: move host disk type to util/
A continuation of the migration of disk details to virstoragefile.
This patch moves a single enum, but converting the name has quite
a bit of fallout.
* src/conf/domain_conf.h (virDomainDiskType): Move...
* src/util/virstoragefile.h (virStorageType): ...and rename.
* src/bhyve/bhyve_command.c (bhyveBuildDiskArgStr)
(virBhyveProcessBuildLoadCmd): Update clients.
* src/conf/domain_conf.c (virDomainDiskSourceDefParse)
(virDomainDiskDefParseXML, virDomainDiskSourceDefFormatInternal)
(virDomainDiskDefFormat, virDomainDiskGetActualType)
(virDomainDiskDefForeachPath, virDomainDiskSourceIsBlockType):
Likewise.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefParseXML)
(virDomainSnapshotAlignDisks, virDomainSnapshotDiskDefFormat):
Likewise.
* src/esx/esx_driver.c (esxAutodetectSCSIControllerModel)
(esxDomainDefineXML): Likewise.
* src/locking/domain_lock.c (virDomainLockManagerAddDisk):
Likewise.
* src/lxc/lxc_controller.c
(virLXCControllerSetupLoopDeviceDisk)
(virLXCControllerSetupNBDDeviceDisk)
(virLXCControllerSetupLoopDevices, virLXCControllerSetupDisk):
Likewise.
* src/parallels/parallels_driver.c (parallelsGetHddInfo):
Likewise.
* src/phyp/phyp_driver.c (phypDiskType): Likewise.
* src/qemu/qemu_command.c (qemuGetDriveSourceString)
(qemuDomainDiskGetSourceString, qemuBuildDriveStr)
(qemuBuildCommandLine, qemuParseCommandLineDisk)
(qemuParseCommandLine): Likewise.
* src/qemu/qemu_conf.c (qemuCheckSharedDevice)
(qemuTranslateDiskSourcePool)
(qemuTranslateSnapshotDiskSourcePool): Likewise.
* src/qemu/qemu_domain.c (qemuDomainDeviceDefPostParse)
(qemuDomainDetermineDiskChain): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo)
(qemuDomainSnapshotPrepareDiskExternalBackingInactive)
(qemuDomainSnapshotPrepareDiskExternalBackingActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayInactive)
(qemuDomainSnapshotPrepareDiskInternal)
(qemuDomainSnapshotPrepare)
(qemuDomainSnapshotCreateSingleDiskActive): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainChangeEjectableMedia):
Likewise.
* src/qemu/qemu_migration.c (qemuMigrationIsSafe): Likewise.
* src/security/security_apparmor.c
(AppArmorRestoreSecurityImageLabel)
(AppArmorSetSecurityImageLabel): Likewise.
* src/security/security_dac.c (virSecurityDACSetSecurityImageLabel)
(virSecurityDACRestoreSecurityImageLabelInt)
(virSecurityDACSetSecurityAllLabel): Likewise.
* src/security/security_selinux.c
(virSecuritySELinuxRestoreSecurityImageLabelInt)
(virSecuritySELinuxSetSecurityImageLabel)
(virSecuritySELinuxSetSecurityAllLabel): Likewise.
* src/storage/storage_backend.c (virStorageFileBackendForType):
Likewise.
* src/storage/storage_backend_fs.c (virStorageFileBackendFile)
(virStorageFileBackendBlock): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGluster): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainGetXMLDesc, vboxAttachDrives)
(vboxDomainAttachDeviceImpl, vboxDomainDetachDevice): Likewise.
* src/vmware/vmware_conf.c (vmwareVmxPath): Likewise.
* src/vmx/vmx.c (virVMXParseDisk, virVMXFormatDisk)
(virVMXFormatFloppy): Likewise.
* src/xenxs/xen_sxpr.c (xenParseSxprDisks, xenParseSxpr)
(xenFormatSxprDisk): Likewise.
* src/xenxs/xen_xm.c (xenParseXM, xenFormatXMDisk): Likewise.
* tests/securityselinuxlabeltest.c (testSELinuxLoadDef):
Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-27 21:57:49 +00:00
|
|
|
"file",
|
2014-04-02 19:01:46 +00:00
|
|
|
"block",
|
conf: move host disk type to util/
A continuation of the migration of disk details to virstoragefile.
This patch moves a single enum, but converting the name has quite
a bit of fallout.
* src/conf/domain_conf.h (virDomainDiskType): Move...
* src/util/virstoragefile.h (virStorageType): ...and rename.
* src/bhyve/bhyve_command.c (bhyveBuildDiskArgStr)
(virBhyveProcessBuildLoadCmd): Update clients.
* src/conf/domain_conf.c (virDomainDiskSourceDefParse)
(virDomainDiskDefParseXML, virDomainDiskSourceDefFormatInternal)
(virDomainDiskDefFormat, virDomainDiskGetActualType)
(virDomainDiskDefForeachPath, virDomainDiskSourceIsBlockType):
Likewise.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefParseXML)
(virDomainSnapshotAlignDisks, virDomainSnapshotDiskDefFormat):
Likewise.
* src/esx/esx_driver.c (esxAutodetectSCSIControllerModel)
(esxDomainDefineXML): Likewise.
* src/locking/domain_lock.c (virDomainLockManagerAddDisk):
Likewise.
* src/lxc/lxc_controller.c
(virLXCControllerSetupLoopDeviceDisk)
(virLXCControllerSetupNBDDeviceDisk)
(virLXCControllerSetupLoopDevices, virLXCControllerSetupDisk):
Likewise.
* src/parallels/parallels_driver.c (parallelsGetHddInfo):
Likewise.
* src/phyp/phyp_driver.c (phypDiskType): Likewise.
* src/qemu/qemu_command.c (qemuGetDriveSourceString)
(qemuDomainDiskGetSourceString, qemuBuildDriveStr)
(qemuBuildCommandLine, qemuParseCommandLineDisk)
(qemuParseCommandLine): Likewise.
* src/qemu/qemu_conf.c (qemuCheckSharedDevice)
(qemuTranslateDiskSourcePool)
(qemuTranslateSnapshotDiskSourcePool): Likewise.
* src/qemu/qemu_domain.c (qemuDomainDeviceDefPostParse)
(qemuDomainDetermineDiskChain): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo)
(qemuDomainSnapshotPrepareDiskExternalBackingInactive)
(qemuDomainSnapshotPrepareDiskExternalBackingActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayInactive)
(qemuDomainSnapshotPrepareDiskInternal)
(qemuDomainSnapshotPrepare)
(qemuDomainSnapshotCreateSingleDiskActive): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainChangeEjectableMedia):
Likewise.
* src/qemu/qemu_migration.c (qemuMigrationIsSafe): Likewise.
* src/security/security_apparmor.c
(AppArmorRestoreSecurityImageLabel)
(AppArmorSetSecurityImageLabel): Likewise.
* src/security/security_dac.c (virSecurityDACSetSecurityImageLabel)
(virSecurityDACRestoreSecurityImageLabelInt)
(virSecurityDACSetSecurityAllLabel): Likewise.
* src/security/security_selinux.c
(virSecuritySELinuxRestoreSecurityImageLabelInt)
(virSecuritySELinuxSetSecurityImageLabel)
(virSecuritySELinuxSetSecurityAllLabel): Likewise.
* src/storage/storage_backend.c (virStorageFileBackendForType):
Likewise.
* src/storage/storage_backend_fs.c (virStorageFileBackendFile)
(virStorageFileBackendBlock): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGluster): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainGetXMLDesc, vboxAttachDrives)
(vboxDomainAttachDeviceImpl, vboxDomainDetachDevice): Likewise.
* src/vmware/vmware_conf.c (vmwareVmxPath): Likewise.
* src/vmx/vmx.c (virVMXParseDisk, virVMXFormatDisk)
(virVMXFormatFloppy): Likewise.
* src/xenxs/xen_sxpr.c (xenParseSxprDisks, xenParseSxpr)
(xenFormatSxprDisk): Likewise.
* src/xenxs/xen_xm.c (xenParseXM, xenFormatXMDisk): Likewise.
* tests/securityselinuxlabeltest.c (testSELinuxLoadDef):
Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-27 21:57:49 +00:00
|
|
|
"dir",
|
|
|
|
"network",
|
|
|
|
"volume")
|
|
|
|
|
2009-09-25 13:20:13 +00:00
|
|
|
VIR_ENUM_IMPL(virStorageFileFormat,
|
|
|
|
VIR_STORAGE_FILE_LAST,
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
"none",
|
2010-11-22 20:08:17 +00:00
|
|
|
"raw", "dir", "bochs",
|
2009-09-25 13:20:13 +00:00
|
|
|
"cloop", "cow", "dmg", "iso",
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
"qcow", "qcow2", "qed", "vmdk", "vpc",
|
2013-02-04 19:18:22 +00:00
|
|
|
"fat", "vhd", "vdi")
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2013-05-07 15:27:43 +00:00
|
|
|
VIR_ENUM_IMPL(virStorageFileFeature,
|
|
|
|
VIR_STORAGE_FILE_FEATURE_LAST,
|
|
|
|
"lazy_refcounts",
|
|
|
|
)
|
|
|
|
|
2014-03-27 22:47:39 +00:00
|
|
|
VIR_ENUM_IMPL(virStorageNetProtocol, VIR_STORAGE_NET_PROTOCOL_LAST,
|
|
|
|
"nbd",
|
|
|
|
"rbd",
|
|
|
|
"sheepdog",
|
|
|
|
"gluster",
|
|
|
|
"iscsi",
|
|
|
|
"http",
|
|
|
|
"https",
|
|
|
|
"ftp",
|
|
|
|
"ftps",
|
|
|
|
"tftp")
|
conf: split network host structs to util/
Continuing the refactoring of host-side storage descriptions out
of conf/domain_conf and into util/virstoragefile, this patch
focuses on details about a host name/port/transport as used by
a network storage volume.
* src/conf/domain_conf.h (virDomainDiskProtocolTransport)
(virDomainDiskHostDef, virDomainDiskHostDefClear)
(virDomainDiskHostDefFree, virDomainDiskHostDefCopy): Move...
* src/util/virstoragefile.h (virStorageNetHostTransport)
(virStorageNetHostDef, virStorageNetHostDefClear)
(virStorageNetHostDefFree, virStorageNetHostDefCopy): ...here,
with better names.
* src/util/virstoragefile.c (virStorageNetHostDefClear)
(virStorageNetHostDefFree, virStorageNetHostDefCopy): Moved from...
* src/conf/domain_conf.c (virDomainDiskHostDefClear)
(virDomainDiskHostDefFree, virDomainDiskHostDefCopy): ...here.
(virDomainDiskSourceDefClear, virDomainDiskSourceDefParse)
(virDomainDiskSourceDefFormatInternal): Adjust callers.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefClear):
Likewise.
* src/qemu/qemu_command.c (qemuAddRBDHost)
(qemuParseDriveURIString, qemuParseNBDString)
(qemuBuildNetworkDriveURI, qemuParseCommandLineDisk)
(qemuParseCommandLine, qemuGetDriveSourceString): Likewise.
* src/qemu/qemu_command.h: Likewise.
* src/qemu/qemu_conf.c (qemuAddISCSIPoolSourceHost)
(qemuTranslateDiskSourcePool): Likewise.
* src/qemu/qemu_driver.c
(qemuDomainSnapshotCreateSingleDiskActive)
(qemuDomainSnapshotUndoSingleDiskActive): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGlusterInit): Likewise.
* src/storage/storage_driver.c (virStorageFileFree)
(virStorageFileInitInternal): Likewise.
* src/storage/storage_driver.h (_virStorageFile): Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-26 22:33:08 +00:00
|
|
|
|
|
|
|
VIR_ENUM_IMPL(virStorageNetHostTransport, VIR_STORAGE_NET_HOST_TRANS_LAST,
|
|
|
|
"tcp",
|
|
|
|
"unix",
|
|
|
|
"rdma")
|
|
|
|
|
2014-03-28 04:33:45 +00:00
|
|
|
VIR_ENUM_IMPL(virStorageSourcePoolMode,
|
|
|
|
VIR_STORAGE_SOURCE_POOL_MODE_LAST,
|
|
|
|
"default",
|
|
|
|
"host",
|
|
|
|
"direct")
|
conf: split network host structs to util/
Continuing the refactoring of host-side storage descriptions out
of conf/domain_conf and into util/virstoragefile, this patch
focuses on details about a host name/port/transport as used by
a network storage volume.
* src/conf/domain_conf.h (virDomainDiskProtocolTransport)
(virDomainDiskHostDef, virDomainDiskHostDefClear)
(virDomainDiskHostDefFree, virDomainDiskHostDefCopy): Move...
* src/util/virstoragefile.h (virStorageNetHostTransport)
(virStorageNetHostDef, virStorageNetHostDefClear)
(virStorageNetHostDefFree, virStorageNetHostDefCopy): ...here,
with better names.
* src/util/virstoragefile.c (virStorageNetHostDefClear)
(virStorageNetHostDefFree, virStorageNetHostDefCopy): Moved from...
* src/conf/domain_conf.c (virDomainDiskHostDefClear)
(virDomainDiskHostDefFree, virDomainDiskHostDefCopy): ...here.
(virDomainDiskSourceDefClear, virDomainDiskSourceDefParse)
(virDomainDiskSourceDefFormatInternal): Adjust callers.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefClear):
Likewise.
* src/qemu/qemu_command.c (qemuAddRBDHost)
(qemuParseDriveURIString, qemuParseNBDString)
(qemuBuildNetworkDriveURI, qemuParseCommandLineDisk)
(qemuParseCommandLine, qemuGetDriveSourceString): Likewise.
* src/qemu/qemu_command.h: Likewise.
* src/qemu/qemu_conf.c (qemuAddISCSIPoolSourceHost)
(qemuTranslateDiskSourcePool): Likewise.
* src/qemu/qemu_driver.c
(qemuDomainSnapshotCreateSingleDiskActive)
(qemuDomainSnapshotUndoSingleDiskActive): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGlusterInit): Likewise.
* src/storage/storage_driver.c (virStorageFileFree)
(virStorageFileInitInternal): Likewise.
* src/storage/storage_driver.h (_virStorageFile): Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-26 22:33:08 +00:00
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
enum lv_endian {
|
|
|
|
LV_LITTLE_ENDIAN = 1, /* 1234 */
|
|
|
|
LV_BIG_ENDIAN /* 4321 */
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
BACKING_STORE_OK,
|
|
|
|
BACKING_STORE_INVALID,
|
|
|
|
BACKING_STORE_ERROR,
|
|
|
|
};
|
|
|
|
|
2013-05-07 15:27:43 +00:00
|
|
|
#define FILE_TYPE_VERSIONS_LAST 2
|
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
/* Either 'magic' or 'extension' *must* be provided */
|
|
|
|
struct FileTypeInfo {
|
2013-02-04 19:16:22 +00:00
|
|
|
int magicOffset; /* Byte offset of the magic */
|
2009-09-29 08:34:48 +00:00
|
|
|
const char *magic; /* Optional string of file magic
|
|
|
|
* to check at head of file */
|
|
|
|
const char *extension; /* Optional file extension to check */
|
|
|
|
enum lv_endian endian; /* Endianness of file format */
|
|
|
|
int versionOffset; /* Byte offset from start of file
|
|
|
|
* where we find version number,
|
2013-06-10 09:44:31 +00:00
|
|
|
* -1 to always fail the version test,
|
|
|
|
* -2 to always pass the version test */
|
2013-05-07 15:27:43 +00:00
|
|
|
int versionNumbers[FILE_TYPE_VERSIONS_LAST];
|
|
|
|
/* Version numbers to validate. Zeroes are ignored. */
|
2009-09-29 08:34:48 +00:00
|
|
|
int sizeOffset; /* Byte offset from start of file
|
|
|
|
* where we find capacity info,
|
|
|
|
* -1 to use st_size as capacity */
|
|
|
|
int sizeBytes; /* Number of bytes for size field */
|
|
|
|
int sizeMultiplier; /* A scaling factor if size is not in bytes */
|
|
|
|
/* Store a COW base image path (possibly relative),
|
|
|
|
* or NULL if there is no COW base image, to RES;
|
|
|
|
* return BACKING_STORE_* */
|
|
|
|
int qcowCryptOffset; /* Byte offset from start of file
|
|
|
|
* where to find encryption mode,
|
|
|
|
* -1 if encryption is not used */
|
2010-06-14 14:53:59 +00:00
|
|
|
int (*getBackingStore)(char **res, int *format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *buf, size_t buf_size);
|
2013-05-07 15:27:43 +00:00
|
|
|
int (*getFeatures)(virBitmapPtr *features, int format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
char *buf, ssize_t len);
|
2009-09-29 08:34:48 +00:00
|
|
|
};
|
|
|
|
|
2010-06-14 14:53:59 +00:00
|
|
|
static int cowGetBackingStore(char **, int *,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *, size_t);
|
2010-06-14 14:53:59 +00:00
|
|
|
static int qcow1GetBackingStore(char **, int *,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *, size_t);
|
2010-06-14 14:53:59 +00:00
|
|
|
static int qcow2GetBackingStore(char **, int *,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *, size_t);
|
2013-05-07 15:27:43 +00:00
|
|
|
static int qcow2GetFeatures(virBitmapPtr *features, int format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
char *buf, ssize_t len);
|
2010-06-14 14:53:59 +00:00
|
|
|
static int vmdk4GetBackingStore(char **, int *,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *, size_t);
|
2010-11-19 23:19:24 +00:00
|
|
|
static int
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
qedGetBackingStore(char **, int *, const char *, size_t);
|
2010-06-14 14:53:59 +00:00
|
|
|
|
|
|
|
#define QCOWX_HDR_VERSION (4)
|
|
|
|
#define QCOWX_HDR_BACKING_FILE_OFFSET (QCOWX_HDR_VERSION+4)
|
|
|
|
#define QCOWX_HDR_BACKING_FILE_SIZE (QCOWX_HDR_BACKING_FILE_OFFSET+8)
|
|
|
|
#define QCOWX_HDR_IMAGE_SIZE (QCOWX_HDR_BACKING_FILE_SIZE+4+4)
|
|
|
|
|
|
|
|
#define QCOW1_HDR_CRYPT (QCOWX_HDR_IMAGE_SIZE+8+1+1)
|
|
|
|
#define QCOW2_HDR_CRYPT (QCOWX_HDR_IMAGE_SIZE+8)
|
|
|
|
|
|
|
|
#define QCOW1_HDR_TOTAL_SIZE (QCOW1_HDR_CRYPT+4+8)
|
|
|
|
#define QCOW2_HDR_TOTAL_SIZE (QCOW2_HDR_CRYPT+4+4+8+8+4+4+8)
|
|
|
|
|
|
|
|
#define QCOW2_HDR_EXTENSION_END 0
|
|
|
|
#define QCOW2_HDR_EXTENSION_BACKING_FORMAT 0xE2792ACA
|
|
|
|
|
2013-05-07 15:27:43 +00:00
|
|
|
#define QCOW2v3_HDR_FEATURES_INCOMPATIBLE (QCOW2_HDR_TOTAL_SIZE)
|
|
|
|
#define QCOW2v3_HDR_FEATURES_COMPATIBLE (QCOW2v3_HDR_FEATURES_INCOMPATIBLE+8)
|
|
|
|
#define QCOW2v3_HDR_FEATURES_AUTOCLEAR (QCOW2v3_HDR_FEATURES_COMPATIBLE+8)
|
|
|
|
|
|
|
|
/* The location of the header size [4 bytes] */
|
|
|
|
#define QCOW2v3_HDR_SIZE (QCOW2_HDR_TOTAL_SIZE+8+8+8+4)
|
|
|
|
|
2010-11-19 23:19:24 +00:00
|
|
|
#define QED_HDR_FEATURES_OFFSET (4+4+4+4)
|
2010-11-22 20:08:17 +00:00
|
|
|
#define QED_HDR_IMAGE_SIZE (QED_HDR_FEATURES_OFFSET+8+8+8+8)
|
|
|
|
#define QED_HDR_BACKING_FILE_OFFSET (QED_HDR_IMAGE_SIZE+8)
|
2010-11-19 23:19:24 +00:00
|
|
|
#define QED_HDR_BACKING_FILE_SIZE (QED_HDR_BACKING_FILE_OFFSET+4)
|
|
|
|
#define QED_F_BACKING_FILE 0x01
|
|
|
|
#define QED_F_BACKING_FORMAT_NO_PROBE 0x04
|
2010-11-19 16:18:16 +00:00
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
|
|
|
|
static struct FileTypeInfo const fileTypeInfo[] = {
|
2013-02-04 19:16:22 +00:00
|
|
|
[VIR_STORAGE_FILE_NONE] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
|
2013-05-07 15:27:43 +00:00
|
|
|
-1, {0}, 0, 0, 0, 0, NULL, NULL },
|
2013-02-04 19:16:22 +00:00
|
|
|
[VIR_STORAGE_FILE_RAW] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
|
2013-05-07 15:27:43 +00:00
|
|
|
-1, {0}, 0, 0, 0, 0, NULL, NULL },
|
2013-02-04 19:16:22 +00:00
|
|
|
[VIR_STORAGE_FILE_DIR] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
|
2013-05-07 15:27:43 +00:00
|
|
|
-1, {0}, 0, 0, 0, 0, NULL, NULL },
|
2010-06-14 15:39:32 +00:00
|
|
|
[VIR_STORAGE_FILE_BOCHS] = {
|
2013-02-04 19:16:22 +00:00
|
|
|
/*"Bochs Virtual HD Image", */ /* Untested */
|
|
|
|
0, NULL, NULL,
|
2013-05-07 15:27:43 +00:00
|
|
|
LV_LITTLE_ENDIAN, 64, {0x20000},
|
|
|
|
32+16+16+4+4+4+4+4, 8, 1, -1, NULL, NULL
|
2010-06-14 15:39:32 +00:00
|
|
|
},
|
|
|
|
[VIR_STORAGE_FILE_CLOOP] = {
|
2013-02-04 19:16:22 +00:00
|
|
|
/* #!/bin/sh
|
|
|
|
#V2.0 Format
|
|
|
|
modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1
|
|
|
|
*/ /* Untested */
|
|
|
|
0, NULL, NULL,
|
2013-05-07 15:27:43 +00:00
|
|
|
LV_LITTLE_ENDIAN, -1, {0},
|
|
|
|
-1, 0, 0, -1, NULL, NULL
|
2010-06-14 15:39:32 +00:00
|
|
|
},
|
|
|
|
[VIR_STORAGE_FILE_COW] = {
|
2013-02-04 19:16:22 +00:00
|
|
|
0, "OOOM", NULL,
|
2013-05-07 15:27:43 +00:00
|
|
|
LV_BIG_ENDIAN, 4, {2},
|
|
|
|
4+4+1024+4, 8, 1, -1, cowGetBackingStore, NULL
|
2010-06-14 15:39:32 +00:00
|
|
|
},
|
|
|
|
[VIR_STORAGE_FILE_DMG] = {
|
2013-02-04 19:16:22 +00:00
|
|
|
/* XXX QEMU says there's no magic for dmg,
|
|
|
|
* /usr/share/misc/magic lists double magic (both offsets
|
|
|
|
* would have to match) but then disables that check. */
|
|
|
|
0, NULL, ".dmg",
|
2013-05-07 15:27:43 +00:00
|
|
|
0, -1, {0},
|
|
|
|
-1, 0, 0, -1, NULL, NULL
|
2010-06-14 15:39:32 +00:00
|
|
|
},
|
|
|
|
[VIR_STORAGE_FILE_ISO] = {
|
2013-02-04 19:16:22 +00:00
|
|
|
32769, "CD001", ".iso",
|
2013-05-07 15:27:43 +00:00
|
|
|
LV_LITTLE_ENDIAN, -2, {0},
|
|
|
|
-1, 0, 0, -1, NULL, NULL
|
2010-06-14 15:39:32 +00:00
|
|
|
},
|
|
|
|
[VIR_STORAGE_FILE_QCOW] = {
|
2013-02-04 19:16:22 +00:00
|
|
|
0, "QFI", NULL,
|
2013-05-07 15:27:43 +00:00
|
|
|
LV_BIG_ENDIAN, 4, {1},
|
|
|
|
QCOWX_HDR_IMAGE_SIZE, 8, 1, QCOW1_HDR_CRYPT, qcow1GetBackingStore, NULL
|
2010-06-14 15:39:32 +00:00
|
|
|
},
|
|
|
|
[VIR_STORAGE_FILE_QCOW2] = {
|
2013-02-04 19:16:22 +00:00
|
|
|
0, "QFI", NULL,
|
2013-05-07 15:27:43 +00:00
|
|
|
LV_BIG_ENDIAN, 4, {2, 3},
|
2010-06-14 15:39:32 +00:00
|
|
|
QCOWX_HDR_IMAGE_SIZE, 8, 1, QCOW2_HDR_CRYPT, qcow2GetBackingStore,
|
2013-05-07 15:27:43 +00:00
|
|
|
qcow2GetFeatures
|
2010-06-14 15:39:32 +00:00
|
|
|
},
|
2010-11-19 16:18:16 +00:00
|
|
|
[VIR_STORAGE_FILE_QED] = {
|
|
|
|
/* http://wiki.qemu.org/Features/QED */
|
2013-02-04 19:16:22 +00:00
|
|
|
0, "QED", NULL,
|
2013-05-07 15:27:43 +00:00
|
|
|
LV_LITTLE_ENDIAN, -2, {0},
|
|
|
|
QED_HDR_IMAGE_SIZE, 8, 1, -1, qedGetBackingStore, NULL
|
2010-11-19 16:18:16 +00:00
|
|
|
},
|
2010-06-14 15:39:32 +00:00
|
|
|
[VIR_STORAGE_FILE_VMDK] = {
|
2013-02-04 19:16:22 +00:00
|
|
|
0, "KDMV", NULL,
|
2013-07-09 13:16:34 +00:00
|
|
|
LV_LITTLE_ENDIAN, 4, {1, 2},
|
2013-05-07 15:27:43 +00:00
|
|
|
4+4+4, 8, 512, -1, vmdk4GetBackingStore, NULL
|
2010-06-14 15:39:32 +00:00
|
|
|
},
|
|
|
|
[VIR_STORAGE_FILE_VPC] = {
|
2013-02-04 19:16:22 +00:00
|
|
|
0, "conectix", NULL,
|
2013-05-07 15:27:43 +00:00
|
|
|
LV_BIG_ENDIAN, 12, {0x10000},
|
|
|
|
8 + 4 + 4 + 8 + 4 + 4 + 2 + 2 + 4, 8, 1, -1, NULL, NULL
|
2010-06-14 15:39:32 +00:00
|
|
|
},
|
2013-02-04 19:18:22 +00:00
|
|
|
/* TODO: add getBackingStore function */
|
|
|
|
[VIR_STORAGE_FILE_VDI] = {
|
|
|
|
64, "\x7f\x10\xda\xbe", ".vdi",
|
2013-05-07 15:27:43 +00:00
|
|
|
LV_LITTLE_ENDIAN, 68, {0x00010001},
|
|
|
|
64 + 5 * 4 + 256 + 7 * 4, 8, 1, -1, NULL, NULL},
|
2013-02-04 19:18:22 +00:00
|
|
|
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
/* Not direct file formats, but used for various drivers */
|
2013-02-04 19:16:22 +00:00
|
|
|
[VIR_STORAGE_FILE_FAT] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
|
2013-05-07 15:27:43 +00:00
|
|
|
-1, {0}, 0, 0, 0, 0, NULL, NULL },
|
2013-02-04 19:16:22 +00:00
|
|
|
[VIR_STORAGE_FILE_VHD] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
|
2013-05-07 15:27:43 +00:00
|
|
|
-1, {0}, 0, 0, 0, 0, NULL, NULL },
|
2009-09-29 08:34:48 +00:00
|
|
|
};
|
2010-06-14 15:39:32 +00:00
|
|
|
verify(ARRAY_CARDINALITY(fileTypeInfo) == VIR_STORAGE_FILE_LAST);
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2013-05-07 15:27:43 +00:00
|
|
|
/* qcow2 compatible features in the order they appear on-disk */
|
|
|
|
enum qcow2CompatibleFeature {
|
|
|
|
QCOW2_COMPATIBLE_FEATURE_LAZY_REFCOUNTS = 0,
|
|
|
|
|
|
|
|
QCOW2_COMPATIBLE_FEATURE_LAST
|
|
|
|
};
|
|
|
|
|
|
|
|
/* conversion to virStorageFileFeature */
|
|
|
|
static const int qcow2CompatibleFeatureArray[] = {
|
|
|
|
VIR_STORAGE_FILE_FEATURE_LAZY_REFCOUNTS,
|
|
|
|
};
|
|
|
|
verify(ARRAY_CARDINALITY(qcow2CompatibleFeatureArray) ==
|
|
|
|
QCOW2_COMPATIBLE_FEATURE_LAST);
|
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
static int
|
2010-02-04 22:46:55 +00:00
|
|
|
cowGetBackingStore(char **res,
|
2010-06-14 14:53:59 +00:00
|
|
|
int *format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *buf,
|
2009-09-29 08:34:48 +00:00
|
|
|
size_t buf_size)
|
|
|
|
{
|
|
|
|
#define COW_FILENAME_MAXLEN 1024
|
|
|
|
*res = NULL;
|
2010-06-14 14:53:59 +00:00
|
|
|
*format = VIR_STORAGE_FILE_AUTO;
|
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
if (buf_size < 4+4+ COW_FILENAME_MAXLEN)
|
|
|
|
return BACKING_STORE_INVALID;
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
if (buf[4+4] == '\0') { /* cow_header_v2.backing_file[0] */
|
|
|
|
*format = VIR_STORAGE_FILE_NONE;
|
2009-09-29 08:34:48 +00:00
|
|
|
return BACKING_STORE_OK;
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2013-05-24 07:19:51 +00:00
|
|
|
if (VIR_STRNDUP(*res, (const char*)buf + 4 + 4, COW_FILENAME_MAXLEN) < 0)
|
2009-09-29 08:34:48 +00:00
|
|
|
return BACKING_STORE_ERROR;
|
|
|
|
return BACKING_STORE_OK;
|
|
|
|
}
|
|
|
|
|
2010-06-14 14:53:59 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
qcow2GetBackingStoreFormat(int *format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *buf,
|
2010-06-14 14:53:59 +00:00
|
|
|
size_t buf_size,
|
|
|
|
size_t extension_start,
|
|
|
|
size_t extension_end)
|
|
|
|
{
|
|
|
|
size_t offset = extension_start;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The extensions take format of
|
|
|
|
*
|
|
|
|
* int32: magic
|
|
|
|
* int32: length
|
|
|
|
* byte[length]: payload
|
|
|
|
*
|
|
|
|
* Unknown extensions can be ignored by skipping
|
|
|
|
* over "length" bytes in the data stream.
|
|
|
|
*/
|
|
|
|
while (offset < (buf_size-8) &&
|
|
|
|
offset < (extension_end-8)) {
|
2013-02-07 01:57:13 +00:00
|
|
|
unsigned int magic = virReadBufInt32BE(buf + offset);
|
|
|
|
unsigned int len = virReadBufInt32BE(buf + offset + 4);
|
2010-06-14 14:53:59 +00:00
|
|
|
|
|
|
|
offset += 8;
|
|
|
|
|
|
|
|
if ((offset + len) < offset)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if ((offset + len) > buf_size)
|
|
|
|
break;
|
|
|
|
|
|
|
|
switch (magic) {
|
|
|
|
case QCOW2_HDR_EXTENSION_END:
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
case QCOW2_HDR_EXTENSION_BACKING_FORMAT:
|
|
|
|
if (buf[offset+len] != '\0')
|
|
|
|
break;
|
|
|
|
*format = virStorageFileFormatTypeFromString(
|
|
|
|
((const char *)buf)+offset);
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
if (*format <= VIR_STORAGE_FILE_NONE)
|
|
|
|
return -1;
|
2010-06-14 14:53:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
offset += len;
|
|
|
|
}
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
done:
|
2010-06-14 14:53:59 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
static int
|
2010-02-04 22:46:55 +00:00
|
|
|
qcowXGetBackingStore(char **res,
|
2010-06-14 14:53:59 +00:00
|
|
|
int *format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *buf,
|
2010-06-14 14:53:59 +00:00
|
|
|
size_t buf_size,
|
|
|
|
bool isQCow2)
|
2009-09-29 08:34:48 +00:00
|
|
|
{
|
|
|
|
unsigned long long offset;
|
2011-06-02 23:52:16 +00:00
|
|
|
unsigned int size;
|
2013-05-07 15:27:43 +00:00
|
|
|
unsigned long long start;
|
|
|
|
int version;
|
2009-09-29 08:34:48 +00:00
|
|
|
|
|
|
|
*res = NULL;
|
2010-06-14 14:53:59 +00:00
|
|
|
if (format)
|
|
|
|
*format = VIR_STORAGE_FILE_AUTO;
|
|
|
|
|
|
|
|
if (buf_size < QCOWX_HDR_BACKING_FILE_OFFSET+8+4)
|
2009-09-29 08:34:48 +00:00
|
|
|
return BACKING_STORE_INVALID;
|
2013-02-07 01:57:13 +00:00
|
|
|
offset = virReadBufInt64BE(buf + QCOWX_HDR_BACKING_FILE_OFFSET);
|
2009-09-29 08:34:48 +00:00
|
|
|
if (offset > buf_size)
|
|
|
|
return BACKING_STORE_INVALID;
|
2013-02-07 01:57:13 +00:00
|
|
|
size = virReadBufInt32BE(buf + QCOWX_HDR_BACKING_FILE_SIZE);
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
if (size == 0) {
|
|
|
|
if (format)
|
|
|
|
*format = VIR_STORAGE_FILE_NONE;
|
2009-09-29 08:34:48 +00:00
|
|
|
return BACKING_STORE_OK;
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
if (offset + size > buf_size || offset + size < offset)
|
|
|
|
return BACKING_STORE_INVALID;
|
|
|
|
if (size + 1 == 0)
|
|
|
|
return BACKING_STORE_INVALID;
|
2013-07-04 10:17:18 +00:00
|
|
|
if (VIR_ALLOC_N(*res, size + 1) < 0)
|
2009-09-29 08:34:48 +00:00
|
|
|
return BACKING_STORE_ERROR;
|
|
|
|
memcpy(*res, buf + offset, size);
|
|
|
|
(*res)[size] = '\0';
|
2010-06-14 14:53:59 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Traditionally QCow2 files had a layout of
|
|
|
|
*
|
|
|
|
* [header]
|
|
|
|
* [backingStoreName]
|
|
|
|
*
|
|
|
|
* Although the backingStoreName typically followed
|
|
|
|
* the header immediately, this was not required by
|
|
|
|
* the format. By specifying a higher byte offset for
|
|
|
|
* the backing file offset in the header, it was
|
|
|
|
* possible to leave space between the header and
|
|
|
|
* start of backingStore.
|
|
|
|
*
|
|
|
|
* This hack is now used to store extensions to the
|
|
|
|
* qcow2 format:
|
|
|
|
*
|
|
|
|
* [header]
|
|
|
|
* [extensions]
|
|
|
|
* [backingStoreName]
|
|
|
|
*
|
|
|
|
* Thus the file region to search for extensions is
|
|
|
|
* between the end of the header (QCOW2_HDR_TOTAL_SIZE)
|
|
|
|
* and the start of the backingStoreName (offset)
|
2013-05-07 15:27:43 +00:00
|
|
|
*
|
|
|
|
* for qcow2 v3 images, the length of the header
|
|
|
|
* is stored at QCOW2v3_HDR_SIZE
|
2010-06-14 14:53:59 +00:00
|
|
|
*/
|
2013-05-07 15:27:43 +00:00
|
|
|
if (isQCow2 && format) {
|
|
|
|
version = virReadBufInt32BE(buf + QCOWX_HDR_VERSION);
|
|
|
|
if (version == 2)
|
|
|
|
start = QCOW2_HDR_TOTAL_SIZE;
|
|
|
|
else
|
|
|
|
start = virReadBufInt32BE(buf + QCOW2v3_HDR_SIZE);
|
|
|
|
if (qcow2GetBackingStoreFormat(format, buf, buf_size,
|
|
|
|
start, offset) < 0)
|
|
|
|
return BACKING_STORE_INVALID;
|
|
|
|
}
|
2010-06-14 14:53:59 +00:00
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
return BACKING_STORE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-14 14:53:59 +00:00
|
|
|
static int
|
|
|
|
qcow1GetBackingStore(char **res,
|
|
|
|
int *format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *buf,
|
2010-06-14 14:53:59 +00:00
|
|
|
size_t buf_size)
|
|
|
|
{
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
int ret;
|
|
|
|
|
2010-06-14 14:53:59 +00:00
|
|
|
/* QCow1 doesn't have the extensions capability
|
|
|
|
* used to store backing format */
|
|
|
|
*format = VIR_STORAGE_FILE_AUTO;
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
ret = qcowXGetBackingStore(res, NULL, buf, buf_size, false);
|
|
|
|
if (ret == 0 && *buf == '\0')
|
|
|
|
*format = VIR_STORAGE_FILE_NONE;
|
|
|
|
return ret;
|
2010-06-14 14:53:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
qcow2GetBackingStore(char **res,
|
|
|
|
int *format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *buf,
|
2010-06-14 14:53:59 +00:00
|
|
|
size_t buf_size)
|
|
|
|
{
|
|
|
|
return qcowXGetBackingStore(res, format, buf, buf_size, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
static int
|
2010-02-04 22:46:55 +00:00
|
|
|
vmdk4GetBackingStore(char **res,
|
2010-06-14 14:53:59 +00:00
|
|
|
int *format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *buf,
|
2009-09-29 08:34:48 +00:00
|
|
|
size_t buf_size)
|
|
|
|
{
|
|
|
|
static const char prefix[] = "parentFileNameHint=\"";
|
2010-06-15 13:58:10 +00:00
|
|
|
char *desc, *start, *end;
|
2009-09-29 08:34:48 +00:00
|
|
|
size_t len;
|
2010-06-15 13:58:10 +00:00
|
|
|
int ret = BACKING_STORE_ERROR;
|
|
|
|
|
2013-11-05 21:12:02 +00:00
|
|
|
if (VIR_ALLOC_N(desc, VIR_STORAGE_MAX_HEADER) < 0)
|
2010-06-15 13:58:10 +00:00
|
|
|
goto cleanup;
|
2009-09-29 08:34:48 +00:00
|
|
|
|
|
|
|
*res = NULL;
|
2010-06-14 14:53:59 +00:00
|
|
|
/*
|
|
|
|
* Technically this should have been VMDK, since
|
|
|
|
* VMDK spec / VMWare impl only support VMDK backed
|
|
|
|
* by VMDK. QEMU isn't following this though and
|
|
|
|
* does probing on VMDK backing files, hence we set
|
|
|
|
* AUTO
|
|
|
|
*/
|
|
|
|
*format = VIR_STORAGE_FILE_AUTO;
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2010-06-15 13:58:10 +00:00
|
|
|
if (buf_size <= 0x200) {
|
|
|
|
ret = BACKING_STORE_INVALID;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
len = buf_size - 0x200;
|
2013-11-05 21:12:02 +00:00
|
|
|
if (len > VIR_STORAGE_MAX_HEADER)
|
|
|
|
len = VIR_STORAGE_MAX_HEADER;
|
2009-09-29 08:34:48 +00:00
|
|
|
memcpy(desc, buf + 0x200, len);
|
|
|
|
desc[len] = '\0';
|
|
|
|
start = strstr(desc, prefix);
|
2010-06-15 13:58:10 +00:00
|
|
|
if (start == NULL) {
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
*format = VIR_STORAGE_FILE_NONE;
|
2010-06-15 13:58:10 +00:00
|
|
|
ret = BACKING_STORE_OK;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
start += strlen(prefix);
|
|
|
|
end = strchr(start, '"');
|
2010-06-15 13:58:10 +00:00
|
|
|
if (end == NULL) {
|
|
|
|
ret = BACKING_STORE_INVALID;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (end == start) {
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
*format = VIR_STORAGE_FILE_NONE;
|
2010-06-15 13:58:10 +00:00
|
|
|
ret = BACKING_STORE_OK;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
*end = '\0';
|
2013-05-24 07:19:51 +00:00
|
|
|
if (VIR_STRDUP(*res, start) < 0)
|
2010-06-15 13:58:10 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = BACKING_STORE_OK;
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2010-06-15 13:58:10 +00:00
|
|
|
VIR_FREE(desc);
|
|
|
|
return ret;
|
2009-09-29 08:34:48 +00:00
|
|
|
}
|
|
|
|
|
2010-11-19 23:19:24 +00:00
|
|
|
static int
|
|
|
|
qedGetBackingStore(char **res,
|
|
|
|
int *format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *buf,
|
2010-11-19 23:19:24 +00:00
|
|
|
size_t buf_size)
|
|
|
|
{
|
|
|
|
unsigned long long flags;
|
|
|
|
unsigned long offset, size;
|
|
|
|
|
|
|
|
*res = NULL;
|
|
|
|
/* Check if this image has a backing file */
|
|
|
|
if (buf_size < QED_HDR_FEATURES_OFFSET+8)
|
|
|
|
return BACKING_STORE_INVALID;
|
2013-02-07 01:57:13 +00:00
|
|
|
flags = virReadBufInt64LE(buf + QED_HDR_FEATURES_OFFSET);
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
if (!(flags & QED_F_BACKING_FILE)) {
|
|
|
|
*format = VIR_STORAGE_FILE_NONE;
|
2010-11-19 23:19:24 +00:00
|
|
|
return BACKING_STORE_OK;
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
}
|
2010-11-19 23:19:24 +00:00
|
|
|
|
|
|
|
/* Parse the backing file */
|
|
|
|
if (buf_size < QED_HDR_BACKING_FILE_OFFSET+8)
|
|
|
|
return BACKING_STORE_INVALID;
|
2013-02-07 01:57:13 +00:00
|
|
|
offset = virReadBufInt32LE(buf + QED_HDR_BACKING_FILE_OFFSET);
|
2010-11-19 23:19:24 +00:00
|
|
|
if (offset > buf_size)
|
|
|
|
return BACKING_STORE_INVALID;
|
2013-02-07 01:57:13 +00:00
|
|
|
size = virReadBufInt32LE(buf + QED_HDR_BACKING_FILE_SIZE);
|
2010-11-19 23:19:24 +00:00
|
|
|
if (size == 0)
|
|
|
|
return BACKING_STORE_OK;
|
|
|
|
if (offset + size > buf_size || offset + size < offset)
|
|
|
|
return BACKING_STORE_INVALID;
|
2013-07-04 10:17:18 +00:00
|
|
|
if (VIR_ALLOC_N(*res, size + 1) < 0)
|
2010-11-19 23:19:24 +00:00
|
|
|
return BACKING_STORE_ERROR;
|
|
|
|
memcpy(*res, buf + offset, size);
|
|
|
|
(*res)[size] = '\0';
|
|
|
|
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
if (flags & QED_F_BACKING_FORMAT_NO_PROBE)
|
|
|
|
*format = VIR_STORAGE_FILE_RAW;
|
|
|
|
else
|
|
|
|
*format = VIR_STORAGE_FILE_AUTO_SAFE;
|
2010-11-19 23:19:24 +00:00
|
|
|
|
|
|
|
return BACKING_STORE_OK;
|
|
|
|
}
|
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
/**
|
2014-04-08 20:26:02 +00:00
|
|
|
* Given a starting point START (a directory containing the original
|
|
|
|
* file, if the original file was opened via a relative path; ignored
|
|
|
|
* if NAME is absolute), determine the location of the backing file
|
|
|
|
* NAME (possibly relative), and compute the relative DIRECTORY
|
|
|
|
* (optional) and CANONICAL (mandatory) location of the backing file.
|
|
|
|
* Return 0 on success, negative on error.
|
2009-09-29 08:34:48 +00:00
|
|
|
*/
|
2014-04-08 20:26:02 +00:00
|
|
|
static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4)
|
|
|
|
virFindBackingFile(const char *start, const char *path,
|
storage: don't follow backing chain symlinks too eagerly
If you have a qcow2 file /path1/to/file pointed to by symlink
/path2/symlink, and pass qemu /path2/symlink, then qemu treats
a relative backing file in the qcow2 metadata as being relative
to /path2, not /path1/to. Yes, this means that it is possible
to create a qcow2 file where the choice of WHICH directory and
symlink you access its contents from will then determine WHICH
backing file (if any) you actually find; the results can be
rather screwy, but we have to match what qemu does.
Libvirt and qemu default to creating absolute backing file
names, so most users don't hit this. But at least VDSM uses
symlinks and relative backing names alongside the
--reuse-external flags to libvirt snapshot operations, with the
result that libvirt was failing to follow the intended chain of
backing files, and then backing files were not granted the
necessary sVirt permissions to be opened by qemu.
See https://bugzilla.redhat.com/show_bug.cgi?id=903248 for
more gory details. This fixes a regression introduced in
commit 8250783.
I tested this patch by creating the following chain:
ls /home/eblake/Downloads/Fedora.iso # raw file for base
cd /var/lib/libvirt/images
qemu-img create -f qcow2 \
-obacking_file=/home/eblake/Downloads/Fedora.iso,backing_fmt=raw one
mkdir sub
cd sub
ln -s ../one onelink
qemu-img create -f qcow2 \
-obacking_file=../sub/onelink,backing_fmt=qcow2 two
mv two ..
ln -s ../two twolink
qemu-img create -f qcow2 \
-obacking_file=../sub/twolink,backing_fmt=qcow2 three
mv three ..
ln -s ../three threelink
then pointing my domain at /var/lib/libvirt/images/sub/threelink.
Prior to this patch, I got complaints about missing backing
files; afterwards, I was able to verify that the backing chain
(and hence DAC and SELinux relabels) of the entire chain worked.
* src/util/virstoragefile.h (_virStorageFileMetadata): Add
directory member.
* src/util/virstoragefile.c (absolutePathFromBaseFile): Drop,
replaced by...
(virFindBackingFile): ...better function.
(virStorageFileGetMetadataInternal): Add an argument.
(virStorageFileGetMetadataFromFD, virStorageFileChainLookup)
(virStorageFileGetMetadata): Update callers.
2013-02-06 22:48:15 +00:00
|
|
|
char **directory, char **canonical)
|
2009-09-29 08:34:48 +00:00
|
|
|
{
|
storage: don't follow backing chain symlinks too eagerly
If you have a qcow2 file /path1/to/file pointed to by symlink
/path2/symlink, and pass qemu /path2/symlink, then qemu treats
a relative backing file in the qcow2 metadata as being relative
to /path2, not /path1/to. Yes, this means that it is possible
to create a qcow2 file where the choice of WHICH directory and
symlink you access its contents from will then determine WHICH
backing file (if any) you actually find; the results can be
rather screwy, but we have to match what qemu does.
Libvirt and qemu default to creating absolute backing file
names, so most users don't hit this. But at least VDSM uses
symlinks and relative backing names alongside the
--reuse-external flags to libvirt snapshot operations, with the
result that libvirt was failing to follow the intended chain of
backing files, and then backing files were not granted the
necessary sVirt permissions to be opened by qemu.
See https://bugzilla.redhat.com/show_bug.cgi?id=903248 for
more gory details. This fixes a regression introduced in
commit 8250783.
I tested this patch by creating the following chain:
ls /home/eblake/Downloads/Fedora.iso # raw file for base
cd /var/lib/libvirt/images
qemu-img create -f qcow2 \
-obacking_file=/home/eblake/Downloads/Fedora.iso,backing_fmt=raw one
mkdir sub
cd sub
ln -s ../one onelink
qemu-img create -f qcow2 \
-obacking_file=../sub/onelink,backing_fmt=qcow2 two
mv two ..
ln -s ../two twolink
qemu-img create -f qcow2 \
-obacking_file=../sub/twolink,backing_fmt=qcow2 three
mv three ..
ln -s ../three threelink
then pointing my domain at /var/lib/libvirt/images/sub/threelink.
Prior to this patch, I got complaints about missing backing
files; afterwards, I was able to verify that the backing chain
(and hence DAC and SELinux relabels) of the entire chain worked.
* src/util/virstoragefile.h (_virStorageFileMetadata): Add
directory member.
* src/util/virstoragefile.c (absolutePathFromBaseFile): Drop,
replaced by...
(virFindBackingFile): ...better function.
(virStorageFileGetMetadataInternal): Add an argument.
(virStorageFileGetMetadataFromFD, virStorageFileChainLookup)
(virStorageFileGetMetadata): Update callers.
2013-02-06 22:48:15 +00:00
|
|
|
char *combined = NULL;
|
|
|
|
int ret = -1;
|
2009-09-29 08:34:48 +00:00
|
|
|
|
storage: don't follow backing chain symlinks too eagerly
If you have a qcow2 file /path1/to/file pointed to by symlink
/path2/symlink, and pass qemu /path2/symlink, then qemu treats
a relative backing file in the qcow2 metadata as being relative
to /path2, not /path1/to. Yes, this means that it is possible
to create a qcow2 file where the choice of WHICH directory and
symlink you access its contents from will then determine WHICH
backing file (if any) you actually find; the results can be
rather screwy, but we have to match what qemu does.
Libvirt and qemu default to creating absolute backing file
names, so most users don't hit this. But at least VDSM uses
symlinks and relative backing names alongside the
--reuse-external flags to libvirt snapshot operations, with the
result that libvirt was failing to follow the intended chain of
backing files, and then backing files were not granted the
necessary sVirt permissions to be opened by qemu.
See https://bugzilla.redhat.com/show_bug.cgi?id=903248 for
more gory details. This fixes a regression introduced in
commit 8250783.
I tested this patch by creating the following chain:
ls /home/eblake/Downloads/Fedora.iso # raw file for base
cd /var/lib/libvirt/images
qemu-img create -f qcow2 \
-obacking_file=/home/eblake/Downloads/Fedora.iso,backing_fmt=raw one
mkdir sub
cd sub
ln -s ../one onelink
qemu-img create -f qcow2 \
-obacking_file=../sub/onelink,backing_fmt=qcow2 two
mv two ..
ln -s ../two twolink
qemu-img create -f qcow2 \
-obacking_file=../sub/twolink,backing_fmt=qcow2 three
mv three ..
ln -s ../three threelink
then pointing my domain at /var/lib/libvirt/images/sub/threelink.
Prior to this patch, I got complaints about missing backing
files; afterwards, I was able to verify that the backing chain
(and hence DAC and SELinux relabels) of the entire chain worked.
* src/util/virstoragefile.h (_virStorageFileMetadata): Add
directory member.
* src/util/virstoragefile.c (absolutePathFromBaseFile): Drop,
replaced by...
(virFindBackingFile): ...better function.
(virStorageFileGetMetadataInternal): Add an argument.
(virStorageFileGetMetadataFromFD, virStorageFileChainLookup)
(virStorageFileGetMetadata): Update callers.
2013-02-06 22:48:15 +00:00
|
|
|
if (*path == '/') {
|
|
|
|
/* Safe to cast away const */
|
|
|
|
combined = (char *)path;
|
2014-04-08 20:26:02 +00:00
|
|
|
} else if (virAsprintf(&combined, "%s/%s", start, path) < 0) {
|
|
|
|
goto cleanup;
|
2012-10-31 10:17:41 +00:00
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
|
storage: don't follow backing chain symlinks too eagerly
If you have a qcow2 file /path1/to/file pointed to by symlink
/path2/symlink, and pass qemu /path2/symlink, then qemu treats
a relative backing file in the qcow2 metadata as being relative
to /path2, not /path1/to. Yes, this means that it is possible
to create a qcow2 file where the choice of WHICH directory and
symlink you access its contents from will then determine WHICH
backing file (if any) you actually find; the results can be
rather screwy, but we have to match what qemu does.
Libvirt and qemu default to creating absolute backing file
names, so most users don't hit this. But at least VDSM uses
symlinks and relative backing names alongside the
--reuse-external flags to libvirt snapshot operations, with the
result that libvirt was failing to follow the intended chain of
backing files, and then backing files were not granted the
necessary sVirt permissions to be opened by qemu.
See https://bugzilla.redhat.com/show_bug.cgi?id=903248 for
more gory details. This fixes a regression introduced in
commit 8250783.
I tested this patch by creating the following chain:
ls /home/eblake/Downloads/Fedora.iso # raw file for base
cd /var/lib/libvirt/images
qemu-img create -f qcow2 \
-obacking_file=/home/eblake/Downloads/Fedora.iso,backing_fmt=raw one
mkdir sub
cd sub
ln -s ../one onelink
qemu-img create -f qcow2 \
-obacking_file=../sub/onelink,backing_fmt=qcow2 two
mv two ..
ln -s ../two twolink
qemu-img create -f qcow2 \
-obacking_file=../sub/twolink,backing_fmt=qcow2 three
mv three ..
ln -s ../three threelink
then pointing my domain at /var/lib/libvirt/images/sub/threelink.
Prior to this patch, I got complaints about missing backing
files; afterwards, I was able to verify that the backing chain
(and hence DAC and SELinux relabels) of the entire chain worked.
* src/util/virstoragefile.h (_virStorageFileMetadata): Add
directory member.
* src/util/virstoragefile.c (absolutePathFromBaseFile): Drop,
replaced by...
(virFindBackingFile): ...better function.
(virStorageFileGetMetadataInternal): Add an argument.
(virStorageFileGetMetadataFromFD, virStorageFileChainLookup)
(virStorageFileGetMetadata): Update callers.
2013-02-06 22:48:15 +00:00
|
|
|
if (directory && !(*directory = mdir_name(combined))) {
|
|
|
|
virReportOOMError();
|
2012-10-31 10:17:41 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2010-02-05 13:57:35 +00:00
|
|
|
|
2013-10-09 11:13:45 +00:00
|
|
|
if (virFileAccessibleAs(combined, F_OK, geteuid(), getegid()) < 0) {
|
2013-07-29 12:51:15 +00:00
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Cannot access backing file '%s'"),
|
|
|
|
combined);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
storage: don't follow backing chain symlinks too eagerly
If you have a qcow2 file /path1/to/file pointed to by symlink
/path2/symlink, and pass qemu /path2/symlink, then qemu treats
a relative backing file in the qcow2 metadata as being relative
to /path2, not /path1/to. Yes, this means that it is possible
to create a qcow2 file where the choice of WHICH directory and
symlink you access its contents from will then determine WHICH
backing file (if any) you actually find; the results can be
rather screwy, but we have to match what qemu does.
Libvirt and qemu default to creating absolute backing file
names, so most users don't hit this. But at least VDSM uses
symlinks and relative backing names alongside the
--reuse-external flags to libvirt snapshot operations, with the
result that libvirt was failing to follow the intended chain of
backing files, and then backing files were not granted the
necessary sVirt permissions to be opened by qemu.
See https://bugzilla.redhat.com/show_bug.cgi?id=903248 for
more gory details. This fixes a regression introduced in
commit 8250783.
I tested this patch by creating the following chain:
ls /home/eblake/Downloads/Fedora.iso # raw file for base
cd /var/lib/libvirt/images
qemu-img create -f qcow2 \
-obacking_file=/home/eblake/Downloads/Fedora.iso,backing_fmt=raw one
mkdir sub
cd sub
ln -s ../one onelink
qemu-img create -f qcow2 \
-obacking_file=../sub/onelink,backing_fmt=qcow2 two
mv two ..
ln -s ../two twolink
qemu-img create -f qcow2 \
-obacking_file=../sub/twolink,backing_fmt=qcow2 three
mv three ..
ln -s ../three threelink
then pointing my domain at /var/lib/libvirt/images/sub/threelink.
Prior to this patch, I got complaints about missing backing
files; afterwards, I was able to verify that the backing chain
(and hence DAC and SELinux relabels) of the entire chain worked.
* src/util/virstoragefile.h (_virStorageFileMetadata): Add
directory member.
* src/util/virstoragefile.c (absolutePathFromBaseFile): Drop,
replaced by...
(virFindBackingFile): ...better function.
(virStorageFileGetMetadataInternal): Add an argument.
(virStorageFileGetMetadataFromFD, virStorageFileChainLookup)
(virStorageFileGetMetadata): Update callers.
2013-02-06 22:48:15 +00:00
|
|
|
if (!(*canonical = canonicalize_file_name(combined))) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Can't canonicalize path '%s'"), path);
|
2012-10-31 10:17:41 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
storage: don't follow backing chain symlinks too eagerly
If you have a qcow2 file /path1/to/file pointed to by symlink
/path2/symlink, and pass qemu /path2/symlink, then qemu treats
a relative backing file in the qcow2 metadata as being relative
to /path2, not /path1/to. Yes, this means that it is possible
to create a qcow2 file where the choice of WHICH directory and
symlink you access its contents from will then determine WHICH
backing file (if any) you actually find; the results can be
rather screwy, but we have to match what qemu does.
Libvirt and qemu default to creating absolute backing file
names, so most users don't hit this. But at least VDSM uses
symlinks and relative backing names alongside the
--reuse-external flags to libvirt snapshot operations, with the
result that libvirt was failing to follow the intended chain of
backing files, and then backing files were not granted the
necessary sVirt permissions to be opened by qemu.
See https://bugzilla.redhat.com/show_bug.cgi?id=903248 for
more gory details. This fixes a regression introduced in
commit 8250783.
I tested this patch by creating the following chain:
ls /home/eblake/Downloads/Fedora.iso # raw file for base
cd /var/lib/libvirt/images
qemu-img create -f qcow2 \
-obacking_file=/home/eblake/Downloads/Fedora.iso,backing_fmt=raw one
mkdir sub
cd sub
ln -s ../one onelink
qemu-img create -f qcow2 \
-obacking_file=../sub/onelink,backing_fmt=qcow2 two
mv two ..
ln -s ../two twolink
qemu-img create -f qcow2 \
-obacking_file=../sub/twolink,backing_fmt=qcow2 three
mv three ..
ln -s ../three threelink
then pointing my domain at /var/lib/libvirt/images/sub/threelink.
Prior to this patch, I got complaints about missing backing
files; afterwards, I was able to verify that the backing chain
(and hence DAC and SELinux relabels) of the entire chain worked.
* src/util/virstoragefile.h (_virStorageFileMetadata): Add
directory member.
* src/util/virstoragefile.c (absolutePathFromBaseFile): Drop,
replaced by...
(virFindBackingFile): ...better function.
(virStorageFileGetMetadataInternal): Add an argument.
(virStorageFileGetMetadataFromFD, virStorageFileChainLookup)
(virStorageFileGetMetadata): Update callers.
2013-02-06 22:48:15 +00:00
|
|
|
ret = 0;
|
2012-10-31 10:17:41 +00:00
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
storage: don't follow backing chain symlinks too eagerly
If you have a qcow2 file /path1/to/file pointed to by symlink
/path2/symlink, and pass qemu /path2/symlink, then qemu treats
a relative backing file in the qcow2 metadata as being relative
to /path2, not /path1/to. Yes, this means that it is possible
to create a qcow2 file where the choice of WHICH directory and
symlink you access its contents from will then determine WHICH
backing file (if any) you actually find; the results can be
rather screwy, but we have to match what qemu does.
Libvirt and qemu default to creating absolute backing file
names, so most users don't hit this. But at least VDSM uses
symlinks and relative backing names alongside the
--reuse-external flags to libvirt snapshot operations, with the
result that libvirt was failing to follow the intended chain of
backing files, and then backing files were not granted the
necessary sVirt permissions to be opened by qemu.
See https://bugzilla.redhat.com/show_bug.cgi?id=903248 for
more gory details. This fixes a regression introduced in
commit 8250783.
I tested this patch by creating the following chain:
ls /home/eblake/Downloads/Fedora.iso # raw file for base
cd /var/lib/libvirt/images
qemu-img create -f qcow2 \
-obacking_file=/home/eblake/Downloads/Fedora.iso,backing_fmt=raw one
mkdir sub
cd sub
ln -s ../one onelink
qemu-img create -f qcow2 \
-obacking_file=../sub/onelink,backing_fmt=qcow2 two
mv two ..
ln -s ../two twolink
qemu-img create -f qcow2 \
-obacking_file=../sub/twolink,backing_fmt=qcow2 three
mv three ..
ln -s ../three threelink
then pointing my domain at /var/lib/libvirt/images/sub/threelink.
Prior to this patch, I got complaints about missing backing
files; afterwards, I was able to verify that the backing chain
(and hence DAC and SELinux relabels) of the entire chain worked.
* src/util/virstoragefile.h (_virStorageFileMetadata): Add
directory member.
* src/util/virstoragefile.c (absolutePathFromBaseFile): Drop,
replaced by...
(virFindBackingFile): ...better function.
(virStorageFileGetMetadataInternal): Add an argument.
(virStorageFileGetMetadataFromFD, virStorageFileChainLookup)
(virStorageFileGetMetadata): Update callers.
2013-02-06 22:48:15 +00:00
|
|
|
if (combined != path)
|
|
|
|
VIR_FREE(combined);
|
|
|
|
return ret;
|
2009-09-29 08:34:48 +00:00
|
|
|
}
|
|
|
|
|
2010-06-15 13:58:10 +00:00
|
|
|
|
|
|
|
static bool
|
|
|
|
virStorageFileMatchesMagic(int format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
char *buf,
|
2010-06-15 13:58:10 +00:00
|
|
|
size_t buflen)
|
2009-09-29 08:34:48 +00:00
|
|
|
{
|
2010-06-15 13:58:10 +00:00
|
|
|
int mlen;
|
2013-02-04 19:16:22 +00:00
|
|
|
int magicOffset = fileTypeInfo[format].magicOffset;
|
|
|
|
const char *magic = fileTypeInfo[format].magic;
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2013-02-04 19:16:22 +00:00
|
|
|
if (magic == NULL)
|
2010-06-15 13:58:10 +00:00
|
|
|
return false;
|
2010-05-18 05:53:31 +00:00
|
|
|
|
2010-06-15 13:58:10 +00:00
|
|
|
/* Validate magic data */
|
2013-02-04 19:16:22 +00:00
|
|
|
mlen = strlen(magic);
|
|
|
|
if (magicOffset + mlen > buflen)
|
2010-06-15 13:58:10 +00:00
|
|
|
return false;
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2013-02-04 19:16:22 +00:00
|
|
|
if (memcmp(buf + magicOffset, magic, mlen) != 0)
|
2010-06-15 13:58:10 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
virStorageFileMatchesExtension(int format,
|
|
|
|
const char *path)
|
|
|
|
{
|
|
|
|
if (fileTypeInfo[format].extension == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (virFileHasSuffix(path, fileTypeInfo[format].extension))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
virStorageFileMatchesVersion(int format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
char *buf,
|
2010-06-15 13:58:10 +00:00
|
|
|
size_t buflen)
|
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/util/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
int version;
|
|
|
|
size_t i;
|
2010-06-15 13:58:10 +00:00
|
|
|
|
|
|
|
/* Validate version number info */
|
|
|
|
if (fileTypeInfo[format].versionOffset == -1)
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
return false;
|
2010-06-15 13:58:10 +00:00
|
|
|
|
2012-12-13 14:25:10 +00:00
|
|
|
/* -2 == non-versioned file format, so trivially match */
|
|
|
|
if (fileTypeInfo[format].versionOffset == -2)
|
|
|
|
return true;
|
|
|
|
|
2010-06-15 13:58:10 +00:00
|
|
|
if ((fileTypeInfo[format].versionOffset + 4) > buflen)
|
|
|
|
return false;
|
|
|
|
|
2013-02-07 01:57:13 +00:00
|
|
|
if (fileTypeInfo[format].endian == LV_LITTLE_ENDIAN)
|
|
|
|
version = virReadBufInt32LE(buf + fileTypeInfo[format].versionOffset);
|
|
|
|
else
|
|
|
|
version = virReadBufInt32BE(buf + fileTypeInfo[format].versionOffset);
|
2012-12-13 14:23:50 +00:00
|
|
|
|
2013-05-07 15:27:43 +00:00
|
|
|
for (i = 0;
|
|
|
|
i < FILE_TYPE_VERSIONS_LAST && fileTypeInfo[format].versionNumbers[i];
|
|
|
|
i++) {
|
|
|
|
VIR_DEBUG("Compare detected version %d vs one of the expected versions %d",
|
|
|
|
version, fileTypeInfo[format].versionNumbers[i]);
|
|
|
|
if (version == fileTypeInfo[format].versionNumbers[i])
|
|
|
|
return true;
|
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2013-05-07 15:27:43 +00:00
|
|
|
return false;
|
2010-06-15 13:58:10 +00:00
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2010-11-03 15:50:11 +00:00
|
|
|
static bool
|
|
|
|
virBackingStoreIsFile(const char *backing)
|
|
|
|
{
|
2013-11-04 21:27:42 +00:00
|
|
|
char *colon = strchr(backing, ':');
|
|
|
|
char *slash = strchr(backing, '/');
|
|
|
|
|
|
|
|
/* Reject anything that looks like a protocol (such as nbd: or
|
|
|
|
* rbd:); if someone really does want a relative file name that
|
|
|
|
* includes ':', they can always prefix './'. */
|
|
|
|
if (colon && (!slash || colon < slash))
|
2010-11-03 15:50:11 +00:00
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2013-11-05 21:12:02 +00:00
|
|
|
int
|
2013-02-06 23:54:08 +00:00
|
|
|
virStorageFileProbeFormatFromBuf(const char *path,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
char *buf,
|
2013-02-06 23:54:08 +00:00
|
|
|
size_t buflen)
|
|
|
|
{
|
|
|
|
int format = VIR_STORAGE_FILE_RAW;
|
Convert 'int i' to 'size_t i' in src/util/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2013-02-06 23:54:08 +00:00
|
|
|
int possibleFormat = VIR_STORAGE_FILE_RAW;
|
2013-11-05 21:12:02 +00:00
|
|
|
VIR_DEBUG("path=%s, buf=%p, buflen=%zu", path, buf, buflen);
|
2013-02-06 23:54:08 +00:00
|
|
|
|
|
|
|
/* First check file magic */
|
2013-05-21 07:58:16 +00:00
|
|
|
for (i = 0; i < VIR_STORAGE_FILE_LAST; i++) {
|
2013-02-06 23:54:08 +00:00
|
|
|
if (virStorageFileMatchesMagic(i, buf, buflen)) {
|
|
|
|
if (!virStorageFileMatchesVersion(i, buf, buflen)) {
|
|
|
|
possibleFormat = i;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
format = i;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (possibleFormat != VIR_STORAGE_FILE_RAW)
|
|
|
|
VIR_WARN("File %s matches %s magic, but version is wrong. "
|
|
|
|
"Please report new version to libvir-list@redhat.com",
|
|
|
|
path, virStorageFileFormatTypeToString(possibleFormat));
|
|
|
|
|
|
|
|
/* No magic, so check file extension */
|
2013-05-21 07:58:16 +00:00
|
|
|
for (i = 0; i < VIR_STORAGE_FILE_LAST; i++) {
|
2013-02-06 23:54:08 +00:00
|
|
|
if (virStorageFileMatchesExtension(i, path)) {
|
|
|
|
format = i;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2013-02-06 23:54:08 +00:00
|
|
|
VIR_DEBUG("format=%d", format);
|
|
|
|
return format;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-05-07 15:27:43 +00:00
|
|
|
static int
|
|
|
|
qcow2GetFeatures(virBitmapPtr *features,
|
|
|
|
int format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
char *buf,
|
2013-05-07 15:27:43 +00:00
|
|
|
ssize_t len)
|
|
|
|
{
|
|
|
|
int version = -1;
|
|
|
|
virBitmapPtr feat = NULL;
|
|
|
|
uint64_t bits;
|
Convert 'int i' to 'size_t i' in src/util/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2013-05-07 15:27:43 +00:00
|
|
|
|
|
|
|
version = virReadBufInt32BE(buf + fileTypeInfo[format].versionOffset);
|
|
|
|
|
|
|
|
if (version == 2)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (len < QCOW2v3_HDR_SIZE)
|
|
|
|
return -1;
|
|
|
|
|
2013-07-04 10:17:18 +00:00
|
|
|
if (!(feat = virBitmapNew(VIR_STORAGE_FILE_FEATURE_LAST)))
|
2013-05-07 15:27:43 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* todo: check for incompatible or autoclear features? */
|
|
|
|
bits = virReadBufInt64BE(buf + QCOW2v3_HDR_FEATURES_COMPATIBLE);
|
|
|
|
for (i = 0; i < QCOW2_COMPATIBLE_FEATURE_LAST; i++) {
|
|
|
|
if (bits & ((uint64_t) 1 << i))
|
|
|
|
ignore_value(virBitmapSetBit(feat, qcow2CompatibleFeatureArray[i]));
|
|
|
|
}
|
|
|
|
|
|
|
|
*features = feat;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-08 20:26:02 +00:00
|
|
|
/* Given a header in BUF with length LEN, as parsed from the file with
|
|
|
|
* user-provided name PATH and opened from CANONPATH, and where any
|
2014-04-08 21:20:36 +00:00
|
|
|
* relative backing file will be opened from DIRECTORY, and assuming
|
|
|
|
* it has the given FORMAT, populate the newly-allocated META with
|
|
|
|
* information about the file and its backing store. */
|
|
|
|
static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
|
|
|
|
ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(7)
|
2013-02-06 23:33:45 +00:00
|
|
|
virStorageFileGetMetadataInternal(const char *path,
|
2014-04-08 20:26:02 +00:00
|
|
|
const char *canonPath,
|
|
|
|
const char *directory,
|
2013-11-05 20:50:29 +00:00
|
|
|
char *buf,
|
|
|
|
size_t len,
|
2014-04-08 21:20:36 +00:00
|
|
|
int format,
|
|
|
|
virStorageFileMetadataPtr meta)
|
2010-06-15 13:58:10 +00:00
|
|
|
{
|
2014-04-08 21:20:36 +00:00
|
|
|
int ret = -1;
|
2013-02-06 23:33:45 +00:00
|
|
|
|
2014-04-08 20:26:02 +00:00
|
|
|
VIR_DEBUG("path=%s, canonPath=%s, dir=%s, buf=%p, len=%zu, format=%d",
|
|
|
|
path, canonPath, directory, buf, len, format);
|
2013-02-09 13:41:01 +00:00
|
|
|
|
2013-02-06 23:33:45 +00:00
|
|
|
if (format == VIR_STORAGE_FILE_AUTO)
|
|
|
|
format = virStorageFileProbeFormatFromBuf(path, buf, len);
|
|
|
|
|
|
|
|
if (format <= VIR_STORAGE_FILE_NONE ||
|
|
|
|
format >= VIR_STORAGE_FILE_LAST) {
|
|
|
|
virReportSystemError(EINVAL, _("unknown storage file format %d"),
|
|
|
|
format);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2012-12-13 14:23:50 +00:00
|
|
|
|
2010-06-15 13:58:10 +00:00
|
|
|
/* XXX we should consider moving virStorageBackendUpdateVolInfo
|
|
|
|
* code into this method, for non-magic files
|
|
|
|
*/
|
2013-02-06 23:33:45 +00:00
|
|
|
if (!fileTypeInfo[format].magic)
|
2013-02-09 13:41:01 +00:00
|
|
|
goto done;
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2010-06-15 13:58:10 +00:00
|
|
|
/* Optionally extract capacity from file */
|
|
|
|
if (fileTypeInfo[format].sizeOffset != -1) {
|
2013-02-09 13:41:01 +00:00
|
|
|
if ((fileTypeInfo[format].sizeOffset + 8) > len)
|
|
|
|
goto done;
|
2010-06-15 13:58:10 +00:00
|
|
|
|
2013-02-07 01:57:13 +00:00
|
|
|
if (fileTypeInfo[format].endian == LV_LITTLE_ENDIAN)
|
|
|
|
meta->capacity = virReadBufInt64LE(buf +
|
|
|
|
fileTypeInfo[format].sizeOffset);
|
|
|
|
else
|
|
|
|
meta->capacity = virReadBufInt64BE(buf +
|
|
|
|
fileTypeInfo[format].sizeOffset);
|
2010-06-15 13:58:10 +00:00
|
|
|
/* Avoid unlikely, but theoretically possible overflow */
|
2013-02-07 01:57:13 +00:00
|
|
|
if (meta->capacity > (ULLONG_MAX /
|
|
|
|
fileTypeInfo[format].sizeMultiplier))
|
2013-02-09 13:41:01 +00:00
|
|
|
goto done;
|
2010-06-15 13:58:10 +00:00
|
|
|
meta->capacity *= fileTypeInfo[format].sizeMultiplier;
|
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2010-06-15 13:58:10 +00:00
|
|
|
if (fileTypeInfo[format].qcowCryptOffset != -1) {
|
|
|
|
int crypt_format;
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2013-02-07 01:57:13 +00:00
|
|
|
crypt_format = virReadBufInt32BE(buf +
|
|
|
|
fileTypeInfo[format].qcowCryptOffset);
|
2014-04-02 01:13:51 +00:00
|
|
|
if (crypt_format && VIR_ALLOC(meta->encryption) < 0)
|
|
|
|
goto cleanup;
|
2010-06-15 13:58:10 +00:00
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2010-06-15 13:58:10 +00:00
|
|
|
if (fileTypeInfo[format].getBackingStore != NULL) {
|
|
|
|
char *backing;
|
|
|
|
int backingFormat;
|
2013-02-09 13:41:01 +00:00
|
|
|
int store = fileTypeInfo[format].getBackingStore(&backing,
|
|
|
|
&backingFormat,
|
|
|
|
buf, len);
|
|
|
|
if (store == BACKING_STORE_INVALID)
|
|
|
|
goto done;
|
2010-06-15 13:58:10 +00:00
|
|
|
|
2013-02-09 13:41:01 +00:00
|
|
|
if (store == BACKING_STORE_ERROR)
|
|
|
|
goto cleanup;
|
2010-06-15 13:58:10 +00:00
|
|
|
|
2010-11-03 15:50:11 +00:00
|
|
|
meta->backingStoreIsFile = false;
|
2010-06-15 13:58:10 +00:00
|
|
|
if (backing != NULL) {
|
2013-05-24 07:19:51 +00:00
|
|
|
if (VIR_STRDUP(meta->backingStore, backing) < 0) {
|
2012-10-09 23:47:42 +00:00
|
|
|
VIR_FREE(backing);
|
2013-02-09 13:41:01 +00:00
|
|
|
goto cleanup;
|
2012-10-09 23:47:42 +00:00
|
|
|
}
|
2010-11-03 15:50:11 +00:00
|
|
|
if (virBackingStoreIsFile(backing)) {
|
|
|
|
meta->backingStoreIsFile = true;
|
2012-10-09 23:47:42 +00:00
|
|
|
meta->backingStoreRaw = meta->backingStore;
|
storage: don't follow backing chain symlinks too eagerly
If you have a qcow2 file /path1/to/file pointed to by symlink
/path2/symlink, and pass qemu /path2/symlink, then qemu treats
a relative backing file in the qcow2 metadata as being relative
to /path2, not /path1/to. Yes, this means that it is possible
to create a qcow2 file where the choice of WHICH directory and
symlink you access its contents from will then determine WHICH
backing file (if any) you actually find; the results can be
rather screwy, but we have to match what qemu does.
Libvirt and qemu default to creating absolute backing file
names, so most users don't hit this. But at least VDSM uses
symlinks and relative backing names alongside the
--reuse-external flags to libvirt snapshot operations, with the
result that libvirt was failing to follow the intended chain of
backing files, and then backing files were not granted the
necessary sVirt permissions to be opened by qemu.
See https://bugzilla.redhat.com/show_bug.cgi?id=903248 for
more gory details. This fixes a regression introduced in
commit 8250783.
I tested this patch by creating the following chain:
ls /home/eblake/Downloads/Fedora.iso # raw file for base
cd /var/lib/libvirt/images
qemu-img create -f qcow2 \
-obacking_file=/home/eblake/Downloads/Fedora.iso,backing_fmt=raw one
mkdir sub
cd sub
ln -s ../one onelink
qemu-img create -f qcow2 \
-obacking_file=../sub/onelink,backing_fmt=qcow2 two
mv two ..
ln -s ../two twolink
qemu-img create -f qcow2 \
-obacking_file=../sub/twolink,backing_fmt=qcow2 three
mv three ..
ln -s ../three threelink
then pointing my domain at /var/lib/libvirt/images/sub/threelink.
Prior to this patch, I got complaints about missing backing
files; afterwards, I was able to verify that the backing chain
(and hence DAC and SELinux relabels) of the entire chain worked.
* src/util/virstoragefile.h (_virStorageFileMetadata): Add
directory member.
* src/util/virstoragefile.c (absolutePathFromBaseFile): Drop,
replaced by...
(virFindBackingFile): ...better function.
(virStorageFileGetMetadataInternal): Add an argument.
(virStorageFileGetMetadataFromFD, virStorageFileChainLookup)
(virStorageFileGetMetadata): Update callers.
2013-02-06 22:48:15 +00:00
|
|
|
meta->backingStore = NULL;
|
2014-04-08 20:26:02 +00:00
|
|
|
if (virFindBackingFile(directory, backing,
|
storage: don't follow backing chain symlinks too eagerly
If you have a qcow2 file /path1/to/file pointed to by symlink
/path2/symlink, and pass qemu /path2/symlink, then qemu treats
a relative backing file in the qcow2 metadata as being relative
to /path2, not /path1/to. Yes, this means that it is possible
to create a qcow2 file where the choice of WHICH directory and
symlink you access its contents from will then determine WHICH
backing file (if any) you actually find; the results can be
rather screwy, but we have to match what qemu does.
Libvirt and qemu default to creating absolute backing file
names, so most users don't hit this. But at least VDSM uses
symlinks and relative backing names alongside the
--reuse-external flags to libvirt snapshot operations, with the
result that libvirt was failing to follow the intended chain of
backing files, and then backing files were not granted the
necessary sVirt permissions to be opened by qemu.
See https://bugzilla.redhat.com/show_bug.cgi?id=903248 for
more gory details. This fixes a regression introduced in
commit 8250783.
I tested this patch by creating the following chain:
ls /home/eblake/Downloads/Fedora.iso # raw file for base
cd /var/lib/libvirt/images
qemu-img create -f qcow2 \
-obacking_file=/home/eblake/Downloads/Fedora.iso,backing_fmt=raw one
mkdir sub
cd sub
ln -s ../one onelink
qemu-img create -f qcow2 \
-obacking_file=../sub/onelink,backing_fmt=qcow2 two
mv two ..
ln -s ../two twolink
qemu-img create -f qcow2 \
-obacking_file=../sub/twolink,backing_fmt=qcow2 three
mv three ..
ln -s ../three threelink
then pointing my domain at /var/lib/libvirt/images/sub/threelink.
Prior to this patch, I got complaints about missing backing
files; afterwards, I was able to verify that the backing chain
(and hence DAC and SELinux relabels) of the entire chain worked.
* src/util/virstoragefile.h (_virStorageFileMetadata): Add
directory member.
* src/util/virstoragefile.c (absolutePathFromBaseFile): Drop,
replaced by...
(virFindBackingFile): ...better function.
(virStorageFileGetMetadataInternal): Add an argument.
(virStorageFileGetMetadataFromFD, virStorageFileChainLookup)
(virStorageFileGetMetadata): Update callers.
2013-02-06 22:48:15 +00:00
|
|
|
&meta->directory,
|
|
|
|
&meta->backingStore) < 0) {
|
2012-11-07 13:53:49 +00:00
|
|
|
/* the backing file is (currently) unavailable, treat this
|
2012-11-21 10:57:22 +00:00
|
|
|
* file as standalone:
|
|
|
|
* backingStoreRaw is kept to mark broken image chains */
|
|
|
|
meta->backingStoreIsFile = false;
|
2012-11-07 13:53:49 +00:00
|
|
|
backingFormat = VIR_STORAGE_FILE_NONE;
|
2012-11-21 10:57:22 +00:00
|
|
|
VIR_WARN("Backing file '%s' of image '%s' is missing.",
|
|
|
|
meta->backingStoreRaw, path);
|
|
|
|
|
2012-10-09 23:47:42 +00:00
|
|
|
}
|
2010-11-03 15:50:11 +00:00
|
|
|
}
|
2010-06-15 13:58:10 +00:00
|
|
|
VIR_FREE(backing);
|
|
|
|
meta->backingStoreFormat = backingFormat;
|
|
|
|
} else {
|
|
|
|
meta->backingStore = NULL;
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
meta->backingStoreFormat = VIR_STORAGE_FILE_NONE;
|
2010-06-15 13:58:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-07 15:27:43 +00:00
|
|
|
if (fileTypeInfo[format].getFeatures != NULL &&
|
|
|
|
fileTypeInfo[format].getFeatures(&meta->features, format, buf, len) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (format == VIR_STORAGE_FILE_QCOW2 && meta->features &&
|
|
|
|
VIR_STRDUP(meta->compat, "1.1") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
done:
|
2014-04-08 21:20:36 +00:00
|
|
|
ret = 0;
|
2013-02-06 23:33:45 +00:00
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2013-02-09 13:41:01 +00:00
|
|
|
return ret;
|
2010-06-15 13:58:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2013-11-05 21:12:02 +00:00
|
|
|
* virStorageFileProbeFormat:
|
2010-06-15 13:58:10 +00:00
|
|
|
*
|
2013-11-05 21:12:02 +00:00
|
|
|
* Probe for the format of 'path', returning the detected
|
|
|
|
* disk format.
|
2010-06-15 13:58:10 +00:00
|
|
|
*
|
|
|
|
* Callers are advised never to trust the returned 'format'
|
|
|
|
* unless it is listed as VIR_STORAGE_FILE_RAW, since a
|
2013-11-05 21:12:02 +00:00
|
|
|
* malicious guest can turn a raw file into any other non-raw
|
2010-06-15 13:58:10 +00:00
|
|
|
* format at will.
|
|
|
|
*
|
|
|
|
* Best option: Don't use this function
|
|
|
|
*/
|
|
|
|
int
|
2013-11-05 21:12:02 +00:00
|
|
|
virStorageFileProbeFormat(const char *path, uid_t uid, gid_t gid)
|
2010-06-15 13:58:10 +00:00
|
|
|
{
|
2013-11-05 21:12:02 +00:00
|
|
|
int fd;
|
2010-06-15 13:58:10 +00:00
|
|
|
int ret = -1;
|
2011-05-26 18:05:32 +00:00
|
|
|
struct stat sb;
|
2013-11-05 21:12:02 +00:00
|
|
|
ssize_t len = VIR_STORAGE_MAX_HEADER;
|
|
|
|
char *header = NULL;
|
2011-05-26 18:05:32 +00:00
|
|
|
|
2013-11-05 21:12:02 +00:00
|
|
|
if ((fd = virFileOpenAs(path, O_RDONLY, 0, uid, gid, 0)) < 0) {
|
|
|
|
virReportSystemError(-fd, _("Failed to open file '%s'"), path);
|
2011-05-26 18:05:32 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-11-05 21:12:02 +00:00
|
|
|
if (fstat(fd, &sb) < 0) {
|
|
|
|
virReportSystemError(errno, _("cannot stat file '%s'"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-26 18:05:32 +00:00
|
|
|
/* No header to probe for directories */
|
|
|
|
if (S_ISDIR(sb.st_mode)) {
|
2013-11-05 21:12:02 +00:00
|
|
|
ret = VIR_STORAGE_FILE_DIR;
|
|
|
|
goto cleanup;
|
2011-05-26 18:05:32 +00:00
|
|
|
}
|
2010-06-15 13:58:10 +00:00
|
|
|
|
|
|
|
if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
|
|
|
|
virReportSystemError(errno, _("cannot set to start of '%s'"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-11-05 21:12:02 +00:00
|
|
|
if ((len = virFileReadHeaderFD(fd, len, &header)) < 0) {
|
2010-06-15 13:58:10 +00:00
|
|
|
virReportSystemError(errno, _("cannot read header '%s'"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-11-05 21:12:02 +00:00
|
|
|
ret = virStorageFileProbeFormatFromBuf(path, header, len);
|
2010-06-15 13:58:10 +00:00
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2013-11-05 21:12:02 +00:00
|
|
|
VIR_FREE(header);
|
2010-11-09 20:48:48 +00:00
|
|
|
VIR_FORCE_CLOSE(fd);
|
2010-06-15 13:58:10 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-11-05 20:50:29 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileGetMetadataFromBuf:
|
|
|
|
* @path: name of file, for error messages
|
|
|
|
* @buf: header bytes from @path
|
|
|
|
* @len: length of @buf
|
|
|
|
* @format: expected image format
|
|
|
|
*
|
|
|
|
* Extract metadata about the storage volume with the specified
|
|
|
|
* image format. If image format is VIR_STORAGE_FILE_AUTO, it
|
|
|
|
* will probe to automatically identify the format. Does not recurse.
|
|
|
|
*
|
|
|
|
* Callers are advised never to use VIR_STORAGE_FILE_AUTO as a
|
|
|
|
* format, since a malicious guest can turn a raw file into any
|
|
|
|
* other non-raw format at will.
|
|
|
|
*
|
|
|
|
* If the returned meta.backingStoreFormat is VIR_STORAGE_FILE_AUTO
|
|
|
|
* it indicates the image didn't specify an explicit format for its
|
|
|
|
* backing store. Callers are advised against probing for the
|
|
|
|
* backing store format in this case.
|
|
|
|
*
|
|
|
|
* Caller MUST free the result after use via virStorageFileFreeMetadata.
|
|
|
|
*/
|
|
|
|
virStorageFileMetadataPtr
|
|
|
|
virStorageFileGetMetadataFromBuf(const char *path,
|
|
|
|
char *buf,
|
|
|
|
size_t len,
|
|
|
|
int format)
|
|
|
|
{
|
2014-04-08 21:20:36 +00:00
|
|
|
virStorageFileMetadataPtr ret = NULL;
|
2014-04-08 20:26:02 +00:00
|
|
|
char *canonPath;
|
|
|
|
|
|
|
|
if (!(canonPath = canonicalize_file_name(path))) {
|
|
|
|
virReportSystemError(errno, _("unable to resolve '%s'"), path);
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-04-08 21:20:36 +00:00
|
|
|
if (VIR_ALLOC(ret) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virStorageFileGetMetadataInternal(path, canonPath, ".", buf, len,
|
|
|
|
format, ret) < 0) {
|
|
|
|
virStorageFileFreeMetadata(ret);
|
|
|
|
ret = NULL;
|
|
|
|
}
|
2014-04-08 20:26:02 +00:00
|
|
|
|
2014-04-08 21:20:36 +00:00
|
|
|
cleanup:
|
2014-04-08 20:26:02 +00:00
|
|
|
VIR_FREE(canonPath);
|
|
|
|
return ret;
|
2013-11-05 20:50:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Internal version that also supports a containing directory name. */
|
2014-04-08 21:20:36 +00:00
|
|
|
static int
|
2013-11-05 20:50:29 +00:00
|
|
|
virStorageFileGetMetadataFromFDInternal(const char *path,
|
2014-04-08 20:26:02 +00:00
|
|
|
const char *canonPath,
|
2013-11-05 20:50:29 +00:00
|
|
|
const char *directory,
|
2014-04-08 20:26:02 +00:00
|
|
|
int fd,
|
2014-04-08 21:20:36 +00:00
|
|
|
int format,
|
|
|
|
virStorageFileMetadataPtr meta)
|
2013-11-05 20:50:29 +00:00
|
|
|
{
|
|
|
|
char *buf = NULL;
|
2013-11-05 21:12:02 +00:00
|
|
|
ssize_t len = VIR_STORAGE_MAX_HEADER;
|
2013-11-05 20:50:29 +00:00
|
|
|
struct stat sb;
|
2014-04-08 21:20:36 +00:00
|
|
|
int ret = -1;
|
2013-11-05 20:50:29 +00:00
|
|
|
|
|
|
|
if (fstat(fd, &sb) < 0) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("cannot stat file '%s'"),
|
|
|
|
path);
|
2014-04-08 21:20:36 +00:00
|
|
|
return -1;
|
2013-11-05 20:50:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* No header to probe for directories, but also no backing file */
|
|
|
|
if (S_ISDIR(sb.st_mode)) {
|
2014-04-08 21:20:36 +00:00
|
|
|
ret = 0;
|
2013-11-05 20:50:29 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
|
|
|
|
virReportSystemError(errno, _("cannot seek to start of '%s'"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((len = virFileReadHeaderFD(fd, len, &buf)) < 0) {
|
|
|
|
virReportSystemError(errno, _("cannot read header '%s'"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-04-08 20:26:02 +00:00
|
|
|
ret = virStorageFileGetMetadataInternal(path, canonPath, directory,
|
2014-04-08 21:20:36 +00:00
|
|
|
buf, len, format, meta);
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2013-11-05 20:50:29 +00:00
|
|
|
VIR_FREE(buf);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-15 13:58:10 +00:00
|
|
|
/**
|
|
|
|
* virStorageFileGetMetadataFromFD:
|
|
|
|
*
|
2010-06-15 15:15:51 +00:00
|
|
|
* Extract metadata about the storage volume with the specified
|
|
|
|
* image format. If image format is VIR_STORAGE_FILE_AUTO, it
|
2012-10-13 16:47:15 +00:00
|
|
|
* will probe to automatically identify the format. Does not recurse.
|
2010-06-15 13:58:10 +00:00
|
|
|
*
|
2010-06-15 15:15:51 +00:00
|
|
|
* Callers are advised never to use VIR_STORAGE_FILE_AUTO as a
|
|
|
|
* format, since a malicious guest can turn a raw file into any
|
|
|
|
* other non-raw format at will.
|
|
|
|
*
|
|
|
|
* If the returned meta.backingStoreFormat is VIR_STORAGE_FILE_AUTO
|
|
|
|
* it indicates the image didn't specify an explicit format for its
|
|
|
|
* backing store. Callers are advised against probing for the
|
|
|
|
* backing store format in this case.
|
2011-07-14 10:53:45 +00:00
|
|
|
*
|
2012-10-13 17:01:27 +00:00
|
|
|
* Caller MUST free the result after use via virStorageFileFreeMetadata.
|
2010-06-15 13:58:10 +00:00
|
|
|
*/
|
2012-10-13 17:01:27 +00:00
|
|
|
virStorageFileMetadataPtr
|
2010-06-15 13:58:10 +00:00
|
|
|
virStorageFileGetMetadataFromFD(const char *path,
|
|
|
|
int fd,
|
2012-10-13 17:01:27 +00:00
|
|
|
int format)
|
2010-06-15 13:58:10 +00:00
|
|
|
{
|
2014-04-08 21:20:36 +00:00
|
|
|
virStorageFileMetadataPtr ret = NULL;
|
2014-04-08 20:26:02 +00:00
|
|
|
char *canonPath;
|
|
|
|
|
|
|
|
if (!(canonPath = canonicalize_file_name(path))) {
|
|
|
|
virReportSystemError(errno, _("unable to resolve '%s'"), path);
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-04-08 21:20:36 +00:00
|
|
|
if (VIR_ALLOC(ret) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virStorageFileGetMetadataFromFDInternal(path, canonPath, ".",
|
|
|
|
fd, format, ret) < 0) {
|
|
|
|
virStorageFileFreeMetadata(ret);
|
|
|
|
ret = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
2014-04-08 20:26:02 +00:00
|
|
|
VIR_FREE(canonPath);
|
|
|
|
return ret;
|
2010-06-15 13:58:10 +00:00
|
|
|
}
|
|
|
|
|
2013-11-05 20:50:29 +00:00
|
|
|
|
2012-10-13 16:47:15 +00:00
|
|
|
/* Recursive workhorse for virStorageFileGetMetadata. */
|
2014-04-08 21:20:36 +00:00
|
|
|
static int
|
2014-04-05 00:05:22 +00:00
|
|
|
virStorageFileGetMetadataRecurse(const char *path, const char *canonPath,
|
|
|
|
const char *directory,
|
storage: don't follow backing chain symlinks too eagerly
If you have a qcow2 file /path1/to/file pointed to by symlink
/path2/symlink, and pass qemu /path2/symlink, then qemu treats
a relative backing file in the qcow2 metadata as being relative
to /path2, not /path1/to. Yes, this means that it is possible
to create a qcow2 file where the choice of WHICH directory and
symlink you access its contents from will then determine WHICH
backing file (if any) you actually find; the results can be
rather screwy, but we have to match what qemu does.
Libvirt and qemu default to creating absolute backing file
names, so most users don't hit this. But at least VDSM uses
symlinks and relative backing names alongside the
--reuse-external flags to libvirt snapshot operations, with the
result that libvirt was failing to follow the intended chain of
backing files, and then backing files were not granted the
necessary sVirt permissions to be opened by qemu.
See https://bugzilla.redhat.com/show_bug.cgi?id=903248 for
more gory details. This fixes a regression introduced in
commit 8250783.
I tested this patch by creating the following chain:
ls /home/eblake/Downloads/Fedora.iso # raw file for base
cd /var/lib/libvirt/images
qemu-img create -f qcow2 \
-obacking_file=/home/eblake/Downloads/Fedora.iso,backing_fmt=raw one
mkdir sub
cd sub
ln -s ../one onelink
qemu-img create -f qcow2 \
-obacking_file=../sub/onelink,backing_fmt=qcow2 two
mv two ..
ln -s ../two twolink
qemu-img create -f qcow2 \
-obacking_file=../sub/twolink,backing_fmt=qcow2 three
mv three ..
ln -s ../three threelink
then pointing my domain at /var/lib/libvirt/images/sub/threelink.
Prior to this patch, I got complaints about missing backing
files; afterwards, I was able to verify that the backing chain
(and hence DAC and SELinux relabels) of the entire chain worked.
* src/util/virstoragefile.h (_virStorageFileMetadata): Add
directory member.
* src/util/virstoragefile.c (absolutePathFromBaseFile): Drop,
replaced by...
(virFindBackingFile): ...better function.
(virStorageFileGetMetadataInternal): Add an argument.
(virStorageFileGetMetadataFromFD, virStorageFileChainLookup)
(virStorageFileGetMetadata): Update callers.
2013-02-06 22:48:15 +00:00
|
|
|
int format, uid_t uid, gid_t gid,
|
2014-04-08 21:20:36 +00:00
|
|
|
bool allow_probe, virHashTablePtr cycle,
|
|
|
|
virStorageFileMetadataPtr meta)
|
2012-10-13 16:47:15 +00:00
|
|
|
{
|
|
|
|
int fd;
|
2014-04-08 21:20:36 +00:00
|
|
|
int ret = -1;
|
2014-04-05 00:05:22 +00:00
|
|
|
VIR_DEBUG("path=%s canonPath=%s dir=%s format=%d uid=%d gid=%d probe=%d",
|
|
|
|
path, canonPath, NULLSTR(directory), format,
|
|
|
|
(int)uid, (int)gid, allow_probe);
|
2012-12-13 14:23:50 +00:00
|
|
|
|
2014-04-05 00:05:22 +00:00
|
|
|
if (virHashLookup(cycle, canonPath)) {
|
2012-10-13 16:47:15 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("backing store for %s is self-referential"),
|
|
|
|
path);
|
2014-04-08 21:20:36 +00:00
|
|
|
return -1;
|
2012-10-13 16:47:15 +00:00
|
|
|
}
|
2014-04-05 00:05:22 +00:00
|
|
|
if (virHashAddEntry(cycle, canonPath, (void *)1) < 0)
|
2014-04-08 21:20:36 +00:00
|
|
|
return -1;
|
2012-10-13 16:47:15 +00:00
|
|
|
|
2014-04-05 00:05:22 +00:00
|
|
|
if ((fd = virFileOpenAs(canonPath, O_RDONLY, 0, uid, gid, 0)) < 0) {
|
util: fix virFileOpenAs return value and resulting error logs
This resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=851411
https://bugzilla.redhat.com/show_bug.cgi?id=955500
The first problem was that virFileOpenAs was returning fd (-1) in one
of the error cases rather than ret (-errno), so the caller thought
that the error was EPERM rather than ENOENT.
The second problem was that some log messages in the general purpose
qemuOpenFile() function would always say "Failed to create" even if
the caller hadn't included O_CREAT (i.e. they were trying to open an
existing file).
This fixes virFileOpenAs to jump down to the error return (which
returns ret instead of fd) in the previously mentioned incorrect
failure case of virFileOpenAs(), removes all error logging from
virFileOpenAs() (since the callers report it), and modifies
qemuOpenFile to appropriately use "open" or "create" in its log
messages.
NB: I seriously considered removing logging from all callers of
virFileOpenAs(), but there is at least one case where the caller
doesn't want virFileOpenAs() to log any errors, because it's just
going to try again (qemuOpenFile()). We can't simply make a silent
variation of virFileOpenAs() though, because qemuOpenFile() can't make
the decision about whether or not it wants to retry until after
virFileOpenAs() has already returned an error code.
Likewise, I also considered changing virFileOpenAs() to return -1 with
errno set on return, and may still do that, but only as a separate
patch, as it obscures the intent of this patch too much.
2013-05-08 19:02:14 +00:00
|
|
|
virReportSystemError(-fd, _("Failed to open file '%s'"), path);
|
2014-04-08 21:20:36 +00:00
|
|
|
return -1;
|
2012-10-13 16:47:15 +00:00
|
|
|
}
|
|
|
|
|
2014-04-08 20:26:02 +00:00
|
|
|
ret = virStorageFileGetMetadataFromFDInternal(path, canonPath, directory,
|
2014-04-08 21:20:36 +00:00
|
|
|
fd, format, meta);
|
2012-10-13 16:47:15 +00:00
|
|
|
|
|
|
|
if (VIR_CLOSE(fd) < 0)
|
|
|
|
VIR_WARN("could not close file %s", path);
|
|
|
|
|
2014-04-08 21:20:36 +00:00
|
|
|
if (ret == 0 && meta->backingStoreIsFile) {
|
|
|
|
virStorageFileMetadataPtr backing;
|
|
|
|
|
|
|
|
if (meta->backingStoreFormat == VIR_STORAGE_FILE_AUTO && !allow_probe)
|
|
|
|
meta->backingStoreFormat = VIR_STORAGE_FILE_RAW;
|
|
|
|
else if (meta->backingStoreFormat == VIR_STORAGE_FILE_AUTO_SAFE)
|
|
|
|
meta->backingStoreFormat = VIR_STORAGE_FILE_AUTO;
|
|
|
|
format = meta->backingStoreFormat;
|
|
|
|
if (VIR_ALLOC(backing) < 0 ||
|
|
|
|
virStorageFileGetMetadataRecurse(meta->backingStoreRaw,
|
|
|
|
meta->backingStore,
|
|
|
|
meta->directory, format,
|
|
|
|
uid, gid, allow_probe,
|
|
|
|
cycle, backing) < 0) {
|
2014-04-05 00:05:22 +00:00
|
|
|
/* If we failed to get backing data, mark the chain broken */
|
2014-04-08 21:20:36 +00:00
|
|
|
meta->backingStoreFormat = VIR_STORAGE_FILE_NONE;
|
|
|
|
VIR_FREE(meta->backingStore);
|
|
|
|
virStorageFileFreeMetadata(backing);
|
|
|
|
} else {
|
|
|
|
meta->backingMeta = backing;
|
2014-04-05 00:05:22 +00:00
|
|
|
}
|
2012-10-13 16:47:15 +00:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-06-15 13:58:10 +00:00
|
|
|
/**
|
|
|
|
* virStorageFileGetMetadata:
|
|
|
|
*
|
2010-06-15 15:15:51 +00:00
|
|
|
* Extract metadata about the storage volume with the specified
|
|
|
|
* image format. If image format is VIR_STORAGE_FILE_AUTO, it
|
2012-10-13 16:47:15 +00:00
|
|
|
* will probe to automatically identify the format. Recurses through
|
|
|
|
* the entire chain.
|
|
|
|
*
|
|
|
|
* Open files using UID and GID (or pass -1 for the current user/group).
|
|
|
|
* Treat any backing files without explicit type as raw, unless ALLOW_PROBE.
|
2010-06-15 13:58:10 +00:00
|
|
|
*
|
2010-06-15 15:15:51 +00:00
|
|
|
* Callers are advised never to use VIR_STORAGE_FILE_AUTO as a
|
|
|
|
* format, since a malicious guest can turn a raw file into any
|
|
|
|
* other non-raw format at will.
|
|
|
|
*
|
|
|
|
* If the returned meta.backingStoreFormat is VIR_STORAGE_FILE_AUTO
|
|
|
|
* it indicates the image didn't specify an explicit format for its
|
2012-10-13 16:47:15 +00:00
|
|
|
* backing store. Callers are advised against using ALLOW_PROBE, as
|
|
|
|
* it would probe the backing store format in this case.
|
2011-07-14 10:53:45 +00:00
|
|
|
*
|
2012-10-13 16:47:15 +00:00
|
|
|
* Caller MUST free result after use via virStorageFileFreeMetadata.
|
2010-06-15 13:58:10 +00:00
|
|
|
*/
|
2012-10-13 16:47:15 +00:00
|
|
|
virStorageFileMetadataPtr
|
|
|
|
virStorageFileGetMetadata(const char *path, int format,
|
|
|
|
uid_t uid, gid_t gid,
|
|
|
|
bool allow_probe)
|
2009-09-29 08:41:23 +00:00
|
|
|
{
|
2012-12-13 14:23:50 +00:00
|
|
|
VIR_DEBUG("path=%s format=%d uid=%d gid=%d probe=%d",
|
|
|
|
path, format, (int)uid, (int)gid, allow_probe);
|
|
|
|
|
2012-10-13 16:47:15 +00:00
|
|
|
virHashTablePtr cycle = virHashCreate(5, NULL);
|
2014-04-08 21:20:36 +00:00
|
|
|
virStorageFileMetadataPtr meta = NULL;
|
2014-04-05 00:05:22 +00:00
|
|
|
virStorageFileMetadataPtr ret = NULL;
|
2014-04-08 20:26:02 +00:00
|
|
|
char *canonPath = NULL;
|
|
|
|
char *directory = NULL;
|
2009-09-29 08:41:23 +00:00
|
|
|
|
2014-04-04 22:56:29 +00:00
|
|
|
if (!cycle)
|
2012-10-13 16:47:15 +00:00
|
|
|
return NULL;
|
2009-09-29 08:41:23 +00:00
|
|
|
|
2014-04-05 00:05:22 +00:00
|
|
|
if (!(canonPath = canonicalize_file_name(path))) {
|
|
|
|
virReportSystemError(errno, _("unable to resolve '%s'"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-04-08 20:26:02 +00:00
|
|
|
if (!(directory = mdir_name(path))) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-04-08 21:20:36 +00:00
|
|
|
if (VIR_ALLOC(meta) < 0)
|
|
|
|
goto cleanup;
|
2014-04-05 00:05:22 +00:00
|
|
|
|
2012-10-13 16:47:15 +00:00
|
|
|
if (format <= VIR_STORAGE_FILE_NONE)
|
|
|
|
format = allow_probe ? VIR_STORAGE_FILE_AUTO : VIR_STORAGE_FILE_RAW;
|
2014-04-08 21:20:36 +00:00
|
|
|
if (virStorageFileGetMetadataRecurse(path, canonPath, directory, format,
|
|
|
|
uid, gid, allow_probe, cycle,
|
|
|
|
meta) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
ret = meta;
|
|
|
|
meta = NULL;
|
|
|
|
|
2014-04-05 00:05:22 +00:00
|
|
|
cleanup:
|
2014-04-08 21:20:36 +00:00
|
|
|
virStorageFileFreeMetadata(meta);
|
2014-04-05 00:05:22 +00:00
|
|
|
VIR_FREE(canonPath);
|
2014-04-08 20:26:02 +00:00
|
|
|
VIR_FREE(directory);
|
2012-10-13 16:47:15 +00:00
|
|
|
virHashFree(cycle);
|
2009-09-29 08:41:23 +00:00
|
|
|
return ret;
|
|
|
|
}
|
Don't reset user/group/security label on shared filesystems during migrate
When QEMU runs with its disk on NFS, and as a non-root user, the
disk is chownd to that non-root user. When migration completes
the last step is shutting down the QEMU on the source host. THis
normally resets user/group/security label. This is bad when the
VM was just migrated because the file is still in use on the dest
host. It is thus neccessary to skip the reset step for any files
found to be on a shared filesystem
* src/libvirt_private.syms: Export virStorageFileIsSharedFS
* src/util/storage_file.c, src/util/storage_file.h: Add a new
method virStorageFileIsSharedFS() to determine if a file is
on a shared filesystem (NFS, GFS, OCFS2, etc)
* src/qemu/qemu_driver.c: Tell security driver not to reset
disk labels on migration completion
* src/qemu/qemu_security_dac.c, src/qemu/qemu_security_stacked.c,
src/security/security_selinux.c, src/security/security_driver.h,
src/security/security_apparmor.c: Add ability to skip disk
restore step for files on shared filesystems.
2010-05-13 15:49:22 +00:00
|
|
|
|
2013-07-29 12:51:15 +00:00
|
|
|
/**
|
|
|
|
* virStorageFileChainCheckBroken
|
|
|
|
*
|
|
|
|
* If CHAIN is broken, set *brokenFile to the broken file name,
|
|
|
|
* otherwise set it to NULL. Caller MUST free *brokenFile after use.
|
|
|
|
* Return 0 on success, negative on error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageFileChainGetBroken(virStorageFileMetadataPtr chain,
|
|
|
|
char **brokenFile)
|
|
|
|
{
|
|
|
|
virStorageFileMetadataPtr tmp;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!chain)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
*brokenFile = NULL;
|
|
|
|
|
|
|
|
tmp = chain;
|
|
|
|
while (tmp) {
|
2014-04-05 00:05:22 +00:00
|
|
|
/* Break if no backing store, backing store is not file, or
|
|
|
|
* other problem such as infinite loop */
|
2013-07-29 12:51:15 +00:00
|
|
|
if (!tmp->backingStoreRaw)
|
|
|
|
break;
|
|
|
|
if (!tmp->backingStore) {
|
|
|
|
if (VIR_STRDUP(*brokenFile, tmp->backingStoreRaw) < 0)
|
|
|
|
goto error;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tmp = tmp->backingMeta;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
error:
|
2013-07-29 12:51:15 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-14 10:53:45 +00:00
|
|
|
/**
|
|
|
|
* virStorageFileFreeMetadata:
|
|
|
|
*
|
|
|
|
* Free pointers in passed structure and structure itself.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
virStorageFileFreeMetadata(virStorageFileMetadata *meta)
|
|
|
|
{
|
|
|
|
if (!meta)
|
|
|
|
return;
|
|
|
|
|
2012-10-13 16:47:15 +00:00
|
|
|
virStorageFileFreeMetadata(meta->backingMeta);
|
2011-07-14 10:53:45 +00:00
|
|
|
VIR_FREE(meta->backingStore);
|
2012-10-09 23:47:42 +00:00
|
|
|
VIR_FREE(meta->backingStoreRaw);
|
2013-05-07 15:27:43 +00:00
|
|
|
VIR_FREE(meta->compat);
|
storage: don't follow backing chain symlinks too eagerly
If you have a qcow2 file /path1/to/file pointed to by symlink
/path2/symlink, and pass qemu /path2/symlink, then qemu treats
a relative backing file in the qcow2 metadata as being relative
to /path2, not /path1/to. Yes, this means that it is possible
to create a qcow2 file where the choice of WHICH directory and
symlink you access its contents from will then determine WHICH
backing file (if any) you actually find; the results can be
rather screwy, but we have to match what qemu does.
Libvirt and qemu default to creating absolute backing file
names, so most users don't hit this. But at least VDSM uses
symlinks and relative backing names alongside the
--reuse-external flags to libvirt snapshot operations, with the
result that libvirt was failing to follow the intended chain of
backing files, and then backing files were not granted the
necessary sVirt permissions to be opened by qemu.
See https://bugzilla.redhat.com/show_bug.cgi?id=903248 for
more gory details. This fixes a regression introduced in
commit 8250783.
I tested this patch by creating the following chain:
ls /home/eblake/Downloads/Fedora.iso # raw file for base
cd /var/lib/libvirt/images
qemu-img create -f qcow2 \
-obacking_file=/home/eblake/Downloads/Fedora.iso,backing_fmt=raw one
mkdir sub
cd sub
ln -s ../one onelink
qemu-img create -f qcow2 \
-obacking_file=../sub/onelink,backing_fmt=qcow2 two
mv two ..
ln -s ../two twolink
qemu-img create -f qcow2 \
-obacking_file=../sub/twolink,backing_fmt=qcow2 three
mv three ..
ln -s ../three threelink
then pointing my domain at /var/lib/libvirt/images/sub/threelink.
Prior to this patch, I got complaints about missing backing
files; afterwards, I was able to verify that the backing chain
(and hence DAC and SELinux relabels) of the entire chain worked.
* src/util/virstoragefile.h (_virStorageFileMetadata): Add
directory member.
* src/util/virstoragefile.c (absolutePathFromBaseFile): Drop,
replaced by...
(virFindBackingFile): ...better function.
(virStorageFileGetMetadataInternal): Add an argument.
(virStorageFileGetMetadataFromFD, virStorageFileChainLookup)
(virStorageFileGetMetadata): Update callers.
2013-02-06 22:48:15 +00:00
|
|
|
VIR_FREE(meta->directory);
|
2013-05-07 15:27:43 +00:00
|
|
|
virBitmapFree(meta->features);
|
2014-04-02 01:13:51 +00:00
|
|
|
virStorageEncryptionFree(meta->encryption);
|
2011-07-14 10:53:45 +00:00
|
|
|
VIR_FREE(meta);
|
|
|
|
}
|
Don't reset user/group/security label on shared filesystems during migrate
When QEMU runs with its disk on NFS, and as a non-root user, the
disk is chownd to that non-root user. When migration completes
the last step is shutting down the QEMU on the source host. THis
normally resets user/group/security label. This is bad when the
VM was just migrated because the file is still in use on the dest
host. It is thus neccessary to skip the reset step for any files
found to be on a shared filesystem
* src/libvirt_private.syms: Export virStorageFileIsSharedFS
* src/util/storage_file.c, src/util/storage_file.h: Add a new
method virStorageFileIsSharedFS() to determine if a file is
on a shared filesystem (NFS, GFS, OCFS2, etc)
* src/qemu/qemu_driver.c: Tell security driver not to reset
disk labels on migration completion
* src/qemu/qemu_security_dac.c, src/qemu/qemu_security_stacked.c,
src/security/security_selinux.c, src/security/security_driver.h,
src/security/security_apparmor.c: Add ability to skip disk
restore step for files on shared filesystems.
2010-05-13 15:49:22 +00:00
|
|
|
|
2012-01-30 07:40:00 +00:00
|
|
|
/**
|
|
|
|
* virStorageFileResize:
|
|
|
|
*
|
|
|
|
* Change the capacity of the raw storage file at 'path'.
|
|
|
|
*/
|
|
|
|
int
|
2013-05-31 05:16:14 +00:00
|
|
|
virStorageFileResize(const char *path,
|
|
|
|
unsigned long long capacity,
|
|
|
|
unsigned long long orig_capacity,
|
|
|
|
bool pre_allocate)
|
2012-01-30 07:40:00 +00:00
|
|
|
{
|
2012-02-08 14:03:29 +00:00
|
|
|
int fd = -1;
|
|
|
|
int ret = -1;
|
2013-06-06 02:33:15 +00:00
|
|
|
int rc ATTRIBUTE_UNUSED;
|
|
|
|
off_t offset ATTRIBUTE_UNUSED;
|
|
|
|
off_t len ATTRIBUTE_UNUSED;
|
|
|
|
|
|
|
|
offset = orig_capacity;
|
|
|
|
len = capacity - orig_capacity;
|
2012-02-08 14:03:29 +00:00
|
|
|
|
|
|
|
if ((fd = open(path, O_RDWR)) < 0) {
|
|
|
|
virReportSystemError(errno, _("Unable to open '%s'"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-05-31 05:16:14 +00:00
|
|
|
if (pre_allocate) {
|
|
|
|
#if HAVE_POSIX_FALLOCATE
|
|
|
|
if ((rc = posix_fallocate(fd, offset, len)) != 0) {
|
|
|
|
virReportSystemError(rc,
|
|
|
|
_("Failed to pre-allocate space for "
|
|
|
|
"file '%s'"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
#elif HAVE_SYS_SYSCALL_H && defined(SYS_fallocate)
|
|
|
|
if (syscall(SYS_fallocate, fd, 0, offset, len) != 0) {
|
|
|
|
virReportSystemError(errno,
|
2013-06-06 02:33:15 +00:00
|
|
|
_("Failed to pre-allocate space for "
|
2013-05-31 05:16:14 +00:00
|
|
|
"file '%s'"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
2013-06-06 02:33:15 +00:00
|
|
|
_("preallocate is not supported on this platform"));
|
2012-02-08 14:03:29 +00:00
|
|
|
goto cleanup;
|
2013-05-31 05:16:14 +00:00
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
if (ftruncate(fd, capacity) < 0) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Failed to truncate file '%s'"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2012-01-30 07:40:00 +00:00
|
|
|
}
|
|
|
|
|
2012-02-08 14:03:29 +00:00
|
|
|
if (VIR_CLOSE(fd) < 0) {
|
|
|
|
virReportSystemError(errno, _("Unable to save '%s'"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2012-02-08 14:03:29 +00:00
|
|
|
VIR_FORCE_CLOSE(fd);
|
|
|
|
return ret;
|
2012-01-30 07:40:00 +00:00
|
|
|
}
|
|
|
|
|
2012-02-21 21:58:50 +00:00
|
|
|
|
|
|
|
int virStorageFileIsClusterFS(const char *path)
|
|
|
|
{
|
|
|
|
/* These are coherent cluster filesystems known to be safe for
|
|
|
|
* migration with cache != none
|
|
|
|
*/
|
2014-03-29 20:15:33 +00:00
|
|
|
return virFileIsSharedFSType(path,
|
|
|
|
VIR_FILE_SHFS_GFS2 |
|
|
|
|
VIR_FILE_SHFS_OCFS);
|
2012-02-21 21:58:50 +00:00
|
|
|
}
|
2011-07-20 09:40:53 +00:00
|
|
|
|
|
|
|
#ifdef LVS
|
2012-12-11 19:10:51 +00:00
|
|
|
int virStorageFileGetLVMKey(const char *path,
|
|
|
|
char **key)
|
2011-07-20 09:40:53 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* # lvs --noheadings --unbuffered --nosuffix --options "uuid" LVNAME
|
|
|
|
* 06UgP5-2rhb-w3Bo-3mdR-WeoL-pytO-SAa2ky
|
|
|
|
*/
|
2012-12-11 19:10:51 +00:00
|
|
|
int status;
|
2011-07-20 09:40:53 +00:00
|
|
|
virCommandPtr cmd = virCommandNewArgList(
|
|
|
|
LVS,
|
|
|
|
"--noheadings", "--unbuffered", "--nosuffix",
|
|
|
|
"--options", "uuid", path,
|
|
|
|
NULL
|
|
|
|
);
|
2012-12-11 19:10:51 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
*key = NULL;
|
2011-07-20 09:40:53 +00:00
|
|
|
|
|
|
|
/* Run the program and capture its output */
|
2012-12-11 19:10:51 +00:00
|
|
|
virCommandSetOutputBuffer(cmd, key);
|
|
|
|
if (virCommandRun(cmd, &status) < 0)
|
2011-07-20 09:40:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2012-12-11 19:10:51 +00:00
|
|
|
/* Explicitly check status == 0, rather than passing NULL
|
|
|
|
* to virCommandRun because we don't want to raise an actual
|
|
|
|
* error in this scenario, just return a NULL key.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (status == 0 && *key) {
|
2011-07-20 09:40:53 +00:00
|
|
|
char *nl;
|
2012-12-11 19:10:51 +00:00
|
|
|
char *tmp = *key;
|
2011-07-20 09:40:53 +00:00
|
|
|
|
|
|
|
/* Find first non-space character */
|
|
|
|
while (*tmp && c_isspace(*tmp)) {
|
|
|
|
tmp++;
|
|
|
|
}
|
|
|
|
/* Kill leading spaces */
|
2012-12-11 19:10:51 +00:00
|
|
|
if (tmp != *key)
|
|
|
|
memmove(*key, tmp, strlen(tmp)+1);
|
2011-07-20 09:40:53 +00:00
|
|
|
|
|
|
|
/* Kill trailing newline */
|
2012-12-11 19:10:51 +00:00
|
|
|
if ((nl = strchr(*key, '\n')))
|
2011-07-20 09:40:53 +00:00
|
|
|
*nl = '\0';
|
|
|
|
}
|
|
|
|
|
2012-12-11 19:10:51 +00:00
|
|
|
ret = 0;
|
2011-07-20 09:40:53 +00:00
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2012-12-11 19:10:51 +00:00
|
|
|
if (*key && STREQ(*key, ""))
|
|
|
|
VIR_FREE(*key);
|
|
|
|
|
2011-07-20 09:40:53 +00:00
|
|
|
virCommandFree(cmd);
|
|
|
|
|
2012-12-11 19:10:51 +00:00
|
|
|
return ret;
|
2011-07-20 09:40:53 +00:00
|
|
|
}
|
|
|
|
#else
|
2012-12-11 19:10:51 +00:00
|
|
|
int virStorageFileGetLVMKey(const char *path,
|
|
|
|
char **key ATTRIBUTE_UNUSED)
|
2011-07-20 09:40:53 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, _("Unable to get LVM key for %s"), path);
|
2012-12-11 19:10:51 +00:00
|
|
|
return -1;
|
2011-07-20 09:40:53 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-09-20 14:24:47 +00:00
|
|
|
#ifdef WITH_UDEV
|
2012-12-11 19:10:51 +00:00
|
|
|
int virStorageFileGetSCSIKey(const char *path,
|
|
|
|
char **key)
|
2011-07-20 09:40:53 +00:00
|
|
|
{
|
2012-12-11 19:10:51 +00:00
|
|
|
int status;
|
2011-07-20 09:40:53 +00:00
|
|
|
virCommandPtr cmd = virCommandNewArgList(
|
|
|
|
"/lib/udev/scsi_id",
|
|
|
|
"--replace-whitespace",
|
|
|
|
"--whitelisted",
|
|
|
|
"--device", path,
|
|
|
|
NULL
|
|
|
|
);
|
2012-12-11 19:10:51 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
*key = NULL;
|
2011-07-20 09:40:53 +00:00
|
|
|
|
|
|
|
/* Run the program and capture its output */
|
2012-12-11 19:10:51 +00:00
|
|
|
virCommandSetOutputBuffer(cmd, key);
|
|
|
|
if (virCommandRun(cmd, &status) < 0)
|
2011-07-20 09:40:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2012-12-11 19:10:51 +00:00
|
|
|
/* Explicitly check status == 0, rather than passing NULL
|
|
|
|
* to virCommandRun because we don't want to raise an actual
|
|
|
|
* error in this scenario, just return a NULL key.
|
|
|
|
*/
|
|
|
|
if (status == 0 && *key) {
|
|
|
|
char *nl = strchr(*key, '\n');
|
2011-07-20 09:40:53 +00:00
|
|
|
if (nl)
|
|
|
|
*nl = '\0';
|
|
|
|
}
|
|
|
|
|
2012-12-11 19:10:51 +00:00
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2012-12-11 19:10:51 +00:00
|
|
|
if (*key && STREQ(*key, ""))
|
|
|
|
VIR_FREE(*key);
|
|
|
|
|
2011-07-20 09:40:53 +00:00
|
|
|
virCommandFree(cmd);
|
|
|
|
|
2012-12-11 19:10:51 +00:00
|
|
|
return ret;
|
2011-07-20 09:40:53 +00:00
|
|
|
}
|
|
|
|
#else
|
2012-12-11 19:10:51 +00:00
|
|
|
int virStorageFileGetSCSIKey(const char *path,
|
|
|
|
char **key ATTRIBUTE_UNUSED)
|
2011-07-20 09:40:53 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, _("Unable to get SCSI key for %s"), path);
|
2012-12-11 19:10:51 +00:00
|
|
|
return -1;
|
2011-07-20 09:40:53 +00:00
|
|
|
}
|
|
|
|
#endif
|
2012-10-12 22:29:14 +00:00
|
|
|
|
|
|
|
/* Given a CHAIN that starts at the named file START, return a string
|
|
|
|
* pointing to either START or within CHAIN that gives the preferred
|
|
|
|
* name for the backing file NAME within that chain. Pass NULL for
|
|
|
|
* NAME to find the base of the chain. If META is not NULL, set *META
|
|
|
|
* to the point in the chain that describes NAME (or to NULL if the
|
|
|
|
* backing element is not a file). If PARENT is not NULL, set *PARENT
|
|
|
|
* to the preferred name of the parent (or to NULL if NAME matches
|
|
|
|
* START). Since the results point within CHAIN, they must not be
|
|
|
|
* independently freed. */
|
|
|
|
const char *
|
|
|
|
virStorageFileChainLookup(virStorageFileMetadataPtr chain, const char *start,
|
|
|
|
const char *name, virStorageFileMetadataPtr *meta,
|
|
|
|
const char **parent)
|
|
|
|
{
|
|
|
|
virStorageFileMetadataPtr owner;
|
|
|
|
const char *tmp;
|
|
|
|
|
|
|
|
if (!parent)
|
|
|
|
parent = &tmp;
|
|
|
|
|
|
|
|
*parent = NULL;
|
|
|
|
if (name ? STREQ(start, name) || virFileLinkPointsTo(start, name) :
|
|
|
|
!chain->backingStore) {
|
|
|
|
if (meta)
|
|
|
|
*meta = chain;
|
|
|
|
return start;
|
|
|
|
}
|
|
|
|
|
|
|
|
owner = chain;
|
|
|
|
*parent = start;
|
|
|
|
while (owner) {
|
|
|
|
if (!owner->backingStore)
|
|
|
|
goto error;
|
|
|
|
if (!name) {
|
|
|
|
if (!owner->backingMeta ||
|
|
|
|
!owner->backingMeta->backingStore)
|
|
|
|
break;
|
|
|
|
} else if (STREQ_NULLABLE(name, owner->backingStoreRaw) ||
|
|
|
|
STREQ(name, owner->backingStore)) {
|
|
|
|
break;
|
|
|
|
} else if (owner->backingStoreIsFile) {
|
storage: don't follow backing chain symlinks too eagerly
If you have a qcow2 file /path1/to/file pointed to by symlink
/path2/symlink, and pass qemu /path2/symlink, then qemu treats
a relative backing file in the qcow2 metadata as being relative
to /path2, not /path1/to. Yes, this means that it is possible
to create a qcow2 file where the choice of WHICH directory and
symlink you access its contents from will then determine WHICH
backing file (if any) you actually find; the results can be
rather screwy, but we have to match what qemu does.
Libvirt and qemu default to creating absolute backing file
names, so most users don't hit this. But at least VDSM uses
symlinks and relative backing names alongside the
--reuse-external flags to libvirt snapshot operations, with the
result that libvirt was failing to follow the intended chain of
backing files, and then backing files were not granted the
necessary sVirt permissions to be opened by qemu.
See https://bugzilla.redhat.com/show_bug.cgi?id=903248 for
more gory details. This fixes a regression introduced in
commit 8250783.
I tested this patch by creating the following chain:
ls /home/eblake/Downloads/Fedora.iso # raw file for base
cd /var/lib/libvirt/images
qemu-img create -f qcow2 \
-obacking_file=/home/eblake/Downloads/Fedora.iso,backing_fmt=raw one
mkdir sub
cd sub
ln -s ../one onelink
qemu-img create -f qcow2 \
-obacking_file=../sub/onelink,backing_fmt=qcow2 two
mv two ..
ln -s ../two twolink
qemu-img create -f qcow2 \
-obacking_file=../sub/twolink,backing_fmt=qcow2 three
mv three ..
ln -s ../three threelink
then pointing my domain at /var/lib/libvirt/images/sub/threelink.
Prior to this patch, I got complaints about missing backing
files; afterwards, I was able to verify that the backing chain
(and hence DAC and SELinux relabels) of the entire chain worked.
* src/util/virstoragefile.h (_virStorageFileMetadata): Add
directory member.
* src/util/virstoragefile.c (absolutePathFromBaseFile): Drop,
replaced by...
(virFindBackingFile): ...better function.
(virStorageFileGetMetadataInternal): Add an argument.
(virStorageFileGetMetadataFromFD, virStorageFileChainLookup)
(virStorageFileGetMetadata): Update callers.
2013-02-06 22:48:15 +00:00
|
|
|
char *absName = NULL;
|
2014-04-08 20:26:02 +00:00
|
|
|
if (virFindBackingFile(owner->directory, name,
|
storage: don't follow backing chain symlinks too eagerly
If you have a qcow2 file /path1/to/file pointed to by symlink
/path2/symlink, and pass qemu /path2/symlink, then qemu treats
a relative backing file in the qcow2 metadata as being relative
to /path2, not /path1/to. Yes, this means that it is possible
to create a qcow2 file where the choice of WHICH directory and
symlink you access its contents from will then determine WHICH
backing file (if any) you actually find; the results can be
rather screwy, but we have to match what qemu does.
Libvirt and qemu default to creating absolute backing file
names, so most users don't hit this. But at least VDSM uses
symlinks and relative backing names alongside the
--reuse-external flags to libvirt snapshot operations, with the
result that libvirt was failing to follow the intended chain of
backing files, and then backing files were not granted the
necessary sVirt permissions to be opened by qemu.
See https://bugzilla.redhat.com/show_bug.cgi?id=903248 for
more gory details. This fixes a regression introduced in
commit 8250783.
I tested this patch by creating the following chain:
ls /home/eblake/Downloads/Fedora.iso # raw file for base
cd /var/lib/libvirt/images
qemu-img create -f qcow2 \
-obacking_file=/home/eblake/Downloads/Fedora.iso,backing_fmt=raw one
mkdir sub
cd sub
ln -s ../one onelink
qemu-img create -f qcow2 \
-obacking_file=../sub/onelink,backing_fmt=qcow2 two
mv two ..
ln -s ../two twolink
qemu-img create -f qcow2 \
-obacking_file=../sub/twolink,backing_fmt=qcow2 three
mv three ..
ln -s ../three threelink
then pointing my domain at /var/lib/libvirt/images/sub/threelink.
Prior to this patch, I got complaints about missing backing
files; afterwards, I was able to verify that the backing chain
(and hence DAC and SELinux relabels) of the entire chain worked.
* src/util/virstoragefile.h (_virStorageFileMetadata): Add
directory member.
* src/util/virstoragefile.c (absolutePathFromBaseFile): Drop,
replaced by...
(virFindBackingFile): ...better function.
(virStorageFileGetMetadataInternal): Add an argument.
(virStorageFileGetMetadataFromFD, virStorageFileChainLookup)
(virStorageFileGetMetadata): Update callers.
2013-02-06 22:48:15 +00:00
|
|
|
NULL, &absName) < 0)
|
|
|
|
goto error;
|
2012-10-12 22:29:14 +00:00
|
|
|
if (absName && STREQ(absName, owner->backingStore)) {
|
|
|
|
VIR_FREE(absName);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
VIR_FREE(absName);
|
|
|
|
}
|
|
|
|
*parent = owner->backingStore;
|
|
|
|
owner = owner->backingMeta;
|
|
|
|
}
|
|
|
|
if (!owner)
|
|
|
|
goto error;
|
|
|
|
if (meta)
|
|
|
|
*meta = owner->backingMeta;
|
|
|
|
return owner->backingStore;
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
error:
|
2012-10-12 22:29:14 +00:00
|
|
|
*parent = NULL;
|
|
|
|
if (meta)
|
|
|
|
*meta = NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
conf: split network host structs to util/
Continuing the refactoring of host-side storage descriptions out
of conf/domain_conf and into util/virstoragefile, this patch
focuses on details about a host name/port/transport as used by
a network storage volume.
* src/conf/domain_conf.h (virDomainDiskProtocolTransport)
(virDomainDiskHostDef, virDomainDiskHostDefClear)
(virDomainDiskHostDefFree, virDomainDiskHostDefCopy): Move...
* src/util/virstoragefile.h (virStorageNetHostTransport)
(virStorageNetHostDef, virStorageNetHostDefClear)
(virStorageNetHostDefFree, virStorageNetHostDefCopy): ...here,
with better names.
* src/util/virstoragefile.c (virStorageNetHostDefClear)
(virStorageNetHostDefFree, virStorageNetHostDefCopy): Moved from...
* src/conf/domain_conf.c (virDomainDiskHostDefClear)
(virDomainDiskHostDefFree, virDomainDiskHostDefCopy): ...here.
(virDomainDiskSourceDefClear, virDomainDiskSourceDefParse)
(virDomainDiskSourceDefFormatInternal): Adjust callers.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefClear):
Likewise.
* src/qemu/qemu_command.c (qemuAddRBDHost)
(qemuParseDriveURIString, qemuParseNBDString)
(qemuBuildNetworkDriveURI, qemuParseCommandLineDisk)
(qemuParseCommandLine, qemuGetDriveSourceString): Likewise.
* src/qemu/qemu_command.h: Likewise.
* src/qemu/qemu_conf.c (qemuAddISCSIPoolSourceHost)
(qemuTranslateDiskSourcePool): Likewise.
* src/qemu/qemu_driver.c
(qemuDomainSnapshotCreateSingleDiskActive)
(qemuDomainSnapshotUndoSingleDiskActive): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGlusterInit): Likewise.
* src/storage/storage_driver.c (virStorageFileFree)
(virStorageFileInitInternal): Likewise.
* src/storage/storage_driver.h (_virStorageFile): Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-26 22:33:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
virStorageNetHostDefClear(virStorageNetHostDefPtr def)
|
|
|
|
{
|
|
|
|
if (!def)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(def->name);
|
|
|
|
VIR_FREE(def->port);
|
|
|
|
VIR_FREE(def->socket);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
virStorageNetHostDefFree(size_t nhosts,
|
|
|
|
virStorageNetHostDefPtr hosts)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!hosts)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < nhosts; i++)
|
|
|
|
virStorageNetHostDefClear(&hosts[i]);
|
|
|
|
|
|
|
|
VIR_FREE(hosts);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
virStorageNetHostDefPtr
|
|
|
|
virStorageNetHostDefCopy(size_t nhosts,
|
|
|
|
virStorageNetHostDefPtr hosts)
|
|
|
|
{
|
|
|
|
virStorageNetHostDefPtr ret = NULL;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(ret, nhosts) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
for (i = 0; i < nhosts; i++) {
|
|
|
|
virStorageNetHostDefPtr src = &hosts[i];
|
|
|
|
virStorageNetHostDefPtr dst = &ret[i];
|
|
|
|
|
|
|
|
dst->transport = src->transport;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(dst->name, src->name) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(dst->port, src->port) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(dst->socket, src->socket) < 0)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virStorageNetHostDefFree(nhosts, ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-03-29 18:00:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
virStorageSourcePoolDefFree(virStorageSourcePoolDefPtr def)
|
|
|
|
{
|
|
|
|
if (!def)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(def->pool);
|
|
|
|
VIR_FREE(def->volume);
|
|
|
|
|
|
|
|
VIR_FREE(def);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
virStorageSourceAuthClear(virStorageSourcePtr def)
|
|
|
|
{
|
|
|
|
VIR_FREE(def->auth.username);
|
|
|
|
|
|
|
|
if (def->auth.secretType == VIR_STORAGE_SECRET_TYPE_USAGE)
|
|
|
|
VIR_FREE(def->auth.secret.usage);
|
|
|
|
|
|
|
|
def->auth.secretType = VIR_STORAGE_SECRET_TYPE_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-08 06:51:06 +00:00
|
|
|
int
|
|
|
|
virStorageSourceGetActualType(virStorageSourcePtr def)
|
|
|
|
{
|
|
|
|
if (def->type == VIR_STORAGE_TYPE_VOLUME && def->srcpool)
|
|
|
|
return def->srcpool->actualtype;
|
|
|
|
|
|
|
|
return def->type;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-29 18:00:38 +00:00
|
|
|
void
|
|
|
|
virStorageSourceClear(virStorageSourcePtr def)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!def)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(def->path);
|
|
|
|
virStorageSourcePoolDefFree(def->srcpool);
|
|
|
|
VIR_FREE(def->driverName);
|
2014-03-30 03:21:06 +00:00
|
|
|
virBitmapFree(def->features);
|
|
|
|
VIR_FREE(def->compat);
|
2014-03-29 18:00:38 +00:00
|
|
|
virStorageEncryptionFree(def->encryption);
|
|
|
|
|
|
|
|
if (def->seclabels) {
|
|
|
|
for (i = 0; i < def->nseclabels; i++)
|
|
|
|
virSecurityDeviceLabelDefFree(def->seclabels[i]);
|
|
|
|
VIR_FREE(def->seclabels);
|
|
|
|
}
|
2014-03-30 03:21:06 +00:00
|
|
|
if (def->perms) {
|
|
|
|
VIR_FREE(def->perms->label);
|
|
|
|
VIR_FREE(def->perms);
|
|
|
|
}
|
|
|
|
VIR_FREE(def->timestamps);
|
2014-03-29 18:00:38 +00:00
|
|
|
|
|
|
|
virStorageNetHostDefFree(def->nhosts, def->hosts);
|
|
|
|
virStorageSourceAuthClear(def);
|
|
|
|
}
|