2008-02-20 15:34:52 +00:00
|
|
|
/*
|
Mark many more strings for translation.
* Makefile.maint (err_func_re): Add to the list and make it readable.
* po/POTFILES.in: Add src/util.c and src/xm_internal.c, and sort.
* src/storage_backend.c: Fix comment.
* src/util.c (virFileLinkPointsTo): Mark a string.
* qemud/remote.c (remoteDispatchClientRequest): Mark strings.
(remoteDispatchOpen, CHECK_CONN, remoteDispatchGetType): Likewise.
(remoteDispatchDomainGetSchedulerType): Likewise.
(remoteDispatchDomainGetSchedulerParameters): Likewise.
(remoteDispatchDomainSetSchedulerParameters): Likewise.
(remoteDispatchDomainBlockStats): Likewise.
(remoteDispatchDomainInterfaceStats): Likewise.
(remoteDispatchDomainAttachDevice, remoteDispatchDomainCreate):
(remoteDispatchDomainDestroy, remoteDispatchDomainDetachDevice):
(remoteDispatchDomainDumpXml, remoteDispatchDomainGetAutostart):
(remoteDispatchDomainGetInfo, remoteDispatchDomainGetMaxMemory):
(remoteDispatchDomainGetMaxVcpus, remoteDispatchDomainGetOsType):
(remoteDispatchDomainGetVcpus): Likewise.
(remoteDispatchDomainMigratePerform): Likewise.
(remoteDispatchListDefinedDomains, remoteDispatchDomainPinVcpu):
(remoteDispatchDomainReboot, remoteDispatchDomainResume):
(remoteDispatchDomainSave, remoteDispatchDomainCoreDump):
(remoteDispatchDomainSetAutostart): Likewise.
(remoteDispatchDomainSetMaxMemory, remoteDispatchDomainSetMemory):
(remoteDispatchDomainSetVcpus, remoteDispatchDomainShutdown):
(remoteDispatchDomainSuspend, remoteDispatchDomainUndefine):
(remoteDispatchListDefinedNetworks, remoteDispatchListDomains):
(remoteDispatchListNetworks, remoteDispatchNetworkCreate):
(remoteDispatchNetworkDestroy, remoteDispatchNetworkDumpXml):
(remoteDispatchNetworkGetAutostart, remoteDispatchNetworkGetBridgeName):
(remoteDispatchNetworkSetAutostart, remoteDispatchNetworkUndefine):
(addrToString, remoteDispatchAuthSaslInit, remoteDispatchAuthSaslStart):
(remoteDispatchAuthSaslStep, remoteDispatchListDefinedStoragePools):
(remoteDispatchListStoragePools, remoteDispatchStoragePoolCreate):
(remoteDispatchStoragePoolBuild, remoteDispatchStoragePoolDestroy):
(remoteDispatchStoragePoolDelete, remoteDispatchStoragePoolRefresh):
(remoteDispatchStoragePoolGetInfo, remoteDispatchStoragePoolDumpXml):
(remoteDispatchStoragePoolGetAutostart): Likewise.
(remoteDispatchStoragePoolSetAutostart):
(remoteDispatchStoragePoolListVolumes):
(remoteDispatchStoragePoolNumOfVolumes):
(remoteDispatchStoragePoolUndefine, remoteDispatchStorageVolCreateXml):
(remoteDispatchStorageVolDelete, remoteDispatchStorageVolGetInfo):
(remoteDispatchStorageVolDumpXml, remoteDispatchStorageVolGetPath):
(remoteDispatchStorageVolLookupByName): Likewise.
* src/qemu_driver.c (qemudOpenMonitor, qemudStartVMDaemon):
(dhcpStartDhcpDaemon, qemudStartNetworkDaemon):
(qemudDomainSuspend, qemudDomainResume, qemudDomainShutdown):
(qemudDomainGetOSType, qemudDomainSetMaxMemory):
(qemudDomainSetMemory, qemudDomainGetInfo, qemudDomainSave):
(qemudDomainRestore, qemudDomainDumpXML, qemudDomainStart):
(qemudDomainUndefine, qemudDomainChangeCDROM):
(qemudDomainAttachDevice, qemudDomainGetAutostart):
(qemudDomainSetAutostart, qemudDomainInterfaceStats):
(qemudNetworkLookupByUUID, qemudNetworkLookupByName):
(qemudNetworkUndefine, qemudNetworkStart, qemudNetworkDestroy):
(qemudNetworkDumpXML, qemudNetworkGetAutostart):
(qemudNetworkSetAutostart): Likewise.
* src/virsh.c (cmdVcpupin, cmdAttachDevice, cmdDetachDevice): Likewise.
* src/xm_internal.c (xenXMConfigCacheRefresh, xenXMDomainPinVcpu): Likewise.
2008-03-27 13:43:01 +00:00
|
|
|
* storage_backend.c: internal storage driver backend contract
|
2008-02-20 15:34:52 +00:00
|
|
|
*
|
2014-04-01 08:52:59 +02:00
|
|
|
* Copyright (C) 2007-2014 Red Hat, Inc.
|
2008-02-20 15:34:52 +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 16:30:55 -06:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 18:06:23 +08:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2008-02-20 15:34:52 +00:00
|
|
|
*
|
|
|
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <string.h>
|
2008-11-17 11:19:33 +00:00
|
|
|
#include <stdio.h>
|
2013-02-11 15:12:16 -07:00
|
|
|
#include <regex.h>
|
2008-02-20 15:34:52 +00:00
|
|
|
#include <sys/types.h>
|
2010-04-28 21:31:16 -06:00
|
|
|
#include <sys/wait.h>
|
2008-02-20 15:34:52 +00:00
|
|
|
#include <unistd.h>
|
2008-02-20 15:38:29 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/stat.h>
|
2009-04-03 14:13:02 +00:00
|
|
|
#include <sys/param.h>
|
2008-02-20 15:38:29 +00:00
|
|
|
#include <dirent.h>
|
2011-05-26 14:05:32 -04:00
|
|
|
#include "dirname.h"
|
2011-03-08 20:06:51 +09:00
|
|
|
#ifdef __linux__
|
|
|
|
# include <sys/ioctl.h>
|
|
|
|
# include <linux/fs.h>
|
2014-07-15 16:49:46 +08:00
|
|
|
# ifndef FS_NOCOW_FL
|
|
|
|
# define FS_NOCOW_FL 0x00800000 /* Do not cow file */
|
|
|
|
# endif
|
2011-03-08 20:06:51 +09:00
|
|
|
#endif
|
2008-02-20 15:38:29 +00:00
|
|
|
|
2012-09-20 13:17:58 +01:00
|
|
|
#if WITH_SELINUX
|
2010-03-09 19:22:22 +01:00
|
|
|
# include <selinux/selinux.h>
|
2008-02-20 15:38:29 +00:00
|
|
|
#endif
|
Standardize use of header files, making internal.h primary.
* qemud/internal.h, qemud/qemud.h: Rename this file so it
doesn't conflict with src/internal.h.
* HACKING: Document how header files should be used.
* qemud/Makefile.am: Add src/ directory to includes.
* qemud/event.c, qemud/mdns.c, qemud/qemud.c, qemud/remote.c,
qemud/remote_protocol.c, qemud/remote_protocol.h,
qemud/remote_protocol.x, src/buf.c, src/libvirt.c,
src/nodeinfo.c, src/qemu_conf.c, src/qemu_driver.c,
src/stats_linux.c, src/storage_backend.c, src/storage_backend_fs.c,
src/storage_backend_iscsi.c, src/storage_backend_logical.c,
src/storage_conf.c, src/storage_driver.c, src/util.c,
src/util.h, src/virsh.c, src/virterror.c, src/xend_internal.c,
src/xml.c, tests/reconnect.c, tests/xmlrpctest.c,
tests/qparamtest.c: Standardize use of header files.
* docs/*, po/*: Rebuild docs.
2008-05-23 08:24:41 +00:00
|
|
|
|
2015-01-23 18:22:34 +08:00
|
|
|
#if HAVE_LINUX_BTRFS_H
|
|
|
|
# include <linux/btrfs.h>
|
|
|
|
#endif
|
|
|
|
|
2009-08-14 20:06:59 +02:00
|
|
|
#include "datatypes.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2009-09-03 10:22:57 +02:00
|
|
|
#include "internal.h"
|
2009-08-14 20:06:59 +02:00
|
|
|
#include "secret_conf.h"
|
2012-12-13 18:01:25 +00:00
|
|
|
#include "viruuid.h"
|
2012-12-13 15:25:48 +00:00
|
|
|
#include "virstoragefile.h"
|
2008-09-05 12:03:45 +00:00
|
|
|
#include "storage_backend.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2011-07-19 12:32:58 -06:00
|
|
|
#include "virfile.h"
|
2012-07-25 09:43:37 +02:00
|
|
|
#include "stat-time.h"
|
2013-04-03 12:36:23 +02:00
|
|
|
#include "virstring.h"
|
2014-04-08 08:42:57 +02:00
|
|
|
#include "virxml.h"
|
2014-07-07 16:50:11 +02:00
|
|
|
#include "fdstream.h"
|
Standardize use of header files, making internal.h primary.
* qemud/internal.h, qemud/qemud.h: Rename this file so it
doesn't conflict with src/internal.h.
* HACKING: Document how header files should be used.
* qemud/Makefile.am: Add src/ directory to includes.
* qemud/event.c, qemud/mdns.c, qemud/qemud.c, qemud/remote.c,
qemud/remote_protocol.c, qemud/remote_protocol.h,
qemud/remote_protocol.x, src/buf.c, src/libvirt.c,
src/nodeinfo.c, src/qemu_conf.c, src/qemu_driver.c,
src/stats_linux.c, src/storage_backend.c, src/storage_backend_fs.c,
src/storage_backend_iscsi.c, src/storage_backend_logical.c,
src/storage_conf.c, src/storage_driver.c, src/util.c,
src/util.h, src/virsh.c, src/virterror.c, src/xend_internal.c,
src/xml.c, tests/reconnect.c, tests/xmlrpctest.c,
tests/qparamtest.c: Standardize use of header files.
* docs/*, po/*: Rebuild docs.
2008-05-23 08:24:41 +00:00
|
|
|
|
2008-11-12 16:28:27 +00:00
|
|
|
#if WITH_STORAGE_LVM
|
2010-03-09 19:22:22 +01:00
|
|
|
# include "storage_backend_logical.h"
|
2008-11-12 16:28:27 +00:00
|
|
|
#endif
|
|
|
|
#if WITH_STORAGE_ISCSI
|
2010-03-09 19:22:22 +01:00
|
|
|
# include "storage_backend_iscsi.h"
|
2008-11-12 16:28:27 +00:00
|
|
|
#endif
|
2009-04-01 16:03:22 +00:00
|
|
|
#if WITH_STORAGE_SCSI
|
2010-03-09 19:22:22 +01:00
|
|
|
# include "storage_backend_scsi.h"
|
2009-04-01 16:03:22 +00:00
|
|
|
#endif
|
2009-09-08 15:47:45 +02:00
|
|
|
#if WITH_STORAGE_MPATH
|
2010-03-09 19:22:22 +01:00
|
|
|
# include "storage_backend_mpath.h"
|
2009-09-08 15:47:45 +02:00
|
|
|
#endif
|
2008-11-12 16:28:27 +00:00
|
|
|
#if WITH_STORAGE_DISK
|
2010-03-09 19:22:22 +01:00
|
|
|
# include "storage_backend_disk.h"
|
2008-11-12 16:28:27 +00:00
|
|
|
#endif
|
|
|
|
#if WITH_STORAGE_DIR
|
2010-03-09 19:22:22 +01:00
|
|
|
# include "storage_backend_fs.h"
|
2008-11-12 16:28:27 +00:00
|
|
|
#endif
|
2012-05-14 11:06:42 +02:00
|
|
|
#if WITH_STORAGE_RBD
|
|
|
|
# include "storage_backend_rbd.h"
|
|
|
|
#endif
|
2012-07-18 20:06:58 +01:00
|
|
|
#if WITH_STORAGE_SHEEPDOG
|
|
|
|
# include "storage_backend_sheepdog.h"
|
|
|
|
#endif
|
2013-11-19 16:26:05 -07:00
|
|
|
#if WITH_STORAGE_GLUSTER
|
|
|
|
# include "storage_backend_gluster.h"
|
|
|
|
#endif
|
2014-07-21 18:38:42 +04:00
|
|
|
#if WITH_STORAGE_ZFS
|
|
|
|
# include "storage_backend_zfs.h"
|
|
|
|
#endif
|
2008-11-12 16:28:27 +00:00
|
|
|
|
2009-01-20 17:13:33 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_STORAGE
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("storage.storage_backend");
|
|
|
|
|
2008-11-12 16:28:27 +00:00
|
|
|
static virStorageBackendPtr backends[] = {
|
|
|
|
#if WITH_STORAGE_DIR
|
|
|
|
&virStorageBackendDirectory,
|
|
|
|
#endif
|
|
|
|
#if WITH_STORAGE_FS
|
|
|
|
&virStorageBackendFileSystem,
|
|
|
|
&virStorageBackendNetFileSystem,
|
|
|
|
#endif
|
|
|
|
#if WITH_STORAGE_LVM
|
|
|
|
&virStorageBackendLogical,
|
|
|
|
#endif
|
|
|
|
#if WITH_STORAGE_ISCSI
|
|
|
|
&virStorageBackendISCSI,
|
|
|
|
#endif
|
2009-04-01 16:03:22 +00:00
|
|
|
#if WITH_STORAGE_SCSI
|
|
|
|
&virStorageBackendSCSI,
|
|
|
|
#endif
|
2009-09-08 15:47:45 +02:00
|
|
|
#if WITH_STORAGE_MPATH
|
|
|
|
&virStorageBackendMpath,
|
|
|
|
#endif
|
2008-11-12 16:28:27 +00:00
|
|
|
#if WITH_STORAGE_DISK
|
|
|
|
&virStorageBackendDisk,
|
2012-05-14 11:06:42 +02:00
|
|
|
#endif
|
|
|
|
#if WITH_STORAGE_RBD
|
|
|
|
&virStorageBackendRBD,
|
2012-07-18 20:06:58 +01:00
|
|
|
#endif
|
|
|
|
#if WITH_STORAGE_SHEEPDOG
|
|
|
|
&virStorageBackendSheepdog,
|
2013-11-19 16:26:05 -07:00
|
|
|
#endif
|
|
|
|
#if WITH_STORAGE_GLUSTER
|
|
|
|
&virStorageBackendGluster,
|
2014-07-21 18:38:42 +04:00
|
|
|
#endif
|
|
|
|
#if WITH_STORAGE_ZFS
|
|
|
|
&virStorageBackendZFS,
|
2008-11-12 16:28:27 +00:00
|
|
|
#endif
|
|
|
|
NULL
|
|
|
|
};
|
2008-11-11 15:52:16 +00:00
|
|
|
|
2014-02-03 16:12:57 +01:00
|
|
|
|
|
|
|
static virStorageFileBackendPtr fileBackends[] = {
|
2014-02-03 16:41:49 +01:00
|
|
|
#if WITH_STORAGE_FS
|
|
|
|
&virStorageFileBackendFile,
|
|
|
|
&virStorageFileBackendBlock,
|
2014-02-03 17:18:24 +01:00
|
|
|
#endif
|
|
|
|
#if WITH_STORAGE_GLUSTER
|
|
|
|
&virStorageFileBackendGluster,
|
2014-02-03 16:41:49 +01:00
|
|
|
#endif
|
2014-02-03 16:12:57 +01:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2009-07-16 12:09:26 -04:00
|
|
|
enum {
|
|
|
|
TOOL_QEMU_IMG,
|
|
|
|
TOOL_KVM_IMG,
|
|
|
|
TOOL_QCOW_CREATE,
|
|
|
|
};
|
|
|
|
|
2011-03-08 20:06:51 +09:00
|
|
|
#define READ_BLOCK_SIZE_DEFAULT (1024 * 1024)
|
|
|
|
#define WRITE_BLOCK_SIZE_DEFAULT (4 * 1024)
|
|
|
|
|
2015-01-23 18:22:34 +08:00
|
|
|
/*
|
|
|
|
* Perform the O(1) btrfs clone operation, if possible.
|
|
|
|
* Upon success, return 0. Otherwise, return -1 and set errno.
|
|
|
|
*/
|
|
|
|
#if HAVE_LINUX_BTRFS_H
|
|
|
|
static inline int
|
|
|
|
btrfsCloneFile(int dest_fd, int src_fd)
|
|
|
|
{
|
|
|
|
return ioctl(dest_fd, BTRFS_IOC_CLONE, src_fd);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static inline int
|
|
|
|
btrfsCloneFile(int dest_fd ATTRIBUTE_UNUSED,
|
|
|
|
int src_fd ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
errno = ENOTSUP;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-10-17 10:23:12 +01:00
|
|
|
static int ATTRIBUTE_NONNULL(2)
|
2010-02-04 21:02:58 +01:00
|
|
|
virStorageBackendCopyToFD(virStorageVolDefPtr vol,
|
2009-06-25 18:34:59 -04:00
|
|
|
virStorageVolDefPtr inputvol,
|
|
|
|
int fd,
|
2009-07-10 14:04:27 -04:00
|
|
|
unsigned long long *total,
|
2015-01-23 18:22:35 +08:00
|
|
|
bool want_sparse,
|
|
|
|
bool reflink_copy)
|
2009-06-25 18:34:59 -04:00
|
|
|
{
|
|
|
|
int inputfd = -1;
|
|
|
|
int amtread = -1;
|
2010-07-19 19:35:30 -04:00
|
|
|
int ret = 0;
|
2011-03-08 20:06:51 +09:00
|
|
|
size_t rbytes = READ_BLOCK_SIZE_DEFAULT;
|
2013-11-07 16:35:10 +08:00
|
|
|
int wbytes = 0;
|
2011-03-08 20:06:51 +09:00
|
|
|
int interval;
|
2013-01-22 09:15:46 -05:00
|
|
|
char *zerobuf = NULL;
|
2009-06-25 18:34:59 -04:00
|
|
|
char *buf = NULL;
|
2011-03-08 20:06:51 +09:00
|
|
|
struct stat st;
|
2009-06-25 18:34:59 -04:00
|
|
|
|
2009-09-03 10:22:57 +02:00
|
|
|
if ((inputfd = open(inputvol->target.path, O_RDONLY)) < 0) {
|
2010-07-19 19:35:30 -04:00
|
|
|
ret = -errno;
|
2010-02-04 21:02:58 +01:00
|
|
|
virReportSystemError(errno,
|
2009-09-03 10:22:57 +02:00
|
|
|
_("could not open input path '%s'"),
|
|
|
|
inputvol->target.path);
|
|
|
|
goto cleanup;
|
2009-06-25 18:34:59 -04:00
|
|
|
}
|
|
|
|
|
2011-03-08 20:06:51 +09:00
|
|
|
#ifdef __linux__
|
2014-11-13 15:25:27 +01:00
|
|
|
if (ioctl(fd, BLKBSZGET, &wbytes) < 0)
|
2011-03-08 20:06:51 +09:00
|
|
|
wbytes = 0;
|
|
|
|
#endif
|
|
|
|
if ((wbytes == 0) && fstat(fd, &st) == 0)
|
|
|
|
wbytes = st.st_blksize;
|
|
|
|
if (wbytes < WRITE_BLOCK_SIZE_DEFAULT)
|
|
|
|
wbytes = WRITE_BLOCK_SIZE_DEFAULT;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(zerobuf, wbytes) < 0) {
|
|
|
|
ret = -errno;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-06-25 18:34:59 -04:00
|
|
|
|
2011-03-08 20:06:51 +09:00
|
|
|
if (VIR_ALLOC_N(buf, rbytes) < 0) {
|
2010-07-19 19:35:30 -04:00
|
|
|
ret = -errno;
|
2009-06-25 18:34:59 -04:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2015-01-23 18:22:35 +08:00
|
|
|
if (reflink_copy) {
|
|
|
|
if (btrfsCloneFile(fd, inputfd) < 0) {
|
|
|
|
ret = -errno;
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("failed to clone files from '%s'"),
|
|
|
|
inputvol->target.path);
|
|
|
|
goto cleanup;
|
|
|
|
} else {
|
|
|
|
VIR_DEBUG("btrfs clone finished.");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-25 18:34:59 -04:00
|
|
|
while (amtread != 0) {
|
|
|
|
int amtleft;
|
|
|
|
|
2012-02-07 14:46:30 -05:00
|
|
|
if (*total < rbytes)
|
|
|
|
rbytes = *total;
|
2009-06-25 18:34:59 -04:00
|
|
|
|
2011-03-08 20:06:51 +09:00
|
|
|
if ((amtread = saferead(inputfd, buf, rbytes)) < 0) {
|
2010-07-19 19:35:30 -04:00
|
|
|
ret = -errno;
|
2010-02-04 21:02:58 +01:00
|
|
|
virReportSystemError(errno,
|
2009-06-25 18:34:59 -04:00
|
|
|
_("failed reading from file '%s'"),
|
|
|
|
inputvol->target.path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2012-02-07 14:46:30 -05:00
|
|
|
*total -= amtread;
|
2009-06-25 18:34:59 -04:00
|
|
|
|
|
|
|
/* Loop over amt read in 512 byte increments, looking for sparse
|
|
|
|
* blocks */
|
|
|
|
amtleft = amtread;
|
|
|
|
do {
|
2011-03-08 20:06:51 +09:00
|
|
|
interval = ((wbytes > amtleft) ? amtleft : wbytes);
|
2009-06-25 18:34:59 -04:00
|
|
|
int offset = amtread - amtleft;
|
|
|
|
|
2013-09-30 19:57:35 +03:00
|
|
|
if (want_sparse && memcmp(buf+offset, zerobuf, interval) == 0) {
|
2009-06-25 18:34:59 -04:00
|
|
|
if (lseek(fd, interval, SEEK_CUR) < 0) {
|
2010-07-19 19:35:30 -04:00
|
|
|
ret = -errno;
|
2010-02-04 21:02:58 +01:00
|
|
|
virReportSystemError(errno,
|
2009-06-25 18:34:59 -04:00
|
|
|
_("cannot extend file '%s'"),
|
|
|
|
vol->target.path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
} else if (safewrite(fd, buf+offset, interval) < 0) {
|
2010-07-19 19:35:30 -04:00
|
|
|
ret = -errno;
|
2010-02-04 21:02:58 +01:00
|
|
|
virReportSystemError(errno,
|
2009-06-25 18:34:59 -04:00
|
|
|
_("failed writing to file '%s'"),
|
|
|
|
vol->target.path);
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
}
|
2011-03-08 20:06:51 +09:00
|
|
|
} while ((amtleft -= interval) > 0);
|
2009-06-25 18:34:59 -04:00
|
|
|
}
|
|
|
|
|
2011-08-18 14:40:03 +02:00
|
|
|
if (fdatasync(fd) < 0) {
|
|
|
|
ret = -errno;
|
|
|
|
virReportSystemError(errno, _("cannot sync data to file '%s'"),
|
|
|
|
vol->target.path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-09 15:48:48 -05:00
|
|
|
if (VIR_CLOSE(inputfd) < 0) {
|
2010-07-19 19:35:30 -04:00
|
|
|
ret = -errno;
|
2010-02-04 21:02:58 +01:00
|
|
|
virReportSystemError(errno,
|
2009-06-25 18:34:59 -04:00
|
|
|
_("cannot close file '%s'"),
|
|
|
|
inputvol->target.path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
inputfd = -1;
|
|
|
|
|
2014-03-25 07:52:40 +01:00
|
|
|
cleanup:
|
2010-11-09 15:48:48 -05:00
|
|
|
VIR_FORCE_CLOSE(inputfd);
|
2009-06-25 18:34:59 -04:00
|
|
|
|
2011-03-08 20:06:51 +09:00
|
|
|
VIR_FREE(zerobuf);
|
2009-12-11 00:54:49 +01:00
|
|
|
VIR_FREE(buf);
|
|
|
|
|
2009-06-25 18:34:59 -04:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-07-09 19:14:51 -04:00
|
|
|
static int
|
2010-02-04 21:02:58 +01:00
|
|
|
virStorageBackendCreateBlockFrom(virConnectPtr conn ATTRIBUTE_UNUSED,
|
2010-01-21 00:41:52 +01:00
|
|
|
virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
|
2009-07-09 19:14:51 -04:00
|
|
|
virStorageVolDefPtr vol,
|
|
|
|
virStorageVolDefPtr inputvol,
|
2011-07-06 16:51:23 -06:00
|
|
|
unsigned int flags)
|
2009-07-09 19:14:51 -04:00
|
|
|
{
|
|
|
|
int fd = -1;
|
|
|
|
int ret = -1;
|
|
|
|
unsigned long long remain;
|
2010-01-21 00:41:52 +01:00
|
|
|
struct stat st;
|
|
|
|
gid_t gid;
|
|
|
|
uid_t uid;
|
2015-04-27 16:48:05 -04:00
|
|
|
mode_t mode;
|
2015-01-23 18:22:35 +08:00
|
|
|
bool reflink_copy = false;
|
2009-07-09 19:14:51 -04:00
|
|
|
|
2015-01-23 18:22:35 +08:00
|
|
|
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA |
|
|
|
|
VIR_STORAGE_VOL_CREATE_REFLINK,
|
|
|
|
-1);
|
2013-06-05 09:38:41 +02:00
|
|
|
|
|
|
|
if (flags & VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("metadata preallocation is not supported for block "
|
|
|
|
"volumes"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-07-06 16:51:23 -06:00
|
|
|
|
2015-01-23 18:22:35 +08:00
|
|
|
if (flags & VIR_STORAGE_VOL_CREATE_REFLINK)
|
|
|
|
reflink_copy = true;
|
|
|
|
|
2009-07-09 19:14:51 -04:00
|
|
|
if ((fd = open(vol->target.path, O_RDWR)) < 0) {
|
2010-02-04 21:02:58 +01:00
|
|
|
virReportSystemError(errno,
|
2009-07-09 19:14:51 -04:00
|
|
|
_("cannot create path '%s'"),
|
|
|
|
vol->target.path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2015-06-26 17:13:26 +05:30
|
|
|
remain = vol->target.capacity;
|
2009-07-09 19:14:51 -04:00
|
|
|
|
|
|
|
if (inputvol) {
|
2010-02-04 21:02:58 +01:00
|
|
|
int res = virStorageBackendCopyToFD(vol, inputvol,
|
2015-01-23 18:22:35 +08:00
|
|
|
fd, &remain, false, reflink_copy);
|
2009-07-09 19:14:51 -04:00
|
|
|
if (res < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2010-01-21 00:41:52 +01:00
|
|
|
if (fstat(fd, &st) == -1) {
|
2010-02-04 21:02:58 +01:00
|
|
|
virReportSystemError(errno, _("stat of '%s' failed"),
|
2010-01-21 00:41:52 +01:00
|
|
|
vol->target.path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-03-29 20:27:44 -06:00
|
|
|
uid = (vol->target.perms->uid != st.st_uid) ? vol->target.perms->uid
|
|
|
|
: (uid_t) -1;
|
|
|
|
gid = (vol->target.perms->gid != st.st_gid) ? vol->target.perms->gid
|
|
|
|
: (gid_t) -1;
|
2013-02-22 17:41:32 +01:00
|
|
|
if (((uid != (uid_t) -1) || (gid != (gid_t) -1))
|
2010-03-04 17:35:27 -05:00
|
|
|
&& (fchown(fd, uid, gid) < 0)) {
|
2010-02-04 21:02:58 +01:00
|
|
|
virReportSystemError(errno,
|
2010-01-21 00:41:52 +01:00
|
|
|
_("cannot chown '%s' to (%u, %u)"),
|
2013-02-22 17:43:15 +01:00
|
|
|
vol->target.path, (unsigned int) uid,
|
|
|
|
(unsigned int) gid);
|
2010-01-21 00:41:52 +01:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2015-04-27 16:48:05 -04:00
|
|
|
|
|
|
|
mode = (vol->target.perms->mode == (mode_t) -1 ?
|
|
|
|
VIR_STORAGE_DEFAULT_VOL_PERM_MODE : vol->target.perms->mode);
|
|
|
|
if (fchmod(fd, mode) < 0) {
|
2010-02-04 21:02:58 +01:00
|
|
|
virReportSystemError(errno,
|
2010-01-21 00:41:52 +01:00
|
|
|
_("cannot set mode of '%s' to %04o"),
|
2015-04-27 16:48:05 -04:00
|
|
|
vol->target.path, mode);
|
2010-01-21 00:41:52 +01:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2010-11-09 15:48:48 -05:00
|
|
|
if (VIR_CLOSE(fd) < 0) {
|
2010-02-04 21:02:58 +01:00
|
|
|
virReportSystemError(errno,
|
2009-07-09 19:14:51 -04:00
|
|
|
_("cannot close file '%s'"),
|
|
|
|
vol->target.path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
fd = -1;
|
|
|
|
|
|
|
|
ret = 0;
|
2014-03-25 07:52:40 +01:00
|
|
|
cleanup:
|
2010-11-09 15:48:48 -05:00
|
|
|
VIR_FORCE_CLOSE(fd);
|
2009-07-09 19:14:51 -04:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-03-03 17:19:12 -07:00
|
|
|
static int
|
|
|
|
createRawFile(int fd, virStorageVolDefPtr vol,
|
2015-01-23 18:22:35 +08:00
|
|
|
virStorageVolDefPtr inputvol,
|
|
|
|
bool reflink_copy)
|
2011-03-03 17:19:12 -07:00
|
|
|
{
|
2013-10-07 15:57:22 +02:00
|
|
|
bool need_alloc = true;
|
2010-02-19 18:12:01 +01:00
|
|
|
int ret = 0;
|
2015-07-03 12:47:02 +02:00
|
|
|
unsigned long long pos = 0;
|
2010-01-21 00:41:52 +01:00
|
|
|
|
2015-06-26 17:13:26 +05:30
|
|
|
/* If the new allocation is lower than the capacity of the original file,
|
|
|
|
* the cloned volume will be sparse */
|
|
|
|
if (inputvol &&
|
|
|
|
vol->target.allocation < inputvol->target.capacity)
|
|
|
|
need_alloc = false;
|
|
|
|
|
2009-07-16 12:09:26 -04:00
|
|
|
/* Seek to the final size, so the capacity is available upfront
|
|
|
|
* for progress reporting */
|
conf: track sizes directly in source struct
One of the features of qcow2 is that a wrapper file can have
more capacity than its backing file from the guest's perspective;
what's more, sparse files make tracking allocation of both
the active and backing file worthwhile. As such, it makes
more sense to show allocation numbers for each file in a chain,
and not just the top-level file. This sets up the fields for
the tracking, although it does not modify XML to display any
new information.
* src/util/virstoragefile.h (_virStorageSource): Add fields.
* src/conf/storage_conf.h (_virStorageVolDef): Drop redundant
fields.
* src/storage/storage_backend.c (virStorageBackendCreateBlockFrom)
(createRawFile, virStorageBackendCreateQemuImgCmd)
(virStorageBackendCreateQcowCreate): Update clients.
* src/storage/storage_driver.c (storageVolDelete)
(storageVolCreateXML, storageVolCreateXMLFrom, storageVolResize)
(storageVolWipeInternal, storageVolGetInfo): Likewise.
* src/storage/storage_backend_fs.c (virStorageBackendProbeTarget)
(virStorageBackendFileSystemRefresh)
(virStorageBackendFileSystemVolResize)
(virStorageBackendFileSystemVolRefresh): Likewise.
* src/storage/storage_backend_logical.c
(virStorageBackendLogicalMakeVol)
(virStorageBackendLogicalCreateVol): Likewise.
* src/storage/storage_backend_scsi.c
(virStorageBackendSCSINewLun): Likewise.
* src/storage/storage_backend_mpath.c
(virStorageBackendMpathNewVol): Likewise.
* src/storage/storage_backend_rbd.c
(volStorageBackendRBDRefreshVolInfo)
(virStorageBackendRBDCreateImage): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol): Likewise.
* src/storage/storage_backend_sheepdog.c
(virStorageBackendSheepdogBuildVol)
(virStorageBackendSheepdogParseVdiList): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageBackendGlusterRefreshVol): Likewise.
* src/conf/storage_conf.c (virStorageVolDefFormat)
(virStorageVolDefParseXML): Likewise.
* src/test/test_driver.c (testOpenVolumesForPool)
(testStorageVolCreateXML, testStorageVolCreateXMLFrom)
(testStorageVolDelete, testStorageVolGetInfo): Likewise.
* src/esx/esx_storage_backend_iscsi.c (esxStorageVolGetXMLDesc):
Likewise.
* src/esx/esx_storage_backend_vmfs.c (esxStorageVolGetXMLDesc)
(esxStorageVolCreateXML): Likewise.
* src/parallels/parallels_driver.c (parallelsAddHddByVolume):
Likewise.
* src/parallels/parallels_storage.c (parallelsDiskDescParseNode)
(parallelsStorageVolDefineXML, parallelsStorageVolCreateXMLFrom)
(parallelsStorageVolDefRemove, parallelsStorageVolGetInfo):
Likewise.
* src/vbox/vbox_tmpl.c (vboxStorageVolCreateXML)
(vboxStorageVolGetXMLDesc): Likewise.
* tests/storagebackendsheepdogtest.c (test_vdi_list_parser):
Likewise.
* src/phyp/phyp_driver.c (phypStorageVolCreateXML): Likewise.
2014-04-01 17:43:36 -06:00
|
|
|
if (ftruncate(fd, vol->target.capacity) < 0) {
|
2010-07-19 19:25:58 -04:00
|
|
|
ret = -errno;
|
2010-02-04 21:02:58 +01:00
|
|
|
virReportSystemError(errno,
|
2009-07-16 12:09:26 -04:00
|
|
|
_("cannot extend file '%s'"),
|
2011-03-03 17:19:12 -07:00
|
|
|
vol->target.path);
|
2009-07-16 12:09:26 -04:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-10-04 17:25:13 -06:00
|
|
|
/* Avoid issues with older kernel's <linux/fs.h> namespace pollution. */
|
|
|
|
#if HAVE_FALLOCATE - 0
|
2013-09-30 19:57:35 +03:00
|
|
|
/* Try to preallocate all requested disk space, but fall back to
|
2013-10-09 09:03:25 -04:00
|
|
|
* other methods if this fails with ENOSYS or EOPNOTSUPP. If allocation
|
|
|
|
* is 0 (or less than 0), then fallocate will fail with EINVAL.
|
2013-09-30 19:57:35 +03:00
|
|
|
* NOTE: do not use posix_fallocate; posix_fallocate falls back
|
|
|
|
* to writing zeroes block by block in case fallocate isn't
|
|
|
|
* available, and since we're going to copy data from another
|
|
|
|
* file it doesn't make sense to write the file twice. */
|
2015-06-26 17:13:26 +05:30
|
|
|
if (vol->target.allocation && need_alloc) {
|
conf: track sizes directly in source struct
One of the features of qcow2 is that a wrapper file can have
more capacity than its backing file from the guest's perspective;
what's more, sparse files make tracking allocation of both
the active and backing file worthwhile. As such, it makes
more sense to show allocation numbers for each file in a chain,
and not just the top-level file. This sets up the fields for
the tracking, although it does not modify XML to display any
new information.
* src/util/virstoragefile.h (_virStorageSource): Add fields.
* src/conf/storage_conf.h (_virStorageVolDef): Drop redundant
fields.
* src/storage/storage_backend.c (virStorageBackendCreateBlockFrom)
(createRawFile, virStorageBackendCreateQemuImgCmd)
(virStorageBackendCreateQcowCreate): Update clients.
* src/storage/storage_driver.c (storageVolDelete)
(storageVolCreateXML, storageVolCreateXMLFrom, storageVolResize)
(storageVolWipeInternal, storageVolGetInfo): Likewise.
* src/storage/storage_backend_fs.c (virStorageBackendProbeTarget)
(virStorageBackendFileSystemRefresh)
(virStorageBackendFileSystemVolResize)
(virStorageBackendFileSystemVolRefresh): Likewise.
* src/storage/storage_backend_logical.c
(virStorageBackendLogicalMakeVol)
(virStorageBackendLogicalCreateVol): Likewise.
* src/storage/storage_backend_scsi.c
(virStorageBackendSCSINewLun): Likewise.
* src/storage/storage_backend_mpath.c
(virStorageBackendMpathNewVol): Likewise.
* src/storage/storage_backend_rbd.c
(volStorageBackendRBDRefreshVolInfo)
(virStorageBackendRBDCreateImage): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol): Likewise.
* src/storage/storage_backend_sheepdog.c
(virStorageBackendSheepdogBuildVol)
(virStorageBackendSheepdogParseVdiList): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageBackendGlusterRefreshVol): Likewise.
* src/conf/storage_conf.c (virStorageVolDefFormat)
(virStorageVolDefParseXML): Likewise.
* src/test/test_driver.c (testOpenVolumesForPool)
(testStorageVolCreateXML, testStorageVolCreateXMLFrom)
(testStorageVolDelete, testStorageVolGetInfo): Likewise.
* src/esx/esx_storage_backend_iscsi.c (esxStorageVolGetXMLDesc):
Likewise.
* src/esx/esx_storage_backend_vmfs.c (esxStorageVolGetXMLDesc)
(esxStorageVolCreateXML): Likewise.
* src/parallels/parallels_driver.c (parallelsAddHddByVolume):
Likewise.
* src/parallels/parallels_storage.c (parallelsDiskDescParseNode)
(parallelsStorageVolDefineXML, parallelsStorageVolCreateXMLFrom)
(parallelsStorageVolDefRemove, parallelsStorageVolGetInfo):
Likewise.
* src/vbox/vbox_tmpl.c (vboxStorageVolCreateXML)
(vboxStorageVolGetXMLDesc): Likewise.
* tests/storagebackendsheepdogtest.c (test_vdi_list_parser):
Likewise.
* src/phyp/phyp_driver.c (phypStorageVolCreateXML): Likewise.
2014-04-01 17:43:36 -06:00
|
|
|
if (fallocate(fd, 0, 0, vol->target.allocation) == 0) {
|
2013-10-09 09:03:25 -04:00
|
|
|
need_alloc = false;
|
|
|
|
} else if (errno != ENOSYS && errno != EOPNOTSUPP) {
|
|
|
|
ret = -errno;
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("cannot allocate %llu bytes in file '%s'"),
|
conf: track sizes directly in source struct
One of the features of qcow2 is that a wrapper file can have
more capacity than its backing file from the guest's perspective;
what's more, sparse files make tracking allocation of both
the active and backing file worthwhile. As such, it makes
more sense to show allocation numbers for each file in a chain,
and not just the top-level file. This sets up the fields for
the tracking, although it does not modify XML to display any
new information.
* src/util/virstoragefile.h (_virStorageSource): Add fields.
* src/conf/storage_conf.h (_virStorageVolDef): Drop redundant
fields.
* src/storage/storage_backend.c (virStorageBackendCreateBlockFrom)
(createRawFile, virStorageBackendCreateQemuImgCmd)
(virStorageBackendCreateQcowCreate): Update clients.
* src/storage/storage_driver.c (storageVolDelete)
(storageVolCreateXML, storageVolCreateXMLFrom, storageVolResize)
(storageVolWipeInternal, storageVolGetInfo): Likewise.
* src/storage/storage_backend_fs.c (virStorageBackendProbeTarget)
(virStorageBackendFileSystemRefresh)
(virStorageBackendFileSystemVolResize)
(virStorageBackendFileSystemVolRefresh): Likewise.
* src/storage/storage_backend_logical.c
(virStorageBackendLogicalMakeVol)
(virStorageBackendLogicalCreateVol): Likewise.
* src/storage/storage_backend_scsi.c
(virStorageBackendSCSINewLun): Likewise.
* src/storage/storage_backend_mpath.c
(virStorageBackendMpathNewVol): Likewise.
* src/storage/storage_backend_rbd.c
(volStorageBackendRBDRefreshVolInfo)
(virStorageBackendRBDCreateImage): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol): Likewise.
* src/storage/storage_backend_sheepdog.c
(virStorageBackendSheepdogBuildVol)
(virStorageBackendSheepdogParseVdiList): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageBackendGlusterRefreshVol): Likewise.
* src/conf/storage_conf.c (virStorageVolDefFormat)
(virStorageVolDefParseXML): Likewise.
* src/test/test_driver.c (testOpenVolumesForPool)
(testStorageVolCreateXML, testStorageVolCreateXMLFrom)
(testStorageVolDelete, testStorageVolGetInfo): Likewise.
* src/esx/esx_storage_backend_iscsi.c (esxStorageVolGetXMLDesc):
Likewise.
* src/esx/esx_storage_backend_vmfs.c (esxStorageVolGetXMLDesc)
(esxStorageVolCreateXML): Likewise.
* src/parallels/parallels_driver.c (parallelsAddHddByVolume):
Likewise.
* src/parallels/parallels_storage.c (parallelsDiskDescParseNode)
(parallelsStorageVolDefineXML, parallelsStorageVolCreateXMLFrom)
(parallelsStorageVolDefRemove, parallelsStorageVolGetInfo):
Likewise.
* src/vbox/vbox_tmpl.c (vboxStorageVolCreateXML)
(vboxStorageVolGetXMLDesc): Likewise.
* tests/storagebackendsheepdogtest.c (test_vdi_list_parser):
Likewise.
* src/phyp/phyp_driver.c (phypStorageVolCreateXML): Likewise.
2014-04-01 17:43:36 -06:00
|
|
|
vol->target.allocation, vol->target.path);
|
2013-10-09 09:03:25 -04:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-09-30 19:57:35 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-03-03 17:19:12 -07:00
|
|
|
if (inputvol) {
|
2015-06-26 17:13:26 +05:30
|
|
|
unsigned long long remain = inputvol->target.capacity;
|
2013-09-30 19:57:35 +03:00
|
|
|
/* allow zero blocks to be skipped if we've requested sparse
|
|
|
|
* allocation (allocation < capacity) or we have already
|
|
|
|
* been able to allocate the required space. */
|
2015-01-23 18:22:35 +08:00
|
|
|
ret = virStorageBackendCopyToFD(vol, inputvol, fd, &remain,
|
2015-06-26 17:13:26 +05:30
|
|
|
!need_alloc, reflink_copy);
|
2014-11-13 15:25:27 +01:00
|
|
|
if (ret < 0)
|
2009-07-16 12:09:26 -04:00
|
|
|
goto cleanup;
|
2015-07-03 12:47:02 +02:00
|
|
|
|
2015-06-26 17:13:26 +05:30
|
|
|
/* If the new allocation is greater than the original capacity,
|
|
|
|
* but fallocate failed, fill the rest with zeroes.
|
|
|
|
*/
|
|
|
|
pos = inputvol->target.capacity - remain;
|
2009-07-16 12:09:26 -04:00
|
|
|
}
|
|
|
|
|
2015-07-03 12:47:02 +02:00
|
|
|
if (need_alloc) {
|
|
|
|
if (safezero(fd, pos, vol->target.allocation - pos) < 0) {
|
2013-06-10 11:10:31 -04:00
|
|
|
ret = -errno;
|
|
|
|
virReportSystemError(errno, _("cannot fill file '%s'"),
|
|
|
|
vol->target.path);
|
|
|
|
goto cleanup;
|
2009-07-16 12:09:26 -04:00
|
|
|
}
|
2010-07-19 18:59:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fsync(fd) < 0) {
|
2010-07-19 19:25:58 -04:00
|
|
|
ret = -errno;
|
2010-07-19 18:59:07 -04:00
|
|
|
virReportSystemError(errno, _("cannot sync data to file '%s'"),
|
2011-03-03 17:19:12 -07:00
|
|
|
vol->target.path);
|
2010-07-19 18:59:07 -04:00
|
|
|
goto cleanup;
|
2009-07-16 12:09:26 -04:00
|
|
|
}
|
|
|
|
|
2014-03-25 07:52:40 +01:00
|
|
|
cleanup:
|
2010-02-19 18:12:01 +01:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
virStorageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
|
|
virStoragePoolObjPtr pool,
|
|
|
|
virStorageVolDefPtr vol,
|
|
|
|
virStorageVolDefPtr inputvol,
|
2011-03-03 12:30:35 -07:00
|
|
|
unsigned int flags)
|
2010-02-19 18:12:01 +01:00
|
|
|
{
|
|
|
|
int ret = -1;
|
2011-03-03 12:30:35 -07:00
|
|
|
int fd = -1;
|
|
|
|
int operation_flags;
|
2015-01-23 18:22:35 +08:00
|
|
|
bool reflink_copy = false;
|
2011-03-03 12:30:35 -07:00
|
|
|
|
2015-01-23 18:22:35 +08:00
|
|
|
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA |
|
|
|
|
VIR_STORAGE_VOL_CREATE_REFLINK,
|
|
|
|
-1);
|
2013-06-05 09:38:41 +02:00
|
|
|
|
|
|
|
if (flags & VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("metadata preallocation is not supported for raw "
|
|
|
|
"volumes"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2010-02-19 18:12:01 +01:00
|
|
|
|
2015-02-17 16:57:02 +01:00
|
|
|
if (vol->target.backingStore) {
|
|
|
|
virReportError(VIR_ERR_NO_SUPPORT, "%s",
|
|
|
|
_("backing storage not supported for raw volumes"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2015-01-23 18:22:35 +08:00
|
|
|
if (flags & VIR_STORAGE_VOL_CREATE_REFLINK)
|
|
|
|
reflink_copy = true;
|
|
|
|
|
|
|
|
|
2010-02-19 18:12:01 +01:00
|
|
|
if (vol->target.encryption != NULL) {
|
2013-06-05 09:41:38 +02:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("storage pool does not support encrypted volumes"));
|
2009-07-16 12:09:26 -04:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2010-02-19 18:12:01 +01:00
|
|
|
|
util: refactor virFileOpenAs
virFileOpenAs previously would only try opening a file as the current
user, or as a different user, but wouldn't try both methods in a
single call. This made it cumbersome to use as a replacement for
open(2). Additionally, it had a lot of historical baggage that led to
it being difficult to understand.
This patch refactors virFileOpenAs in the following ways:
* reorganize the code so that everything dealing with both the parent
and child sides of the "fork+setuid+setgid+open" method are in a
separate function. This makes the public function easier to understand.
* Allow a single call to virFileOpenAs() to first attempt the open as
the current user, and if that fails to automatically re-try after
doing fork+setuid (if deemed appropriate, i.e. errno indicates it
would now be successful, and the file is on a networkFS). This makes
it possible (in many, but possibly not all, cases) to drop-in
virFileOpenAs() as a replacement for open(2).
(NB: currently qemuOpenFile() calls virFileOpenAs() twice, once
without forking, then again with forking. That unfortunately can't
be changed without at least some discussion of the ramifications,
because the requested file permissions are different in each case,
which is something that a single call to virFileOpenAs() can't deal
with.)
* Add a flag so that any fchown() of the file to a different uid:gid
is explicitly requested when the function is called, rather than it
being implied by the presence of the O_CREAT flag. This just makes
for less subtle surprises to consumers. (Commit
b1643dc15c5de886fefe56ad18608d65f1325a2c added the check for O_CREAT
before forcing ownership. This patch just makes that restriction
more explicit.)
* If either the uid or gid is specified as "-1", virFileOpenAs will
interpret this to mean "the current [gu]id".
All current consumers of virFileOpenAs should retain their present
behavior (after a few minor changes to their setup code and
arguments).
2012-01-13 15:26:45 -05:00
|
|
|
operation_flags = VIR_FILE_OPEN_FORCE_MODE | VIR_FILE_OPEN_FORCE_OWNER;
|
2011-03-03 12:30:35 -07:00
|
|
|
if (pool->def->type == VIR_STORAGE_POOL_NETFS)
|
util: refactor virFileOpenAs
virFileOpenAs previously would only try opening a file as the current
user, or as a different user, but wouldn't try both methods in a
single call. This made it cumbersome to use as a replacement for
open(2). Additionally, it had a lot of historical baggage that led to
it being difficult to understand.
This patch refactors virFileOpenAs in the following ways:
* reorganize the code so that everything dealing with both the parent
and child sides of the "fork+setuid+setgid+open" method are in a
separate function. This makes the public function easier to understand.
* Allow a single call to virFileOpenAs() to first attempt the open as
the current user, and if that fails to automatically re-try after
doing fork+setuid (if deemed appropriate, i.e. errno indicates it
would now be successful, and the file is on a networkFS). This makes
it possible (in many, but possibly not all, cases) to drop-in
virFileOpenAs() as a replacement for open(2).
(NB: currently qemuOpenFile() calls virFileOpenAs() twice, once
without forking, then again with forking. That unfortunately can't
be changed without at least some discussion of the ramifications,
because the requested file permissions are different in each case,
which is something that a single call to virFileOpenAs() can't deal
with.)
* Add a flag so that any fchown() of the file to a different uid:gid
is explicitly requested when the function is called, rather than it
being implied by the presence of the O_CREAT flag. This just makes
for less subtle surprises to consumers. (Commit
b1643dc15c5de886fefe56ad18608d65f1325a2c added the check for O_CREAT
before forcing ownership. This patch just makes that restriction
more explicit.)
* If either the uid or gid is specified as "-1", virFileOpenAs will
interpret this to mean "the current [gu]id".
All current consumers of virFileOpenAs should retain their present
behavior (after a few minor changes to their setup code and
arguments).
2012-01-13 15:26:45 -05:00
|
|
|
operation_flags |= VIR_FILE_OPEN_FORK;
|
2011-03-03 12:30:35 -07:00
|
|
|
|
2011-03-22 13:15:44 -06:00
|
|
|
if ((fd = virFileOpenAs(vol->target.path,
|
|
|
|
O_RDWR | O_CREAT | O_EXCL,
|
2015-04-27 16:48:05 -04:00
|
|
|
(vol->target.perms->mode ?
|
|
|
|
VIR_STORAGE_DEFAULT_VOL_PERM_MODE :
|
|
|
|
vol->target.perms->mode),
|
2014-03-29 20:27:44 -06:00
|
|
|
vol->target.perms->uid,
|
|
|
|
vol->target.perms->gid,
|
2011-03-22 13:15:44 -06:00
|
|
|
operation_flags)) < 0) {
|
2011-03-03 12:30:35 -07:00
|
|
|
virReportSystemError(-fd,
|
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 15:02:14 -04:00
|
|
|
_("Failed to create file '%s'"),
|
2011-03-03 12:30:35 -07:00
|
|
|
vol->target.path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-07-15 16:49:46 +08:00
|
|
|
if (vol->target.nocow) {
|
|
|
|
#ifdef __linux__
|
|
|
|
int attr;
|
|
|
|
|
|
|
|
/* Set NOCOW flag. This is an optimisation for btrfs.
|
|
|
|
* The FS_IOC_SETFLAGS ioctl return value will be ignored since any
|
2014-07-17 12:18:56 +02:00
|
|
|
* failure of this operation should not block the volume creation.
|
2014-07-15 16:49:46 +08:00
|
|
|
*/
|
2014-07-17 12:18:56 +02:00
|
|
|
if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0) {
|
|
|
|
virReportSystemError(errno, "%s", _("Failed to get fs flags"));
|
|
|
|
} else {
|
2014-07-15 16:49:46 +08:00
|
|
|
attr |= FS_NOCOW_FL;
|
2014-07-17 12:18:56 +02:00
|
|
|
if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Failed to set NOCOW flag"));
|
|
|
|
}
|
2014-07-15 16:49:46 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-01-23 18:22:35 +08:00
|
|
|
if ((ret = createRawFile(fd, vol, inputvol, reflink_copy)) < 0)
|
2011-07-04 16:13:23 +08:00
|
|
|
/* createRawFile already reported the exact error. */
|
2011-03-03 12:30:35 -07:00
|
|
|
ret = -1;
|
2009-07-16 12:09:26 -04:00
|
|
|
|
2014-03-25 07:52:40 +01:00
|
|
|
cleanup:
|
2011-03-03 12:30:35 -07:00
|
|
|
VIR_FORCE_CLOSE(fd);
|
2009-07-16 12:09:26 -04:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
Fix UUID handling in secrets/storage encryption APIs
Convert all the secret/storage encryption APIs / wire format to
handle UUIDs in raw format instead of non-canonical printable
format. Guarentees data format correctness.
* docs/schemas/storageencryption.rng: Make UUID mandatory for a secret
and validate fully
* docs/schemas/secret.rng: Fully validate UUID
* include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add
virSecretLookupByUUID and virSecretGetUUID. Make
virSecretGetUUIDString follow normal API design pattern
* python/generator.py: Skip generation of virSecretGetUUID,
virSecretGetUUIDString and virSecretLookupByUUID
* python/libvir.c, python/libvirt-python-api.xml: Manual impl
of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID
* qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/
Fix get_nonnull_secret/make_nonnull_secret to use unsigned char
* qemud/remote_protocol.x: Fix remote_nonnull_secret to use a
remote_uuid instead of remote_nonnull_string for UUID field.
Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to
REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an
remote_uuid value
* qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h,
qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h,
qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate
* src/datatypes.h, src/datatypes.c: Store UUID in raw format instead
of printable. Change virGetSecret to use raw format UUID
* src/driver.h: Rename virDrvSecretLookupByUUIDString to
virDrvSecretLookupByUUID and use raw format UUID
* src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID
and re-implement virSecretLookupByUUIDString and
virSecretGetUUIDString in terms of those
* src/libvirt_public.syms: Add virSecretLookupByUUID and
virSecretGetUUID
* src/remote_internal.c: Rename remoteSecretLookupByUUIDString
to remoteSecretLookupByUUID. Fix typo in args for
remoteSecretDefineXML impl. Use raw UUID format for
get_nonnull_secret and make_nonnull_secret
* src/storage_encryption_conf.c, src/storage_encryption_conf.h:
Storage UUID in raw format, and require it to be present in
XML. Use UUID parser to validate.
* secret_conf.h, secret_conf.c: Generate a UUID if none is provided.
Storage UUID in raw format.
* src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets
in a filed with printable UUID, instead of base64 UUID.
* src/virsh.c: Adjust for changed public API contract of
virSecretGetUUIDString.
* src/storage_Backend.c: DOn't undefine secret we just generated
upon successful volume creation. Fix to handle raw UUIDs. Generate
a non-clashing UUID
* src/qemu_driver.c: Change to use lookupByUUID instead of
lookupByUUIDString
2009-09-10 17:44:12 +01:00
|
|
|
static int
|
|
|
|
virStorageGenerateSecretUUID(virConnectPtr conn,
|
|
|
|
unsigned char *uuid)
|
|
|
|
{
|
|
|
|
unsigned attempt;
|
|
|
|
|
|
|
|
for (attempt = 0; attempt < 65536; attempt++) {
|
|
|
|
virSecretPtr tmp;
|
|
|
|
if (virUUIDGenerate(uuid) < 0) {
|
2012-07-18 12:38:29 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("unable to generate uuid"));
|
Fix UUID handling in secrets/storage encryption APIs
Convert all the secret/storage encryption APIs / wire format to
handle UUIDs in raw format instead of non-canonical printable
format. Guarentees data format correctness.
* docs/schemas/storageencryption.rng: Make UUID mandatory for a secret
and validate fully
* docs/schemas/secret.rng: Fully validate UUID
* include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add
virSecretLookupByUUID and virSecretGetUUID. Make
virSecretGetUUIDString follow normal API design pattern
* python/generator.py: Skip generation of virSecretGetUUID,
virSecretGetUUIDString and virSecretLookupByUUID
* python/libvir.c, python/libvirt-python-api.xml: Manual impl
of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID
* qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/
Fix get_nonnull_secret/make_nonnull_secret to use unsigned char
* qemud/remote_protocol.x: Fix remote_nonnull_secret to use a
remote_uuid instead of remote_nonnull_string for UUID field.
Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to
REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an
remote_uuid value
* qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h,
qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h,
qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate
* src/datatypes.h, src/datatypes.c: Store UUID in raw format instead
of printable. Change virGetSecret to use raw format UUID
* src/driver.h: Rename virDrvSecretLookupByUUIDString to
virDrvSecretLookupByUUID and use raw format UUID
* src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID
and re-implement virSecretLookupByUUIDString and
virSecretGetUUIDString in terms of those
* src/libvirt_public.syms: Add virSecretLookupByUUID and
virSecretGetUUID
* src/remote_internal.c: Rename remoteSecretLookupByUUIDString
to remoteSecretLookupByUUID. Fix typo in args for
remoteSecretDefineXML impl. Use raw UUID format for
get_nonnull_secret and make_nonnull_secret
* src/storage_encryption_conf.c, src/storage_encryption_conf.h:
Storage UUID in raw format, and require it to be present in
XML. Use UUID parser to validate.
* secret_conf.h, secret_conf.c: Generate a UUID if none is provided.
Storage UUID in raw format.
* src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets
in a filed with printable UUID, instead of base64 UUID.
* src/virsh.c: Adjust for changed public API contract of
virSecretGetUUIDString.
* src/storage_Backend.c: DOn't undefine secret we just generated
upon successful volume creation. Fix to handle raw UUIDs. Generate
a non-clashing UUID
* src/qemu_driver.c: Change to use lookupByUUID instead of
lookupByUUIDString
2009-09-10 17:44:12 +01:00
|
|
|
return -1;
|
|
|
|
}
|
2013-04-22 18:26:01 +01:00
|
|
|
tmp = conn->secretDriver->secretLookupByUUID(conn, uuid);
|
Fix UUID handling in secrets/storage encryption APIs
Convert all the secret/storage encryption APIs / wire format to
handle UUIDs in raw format instead of non-canonical printable
format. Guarentees data format correctness.
* docs/schemas/storageencryption.rng: Make UUID mandatory for a secret
and validate fully
* docs/schemas/secret.rng: Fully validate UUID
* include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add
virSecretLookupByUUID and virSecretGetUUID. Make
virSecretGetUUIDString follow normal API design pattern
* python/generator.py: Skip generation of virSecretGetUUID,
virSecretGetUUIDString and virSecretLookupByUUID
* python/libvir.c, python/libvirt-python-api.xml: Manual impl
of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID
* qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/
Fix get_nonnull_secret/make_nonnull_secret to use unsigned char
* qemud/remote_protocol.x: Fix remote_nonnull_secret to use a
remote_uuid instead of remote_nonnull_string for UUID field.
Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to
REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an
remote_uuid value
* qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h,
qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h,
qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate
* src/datatypes.h, src/datatypes.c: Store UUID in raw format instead
of printable. Change virGetSecret to use raw format UUID
* src/driver.h: Rename virDrvSecretLookupByUUIDString to
virDrvSecretLookupByUUID and use raw format UUID
* src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID
and re-implement virSecretLookupByUUIDString and
virSecretGetUUIDString in terms of those
* src/libvirt_public.syms: Add virSecretLookupByUUID and
virSecretGetUUID
* src/remote_internal.c: Rename remoteSecretLookupByUUIDString
to remoteSecretLookupByUUID. Fix typo in args for
remoteSecretDefineXML impl. Use raw UUID format for
get_nonnull_secret and make_nonnull_secret
* src/storage_encryption_conf.c, src/storage_encryption_conf.h:
Storage UUID in raw format, and require it to be present in
XML. Use UUID parser to validate.
* secret_conf.h, secret_conf.c: Generate a UUID if none is provided.
Storage UUID in raw format.
* src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets
in a filed with printable UUID, instead of base64 UUID.
* src/virsh.c: Adjust for changed public API contract of
virSecretGetUUIDString.
* src/storage_Backend.c: DOn't undefine secret we just generated
upon successful volume creation. Fix to handle raw UUIDs. Generate
a non-clashing UUID
* src/qemu_driver.c: Change to use lookupByUUID instead of
lookupByUUIDString
2009-09-10 17:44:12 +01:00
|
|
|
if (tmp == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2014-11-30 11:48:06 -05:00
|
|
|
virObjectUnref(tmp);
|
Fix UUID handling in secrets/storage encryption APIs
Convert all the secret/storage encryption APIs / wire format to
handle UUIDs in raw format instead of non-canonical printable
format. Guarentees data format correctness.
* docs/schemas/storageencryption.rng: Make UUID mandatory for a secret
and validate fully
* docs/schemas/secret.rng: Fully validate UUID
* include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add
virSecretLookupByUUID and virSecretGetUUID. Make
virSecretGetUUIDString follow normal API design pattern
* python/generator.py: Skip generation of virSecretGetUUID,
virSecretGetUUIDString and virSecretLookupByUUID
* python/libvir.c, python/libvirt-python-api.xml: Manual impl
of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID
* qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/
Fix get_nonnull_secret/make_nonnull_secret to use unsigned char
* qemud/remote_protocol.x: Fix remote_nonnull_secret to use a
remote_uuid instead of remote_nonnull_string for UUID field.
Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to
REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an
remote_uuid value
* qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h,
qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h,
qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate
* src/datatypes.h, src/datatypes.c: Store UUID in raw format instead
of printable. Change virGetSecret to use raw format UUID
* src/driver.h: Rename virDrvSecretLookupByUUIDString to
virDrvSecretLookupByUUID and use raw format UUID
* src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID
and re-implement virSecretLookupByUUIDString and
virSecretGetUUIDString in terms of those
* src/libvirt_public.syms: Add virSecretLookupByUUID and
virSecretGetUUID
* src/remote_internal.c: Rename remoteSecretLookupByUUIDString
to remoteSecretLookupByUUID. Fix typo in args for
remoteSecretDefineXML impl. Use raw UUID format for
get_nonnull_secret and make_nonnull_secret
* src/storage_encryption_conf.c, src/storage_encryption_conf.h:
Storage UUID in raw format, and require it to be present in
XML. Use UUID parser to validate.
* secret_conf.h, secret_conf.c: Generate a UUID if none is provided.
Storage UUID in raw format.
* src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets
in a filed with printable UUID, instead of base64 UUID.
* src/virsh.c: Adjust for changed public API contract of
virSecretGetUUIDString.
* src/storage_Backend.c: DOn't undefine secret we just generated
upon successful volume creation. Fix to handle raw UUIDs. Generate
a non-clashing UUID
* src/qemu_driver.c: Change to use lookupByUUID instead of
lookupByUUIDString
2009-09-10 17:44:12 +01:00
|
|
|
}
|
|
|
|
|
2012-07-18 12:38:29 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
2014-04-21 01:37:46 +05:30
|
|
|
_("too many conflicts when generating a uuid"));
|
Fix UUID handling in secrets/storage encryption APIs
Convert all the secret/storage encryption APIs / wire format to
handle UUIDs in raw format instead of non-canonical printable
format. Guarentees data format correctness.
* docs/schemas/storageencryption.rng: Make UUID mandatory for a secret
and validate fully
* docs/schemas/secret.rng: Fully validate UUID
* include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add
virSecretLookupByUUID and virSecretGetUUID. Make
virSecretGetUUIDString follow normal API design pattern
* python/generator.py: Skip generation of virSecretGetUUID,
virSecretGetUUIDString and virSecretLookupByUUID
* python/libvir.c, python/libvirt-python-api.xml: Manual impl
of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID
* qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/
Fix get_nonnull_secret/make_nonnull_secret to use unsigned char
* qemud/remote_protocol.x: Fix remote_nonnull_secret to use a
remote_uuid instead of remote_nonnull_string for UUID field.
Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to
REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an
remote_uuid value
* qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h,
qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h,
qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate
* src/datatypes.h, src/datatypes.c: Store UUID in raw format instead
of printable. Change virGetSecret to use raw format UUID
* src/driver.h: Rename virDrvSecretLookupByUUIDString to
virDrvSecretLookupByUUID and use raw format UUID
* src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID
and re-implement virSecretLookupByUUIDString and
virSecretGetUUIDString in terms of those
* src/libvirt_public.syms: Add virSecretLookupByUUID and
virSecretGetUUID
* src/remote_internal.c: Rename remoteSecretLookupByUUIDString
to remoteSecretLookupByUUID. Fix typo in args for
remoteSecretDefineXML impl. Use raw UUID format for
get_nonnull_secret and make_nonnull_secret
* src/storage_encryption_conf.c, src/storage_encryption_conf.h:
Storage UUID in raw format, and require it to be present in
XML. Use UUID parser to validate.
* secret_conf.h, secret_conf.c: Generate a UUID if none is provided.
Storage UUID in raw format.
* src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets
in a filed with printable UUID, instead of base64 UUID.
* src/virsh.c: Adjust for changed public API contract of
virSecretGetUUIDString.
* src/storage_Backend.c: DOn't undefine secret we just generated
upon successful volume creation. Fix to handle raw UUIDs. Generate
a non-clashing UUID
* src/qemu_driver.c: Change to use lookupByUUID instead of
lookupByUUIDString
2009-09-10 17:44:12 +01:00
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-08-14 20:06:59 +02:00
|
|
|
static int
|
|
|
|
virStorageGenerateQcowEncryption(virConnectPtr conn,
|
|
|
|
virStorageVolDefPtr vol)
|
|
|
|
{
|
|
|
|
virSecretDefPtr def = NULL;
|
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
|
virStorageEncryptionPtr enc;
|
|
|
|
virStorageEncryptionSecretPtr enc_secret = NULL;
|
|
|
|
virSecretPtr secret = NULL;
|
Fix UUID handling in secrets/storage encryption APIs
Convert all the secret/storage encryption APIs / wire format to
handle UUIDs in raw format instead of non-canonical printable
format. Guarentees data format correctness.
* docs/schemas/storageencryption.rng: Make UUID mandatory for a secret
and validate fully
* docs/schemas/secret.rng: Fully validate UUID
* include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add
virSecretLookupByUUID and virSecretGetUUID. Make
virSecretGetUUIDString follow normal API design pattern
* python/generator.py: Skip generation of virSecretGetUUID,
virSecretGetUUIDString and virSecretLookupByUUID
* python/libvir.c, python/libvirt-python-api.xml: Manual impl
of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID
* qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/
Fix get_nonnull_secret/make_nonnull_secret to use unsigned char
* qemud/remote_protocol.x: Fix remote_nonnull_secret to use a
remote_uuid instead of remote_nonnull_string for UUID field.
Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to
REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an
remote_uuid value
* qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h,
qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h,
qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate
* src/datatypes.h, src/datatypes.c: Store UUID in raw format instead
of printable. Change virGetSecret to use raw format UUID
* src/driver.h: Rename virDrvSecretLookupByUUIDString to
virDrvSecretLookupByUUID and use raw format UUID
* src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID
and re-implement virSecretLookupByUUIDString and
virSecretGetUUIDString in terms of those
* src/libvirt_public.syms: Add virSecretLookupByUUID and
virSecretGetUUID
* src/remote_internal.c: Rename remoteSecretLookupByUUIDString
to remoteSecretLookupByUUID. Fix typo in args for
remoteSecretDefineXML impl. Use raw UUID format for
get_nonnull_secret and make_nonnull_secret
* src/storage_encryption_conf.c, src/storage_encryption_conf.h:
Storage UUID in raw format, and require it to be present in
XML. Use UUID parser to validate.
* secret_conf.h, secret_conf.c: Generate a UUID if none is provided.
Storage UUID in raw format.
* src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets
in a filed with printable UUID, instead of base64 UUID.
* src/virsh.c: Adjust for changed public API contract of
virSecretGetUUIDString.
* src/storage_Backend.c: DOn't undefine secret we just generated
upon successful volume creation. Fix to handle raw UUIDs. Generate
a non-clashing UUID
* src/qemu_driver.c: Change to use lookupByUUID instead of
lookupByUUIDString
2009-09-10 17:44:12 +01:00
|
|
|
char *xml;
|
2009-08-14 20:06:59 +02:00
|
|
|
unsigned char value[VIR_STORAGE_QCOW_PASSPHRASE_SIZE];
|
|
|
|
int ret = -1;
|
|
|
|
|
Fix UUID handling in secrets/storage encryption APIs
Convert all the secret/storage encryption APIs / wire format to
handle UUIDs in raw format instead of non-canonical printable
format. Guarentees data format correctness.
* docs/schemas/storageencryption.rng: Make UUID mandatory for a secret
and validate fully
* docs/schemas/secret.rng: Fully validate UUID
* include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add
virSecretLookupByUUID and virSecretGetUUID. Make
virSecretGetUUIDString follow normal API design pattern
* python/generator.py: Skip generation of virSecretGetUUID,
virSecretGetUUIDString and virSecretLookupByUUID
* python/libvir.c, python/libvirt-python-api.xml: Manual impl
of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID
* qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/
Fix get_nonnull_secret/make_nonnull_secret to use unsigned char
* qemud/remote_protocol.x: Fix remote_nonnull_secret to use a
remote_uuid instead of remote_nonnull_string for UUID field.
Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to
REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an
remote_uuid value
* qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h,
qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h,
qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate
* src/datatypes.h, src/datatypes.c: Store UUID in raw format instead
of printable. Change virGetSecret to use raw format UUID
* src/driver.h: Rename virDrvSecretLookupByUUIDString to
virDrvSecretLookupByUUID and use raw format UUID
* src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID
and re-implement virSecretLookupByUUIDString and
virSecretGetUUIDString in terms of those
* src/libvirt_public.syms: Add virSecretLookupByUUID and
virSecretGetUUID
* src/remote_internal.c: Rename remoteSecretLookupByUUIDString
to remoteSecretLookupByUUID. Fix typo in args for
remoteSecretDefineXML impl. Use raw UUID format for
get_nonnull_secret and make_nonnull_secret
* src/storage_encryption_conf.c, src/storage_encryption_conf.h:
Storage UUID in raw format, and require it to be present in
XML. Use UUID parser to validate.
* secret_conf.h, secret_conf.c: Generate a UUID if none is provided.
Storage UUID in raw format.
* src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets
in a filed with printable UUID, instead of base64 UUID.
* src/virsh.c: Adjust for changed public API contract of
virSecretGetUUIDString.
* src/storage_Backend.c: DOn't undefine secret we just generated
upon successful volume creation. Fix to handle raw UUIDs. Generate
a non-clashing UUID
* src/qemu_driver.c: Change to use lookupByUUID instead of
lookupByUUIDString
2009-09-10 17:44:12 +01:00
|
|
|
if (conn->secretDriver == NULL ||
|
2013-04-22 18:26:01 +01:00
|
|
|
conn->secretDriver->secretLookupByUUID == NULL ||
|
|
|
|
conn->secretDriver->secretDefineXML == NULL ||
|
|
|
|
conn->secretDriver->secretSetValue == NULL) {
|
2012-07-18 12:38:29 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("secret storage not supported"));
|
2009-08-14 20:06:59 +02:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
enc = vol->target.encryption;
|
|
|
|
if (enc->nsecrets != 0) {
|
2012-07-18 12:38:29 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("secrets already defined"));
|
2009-08-14 20:06:59 +02:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(enc_secret) < 0 || VIR_REALLOC_N(enc->secrets, 1) < 0 ||
|
2013-07-04 12:16:29 +02:00
|
|
|
VIR_ALLOC(def) < 0)
|
2009-08-14 20:06:59 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-11 11:50:23 +08:00
|
|
|
def->ephemeral = false;
|
2013-04-11 11:54:37 +08:00
|
|
|
def->private = false;
|
Fix UUID handling in secrets/storage encryption APIs
Convert all the secret/storage encryption APIs / wire format to
handle UUIDs in raw format instead of non-canonical printable
format. Guarentees data format correctness.
* docs/schemas/storageencryption.rng: Make UUID mandatory for a secret
and validate fully
* docs/schemas/secret.rng: Fully validate UUID
* include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add
virSecretLookupByUUID and virSecretGetUUID. Make
virSecretGetUUIDString follow normal API design pattern
* python/generator.py: Skip generation of virSecretGetUUID,
virSecretGetUUIDString and virSecretLookupByUUID
* python/libvir.c, python/libvirt-python-api.xml: Manual impl
of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID
* qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/
Fix get_nonnull_secret/make_nonnull_secret to use unsigned char
* qemud/remote_protocol.x: Fix remote_nonnull_secret to use a
remote_uuid instead of remote_nonnull_string for UUID field.
Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to
REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an
remote_uuid value
* qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h,
qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h,
qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate
* src/datatypes.h, src/datatypes.c: Store UUID in raw format instead
of printable. Change virGetSecret to use raw format UUID
* src/driver.h: Rename virDrvSecretLookupByUUIDString to
virDrvSecretLookupByUUID and use raw format UUID
* src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID
and re-implement virSecretLookupByUUIDString and
virSecretGetUUIDString in terms of those
* src/libvirt_public.syms: Add virSecretLookupByUUID and
virSecretGetUUID
* src/remote_internal.c: Rename remoteSecretLookupByUUIDString
to remoteSecretLookupByUUID. Fix typo in args for
remoteSecretDefineXML impl. Use raw UUID format for
get_nonnull_secret and make_nonnull_secret
* src/storage_encryption_conf.c, src/storage_encryption_conf.h:
Storage UUID in raw format, and require it to be present in
XML. Use UUID parser to validate.
* secret_conf.h, secret_conf.c: Generate a UUID if none is provided.
Storage UUID in raw format.
* src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets
in a filed with printable UUID, instead of base64 UUID.
* src/virsh.c: Adjust for changed public API contract of
virSecretGetUUIDString.
* src/storage_Backend.c: DOn't undefine secret we just generated
upon successful volume creation. Fix to handle raw UUIDs. Generate
a non-clashing UUID
* src/qemu_driver.c: Change to use lookupByUUID instead of
lookupByUUIDString
2009-09-10 17:44:12 +01:00
|
|
|
if (virStorageGenerateSecretUUID(conn, def->uuid) < 0)
|
2009-08-14 20:06:59 +02:00
|
|
|
goto cleanup;
|
Fix UUID handling in secrets/storage encryption APIs
Convert all the secret/storage encryption APIs / wire format to
handle UUIDs in raw format instead of non-canonical printable
format. Guarentees data format correctness.
* docs/schemas/storageencryption.rng: Make UUID mandatory for a secret
and validate fully
* docs/schemas/secret.rng: Fully validate UUID
* include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add
virSecretLookupByUUID and virSecretGetUUID. Make
virSecretGetUUIDString follow normal API design pattern
* python/generator.py: Skip generation of virSecretGetUUID,
virSecretGetUUIDString and virSecretLookupByUUID
* python/libvir.c, python/libvirt-python-api.xml: Manual impl
of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID
* qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/
Fix get_nonnull_secret/make_nonnull_secret to use unsigned char
* qemud/remote_protocol.x: Fix remote_nonnull_secret to use a
remote_uuid instead of remote_nonnull_string for UUID field.
Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to
REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an
remote_uuid value
* qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h,
qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h,
qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate
* src/datatypes.h, src/datatypes.c: Store UUID in raw format instead
of printable. Change virGetSecret to use raw format UUID
* src/driver.h: Rename virDrvSecretLookupByUUIDString to
virDrvSecretLookupByUUID and use raw format UUID
* src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID
and re-implement virSecretLookupByUUIDString and
virSecretGetUUIDString in terms of those
* src/libvirt_public.syms: Add virSecretLookupByUUID and
virSecretGetUUID
* src/remote_internal.c: Rename remoteSecretLookupByUUIDString
to remoteSecretLookupByUUID. Fix typo in args for
remoteSecretDefineXML impl. Use raw UUID format for
get_nonnull_secret and make_nonnull_secret
* src/storage_encryption_conf.c, src/storage_encryption_conf.h:
Storage UUID in raw format, and require it to be present in
XML. Use UUID parser to validate.
* secret_conf.h, secret_conf.c: Generate a UUID if none is provided.
Storage UUID in raw format.
* src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets
in a filed with printable UUID, instead of base64 UUID.
* src/virsh.c: Adjust for changed public API contract of
virSecretGetUUIDString.
* src/storage_Backend.c: DOn't undefine secret we just generated
upon successful volume creation. Fix to handle raw UUIDs. Generate
a non-clashing UUID
* src/qemu_driver.c: Change to use lookupByUUID instead of
lookupByUUIDString
2009-09-10 17:44:12 +01:00
|
|
|
|
2009-08-14 20:06:59 +02:00
|
|
|
def->usage_type = VIR_SECRET_USAGE_TYPE_VOLUME;
|
2013-05-03 14:49:08 +02:00
|
|
|
if (VIR_STRDUP(def->usage.volume, vol->target.path) < 0)
|
2009-08-14 20:06:59 +02:00
|
|
|
goto cleanup;
|
2010-02-10 12:33:34 +00:00
|
|
|
xml = virSecretDefFormat(def);
|
2009-08-14 20:06:59 +02:00
|
|
|
virSecretDefFree(def);
|
|
|
|
def = NULL;
|
|
|
|
if (xml == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-22 18:26:01 +01:00
|
|
|
secret = conn->secretDriver->secretDefineXML(conn, xml, 0);
|
2009-08-14 20:06:59 +02:00
|
|
|
if (secret == NULL) {
|
|
|
|
VIR_FREE(xml);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
VIR_FREE(xml);
|
|
|
|
|
2010-02-10 11:42:56 +00:00
|
|
|
if (virStorageGenerateQcowPassphrase(value) < 0)
|
2009-08-14 20:06:59 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-22 18:26:01 +01:00
|
|
|
if (conn->secretDriver->secretSetValue(secret, value, sizeof(value), 0) < 0)
|
2009-08-14 20:06:59 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
enc_secret->type = VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE;
|
Fix UUID handling in secrets/storage encryption APIs
Convert all the secret/storage encryption APIs / wire format to
handle UUIDs in raw format instead of non-canonical printable
format. Guarentees data format correctness.
* docs/schemas/storageencryption.rng: Make UUID mandatory for a secret
and validate fully
* docs/schemas/secret.rng: Fully validate UUID
* include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add
virSecretLookupByUUID and virSecretGetUUID. Make
virSecretGetUUIDString follow normal API design pattern
* python/generator.py: Skip generation of virSecretGetUUID,
virSecretGetUUIDString and virSecretLookupByUUID
* python/libvir.c, python/libvirt-python-api.xml: Manual impl
of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID
* qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/
Fix get_nonnull_secret/make_nonnull_secret to use unsigned char
* qemud/remote_protocol.x: Fix remote_nonnull_secret to use a
remote_uuid instead of remote_nonnull_string for UUID field.
Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to
REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an
remote_uuid value
* qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h,
qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h,
qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate
* src/datatypes.h, src/datatypes.c: Store UUID in raw format instead
of printable. Change virGetSecret to use raw format UUID
* src/driver.h: Rename virDrvSecretLookupByUUIDString to
virDrvSecretLookupByUUID and use raw format UUID
* src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID
and re-implement virSecretLookupByUUIDString and
virSecretGetUUIDString in terms of those
* src/libvirt_public.syms: Add virSecretLookupByUUID and
virSecretGetUUID
* src/remote_internal.c: Rename remoteSecretLookupByUUIDString
to remoteSecretLookupByUUID. Fix typo in args for
remoteSecretDefineXML impl. Use raw UUID format for
get_nonnull_secret and make_nonnull_secret
* src/storage_encryption_conf.c, src/storage_encryption_conf.h:
Storage UUID in raw format, and require it to be present in
XML. Use UUID parser to validate.
* secret_conf.h, secret_conf.c: Generate a UUID if none is provided.
Storage UUID in raw format.
* src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets
in a filed with printable UUID, instead of base64 UUID.
* src/virsh.c: Adjust for changed public API contract of
virSecretGetUUIDString.
* src/storage_Backend.c: DOn't undefine secret we just generated
upon successful volume creation. Fix to handle raw UUIDs. Generate
a non-clashing UUID
* src/qemu_driver.c: Change to use lookupByUUID instead of
lookupByUUIDString
2009-09-10 17:44:12 +01:00
|
|
|
memcpy(enc_secret->uuid, secret->uuid, VIR_UUID_BUFLEN);
|
2009-08-14 20:06:59 +02:00
|
|
|
enc->format = VIR_STORAGE_ENCRYPTION_FORMAT_QCOW;
|
|
|
|
enc->secrets[0] = enc_secret; /* Space for secrets[0] allocated above */
|
|
|
|
enc_secret = NULL;
|
|
|
|
enc->nsecrets = 1;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 07:52:40 +01:00
|
|
|
cleanup:
|
2009-08-14 20:06:59 +02:00
|
|
|
if (secret != NULL) {
|
Fix UUID handling in secrets/storage encryption APIs
Convert all the secret/storage encryption APIs / wire format to
handle UUIDs in raw format instead of non-canonical printable
format. Guarentees data format correctness.
* docs/schemas/storageencryption.rng: Make UUID mandatory for a secret
and validate fully
* docs/schemas/secret.rng: Fully validate UUID
* include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add
virSecretLookupByUUID and virSecretGetUUID. Make
virSecretGetUUIDString follow normal API design pattern
* python/generator.py: Skip generation of virSecretGetUUID,
virSecretGetUUIDString and virSecretLookupByUUID
* python/libvir.c, python/libvirt-python-api.xml: Manual impl
of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID
* qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/
Fix get_nonnull_secret/make_nonnull_secret to use unsigned char
* qemud/remote_protocol.x: Fix remote_nonnull_secret to use a
remote_uuid instead of remote_nonnull_string for UUID field.
Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to
REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an
remote_uuid value
* qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h,
qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h,
qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate
* src/datatypes.h, src/datatypes.c: Store UUID in raw format instead
of printable. Change virGetSecret to use raw format UUID
* src/driver.h: Rename virDrvSecretLookupByUUIDString to
virDrvSecretLookupByUUID and use raw format UUID
* src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID
and re-implement virSecretLookupByUUIDString and
virSecretGetUUIDString in terms of those
* src/libvirt_public.syms: Add virSecretLookupByUUID and
virSecretGetUUID
* src/remote_internal.c: Rename remoteSecretLookupByUUIDString
to remoteSecretLookupByUUID. Fix typo in args for
remoteSecretDefineXML impl. Use raw UUID format for
get_nonnull_secret and make_nonnull_secret
* src/storage_encryption_conf.c, src/storage_encryption_conf.h:
Storage UUID in raw format, and require it to be present in
XML. Use UUID parser to validate.
* secret_conf.h, secret_conf.c: Generate a UUID if none is provided.
Storage UUID in raw format.
* src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets
in a filed with printable UUID, instead of base64 UUID.
* src/virsh.c: Adjust for changed public API contract of
virSecretGetUUIDString.
* src/storage_Backend.c: DOn't undefine secret we just generated
upon successful volume creation. Fix to handle raw UUIDs. Generate
a non-clashing UUID
* src/qemu_driver.c: Change to use lookupByUUID instead of
lookupByUUIDString
2009-09-10 17:44:12 +01:00
|
|
|
if (ret != 0 &&
|
2013-04-22 18:26:01 +01:00
|
|
|
conn->secretDriver->secretUndefine != NULL)
|
|
|
|
conn->secretDriver->secretUndefine(secret);
|
2014-11-30 11:48:06 -05:00
|
|
|
virObjectUnref(secret);
|
2009-08-14 20:06:59 +02:00
|
|
|
}
|
2009-12-10 00:00:50 +01:00
|
|
|
virBufferFreeAndReset(&buf);
|
2009-08-14 20:06:59 +02:00
|
|
|
virSecretDefFree(def);
|
|
|
|
VIR_FREE(enc_secret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-06-05 09:41:38 +02:00
|
|
|
static int
|
|
|
|
virStorageBackendCreateExecCommand(virStoragePoolObjPtr pool,
|
|
|
|
virStorageVolDefPtr vol,
|
|
|
|
virCommandPtr cmd)
|
|
|
|
{
|
2010-01-21 00:41:52 +01:00
|
|
|
struct stat st;
|
|
|
|
gid_t gid;
|
|
|
|
uid_t uid;
|
2015-04-27 16:48:05 -04:00
|
|
|
mode_t mode;
|
2013-05-24 12:14:02 +02:00
|
|
|
bool filecreated = false;
|
2010-01-21 00:41:52 +01:00
|
|
|
|
|
|
|
if ((pool->def->type == VIR_STORAGE_POOL_NETFS)
|
2013-10-09 12:13:45 +01:00
|
|
|
&& (((geteuid() == 0)
|
2014-03-29 20:27:44 -06:00
|
|
|
&& (vol->target.perms->uid != (uid_t) -1)
|
|
|
|
&& (vol->target.perms->uid != 0))
|
|
|
|
|| ((vol->target.perms->gid != (gid_t) -1)
|
|
|
|
&& (vol->target.perms->gid != getegid())))) {
|
2011-05-06 14:35:51 -04:00
|
|
|
|
2014-03-29 20:27:44 -06:00
|
|
|
virCommandSetUID(cmd, vol->target.perms->uid);
|
|
|
|
virCommandSetGID(cmd, vol->target.perms->gid);
|
2011-05-06 14:35:51 -04:00
|
|
|
|
|
|
|
if (virCommandRun(cmd, NULL) == 0) {
|
2010-01-21 00:41:52 +01:00
|
|
|
/* command was successfully run, check if the file was created */
|
2014-08-11 17:04:19 -06:00
|
|
|
if (stat(vol->target.path, &st) >= 0)
|
2013-05-24 12:14:02 +02:00
|
|
|
filecreated = true;
|
2010-01-21 00:41:52 +01:00
|
|
|
}
|
|
|
|
}
|
2011-05-06 14:35:51 -04:00
|
|
|
|
2013-01-30 22:26:16 -05:00
|
|
|
/* don't change uid/gid if we retry */
|
|
|
|
virCommandSetUID(cmd, -1);
|
|
|
|
virCommandSetGID(cmd, -1);
|
2011-05-06 14:35:51 -04:00
|
|
|
|
2010-01-21 00:41:52 +01:00
|
|
|
if (!filecreated) {
|
2014-11-13 15:25:27 +01:00
|
|
|
if (virCommandRun(cmd, NULL) < 0)
|
2010-01-21 00:41:52 +01:00
|
|
|
return -1;
|
|
|
|
if (stat(vol->target.path, &st) < 0) {
|
2010-02-04 21:02:58 +01:00
|
|
|
virReportSystemError(errno,
|
2011-05-06 14:35:51 -04:00
|
|
|
_("failed to create %s"), vol->target.path);
|
2010-01-21 00:41:52 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-29 20:27:44 -06:00
|
|
|
uid = (vol->target.perms->uid != st.st_uid) ? vol->target.perms->uid
|
|
|
|
: (uid_t) -1;
|
|
|
|
gid = (vol->target.perms->gid != st.st_gid) ? vol->target.perms->gid
|
|
|
|
: (gid_t) -1;
|
2013-02-22 17:41:32 +01:00
|
|
|
if (((uid != (uid_t) -1) || (gid != (gid_t) -1))
|
2010-01-21 00:41:52 +01:00
|
|
|
&& (chown(vol->target.path, uid, gid) < 0)) {
|
2010-02-04 21:02:58 +01:00
|
|
|
virReportSystemError(errno,
|
2010-01-21 00:41:52 +01:00
|
|
|
_("cannot chown %s to (%u, %u)"),
|
2013-02-22 17:43:15 +01:00
|
|
|
vol->target.path, (unsigned int) uid,
|
|
|
|
(unsigned int) gid);
|
2010-01-21 00:41:52 +01:00
|
|
|
return -1;
|
|
|
|
}
|
2015-04-27 16:48:05 -04:00
|
|
|
|
|
|
|
mode = (vol->target.perms->mode == (mode_t) -1 ?
|
|
|
|
VIR_STORAGE_DEFAULT_VOL_PERM_MODE : vol->target.perms->mode);
|
|
|
|
if (chmod(vol->target.path, mode) < 0) {
|
2010-02-04 21:02:58 +01:00
|
|
|
virReportSystemError(errno,
|
2010-01-21 00:41:52 +01:00
|
|
|
_("cannot set mode of '%s' to %04o"),
|
2015-04-27 16:48:05 -04:00
|
|
|
vol->target.path, mode);
|
2010-01-21 00:41:52 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-06-16 14:14:05 +01:00
|
|
|
enum {
|
|
|
|
QEMU_IMG_BACKING_FORMAT_NONE = 0,
|
|
|
|
QEMU_IMG_BACKING_FORMAT_FLAG,
|
|
|
|
QEMU_IMG_BACKING_FORMAT_OPTIONS,
|
2013-08-20 17:37:08 +02:00
|
|
|
QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT,
|
2010-06-16 14:14:05 +01:00
|
|
|
};
|
|
|
|
|
2013-08-20 17:37:08 +02:00
|
|
|
static bool
|
|
|
|
virStorageBackendQemuImgSupportsCompat(const char *qemuimg)
|
|
|
|
{
|
|
|
|
bool ret = false;
|
|
|
|
char *output;
|
|
|
|
virCommandPtr cmd = NULL;
|
|
|
|
|
|
|
|
cmd = virCommandNewArgList(qemuimg, "create", "-o", "?", "-f", "qcow2",
|
|
|
|
"/dev/null", NULL);
|
|
|
|
|
|
|
|
virCommandAddEnvString(cmd, "LC_ALL=C");
|
|
|
|
virCommandSetOutputBuffer(cmd, &output);
|
|
|
|
|
|
|
|
if (virCommandRun(cmd, NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (strstr(output, "\ncompat "))
|
|
|
|
ret = true;
|
|
|
|
|
2014-03-25 07:52:40 +01:00
|
|
|
cleanup:
|
2013-08-20 17:37:08 +02:00
|
|
|
virCommandFree(cmd);
|
|
|
|
VIR_FREE(output);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-06-05 09:41:38 +02:00
|
|
|
static int
|
|
|
|
virStorageBackendQEMUImgBackingFormat(const char *qemuimg)
|
2010-06-16 14:14:05 +01:00
|
|
|
{
|
|
|
|
char *help = NULL;
|
|
|
|
char *start;
|
|
|
|
char *end;
|
|
|
|
char *tmp;
|
|
|
|
int ret = -1;
|
2011-05-23 09:08:01 +02:00
|
|
|
int exitstatus;
|
2011-05-06 15:25:52 -04:00
|
|
|
virCommandPtr cmd = virCommandNewArgList(qemuimg, "-h", NULL);
|
2010-06-16 14:14:05 +01:00
|
|
|
|
2011-05-06 15:25:52 -04:00
|
|
|
virCommandAddEnvString(cmd, "LC_ALL=C");
|
|
|
|
virCommandSetOutputBuffer(cmd, &help);
|
|
|
|
virCommandClearCaps(cmd);
|
2010-06-16 14:14:05 +01:00
|
|
|
|
2011-05-24 08:54:37 +02:00
|
|
|
/* qemuimg doesn't return zero exit status on -h,
|
|
|
|
* therefore we need to provide pointer for storing
|
|
|
|
* exit status, although we don't parse it any later */
|
2011-05-23 09:08:01 +02:00
|
|
|
if (virCommandRun(cmd, &exitstatus) < 0)
|
2010-06-16 14:14:05 +01:00
|
|
|
goto cleanup;
|
|
|
|
|
2011-10-21 15:34:34 -06:00
|
|
|
if ((start = strstr(help, " create ")) == NULL ||
|
|
|
|
(end = strstr(start, "\n")) == NULL) {
|
2012-07-18 12:38:29 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unable to parse qemu-img output '%s'"),
|
|
|
|
help);
|
2011-10-21 15:34:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-03-10 15:02:28 +08:00
|
|
|
if (((tmp = strstr(start, "-F fmt")) && tmp < end) ||
|
2013-08-20 17:37:08 +02:00
|
|
|
((tmp = strstr(start, "-F backing_fmt")) && tmp < end)) {
|
2010-06-16 14:14:05 +01:00
|
|
|
ret = QEMU_IMG_BACKING_FORMAT_FLAG;
|
2013-08-20 17:37:08 +02:00
|
|
|
} else if ((tmp = strstr(start, "[-o options]")) && tmp < end) {
|
|
|
|
if (virStorageBackendQemuImgSupportsCompat(qemuimg))
|
|
|
|
ret = QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT;
|
|
|
|
else
|
|
|
|
ret = QEMU_IMG_BACKING_FORMAT_OPTIONS;
|
|
|
|
} else {
|
2010-06-16 14:14:05 +01:00
|
|
|
ret = QEMU_IMG_BACKING_FORMAT_NONE;
|
2013-08-20 17:37:08 +02:00
|
|
|
}
|
2010-06-16 14:14:05 +01:00
|
|
|
|
2014-03-25 07:52:40 +01:00
|
|
|
cleanup:
|
2011-05-06 15:25:52 -04:00
|
|
|
virCommandFree(cmd);
|
2010-06-16 14:14:05 +01:00
|
|
|
VIR_FREE(help);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-07-31 18:07:56 +02:00
|
|
|
struct _virStorageBackendQemuImgInfo {
|
|
|
|
int format;
|
|
|
|
const char *path;
|
|
|
|
unsigned long long size_arg;
|
|
|
|
bool encryption;
|
|
|
|
bool preallocate;
|
|
|
|
const char *compat;
|
|
|
|
virBitmapPtr features;
|
|
|
|
bool nocow;
|
|
|
|
|
|
|
|
const char *backingPath;
|
|
|
|
int backingFormat;
|
|
|
|
|
|
|
|
const char *inputPath;
|
|
|
|
int inputFormat;
|
|
|
|
};
|
|
|
|
|
2013-05-13 10:16:52 +02:00
|
|
|
static int
|
|
|
|
virStorageBackendCreateQemuImgOpts(char **opts,
|
2014-07-31 18:07:56 +02:00
|
|
|
struct _virStorageBackendQemuImgInfo info)
|
2013-05-13 10:16:52 +02:00
|
|
|
{
|
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
2013-05-16 12:40:45 +02:00
|
|
|
|
2014-07-31 18:07:56 +02:00
|
|
|
if (info.backingPath)
|
|
|
|
virBufferAsprintf(&buf, "backing_fmt=%s,",
|
|
|
|
virStorageFileFormatTypeToString(info.backingFormat));
|
|
|
|
if (info.encryption)
|
2013-05-13 10:16:52 +02:00
|
|
|
virBufferAddLit(&buf, "encryption=on,");
|
2014-07-31 18:07:56 +02:00
|
|
|
if (info.preallocate)
|
2013-05-13 10:16:52 +02:00
|
|
|
virBufferAddLit(&buf, "preallocation=metadata,");
|
2014-07-31 18:07:56 +02:00
|
|
|
if (info.nocow)
|
2014-07-15 16:49:46 +08:00
|
|
|
virBufferAddLit(&buf, "nocow=on,");
|
2013-05-13 10:16:52 +02:00
|
|
|
|
2014-07-31 18:07:56 +02:00
|
|
|
if (info.compat)
|
|
|
|
virBufferAsprintf(&buf, "compat=%s,", info.compat);
|
2015-04-10 14:28:41 +02:00
|
|
|
|
2014-07-31 18:07:56 +02:00
|
|
|
if (info.features && info.format == VIR_STORAGE_FILE_QCOW2) {
|
2015-04-10 14:28:41 +02:00
|
|
|
if (virBitmapIsBitSet(info.features,
|
|
|
|
VIR_STORAGE_FILE_FEATURE_LAZY_REFCOUNTS)) {
|
|
|
|
if (STREQ_NULLABLE(info.compat, "0.10")) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("lazy_refcounts not supported with compat"
|
|
|
|
" level %s"),
|
|
|
|
info.compat);
|
|
|
|
goto error;
|
2013-05-16 12:40:45 +02:00
|
|
|
}
|
2015-04-10 14:28:41 +02:00
|
|
|
virBufferAddLit(&buf, "lazy_refcounts,");
|
2013-05-16 12:40:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-13 10:16:52 +02:00
|
|
|
virBufferTrim(&buf, ",", -1);
|
|
|
|
|
2014-06-27 10:40:15 +02:00
|
|
|
if (virBufferCheckError(&buf) < 0)
|
|
|
|
goto error;
|
2013-05-13 10:16:52 +02:00
|
|
|
|
|
|
|
*opts = virBufferContentAndReset(&buf);
|
|
|
|
return 0;
|
2013-05-16 12:40:45 +02:00
|
|
|
|
2014-03-25 07:52:40 +01:00
|
|
|
error:
|
2013-05-16 12:40:45 +02:00
|
|
|
virBufferFreeAndReset(&buf);
|
|
|
|
return -1;
|
2013-05-13 10:16:52 +02:00
|
|
|
}
|
|
|
|
|
2014-07-31 18:08:33 +02:00
|
|
|
/* Create a qemu-img virCommand from the supplied binary path,
|
|
|
|
* volume definitions and imgformat
|
|
|
|
*/
|
2013-02-18 12:52:58 +01:00
|
|
|
virCommandPtr
|
2014-07-31 18:08:33 +02:00
|
|
|
virStorageBackendCreateQemuImgCmdFromVol(virConnectPtr conn,
|
|
|
|
virStoragePoolObjPtr pool,
|
|
|
|
virStorageVolDefPtr vol,
|
|
|
|
virStorageVolDefPtr inputvol,
|
|
|
|
unsigned int flags,
|
|
|
|
const char *create_tool,
|
|
|
|
int imgformat)
|
2009-07-16 12:09:26 -04:00
|
|
|
{
|
2011-05-06 14:35:51 -04:00
|
|
|
virCommandPtr cmd = NULL;
|
2013-06-05 09:42:59 +02:00
|
|
|
const char *type;
|
|
|
|
const char *backingType = NULL;
|
|
|
|
const char *inputType = NULL;
|
2013-05-13 10:16:52 +02:00
|
|
|
char *opts = NULL;
|
2014-07-31 18:07:56 +02:00
|
|
|
struct _virStorageBackendQemuImgInfo info = {
|
|
|
|
.format = vol->target.format,
|
|
|
|
.path = vol->target.path,
|
|
|
|
.encryption = vol->target.encryption != NULL,
|
|
|
|
.preallocate = !!(flags & VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA),
|
|
|
|
.compat = vol->target.compat,
|
|
|
|
.features = vol->target.features,
|
|
|
|
.nocow = vol->target.nocow,
|
|
|
|
};
|
2009-07-16 12:09:26 -04:00
|
|
|
|
2013-02-18 12:50:46 +01:00
|
|
|
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
|
|
|
|
|
2013-06-05 09:42:59 +02:00
|
|
|
/* Treat output block devices as 'raw' format */
|
2014-07-31 18:07:56 +02:00
|
|
|
if (vol->type == VIR_STORAGE_VOL_BLOCK)
|
|
|
|
info.format = VIR_STORAGE_FILE_RAW;
|
2013-02-18 12:50:46 +01:00
|
|
|
|
2014-07-31 18:07:56 +02:00
|
|
|
if (!(type = virStorageFileFormatTypeToString(info.format))) {
|
2012-07-18 12:38:29 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unknown storage vol type %d"),
|
2014-07-31 18:07:56 +02:00
|
|
|
info.format);
|
2013-02-18 12:52:58 +01:00
|
|
|
return NULL;
|
2009-07-16 12:09:26 -04:00
|
|
|
}
|
2013-06-05 09:42:59 +02:00
|
|
|
|
2014-07-31 18:07:56 +02:00
|
|
|
if (info.preallocate && info.format != VIR_STORAGE_FILE_QCOW2) {
|
2012-12-05 11:48:07 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("metadata preallocation only available with qcow2"));
|
2013-02-18 12:52:58 +01:00
|
|
|
return NULL;
|
2012-12-05 11:48:07 +01:00
|
|
|
}
|
2014-07-31 18:07:56 +02:00
|
|
|
if (info.compat && info.format != VIR_STORAGE_FILE_QCOW2) {
|
2013-05-16 12:40:45 +02:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("compatibility option only available with qcow2"));
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-07-31 18:07:56 +02:00
|
|
|
if (info.features && info.format != VIR_STORAGE_FILE_QCOW2) {
|
2013-05-16 12:40:45 +02:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("format features only available with qcow2"));
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-07-16 12:09:26 -04:00
|
|
|
|
2013-06-05 09:42:59 +02:00
|
|
|
if (inputvol) {
|
2014-07-31 18:07:56 +02:00
|
|
|
if (!(info.inputPath = inputvol->target.path)) {
|
2013-06-05 09:42:59 +02:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("missing input volume target path"));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-07-31 18:07:56 +02:00
|
|
|
info.inputFormat = inputvol->target.format;
|
|
|
|
if (inputvol->type == VIR_STORAGE_VOL_BLOCK)
|
|
|
|
info.inputFormat = VIR_STORAGE_FILE_RAW;
|
|
|
|
if (!(inputType = virStorageFileFormatTypeToString(info.inputFormat))) {
|
2013-06-05 09:42:59 +02:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unknown storage vol type %d"),
|
2014-07-31 18:07:56 +02:00
|
|
|
info.inputFormat);
|
2013-06-05 09:42:59 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-14 15:19:49 +02:00
|
|
|
if (vol->target.backingStore) {
|
2011-03-27 20:30:14 -05:00
|
|
|
int accessRetCode = -1;
|
|
|
|
char *absolutePath = NULL;
|
2009-07-16 12:09:26 -04:00
|
|
|
|
2014-07-31 18:07:56 +02:00
|
|
|
info.backingFormat = vol->target.backingStore->format;
|
|
|
|
info.backingPath = vol->target.backingStore->path;
|
2013-06-05 09:42:59 +02:00
|
|
|
|
2014-07-31 18:07:56 +02:00
|
|
|
if (info.preallocate) {
|
2012-12-05 11:48:07 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("metadata preallocation conflicts with backing"
|
|
|
|
" store"));
|
2013-02-18 12:52:58 +01:00
|
|
|
return NULL;
|
2012-12-05 11:48:07 +01:00
|
|
|
}
|
|
|
|
|
2009-07-16 12:09:26 -04:00
|
|
|
/* XXX: Not strictly required: qemu-img has an option a different
|
|
|
|
* backing store, not really sure what use it serves though, and it
|
|
|
|
* may cause issues with lvm. Untested essentially.
|
|
|
|
*/
|
2014-08-01 15:24:20 +02:00
|
|
|
if (inputvol && inputvol->target.backingStore &&
|
2014-07-31 18:07:56 +02:00
|
|
|
STRNEQ_NULLABLE(inputvol->target.backingStore->path, info.backingPath)) {
|
2013-06-05 09:42:59 +02:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("a different backing store cannot be specified."));
|
2013-02-18 12:52:58 +01:00
|
|
|
return NULL;
|
2009-07-16 12:09:26 -04:00
|
|
|
}
|
|
|
|
|
2014-07-31 18:07:56 +02:00
|
|
|
if (!(backingType = virStorageFileFormatTypeToString(info.backingFormat))) {
|
2012-07-18 12:38:29 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unknown storage vol backing store type %d"),
|
2014-07-31 18:07:56 +02:00
|
|
|
info.backingFormat);
|
2013-02-18 12:52:58 +01:00
|
|
|
return NULL;
|
2009-07-16 12:09:26 -04:00
|
|
|
}
|
2011-03-27 20:30:14 -05:00
|
|
|
|
|
|
|
/* Convert relative backing store paths to absolute paths for access
|
|
|
|
* validation.
|
|
|
|
*/
|
2014-07-31 18:07:56 +02:00
|
|
|
if ('/' != *(info.backingPath) &&
|
2011-03-27 20:30:14 -05:00
|
|
|
virAsprintf(&absolutePath, "%s/%s", pool->def->target.path,
|
2014-07-31 18:07:56 +02:00
|
|
|
info.backingPath) < 0)
|
2013-02-18 12:52:58 +01:00
|
|
|
return NULL;
|
2014-07-31 18:07:56 +02:00
|
|
|
accessRetCode = access(absolutePath ? absolutePath : info.backingPath, R_OK);
|
2011-03-27 20:30:14 -05:00
|
|
|
VIR_FREE(absolutePath);
|
|
|
|
if (accessRetCode != 0) {
|
2010-02-04 21:02:58 +01:00
|
|
|
virReportSystemError(errno,
|
2009-07-16 12:09:26 -04:00
|
|
|
_("inaccessible backing store volume %s"),
|
2014-07-31 18:07:56 +02:00
|
|
|
info.backingPath);
|
2013-02-18 12:52:58 +01:00
|
|
|
return NULL;
|
2009-07-16 12:09:26 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-31 18:07:56 +02:00
|
|
|
if (info.encryption) {
|
2009-08-14 20:06:59 +02:00
|
|
|
virStorageEncryptionPtr enc;
|
|
|
|
|
2014-07-31 18:07:56 +02:00
|
|
|
if (info.format != VIR_STORAGE_FILE_QCOW &&
|
|
|
|
info.format != VIR_STORAGE_FILE_QCOW2) {
|
2012-07-18 12:38:29 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("qcow volume encryption unsupported with "
|
|
|
|
"volume format %s"), type);
|
2013-02-18 12:52:58 +01:00
|
|
|
return NULL;
|
2009-07-21 04:40:50 +02:00
|
|
|
}
|
2009-08-14 20:06:59 +02:00
|
|
|
enc = vol->target.encryption;
|
|
|
|
if (enc->format != VIR_STORAGE_ENCRYPTION_FORMAT_QCOW &&
|
|
|
|
enc->format != VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT) {
|
2012-07-18 12:38:29 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("unsupported volume encryption format %d"),
|
|
|
|
vol->target.encryption->format);
|
2013-02-18 12:52:58 +01:00
|
|
|
return NULL;
|
2009-07-21 04:40:50 +02:00
|
|
|
}
|
2009-08-14 20:06:59 +02:00
|
|
|
if (enc->nsecrets > 1) {
|
2012-07-18 12:38:29 +01:00
|
|
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
|
_("too many secrets for qcow encryption"));
|
2013-02-18 12:52:58 +01:00
|
|
|
return NULL;
|
2009-07-21 04:40:50 +02:00
|
|
|
}
|
2009-08-14 20:06:59 +02:00
|
|
|
if (enc->format == VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT ||
|
|
|
|
enc->nsecrets == 0) {
|
|
|
|
if (virStorageGenerateQcowEncryption(conn, vol) < 0)
|
2013-02-18 12:52:58 +01:00
|
|
|
return NULL;
|
2009-08-14 20:06:59 +02:00
|
|
|
}
|
2009-07-21 04:40:50 +02:00
|
|
|
}
|
|
|
|
|
2010-06-16 14:14:05 +01:00
|
|
|
/* Size in KB */
|
2014-07-31 18:07:56 +02:00
|
|
|
info.size_arg = VIR_DIV_UP(vol->target.capacity, 1024);
|
2010-06-16 14:14:05 +01:00
|
|
|
|
2011-05-06 14:35:51 -04:00
|
|
|
cmd = virCommandNew(create_tool);
|
|
|
|
|
2014-07-31 18:07:56 +02:00
|
|
|
/* ignore the backing volume when we're converting a volume */
|
|
|
|
if (info.inputPath) {
|
|
|
|
info.backingPath = NULL;
|
|
|
|
backingType = NULL;
|
|
|
|
}
|
2011-05-06 14:35:51 -04:00
|
|
|
|
2014-07-31 18:07:56 +02:00
|
|
|
if (info.inputPath)
|
2013-05-13 10:16:52 +02:00
|
|
|
virCommandAddArgList(cmd, "convert", "-f", inputType, "-O", type, NULL);
|
|
|
|
else
|
2013-02-18 14:45:03 +01:00
|
|
|
virCommandAddArgList(cmd, "create", "-f", type, NULL);
|
2011-05-06 14:35:51 -04:00
|
|
|
|
2014-07-31 18:07:56 +02:00
|
|
|
if (info.backingPath)
|
|
|
|
virCommandAddArgList(cmd, "-b", info.backingPath, NULL);
|
2013-05-13 10:16:52 +02:00
|
|
|
|
2013-08-20 17:37:08 +02:00
|
|
|
if (imgformat >= QEMU_IMG_BACKING_FORMAT_OPTIONS) {
|
2014-07-31 18:07:56 +02:00
|
|
|
if (info.format == VIR_STORAGE_FILE_QCOW2 && !info.compat &&
|
2013-08-20 17:37:08 +02:00
|
|
|
imgformat == QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT)
|
2014-07-31 18:07:56 +02:00
|
|
|
info.compat = "0.10";
|
|
|
|
|
|
|
|
if (virStorageBackendCreateQemuImgOpts(&opts, info) < 0) {
|
2013-06-28 12:18:01 -04:00
|
|
|
virCommandFree(cmd);
|
2013-05-13 10:16:52 +02:00
|
|
|
return NULL;
|
2013-06-28 12:18:01 -04:00
|
|
|
}
|
2013-05-13 10:16:52 +02:00
|
|
|
if (opts)
|
|
|
|
virCommandAddArgList(cmd, "-o", opts, NULL);
|
|
|
|
VIR_FREE(opts);
|
|
|
|
} else {
|
2014-07-31 18:07:56 +02:00
|
|
|
if (info.backingPath) {
|
2013-05-13 10:16:52 +02:00
|
|
|
if (imgformat == QEMU_IMG_BACKING_FORMAT_FLAG)
|
|
|
|
virCommandAddArgList(cmd, "-F", backingType, NULL);
|
|
|
|
else
|
|
|
|
VIR_DEBUG("Unable to set backing store format for %s with %s",
|
2014-07-31 18:07:56 +02:00
|
|
|
info.path, create_tool);
|
2011-03-10 10:05:14 +08:00
|
|
|
}
|
2014-07-31 18:07:56 +02:00
|
|
|
if (info.encryption)
|
2013-05-13 10:16:52 +02:00
|
|
|
virCommandAddArg(cmd, "-e");
|
2010-06-16 14:14:05 +01:00
|
|
|
}
|
2009-07-16 12:09:26 -04:00
|
|
|
|
2014-07-31 18:07:56 +02:00
|
|
|
if (info.inputPath)
|
|
|
|
virCommandAddArg(cmd, info.inputPath);
|
|
|
|
virCommandAddArg(cmd, info.path);
|
|
|
|
if (!info.inputPath && info.size_arg)
|
|
|
|
virCommandAddArgFormat(cmd, "%lluK", info.size_arg);
|
2013-05-13 10:16:52 +02:00
|
|
|
|
2013-02-18 12:52:58 +01:00
|
|
|
return cmd;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virStorageBackendCreateQemuImg(virConnectPtr conn,
|
|
|
|
virStoragePoolObjPtr pool,
|
|
|
|
virStorageVolDefPtr vol,
|
|
|
|
virStorageVolDefPtr inputvol,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
2013-09-03 12:36:22 +01:00
|
|
|
char *create_tool;
|
2013-02-18 12:52:58 +01:00
|
|
|
int imgformat;
|
|
|
|
virCommandPtr cmd;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1);
|
|
|
|
|
|
|
|
/* KVM is usually ahead of qemu on features, so try that first */
|
|
|
|
create_tool = virFindFileInPath("kvm-img");
|
|
|
|
if (!create_tool)
|
|
|
|
create_tool = virFindFileInPath("qemu-img");
|
|
|
|
|
|
|
|
if (!create_tool) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("unable to find kvm-img or qemu-img"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
imgformat = virStorageBackendQEMUImgBackingFormat(create_tool);
|
|
|
|
if (imgformat < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-07-31 18:08:33 +02:00
|
|
|
cmd = virStorageBackendCreateQemuImgCmdFromVol(conn, pool, vol, inputvol,
|
|
|
|
flags, create_tool, imgformat);
|
2013-02-18 12:52:58 +01:00
|
|
|
if (!cmd)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-05-06 14:35:51 -04:00
|
|
|
ret = virStorageBackendCreateExecCommand(pool, vol, cmd);
|
2013-02-18 12:52:58 +01:00
|
|
|
|
|
|
|
virCommandFree(cmd);
|
2014-03-25 07:52:40 +01:00
|
|
|
cleanup:
|
2010-06-16 14:14:05 +01:00
|
|
|
VIR_FREE(create_tool);
|
2010-01-21 00:41:52 +01:00
|
|
|
return ret;
|
2009-07-16 12:09:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Xen removed the fully-functional qemu-img, and replaced it
|
|
|
|
* with a partially functional qcow-create. Go figure ??!?
|
|
|
|
*/
|
|
|
|
static int
|
2010-02-10 11:42:56 +00:00
|
|
|
virStorageBackendCreateQcowCreate(virConnectPtr conn ATTRIBUTE_UNUSED,
|
2010-01-21 00:41:52 +01:00
|
|
|
virStoragePoolObjPtr pool,
|
2009-07-16 12:09:26 -04:00
|
|
|
virStorageVolDefPtr vol,
|
2009-07-16 12:27:07 -04:00
|
|
|
virStorageVolDefPtr inputvol,
|
2011-07-06 16:51:23 -06:00
|
|
|
unsigned int flags)
|
2009-07-16 12:09:26 -04:00
|
|
|
{
|
2010-01-21 00:41:52 +01:00
|
|
|
int ret;
|
2010-08-18 15:54:11 -06:00
|
|
|
char *size;
|
2011-05-06 14:35:51 -04:00
|
|
|
virCommandPtr cmd;
|
2009-07-16 12:09:26 -04:00
|
|
|
|
2013-06-05 09:38:41 +02:00
|
|
|
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1);
|
|
|
|
|
|
|
|
if (flags & VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("metadata preallocation is not supported with "
|
|
|
|
"qcow-create"));
|
|
|
|
return -1;
|
|
|
|
}
|
2011-07-06 16:51:23 -06:00
|
|
|
|
2009-07-16 12:09:26 -04:00
|
|
|
if (inputvol) {
|
2012-07-18 12:38:29 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("cannot copy from volume with qcow-create"));
|
2009-07-16 12:09:26 -04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-09-25 14:20:13 +01:00
|
|
|
if (vol->target.format != VIR_STORAGE_FILE_QCOW2) {
|
2012-07-18 12:38:29 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unsupported storage vol type %d"),
|
|
|
|
vol->target.format);
|
2009-07-16 12:09:26 -04:00
|
|
|
return -1;
|
|
|
|
}
|
2014-07-14 15:19:49 +02:00
|
|
|
if (vol->target.backingStore != NULL) {
|
2012-07-18 12:38:29 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("copy-on-write image not supported with "
|
|
|
|
"qcow-create"));
|
2009-07-16 12:09:26 -04:00
|
|
|
return -1;
|
|
|
|
}
|
2009-07-21 04:40:50 +02:00
|
|
|
if (vol->target.encryption != NULL) {
|
2012-07-18 12:38:29 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
"%s", _("encrypted volumes not supported with "
|
|
|
|
"qcow-create"));
|
2009-07-21 04:40:50 +02:00
|
|
|
return -1;
|
|
|
|
}
|
2009-07-16 12:09:26 -04:00
|
|
|
|
|
|
|
/* Size in MB - yes different units to qemu-img :-( */
|
2011-01-28 22:03:24 +01:00
|
|
|
if (virAsprintf(&size, "%llu",
|
conf: track sizes directly in source struct
One of the features of qcow2 is that a wrapper file can have
more capacity than its backing file from the guest's perspective;
what's more, sparse files make tracking allocation of both
the active and backing file worthwhile. As such, it makes
more sense to show allocation numbers for each file in a chain,
and not just the top-level file. This sets up the fields for
the tracking, although it does not modify XML to display any
new information.
* src/util/virstoragefile.h (_virStorageSource): Add fields.
* src/conf/storage_conf.h (_virStorageVolDef): Drop redundant
fields.
* src/storage/storage_backend.c (virStorageBackendCreateBlockFrom)
(createRawFile, virStorageBackendCreateQemuImgCmd)
(virStorageBackendCreateQcowCreate): Update clients.
* src/storage/storage_driver.c (storageVolDelete)
(storageVolCreateXML, storageVolCreateXMLFrom, storageVolResize)
(storageVolWipeInternal, storageVolGetInfo): Likewise.
* src/storage/storage_backend_fs.c (virStorageBackendProbeTarget)
(virStorageBackendFileSystemRefresh)
(virStorageBackendFileSystemVolResize)
(virStorageBackendFileSystemVolRefresh): Likewise.
* src/storage/storage_backend_logical.c
(virStorageBackendLogicalMakeVol)
(virStorageBackendLogicalCreateVol): Likewise.
* src/storage/storage_backend_scsi.c
(virStorageBackendSCSINewLun): Likewise.
* src/storage/storage_backend_mpath.c
(virStorageBackendMpathNewVol): Likewise.
* src/storage/storage_backend_rbd.c
(volStorageBackendRBDRefreshVolInfo)
(virStorageBackendRBDCreateImage): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol): Likewise.
* src/storage/storage_backend_sheepdog.c
(virStorageBackendSheepdogBuildVol)
(virStorageBackendSheepdogParseVdiList): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageBackendGlusterRefreshVol): Likewise.
* src/conf/storage_conf.c (virStorageVolDefFormat)
(virStorageVolDefParseXML): Likewise.
* src/test/test_driver.c (testOpenVolumesForPool)
(testStorageVolCreateXML, testStorageVolCreateXMLFrom)
(testStorageVolDelete, testStorageVolGetInfo): Likewise.
* src/esx/esx_storage_backend_iscsi.c (esxStorageVolGetXMLDesc):
Likewise.
* src/esx/esx_storage_backend_vmfs.c (esxStorageVolGetXMLDesc)
(esxStorageVolCreateXML): Likewise.
* src/parallels/parallels_driver.c (parallelsAddHddByVolume):
Likewise.
* src/parallels/parallels_storage.c (parallelsDiskDescParseNode)
(parallelsStorageVolDefineXML, parallelsStorageVolCreateXMLFrom)
(parallelsStorageVolDefRemove, parallelsStorageVolGetInfo):
Likewise.
* src/vbox/vbox_tmpl.c (vboxStorageVolCreateXML)
(vboxStorageVolGetXMLDesc): Likewise.
* tests/storagebackendsheepdogtest.c (test_vdi_list_parser):
Likewise.
* src/phyp/phyp_driver.c (phypStorageVolCreateXML): Likewise.
2014-04-01 17:43:36 -06:00
|
|
|
VIR_DIV_UP(vol->target.capacity, (1024 * 1024))) < 0)
|
2010-08-18 15:54:11 -06:00
|
|
|
return -1;
|
2009-07-16 12:09:26 -04:00
|
|
|
|
2011-05-06 14:35:51 -04:00
|
|
|
cmd = virCommandNewArgList("qcow-create", size, vol->target.path, NULL);
|
2009-07-16 12:09:26 -04:00
|
|
|
|
2011-05-06 14:35:51 -04:00
|
|
|
ret = virStorageBackendCreateExecCommand(pool, vol, cmd);
|
|
|
|
virCommandFree(cmd);
|
2010-08-18 15:54:11 -06:00
|
|
|
VIR_FREE(size);
|
2009-07-16 12:09:26 -04:00
|
|
|
|
2010-01-21 00:41:52 +01:00
|
|
|
return ret;
|
2009-07-16 12:09:26 -04:00
|
|
|
}
|
|
|
|
|
2009-07-16 12:27:07 -04:00
|
|
|
virStorageBackendBuildVolFrom
|
2010-02-10 11:42:56 +00:00
|
|
|
virStorageBackendFSImageToolTypeToFunc(int tool_type)
|
2009-07-16 12:09:26 -04:00
|
|
|
{
|
|
|
|
switch (tool_type) {
|
|
|
|
case TOOL_KVM_IMG:
|
|
|
|
case TOOL_QEMU_IMG:
|
|
|
|
return virStorageBackendCreateQemuImg;
|
|
|
|
case TOOL_QCOW_CREATE:
|
|
|
|
return virStorageBackendCreateQcowCreate;
|
|
|
|
default:
|
2012-07-18 12:38:29 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unknown file create tool type '%d'."),
|
|
|
|
tool_type);
|
2009-07-16 12:09:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
virStorageBackendFindFSImageTool(char **tool)
|
|
|
|
{
|
|
|
|
int tool_type = -1;
|
|
|
|
char *tmp = NULL;
|
|
|
|
|
|
|
|
if ((tmp = virFindFileInPath("kvm-img")) != NULL) {
|
|
|
|
tool_type = TOOL_KVM_IMG;
|
|
|
|
} else if ((tmp = virFindFileInPath("qemu-img")) != NULL) {
|
|
|
|
tool_type = TOOL_QEMU_IMG;
|
|
|
|
} else if ((tmp = virFindFileInPath("qcow-create")) != NULL) {
|
|
|
|
tool_type = TOOL_QCOW_CREATE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tool)
|
|
|
|
*tool = tmp;
|
|
|
|
else
|
|
|
|
VIR_FREE(tmp);
|
|
|
|
|
|
|
|
return tool_type;
|
|
|
|
}
|
|
|
|
|
2009-07-16 12:27:07 -04:00
|
|
|
virStorageBackendBuildVolFrom
|
2010-02-10 11:42:56 +00:00
|
|
|
virStorageBackendGetBuildVolFromFunction(virStorageVolDefPtr vol,
|
2009-07-16 12:09:26 -04:00
|
|
|
virStorageVolDefPtr inputvol)
|
|
|
|
{
|
|
|
|
int tool_type;
|
|
|
|
|
|
|
|
if (!inputvol)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* If either volume is a non-raw file vol, we need to use an external
|
|
|
|
* tool for converting
|
|
|
|
*/
|
|
|
|
if ((vol->type == VIR_STORAGE_VOL_FILE &&
|
2009-09-25 14:20:13 +01:00
|
|
|
vol->target.format != VIR_STORAGE_FILE_RAW) ||
|
2009-07-16 12:09:26 -04:00
|
|
|
(inputvol->type == VIR_STORAGE_VOL_FILE &&
|
2009-09-25 14:20:13 +01:00
|
|
|
inputvol->target.format != VIR_STORAGE_FILE_RAW)) {
|
2009-07-16 12:09:26 -04:00
|
|
|
|
2009-07-17 13:33:24 +01:00
|
|
|
if ((tool_type = virStorageBackendFindFSImageTool(NULL)) < 0) {
|
2013-06-05 09:41:38 +02:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("creation of non-raw file images is "
|
|
|
|
"not supported without qemu-img."));
|
2009-07-16 12:09:26 -04:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-02-10 11:42:56 +00:00
|
|
|
return virStorageBackendFSImageToolTypeToFunc(tool_type);
|
2009-07-16 12:09:26 -04:00
|
|
|
}
|
|
|
|
|
2009-07-09 19:14:51 -04:00
|
|
|
if (vol->type == VIR_STORAGE_VOL_BLOCK)
|
|
|
|
return virStorageBackendCreateBlockFrom;
|
|
|
|
else
|
|
|
|
return virStorageBackendCreateRaw;
|
2009-07-16 12:09:26 -04:00
|
|
|
}
|
2008-11-11 15:52:16 +00:00
|
|
|
|
2009-06-17 08:38:17 +00:00
|
|
|
|
2008-02-20 15:34:52 +00:00
|
|
|
virStorageBackendPtr
|
2013-06-05 09:41:38 +02:00
|
|
|
virStorageBackendForType(int type)
|
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/storage/ 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 15:09:33 +01:00
|
|
|
size_t i;
|
2008-11-12 16:28:27 +00:00
|
|
|
for (i = 0; backends[i]; i++)
|
2008-02-20 15:42:30 +00:00
|
|
|
if (backends[i]->type == type)
|
|
|
|
return backends[i];
|
|
|
|
|
2012-07-18 12:38:29 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2013-12-13 18:22:04 +01:00
|
|
|
_("missing backend for pool type %d (%s)"),
|
|
|
|
type, NULLSTR(virStoragePoolTypeToString(type)));
|
2008-02-20 15:34:52 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-02-03 16:12:57 +01:00
|
|
|
virStorageFileBackendPtr
|
2014-04-24 16:21:20 +02:00
|
|
|
virStorageFileBackendForTypeInternal(int type,
|
|
|
|
int protocol,
|
|
|
|
bool report)
|
2014-02-03 16:12:57 +01:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; fileBackends[i]; i++) {
|
|
|
|
if (fileBackends[i]->type == type) {
|
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 15:57:49 -06:00
|
|
|
if (type == VIR_STORAGE_TYPE_NETWORK &&
|
2014-02-03 16:12:57 +01:00
|
|
|
fileBackends[i]->protocol != protocol)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
return fileBackends[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-24 16:21:20 +02:00
|
|
|
if (!report)
|
|
|
|
return NULL;
|
|
|
|
|
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 15:57:49 -06:00
|
|
|
if (type == VIR_STORAGE_TYPE_NETWORK) {
|
2014-02-03 16:12:57 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("missing storage backend for network files "
|
|
|
|
"using %s protocol"),
|
2014-03-27 16:47:39 -06:00
|
|
|
virStorageNetProtocolTypeToString(protocol));
|
2014-02-03 16:12:57 +01:00
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("missing storage backend for '%s' storage"),
|
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 15:57:49 -06:00
|
|
|
virStorageTypeToString(type));
|
2014-02-03 16:12:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-24 16:21:20 +02:00
|
|
|
virStorageFileBackendPtr
|
|
|
|
virStorageFileBackendForType(int type,
|
|
|
|
int protocol)
|
|
|
|
{
|
|
|
|
return virStorageFileBackendForTypeInternal(type, protocol, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-30 18:50:36 -04:00
|
|
|
struct diskType {
|
|
|
|
int part_table_type;
|
|
|
|
unsigned short offset;
|
|
|
|
unsigned short length;
|
|
|
|
unsigned long long magic;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static struct diskType const disk_types[] = {
|
|
|
|
{ VIR_STORAGE_POOL_DISK_LVM2, 0x218, 8, 0x31303020324D564CULL },
|
|
|
|
{ VIR_STORAGE_POOL_DISK_GPT, 0x200, 8, 0x5452415020494645ULL },
|
|
|
|
{ VIR_STORAGE_POOL_DISK_DVH, 0x0, 4, 0x41A9E50BULL },
|
|
|
|
{ VIR_STORAGE_POOL_DISK_MAC, 0x0, 2, 0x5245ULL },
|
|
|
|
{ VIR_STORAGE_POOL_DISK_BSD, 0x40, 4, 0x82564557ULL },
|
|
|
|
{ VIR_STORAGE_POOL_DISK_SUN, 0x1fc, 2, 0xBEDAULL },
|
|
|
|
/*
|
|
|
|
* NOTE: pc98 is funky; the actual signature is 0x55AA (just like dos), so
|
|
|
|
* we can't use that. At the moment I'm relying on the "dummy" IPL
|
|
|
|
* bootloader data that comes from parted. Luckily, the chances of running
|
|
|
|
* into a pc98 machine running libvirt are approximately nil.
|
|
|
|
*/
|
|
|
|
/*{ 0x1fe, 2, 0xAA55UL },*/
|
|
|
|
{ VIR_STORAGE_POOL_DISK_PC98, 0x0, 8, 0x314C5049000000CBULL },
|
|
|
|
/*
|
|
|
|
* NOTE: the order is important here; some other disk types (like GPT and
|
|
|
|
* and PC98) also have 0x55AA at this offset. For that reason, the DOS
|
|
|
|
* one must be the last one.
|
|
|
|
*/
|
|
|
|
{ VIR_STORAGE_POOL_DISK_DOS, 0x1fe, 2, 0xAA55ULL },
|
|
|
|
{ -1, 0x0, 0, 0x0ULL },
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2014-04-01 15:11:30 -06:00
|
|
|
virStorageBackendDetectBlockVolFormatFD(virStorageSourcePtr target,
|
2014-03-30 18:50:36 -04:00
|
|
|
int fd)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
off_t start;
|
|
|
|
unsigned char buffer[1024];
|
|
|
|
ssize_t bytes;
|
|
|
|
|
|
|
|
/* make sure to set the target format "unknown" to begin with */
|
|
|
|
target->format = VIR_STORAGE_POOL_DISK_UNKNOWN;
|
|
|
|
|
|
|
|
start = lseek(fd, 0, SEEK_SET);
|
|
|
|
if (start < 0) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("cannot seek to beginning of file '%s'"),
|
|
|
|
target->path);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
bytes = saferead(fd, buffer, sizeof(buffer));
|
|
|
|
if (bytes < 0) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("cannot read beginning of file '%s'"),
|
|
|
|
target->path);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; disk_types[i].part_table_type != -1; i++) {
|
|
|
|
if (disk_types[i].offset + disk_types[i].length > bytes)
|
|
|
|
continue;
|
|
|
|
if (memcmp(buffer+disk_types[i].offset, &disk_types[i].magic,
|
|
|
|
disk_types[i].length) == 0) {
|
|
|
|
target->format = disk_types[i].part_table_type;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
storage: Check for invalid storage mode before opening
If a directory pool contains pipes or sockets, a pool start can fail or hang:
https://bugzilla.redhat.com/show_bug.cgi?id=589577
We already try to avoid these special files, but only attempt after
opening the path, which is where the problems lie. Unify volume opening
into helper functions, which use the proper open() flags to avoid error,
followed by fstat to validate storage mode.
Previously, virStorageBackendUpdateVolTargetInfoFD attempted to enforce the
storage mode check, but allowed callers to detect this case and silently
continue. In practice, only the FS backend was using this feature, the rest
were treating unknown mode as an error condition. Unfortunately the InfoFD
function wasn't raising an error message here, so error reporting was
busted.
This patch adds 2 functions: virStorageBackendVolOpen, and
virStorageBackendVolOpenModeSkip. The latter retains the original opt out
semantics, the former now throws an explicit error.
This patch maintains the previous volume mode checks: allowing specific
modes for specific pool types requires a bit of surgery, since VolOpen
is called through several different helper functions.
v2: Use ATTRIBUTE_NONNULL. Drop stat check, just open with
O_NONBLOCK|O_NOCTTY.
v3: Move mode check logic back to VolOpen. Use 2 VolOpen functions with
different error semantics.
v4: Make second VolOpen function more extensible. Didn't opt to change
FS backend defaults, this can just be to fix the original bug.
v5: Prefix default flags with VIR_, use ATTRIBUTE_RETURN_CHECK
2010-05-20 14:25:01 -04:00
|
|
|
/*
|
|
|
|
* Allows caller to silently ignore files with improper mode
|
|
|
|
*
|
2014-04-02 11:51:45 -04:00
|
|
|
* Returns -1 on error. If VIR_STORAGE_VOL_OPEN_NOERROR is passed, we
|
|
|
|
* return -2 if file mode is unexpected or the volume is a dangling
|
|
|
|
* symbolic link.
|
storage: Check for invalid storage mode before opening
If a directory pool contains pipes or sockets, a pool start can fail or hang:
https://bugzilla.redhat.com/show_bug.cgi?id=589577
We already try to avoid these special files, but only attempt after
opening the path, which is where the problems lie. Unify volume opening
into helper functions, which use the proper open() flags to avoid error,
followed by fstat to validate storage mode.
Previously, virStorageBackendUpdateVolTargetInfoFD attempted to enforce the
storage mode check, but allowed callers to detect this case and silently
continue. In practice, only the FS backend was using this feature, the rest
were treating unknown mode as an error condition. Unfortunately the InfoFD
function wasn't raising an error message here, so error reporting was
busted.
This patch adds 2 functions: virStorageBackendVolOpen, and
virStorageBackendVolOpenModeSkip. The latter retains the original opt out
semantics, the former now throws an explicit error.
This patch maintains the previous volume mode checks: allowing specific
modes for specific pool types requires a bit of surgery, since VolOpen
is called through several different helper functions.
v2: Use ATTRIBUTE_NONNULL. Drop stat check, just open with
O_NONBLOCK|O_NOCTTY.
v3: Move mode check logic back to VolOpen. Use 2 VolOpen functions with
different error semantics.
v4: Make second VolOpen function more extensible. Didn't opt to change
FS backend defaults, this can just be to fix the original bug.
v5: Prefix default flags with VIR_, use ATTRIBUTE_RETURN_CHECK
2010-05-20 14:25:01 -04:00
|
|
|
*/
|
2008-02-20 15:38:29 +00:00
|
|
|
int
|
2014-03-30 19:01:23 -04:00
|
|
|
virStorageBackendVolOpen(const char *path, struct stat *sb,
|
|
|
|
unsigned int flags)
|
2008-02-20 15:38:29 +00:00
|
|
|
{
|
storage: Check for invalid storage mode before opening
If a directory pool contains pipes or sockets, a pool start can fail or hang:
https://bugzilla.redhat.com/show_bug.cgi?id=589577
We already try to avoid these special files, but only attempt after
opening the path, which is where the problems lie. Unify volume opening
into helper functions, which use the proper open() flags to avoid error,
followed by fstat to validate storage mode.
Previously, virStorageBackendUpdateVolTargetInfoFD attempted to enforce the
storage mode check, but allowed callers to detect this case and silently
continue. In practice, only the FS backend was using this feature, the rest
were treating unknown mode as an error condition. Unfortunately the InfoFD
function wasn't raising an error message here, so error reporting was
busted.
This patch adds 2 functions: virStorageBackendVolOpen, and
virStorageBackendVolOpenModeSkip. The latter retains the original opt out
semantics, the former now throws an explicit error.
This patch maintains the previous volume mode checks: allowing specific
modes for specific pool types requires a bit of surgery, since VolOpen
is called through several different helper functions.
v2: Use ATTRIBUTE_NONNULL. Drop stat check, just open with
O_NONBLOCK|O_NOCTTY.
v3: Move mode check logic back to VolOpen. Use 2 VolOpen functions with
different error semantics.
v4: Make second VolOpen function more extensible. Didn't opt to change
FS backend defaults, this can just be to fix the original bug.
v5: Prefix default flags with VIR_, use ATTRIBUTE_RETURN_CHECK
2010-05-20 14:25:01 -04:00
|
|
|
int fd, mode = 0;
|
2011-05-26 14:05:32 -04:00
|
|
|
char *base = last_component(path);
|
2014-04-02 11:51:45 -04:00
|
|
|
bool noerror = (flags & VIR_STORAGE_VOL_OPEN_NOERROR);
|
2008-02-20 15:38:29 +00:00
|
|
|
|
2013-11-05 08:30:01 -07:00
|
|
|
if (lstat(path, sb) < 0) {
|
2014-06-13 16:48:15 +02:00
|
|
|
if (errno == ENOENT) {
|
|
|
|
if (noerror) {
|
|
|
|
VIR_WARN("ignoring missing file '%s'", path);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
virReportError(VIR_ERR_NO_STORAGE_VOL,
|
|
|
|
_("no storage vol with matching path '%s'"),
|
|
|
|
path);
|
|
|
|
return -1;
|
2014-03-20 16:35:00 +01:00
|
|
|
}
|
2011-11-24 15:16:19 +01:00
|
|
|
virReportSystemError(errno,
|
|
|
|
_("cannot stat file '%s'"),
|
|
|
|
path);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-11-05 08:30:01 -07:00
|
|
|
if (S_ISFIFO(sb->st_mode)) {
|
2014-04-02 11:51:45 -04:00
|
|
|
if (noerror) {
|
|
|
|
VIR_WARN("ignoring FIFO '%s'", path);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Volume path '%s' is a FIFO"), path);
|
|
|
|
return -1;
|
2013-11-05 08:30:01 -07:00
|
|
|
} else if (S_ISSOCK(sb->st_mode)) {
|
2014-04-02 11:51:45 -04:00
|
|
|
if (noerror) {
|
|
|
|
VIR_WARN("ignoring socket '%s'", path);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Volume path '%s' is a socket"), path);
|
|
|
|
return -1;
|
2011-11-24 15:16:19 +01:00
|
|
|
}
|
|
|
|
|
2013-11-25 14:38:22 -07:00
|
|
|
/* O_NONBLOCK should only matter during open() for fifos and
|
|
|
|
* sockets, which we already filtered; but using it prevents a
|
|
|
|
* TOCTTOU race. However, later on we will want to read() the
|
|
|
|
* header from this fd, and virFileRead* routines require a
|
|
|
|
* blocking fd, so fix it up after verifying we avoided a
|
|
|
|
* race. */
|
storage: Check for invalid storage mode before opening
If a directory pool contains pipes or sockets, a pool start can fail or hang:
https://bugzilla.redhat.com/show_bug.cgi?id=589577
We already try to avoid these special files, but only attempt after
opening the path, which is where the problems lie. Unify volume opening
into helper functions, which use the proper open() flags to avoid error,
followed by fstat to validate storage mode.
Previously, virStorageBackendUpdateVolTargetInfoFD attempted to enforce the
storage mode check, but allowed callers to detect this case and silently
continue. In practice, only the FS backend was using this feature, the rest
were treating unknown mode as an error condition. Unfortunately the InfoFD
function wasn't raising an error message here, so error reporting was
busted.
This patch adds 2 functions: virStorageBackendVolOpen, and
virStorageBackendVolOpenModeSkip. The latter retains the original opt out
semantics, the former now throws an explicit error.
This patch maintains the previous volume mode checks: allowing specific
modes for specific pool types requires a bit of surgery, since VolOpen
is called through several different helper functions.
v2: Use ATTRIBUTE_NONNULL. Drop stat check, just open with
O_NONBLOCK|O_NOCTTY.
v3: Move mode check logic back to VolOpen. Use 2 VolOpen functions with
different error semantics.
v4: Make second VolOpen function more extensible. Didn't opt to change
FS backend defaults, this can just be to fix the original bug.
v5: Prefix default flags with VIR_, use ATTRIBUTE_RETURN_CHECK
2010-05-20 14:25:01 -04:00
|
|
|
if ((fd = open(path, O_RDONLY|O_NONBLOCK|O_NOCTTY)) < 0) {
|
2010-12-21 14:45:24 +08:00
|
|
|
if ((errno == ENOENT || errno == ELOOP) &&
|
2014-04-02 11:51:45 -04:00
|
|
|
S_ISLNK(sb->st_mode) && noerror) {
|
2010-12-21 14:45:24 +08:00
|
|
|
VIR_WARN("ignoring dangling symlink '%s'", path);
|
|
|
|
return -2;
|
2014-03-20 16:35:00 +01:00
|
|
|
}
|
2014-04-02 11:51:45 -04:00
|
|
|
if (errno == ENOENT && noerror) {
|
2014-03-20 16:35:00 +01:00
|
|
|
VIR_WARN("ignoring missing file '%s'", path);
|
|
|
|
return -2;
|
2010-12-21 14:45:24 +08:00
|
|
|
}
|
2015-01-22 09:12:04 -05:00
|
|
|
if (errno == ENXIO && noerror) {
|
|
|
|
VIR_WARN("ignoring missing fifo '%s'", path);
|
|
|
|
return -2;
|
|
|
|
}
|
2015-04-27 11:47:28 -04:00
|
|
|
if ((errno == EACCES || errno == EPERM) && noerror) {
|
|
|
|
VIR_WARN("ignoring permission error for '%s'", path);
|
|
|
|
return -2;
|
|
|
|
}
|
2010-12-21 14:45:24 +08:00
|
|
|
|
2014-04-02 11:51:45 -04:00
|
|
|
virReportSystemError(errno, _("cannot open volume '%s'"), path);
|
2008-02-20 15:38:29 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-11-05 08:30:01 -07:00
|
|
|
if (fstat(fd, sb) < 0) {
|
2014-04-02 11:51:45 -04:00
|
|
|
virReportSystemError(errno, _("cannot stat file '%s'"), path);
|
2011-11-25 13:25:19 +01:00
|
|
|
VIR_FORCE_CLOSE(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-11-25 14:38:22 -07:00
|
|
|
if (S_ISREG(sb->st_mode)) {
|
storage: Check for invalid storage mode before opening
If a directory pool contains pipes or sockets, a pool start can fail or hang:
https://bugzilla.redhat.com/show_bug.cgi?id=589577
We already try to avoid these special files, but only attempt after
opening the path, which is where the problems lie. Unify volume opening
into helper functions, which use the proper open() flags to avoid error,
followed by fstat to validate storage mode.
Previously, virStorageBackendUpdateVolTargetInfoFD attempted to enforce the
storage mode check, but allowed callers to detect this case and silently
continue. In practice, only the FS backend was using this feature, the rest
were treating unknown mode as an error condition. Unfortunately the InfoFD
function wasn't raising an error message here, so error reporting was
busted.
This patch adds 2 functions: virStorageBackendVolOpen, and
virStorageBackendVolOpenModeSkip. The latter retains the original opt out
semantics, the former now throws an explicit error.
This patch maintains the previous volume mode checks: allowing specific
modes for specific pool types requires a bit of surgery, since VolOpen
is called through several different helper functions.
v2: Use ATTRIBUTE_NONNULL. Drop stat check, just open with
O_NONBLOCK|O_NOCTTY.
v3: Move mode check logic back to VolOpen. Use 2 VolOpen functions with
different error semantics.
v4: Make second VolOpen function more extensible. Didn't opt to change
FS backend defaults, this can just be to fix the original bug.
v5: Prefix default flags with VIR_, use ATTRIBUTE_RETURN_CHECK
2010-05-20 14:25:01 -04:00
|
|
|
mode = VIR_STORAGE_VOL_OPEN_REG;
|
2013-11-25 14:38:22 -07:00
|
|
|
} else if (S_ISCHR(sb->st_mode)) {
|
storage: Check for invalid storage mode before opening
If a directory pool contains pipes or sockets, a pool start can fail or hang:
https://bugzilla.redhat.com/show_bug.cgi?id=589577
We already try to avoid these special files, but only attempt after
opening the path, which is where the problems lie. Unify volume opening
into helper functions, which use the proper open() flags to avoid error,
followed by fstat to validate storage mode.
Previously, virStorageBackendUpdateVolTargetInfoFD attempted to enforce the
storage mode check, but allowed callers to detect this case and silently
continue. In practice, only the FS backend was using this feature, the rest
were treating unknown mode as an error condition. Unfortunately the InfoFD
function wasn't raising an error message here, so error reporting was
busted.
This patch adds 2 functions: virStorageBackendVolOpen, and
virStorageBackendVolOpenModeSkip. The latter retains the original opt out
semantics, the former now throws an explicit error.
This patch maintains the previous volume mode checks: allowing specific
modes for specific pool types requires a bit of surgery, since VolOpen
is called through several different helper functions.
v2: Use ATTRIBUTE_NONNULL. Drop stat check, just open with
O_NONBLOCK|O_NOCTTY.
v3: Move mode check logic back to VolOpen. Use 2 VolOpen functions with
different error semantics.
v4: Make second VolOpen function more extensible. Didn't opt to change
FS backend defaults, this can just be to fix the original bug.
v5: Prefix default flags with VIR_, use ATTRIBUTE_RETURN_CHECK
2010-05-20 14:25:01 -04:00
|
|
|
mode = VIR_STORAGE_VOL_OPEN_CHAR;
|
2013-11-25 14:38:22 -07:00
|
|
|
} else if (S_ISBLK(sb->st_mode)) {
|
storage: Check for invalid storage mode before opening
If a directory pool contains pipes or sockets, a pool start can fail or hang:
https://bugzilla.redhat.com/show_bug.cgi?id=589577
We already try to avoid these special files, but only attempt after
opening the path, which is where the problems lie. Unify volume opening
into helper functions, which use the proper open() flags to avoid error,
followed by fstat to validate storage mode.
Previously, virStorageBackendUpdateVolTargetInfoFD attempted to enforce the
storage mode check, but allowed callers to detect this case and silently
continue. In practice, only the FS backend was using this feature, the rest
were treating unknown mode as an error condition. Unfortunately the InfoFD
function wasn't raising an error message here, so error reporting was
busted.
This patch adds 2 functions: virStorageBackendVolOpen, and
virStorageBackendVolOpenModeSkip. The latter retains the original opt out
semantics, the former now throws an explicit error.
This patch maintains the previous volume mode checks: allowing specific
modes for specific pool types requires a bit of surgery, since VolOpen
is called through several different helper functions.
v2: Use ATTRIBUTE_NONNULL. Drop stat check, just open with
O_NONBLOCK|O_NOCTTY.
v3: Move mode check logic back to VolOpen. Use 2 VolOpen functions with
different error semantics.
v4: Make second VolOpen function more extensible. Didn't opt to change
FS backend defaults, this can just be to fix the original bug.
v5: Prefix default flags with VIR_, use ATTRIBUTE_RETURN_CHECK
2010-05-20 14:25:01 -04:00
|
|
|
mode = VIR_STORAGE_VOL_OPEN_BLOCK;
|
2013-11-25 14:38:22 -07:00
|
|
|
} else if (S_ISDIR(sb->st_mode)) {
|
2011-05-26 14:05:32 -04:00
|
|
|
mode = VIR_STORAGE_VOL_OPEN_DIR;
|
|
|
|
|
|
|
|
if (STREQ(base, ".") ||
|
|
|
|
STREQ(base, "..")) {
|
|
|
|
VIR_FORCE_CLOSE(fd);
|
2014-04-02 11:51:45 -04:00
|
|
|
if (noerror) {
|
|
|
|
VIR_INFO("Skipping special dir '%s'", base);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Cannot use volume path '%s'"), path);
|
|
|
|
return -1;
|
2011-05-26 14:05:32 -04:00
|
|
|
}
|
2013-11-25 14:38:22 -07:00
|
|
|
} else {
|
|
|
|
VIR_FORCE_CLOSE(fd);
|
2014-04-02 11:51:45 -04:00
|
|
|
if (noerror) {
|
|
|
|
VIR_WARN("ignoring unexpected type for file '%s'", path);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected type for file '%s'"), path);
|
|
|
|
return -1;
|
2013-11-25 14:38:22 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (virSetBlocking(fd, true) < 0) {
|
2014-04-02 11:51:45 -04:00
|
|
|
VIR_FORCE_CLOSE(fd);
|
2013-11-25 14:38:22 -07:00
|
|
|
virReportSystemError(errno, _("unable to set blocking mode for '%s'"),
|
|
|
|
path);
|
2014-04-02 11:51:45 -04:00
|
|
|
return -1;
|
2011-05-26 14:05:32 -04:00
|
|
|
}
|
storage: Check for invalid storage mode before opening
If a directory pool contains pipes or sockets, a pool start can fail or hang:
https://bugzilla.redhat.com/show_bug.cgi?id=589577
We already try to avoid these special files, but only attempt after
opening the path, which is where the problems lie. Unify volume opening
into helper functions, which use the proper open() flags to avoid error,
followed by fstat to validate storage mode.
Previously, virStorageBackendUpdateVolTargetInfoFD attempted to enforce the
storage mode check, but allowed callers to detect this case and silently
continue. In practice, only the FS backend was using this feature, the rest
were treating unknown mode as an error condition. Unfortunately the InfoFD
function wasn't raising an error message here, so error reporting was
busted.
This patch adds 2 functions: virStorageBackendVolOpen, and
virStorageBackendVolOpenModeSkip. The latter retains the original opt out
semantics, the former now throws an explicit error.
This patch maintains the previous volume mode checks: allowing specific
modes for specific pool types requires a bit of surgery, since VolOpen
is called through several different helper functions.
v2: Use ATTRIBUTE_NONNULL. Drop stat check, just open with
O_NONBLOCK|O_NOCTTY.
v3: Move mode check logic back to VolOpen. Use 2 VolOpen functions with
different error semantics.
v4: Make second VolOpen function more extensible. Didn't opt to change
FS backend defaults, this can just be to fix the original bug.
v5: Prefix default flags with VIR_, use ATTRIBUTE_RETURN_CHECK
2010-05-20 14:25:01 -04:00
|
|
|
|
|
|
|
if (!(mode & flags)) {
|
2010-11-09 15:48:48 -05:00
|
|
|
VIR_FORCE_CLOSE(fd);
|
2014-04-02 11:51:45 -04:00
|
|
|
if (noerror) {
|
|
|
|
VIR_INFO("Skipping volume '%s'", path);
|
|
|
|
return -2;
|
storage: Check for invalid storage mode before opening
If a directory pool contains pipes or sockets, a pool start can fail or hang:
https://bugzilla.redhat.com/show_bug.cgi?id=589577
We already try to avoid these special files, but only attempt after
opening the path, which is where the problems lie. Unify volume opening
into helper functions, which use the proper open() flags to avoid error,
followed by fstat to validate storage mode.
Previously, virStorageBackendUpdateVolTargetInfoFD attempted to enforce the
storage mode check, but allowed callers to detect this case and silently
continue. In practice, only the FS backend was using this feature, the rest
were treating unknown mode as an error condition. Unfortunately the InfoFD
function wasn't raising an error message here, so error reporting was
busted.
This patch adds 2 functions: virStorageBackendVolOpen, and
virStorageBackendVolOpenModeSkip. The latter retains the original opt out
semantics, the former now throws an explicit error.
This patch maintains the previous volume mode checks: allowing specific
modes for specific pool types requires a bit of surgery, since VolOpen
is called through several different helper functions.
v2: Use ATTRIBUTE_NONNULL. Drop stat check, just open with
O_NONBLOCK|O_NOCTTY.
v3: Move mode check logic back to VolOpen. Use 2 VolOpen functions with
different error semantics.
v4: Make second VolOpen function more extensible. Didn't opt to change
FS backend defaults, this can just be to fix the original bug.
v5: Prefix default flags with VIR_, use ATTRIBUTE_RETURN_CHECK
2010-05-20 14:25:01 -04:00
|
|
|
}
|
|
|
|
|
2014-04-02 11:51:45 -04:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected storage mode for '%s'"), path);
|
|
|
|
return -1;
|
storage: Check for invalid storage mode before opening
If a directory pool contains pipes or sockets, a pool start can fail or hang:
https://bugzilla.redhat.com/show_bug.cgi?id=589577
We already try to avoid these special files, but only attempt after
opening the path, which is where the problems lie. Unify volume opening
into helper functions, which use the proper open() flags to avoid error,
followed by fstat to validate storage mode.
Previously, virStorageBackendUpdateVolTargetInfoFD attempted to enforce the
storage mode check, but allowed callers to detect this case and silently
continue. In practice, only the FS backend was using this feature, the rest
were treating unknown mode as an error condition. Unfortunately the InfoFD
function wasn't raising an error message here, so error reporting was
busted.
This patch adds 2 functions: virStorageBackendVolOpen, and
virStorageBackendVolOpenModeSkip. The latter retains the original opt out
semantics, the former now throws an explicit error.
This patch maintains the previous volume mode checks: allowing specific
modes for specific pool types requires a bit of surgery, since VolOpen
is called through several different helper functions.
v2: Use ATTRIBUTE_NONNULL. Drop stat check, just open with
O_NONBLOCK|O_NOCTTY.
v3: Move mode check logic back to VolOpen. Use 2 VolOpen functions with
different error semantics.
v4: Make second VolOpen function more extensible. Didn't opt to change
FS backend defaults, this can just be to fix the original bug.
v5: Prefix default flags with VIR_, use ATTRIBUTE_RETURN_CHECK
2010-05-20 14:25:01 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2014-04-01 15:11:30 -06:00
|
|
|
virStorageBackendUpdateVolTargetInfo(virStorageSourcePtr target,
|
2014-03-30 18:50:36 -04:00
|
|
|
bool withBlockVolFormat,
|
2011-05-26 14:05:32 -04:00
|
|
|
unsigned int openflags)
|
storage: Check for invalid storage mode before opening
If a directory pool contains pipes or sockets, a pool start can fail or hang:
https://bugzilla.redhat.com/show_bug.cgi?id=589577
We already try to avoid these special files, but only attempt after
opening the path, which is where the problems lie. Unify volume opening
into helper functions, which use the proper open() flags to avoid error,
followed by fstat to validate storage mode.
Previously, virStorageBackendUpdateVolTargetInfoFD attempted to enforce the
storage mode check, but allowed callers to detect this case and silently
continue. In practice, only the FS backend was using this feature, the rest
were treating unknown mode as an error condition. Unfortunately the InfoFD
function wasn't raising an error message here, so error reporting was
busted.
This patch adds 2 functions: virStorageBackendVolOpen, and
virStorageBackendVolOpenModeSkip. The latter retains the original opt out
semantics, the former now throws an explicit error.
This patch maintains the previous volume mode checks: allowing specific
modes for specific pool types requires a bit of surgery, since VolOpen
is called through several different helper functions.
v2: Use ATTRIBUTE_NONNULL. Drop stat check, just open with
O_NONBLOCK|O_NOCTTY.
v3: Move mode check logic back to VolOpen. Use 2 VolOpen functions with
different error semantics.
v4: Make second VolOpen function more extensible. Didn't opt to change
FS backend defaults, this can just be to fix the original bug.
v5: Prefix default flags with VIR_, use ATTRIBUTE_RETURN_CHECK
2010-05-20 14:25:01 -04:00
|
|
|
{
|
2014-03-30 18:50:36 -04:00
|
|
|
int ret, fd = -1;
|
2013-11-05 08:30:01 -07:00
|
|
|
struct stat sb;
|
2015-02-19 13:35:20 +01:00
|
|
|
virStorageSourcePtr meta = NULL;
|
|
|
|
char *buf = NULL;
|
|
|
|
ssize_t len = VIR_STORAGE_MAX_HEADER;
|
storage: Check for invalid storage mode before opening
If a directory pool contains pipes or sockets, a pool start can fail or hang:
https://bugzilla.redhat.com/show_bug.cgi?id=589577
We already try to avoid these special files, but only attempt after
opening the path, which is where the problems lie. Unify volume opening
into helper functions, which use the proper open() flags to avoid error,
followed by fstat to validate storage mode.
Previously, virStorageBackendUpdateVolTargetInfoFD attempted to enforce the
storage mode check, but allowed callers to detect this case and silently
continue. In practice, only the FS backend was using this feature, the rest
were treating unknown mode as an error condition. Unfortunately the InfoFD
function wasn't raising an error message here, so error reporting was
busted.
This patch adds 2 functions: virStorageBackendVolOpen, and
virStorageBackendVolOpenModeSkip. The latter retains the original opt out
semantics, the former now throws an explicit error.
This patch maintains the previous volume mode checks: allowing specific
modes for specific pool types requires a bit of surgery, since VolOpen
is called through several different helper functions.
v2: Use ATTRIBUTE_NONNULL. Drop stat check, just open with
O_NONBLOCK|O_NOCTTY.
v3: Move mode check logic back to VolOpen. Use 2 VolOpen functions with
different error semantics.
v4: Make second VolOpen function more extensible. Didn't opt to change
FS backend defaults, this can just be to fix the original bug.
v5: Prefix default flags with VIR_, use ATTRIBUTE_RETURN_CHECK
2010-05-20 14:25:01 -04:00
|
|
|
|
2014-03-30 19:01:23 -04:00
|
|
|
if ((ret = virStorageBackendVolOpen(target->path, &sb, openflags)) < 0)
|
2014-03-30 18:50:36 -04:00
|
|
|
goto cleanup;
|
storage: Check for invalid storage mode before opening
If a directory pool contains pipes or sockets, a pool start can fail or hang:
https://bugzilla.redhat.com/show_bug.cgi?id=589577
We already try to avoid these special files, but only attempt after
opening the path, which is where the problems lie. Unify volume opening
into helper functions, which use the proper open() flags to avoid error,
followed by fstat to validate storage mode.
Previously, virStorageBackendUpdateVolTargetInfoFD attempted to enforce the
storage mode check, but allowed callers to detect this case and silently
continue. In practice, only the FS backend was using this feature, the rest
were treating unknown mode as an error condition. Unfortunately the InfoFD
function wasn't raising an error message here, so error reporting was
busted.
This patch adds 2 functions: virStorageBackendVolOpen, and
virStorageBackendVolOpenModeSkip. The latter retains the original opt out
semantics, the former now throws an explicit error.
This patch maintains the previous volume mode checks: allowing specific
modes for specific pool types requires a bit of surgery, since VolOpen
is called through several different helper functions.
v2: Use ATTRIBUTE_NONNULL. Drop stat check, just open with
O_NONBLOCK|O_NOCTTY.
v3: Move mode check logic back to VolOpen. Use 2 VolOpen functions with
different error semantics.
v4: Make second VolOpen function more extensible. Didn't opt to change
FS backend defaults, this can just be to fix the original bug.
v5: Prefix default flags with VIR_, use ATTRIBUTE_RETURN_CHECK
2010-05-20 14:25:01 -04:00
|
|
|
fd = ret;
|
2008-02-20 15:38:29 +00:00
|
|
|
|
2015-02-19 13:43:03 +01:00
|
|
|
if ((ret = virStorageBackendUpdateVolTargetInfoFD(target, fd, &sb)) < 0)
|
2014-03-30 18:50:36 -04:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-02-19 13:35:20 +01:00
|
|
|
if (target->type == VIR_STORAGE_VOL_FILE &&
|
|
|
|
target->format != VIR_STORAGE_FILE_NONE) {
|
|
|
|
if (S_ISDIR(sb.st_mode)) {
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
|
|
|
|
virReportSystemError(errno, _("cannot seek to start of '%s'"), target->path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((len = virFileReadHeaderFD(fd, len, &buf)) < 0) {
|
|
|
|
virReportSystemError(errno, _("cannot read header '%s'"), target->path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(meta = virStorageFileGetMetadataFromBuf(target->path, buf, len, target->format,
|
|
|
|
NULL))) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (meta->capacity)
|
|
|
|
target->capacity = meta->capacity;
|
|
|
|
}
|
|
|
|
|
2014-03-30 18:50:36 -04:00
|
|
|
if (withBlockVolFormat) {
|
|
|
|
if ((ret = virStorageBackendDetectBlockVolFormatFD(target, fd)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-04-01 08:52:59 +02:00
|
|
|
cleanup:
|
2015-02-19 13:35:20 +01:00
|
|
|
virStorageSourceFree(meta);
|
2010-11-09 15:48:48 -05:00
|
|
|
VIR_FORCE_CLOSE(fd);
|
2015-02-19 13:35:20 +01:00
|
|
|
VIR_FREE(buf);
|
2008-02-20 15:38:29 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-01-27 18:30:03 +00:00
|
|
|
int
|
2014-03-30 18:27:14 -04:00
|
|
|
virStorageBackendUpdateVolInfo(virStorageVolDefPtr vol,
|
2014-03-30 18:50:36 -04:00
|
|
|
bool withBlockVolFormat,
|
2014-03-30 18:27:14 -04:00
|
|
|
unsigned int openflags)
|
2009-01-27 18:30:03 +00:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
2010-02-04 21:02:58 +01:00
|
|
|
if ((ret = virStorageBackendUpdateVolTargetInfo(&vol->target,
|
2014-07-14 13:29:43 +02:00
|
|
|
withBlockVolFormat,
|
|
|
|
openflags)) < 0)
|
2009-01-27 18:30:03 +00:00
|
|
|
return ret;
|
|
|
|
|
2014-07-14 15:19:49 +02:00
|
|
|
if (vol->target.backingStore &&
|
|
|
|
(ret = virStorageBackendUpdateVolTargetInfo(vol->target.backingStore,
|
2014-07-14 13:29:43 +02:00
|
|
|
withBlockVolFormat,
|
2014-07-15 14:41:58 +02:00
|
|
|
VIR_STORAGE_VOL_OPEN_DEFAULT |
|
|
|
|
VIR_STORAGE_VOL_OPEN_NOERROR) < 0))
|
2009-01-27 18:30:03 +00:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-05-12 19:59:46 +00:00
|
|
|
/*
|
|
|
|
* virStorageBackendUpdateVolTargetInfoFD:
|
|
|
|
* @target: target definition ptr of volume to update
|
2013-11-18 12:45:31 -07:00
|
|
|
* @fd: fd of storage volume to update, via virStorageBackendOpenVol*, or -1
|
|
|
|
* @sb: details about file (must match @fd, if that is provided)
|
2009-05-12 19:59:46 +00:00
|
|
|
*
|
storage: Check for invalid storage mode before opening
If a directory pool contains pipes or sockets, a pool start can fail or hang:
https://bugzilla.redhat.com/show_bug.cgi?id=589577
We already try to avoid these special files, but only attempt after
opening the path, which is where the problems lie. Unify volume opening
into helper functions, which use the proper open() flags to avoid error,
followed by fstat to validate storage mode.
Previously, virStorageBackendUpdateVolTargetInfoFD attempted to enforce the
storage mode check, but allowed callers to detect this case and silently
continue. In practice, only the FS backend was using this feature, the rest
were treating unknown mode as an error condition. Unfortunately the InfoFD
function wasn't raising an error message here, so error reporting was
busted.
This patch adds 2 functions: virStorageBackendVolOpen, and
virStorageBackendVolOpenModeSkip. The latter retains the original opt out
semantics, the former now throws an explicit error.
This patch maintains the previous volume mode checks: allowing specific
modes for specific pool types requires a bit of surgery, since VolOpen
is called through several different helper functions.
v2: Use ATTRIBUTE_NONNULL. Drop stat check, just open with
O_NONBLOCK|O_NOCTTY.
v3: Move mode check logic back to VolOpen. Use 2 VolOpen functions with
different error semantics.
v4: Make second VolOpen function more extensible. Didn't opt to change
FS backend defaults, this can just be to fix the original bug.
v5: Prefix default flags with VIR_, use ATTRIBUTE_RETURN_CHECK
2010-05-20 14:25:01 -04:00
|
|
|
* Returns 0 for success, -1 on a legitimate error condition.
|
2009-05-12 19:59:46 +00:00
|
|
|
*/
|
2008-02-20 15:38:29 +00:00
|
|
|
int
|
2014-04-01 15:11:30 -06:00
|
|
|
virStorageBackendUpdateVolTargetInfoFD(virStorageSourcePtr target,
|
2009-01-27 18:30:03 +00:00
|
|
|
int fd,
|
2015-02-19 13:43:03 +01:00
|
|
|
struct stat *sb)
|
2008-02-20 15:38:29 +00:00
|
|
|
{
|
2012-09-20 13:17:58 +01:00
|
|
|
#if WITH_SELINUX
|
2008-02-20 15:38:29 +00:00
|
|
|
security_context_t filecon = NULL;
|
|
|
|
#endif
|
|
|
|
|
2014-04-01 17:52:41 -06:00
|
|
|
if (S_ISREG(sb->st_mode)) {
|
2010-05-03 14:44:12 -06:00
|
|
|
#ifndef WIN32
|
2014-04-01 17:52:41 -06:00
|
|
|
target->allocation = (unsigned long long)sb->st_blocks *
|
|
|
|
(unsigned long long)DEV_BSIZE;
|
2008-09-05 12:03:45 +00:00
|
|
|
#else
|
2014-04-01 17:52:41 -06:00
|
|
|
target->allocation = sb->st_size;
|
2008-09-05 12:03:45 +00:00
|
|
|
#endif
|
2014-04-01 17:52:41 -06:00
|
|
|
/* Regular files may be sparse, so logical size (capacity) is not same
|
|
|
|
* as actual allocation above
|
|
|
|
*/
|
2015-02-19 13:43:03 +01:00
|
|
|
target->capacity = sb->st_size;
|
2014-04-01 17:52:41 -06:00
|
|
|
} else if (S_ISDIR(sb->st_mode)) {
|
|
|
|
target->allocation = 0;
|
2015-02-19 13:43:03 +01:00
|
|
|
target->capacity = 0;
|
2014-04-01 17:52:41 -06:00
|
|
|
} else if (fd >= 0) {
|
|
|
|
off_t end;
|
|
|
|
/* XXX this is POSIX compliant, but doesn't work for CHAR files,
|
|
|
|
* only BLOCK. There is a Linux specific ioctl() for getting
|
|
|
|
* size of both CHAR / BLOCK devices we should check for in
|
|
|
|
* configure
|
|
|
|
*/
|
|
|
|
end = lseek(fd, 0, SEEK_END);
|
|
|
|
if (end == (off_t)-1) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("cannot seek to end of file '%s'"),
|
|
|
|
target->path);
|
|
|
|
return -1;
|
2008-02-20 15:38:29 +00:00
|
|
|
}
|
2014-04-01 17:52:41 -06:00
|
|
|
target->allocation = end;
|
2015-02-19 13:43:03 +01:00
|
|
|
target->capacity = end;
|
2008-02-20 15:38:29 +00:00
|
|
|
}
|
|
|
|
|
2014-03-29 20:27:44 -06:00
|
|
|
if (!target->perms && VIR_ALLOC(target->perms) < 0)
|
|
|
|
return -1;
|
|
|
|
target->perms->mode = sb->st_mode & S_IRWXUGO;
|
|
|
|
target->perms->uid = sb->st_uid;
|
|
|
|
target->perms->gid = sb->st_gid;
|
2008-02-20 15:38:29 +00:00
|
|
|
|
2013-07-04 12:16:29 +02:00
|
|
|
if (!target->timestamps && VIR_ALLOC(target->timestamps) < 0)
|
2012-07-25 09:43:37 +02:00
|
|
|
return -1;
|
2013-11-05 08:30:01 -07:00
|
|
|
target->timestamps->atime = get_stat_atime(sb);
|
|
|
|
target->timestamps->btime = get_stat_birthtime(sb);
|
|
|
|
target->timestamps->ctime = get_stat_ctime(sb);
|
|
|
|
target->timestamps->mtime = get_stat_mtime(sb);
|
2012-07-25 09:43:37 +02:00
|
|
|
|
2014-03-29 20:27:44 -06:00
|
|
|
VIR_FREE(target->perms->label);
|
2008-02-20 15:38:29 +00:00
|
|
|
|
2012-09-20 13:17:58 +01:00
|
|
|
#if WITH_SELINUX
|
2009-03-03 09:44:41 +00:00
|
|
|
/* XXX: make this a security driver call */
|
2013-11-26 20:57:05 -07:00
|
|
|
if (fd >= 0) {
|
|
|
|
if (fgetfilecon_raw(fd, &filecon) == -1) {
|
|
|
|
if (errno != ENODATA && errno != ENOTSUP) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("cannot get file context of '%s'"),
|
|
|
|
target->path);
|
|
|
|
return -1;
|
|
|
|
}
|
2008-03-17 15:09:38 +00:00
|
|
|
} else {
|
2014-03-29 20:27:44 -06:00
|
|
|
if (VIR_STRDUP(target->perms->label, filecon) < 0) {
|
2013-11-26 20:57:05 -07:00
|
|
|
freecon(filecon);
|
|
|
|
return -1;
|
|
|
|
}
|
2013-05-03 14:49:08 +02:00
|
|
|
freecon(filecon);
|
2008-03-17 15:09:38 +00:00
|
|
|
}
|
2008-02-20 15:38:29 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-04-07 10:53:37 -04:00
|
|
|
bool
|
|
|
|
virStorageBackendPoolPathIsStable(const char *path)
|
|
|
|
{
|
|
|
|
if (path == NULL || STREQ(path, "/dev") || STREQ(path, "/dev/"))
|
|
|
|
return false;
|
|
|
|
|
2015-04-21 06:07:50 -04:00
|
|
|
if (!STRPREFIX(path, "/dev/"))
|
2015-04-07 10:53:37 -04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2009-09-08 15:47:45 +02:00
|
|
|
|
2008-02-20 15:38:29 +00:00
|
|
|
/*
|
|
|
|
* Given a volume path directly in /dev/XXX, iterate over the
|
|
|
|
* entries in the directory pool->def->target.path and find the
|
|
|
|
* first symlink pointing to the volume path.
|
|
|
|
*
|
|
|
|
* If, the target.path is /dev/, then return the original volume
|
|
|
|
* path.
|
|
|
|
*
|
|
|
|
* If no symlink is found, then return the original volume path
|
|
|
|
*
|
|
|
|
* Typically target.path is one of the /dev/disk/by-XXX dirs
|
|
|
|
* with stable paths.
|
2012-10-21 12:53:20 -04:00
|
|
|
*
|
2012-10-23 13:33:21 +02:00
|
|
|
* If 'loop' is true, we use a timeout loop to give dynamic paths
|
2012-10-21 12:53:20 -04:00
|
|
|
* a change to appear.
|
2008-02-20 15:38:29 +00:00
|
|
|
*/
|
|
|
|
char *
|
2010-02-04 21:02:58 +01:00
|
|
|
virStorageBackendStablePath(virStoragePoolObjPtr pool,
|
2012-10-21 12:53:20 -04:00
|
|
|
const char *devpath,
|
2012-10-23 13:33:21 +02:00
|
|
|
bool loop)
|
2008-02-20 15:38:29 +00:00
|
|
|
{
|
|
|
|
DIR *dh;
|
|
|
|
struct dirent *dent;
|
2008-11-03 11:37:11 +00:00
|
|
|
char *stablepath;
|
2008-11-28 07:42:21 +00:00
|
|
|
int opentries = 0;
|
2012-09-24 16:44:20 +08:00
|
|
|
int retry = 0;
|
2014-04-24 15:48:55 -06:00
|
|
|
int direrr;
|
2008-02-20 15:38:29 +00:00
|
|
|
|
2012-01-25 12:07:14 -05:00
|
|
|
/* Logical pools are under /dev but already have stable paths */
|
2015-04-07 10:53:37 -04:00
|
|
|
if (pool->def->type == VIR_STORAGE_POOL_LOGICAL ||
|
|
|
|
!virStorageBackendPoolPathIsStable(pool->def->target.path))
|
2012-01-25 12:07:14 -05:00
|
|
|
goto ret_strdup;
|
|
|
|
|
2008-11-28 07:42:21 +00:00
|
|
|
/* We loop here because /dev/disk/by-{id,path} may not have existed
|
|
|
|
* before we started this operation, so we have to give it some time to
|
|
|
|
* get created.
|
2008-02-20 15:38:29 +00:00
|
|
|
*/
|
2008-11-28 07:42:21 +00:00
|
|
|
reopen:
|
2008-02-20 15:38:29 +00:00
|
|
|
if ((dh = opendir(pool->def->target.path)) == NULL) {
|
2008-11-28 07:42:21 +00:00
|
|
|
opentries++;
|
2012-10-23 13:33:21 +02:00
|
|
|
if (loop && errno == ENOENT && opentries < 50) {
|
2008-11-28 07:42:21 +00:00
|
|
|
usleep(100 * 1000);
|
|
|
|
goto reopen;
|
|
|
|
}
|
2010-02-04 21:02:58 +01:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot read dir '%s'"),
|
|
|
|
pool->def->target.path);
|
2008-02-20 15:38:29 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-11-28 07:42:21 +00:00
|
|
|
/* The pool is pointing somewhere like /dev/disk/by-path
|
|
|
|
* or /dev/disk/by-id, so we need to check all symlinks in
|
|
|
|
* the target directory and figure out which one points
|
2012-09-24 16:44:20 +08:00
|
|
|
* to this device node.
|
|
|
|
*
|
2012-10-21 12:53:20 -04:00
|
|
|
* And it might need some time till the stable path shows
|
2014-04-24 15:48:55 -06:00
|
|
|
* up, so add timeout to retry here. Ignore readdir failures,
|
|
|
|
* since we have a fallback.
|
2008-11-28 07:42:21 +00:00
|
|
|
*/
|
2012-09-24 16:44:20 +08:00
|
|
|
retry:
|
2014-04-24 15:48:55 -06:00
|
|
|
while ((direrr = virDirRead(dh, &dent, NULL)) > 0) {
|
2008-02-20 15:38:29 +00:00
|
|
|
if (dent->d_name[0] == '.')
|
|
|
|
continue;
|
|
|
|
|
2009-05-19 13:15:50 +00:00
|
|
|
if (virAsprintf(&stablepath, "%s/%s",
|
|
|
|
pool->def->target.path,
|
|
|
|
dent->d_name) == -1) {
|
2008-02-20 15:38:29 +00:00
|
|
|
closedir(dh);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virFileLinkPointsTo(stablepath, devpath)) {
|
|
|
|
closedir(dh);
|
|
|
|
return stablepath;
|
|
|
|
}
|
|
|
|
|
2008-06-06 11:09:57 +00:00
|
|
|
VIR_FREE(stablepath);
|
2008-02-20 15:38:29 +00:00
|
|
|
}
|
|
|
|
|
2014-04-24 15:48:55 -06:00
|
|
|
if (!direrr && loop && ++retry < 100) {
|
2012-09-24 16:44:20 +08:00
|
|
|
usleep(100 * 1000);
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
|
2008-02-20 15:38:29 +00:00
|
|
|
closedir(dh);
|
|
|
|
|
2008-11-03 11:37:11 +00:00
|
|
|
ret_strdup:
|
2008-02-20 15:38:29 +00:00
|
|
|
/* Couldn't find any matching stable link so give back
|
|
|
|
* the original non-stable dev path
|
|
|
|
*/
|
2008-11-03 11:37:11 +00:00
|
|
|
|
2013-05-03 14:49:08 +02:00
|
|
|
ignore_value(VIR_STRDUP(stablepath, devpath));
|
2008-11-03 11:37:11 +00:00
|
|
|
|
|
|
|
return stablepath;
|
2008-02-20 15:38:29 +00:00
|
|
|
}
|
2014-03-26 19:17:55 +01:00
|
|
|
|
2014-07-07 16:50:11 +02:00
|
|
|
int
|
|
|
|
virStorageBackendVolUploadLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
|
|
virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
|
|
|
|
virStorageVolDefPtr vol,
|
|
|
|
virStreamPtr stream,
|
|
|
|
unsigned long long offset,
|
|
|
|
unsigned long long len,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
|
|
|
/* Not using O_CREAT because the file is required to already exist at
|
|
|
|
* this point */
|
2014-08-15 12:11:35 +04:00
|
|
|
return virFDStreamOpenBlockDevice(stream, vol->target.path,
|
|
|
|
offset, len, O_WRONLY);
|
2014-07-07 16:50:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
virStorageBackendVolDownloadLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
|
|
virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
|
|
|
|
virStorageVolDefPtr vol,
|
|
|
|
virStreamPtr stream,
|
|
|
|
unsigned long long offset,
|
|
|
|
unsigned long long len,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2014-08-15 12:11:35 +04:00
|
|
|
return virFDStreamOpenBlockDevice(stream, vol->target.path,
|
|
|
|
offset, len, O_RDONLY);
|
2014-07-07 16:50:11 +02:00
|
|
|
}
|
|
|
|
|
2014-07-07 15:41:33 +02:00
|
|
|
|
|
|
|
/* If the volume we're wiping is already a sparse file, we simply
|
|
|
|
* truncate and extend it to its original size, filling it with
|
|
|
|
* zeroes. This behavior is guaranteed by POSIX:
|
|
|
|
*
|
|
|
|
* http://www.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html
|
|
|
|
*
|
|
|
|
* If fildes refers to a regular file, the ftruncate() function shall
|
|
|
|
* cause the size of the file to be truncated to length. If the size
|
|
|
|
* of the file previously exceeded length, the extra data shall no
|
|
|
|
* longer be available to reads on the file. If the file previously
|
|
|
|
* was smaller than this size, ftruncate() shall increase the size of
|
|
|
|
* the file. If the file size is increased, the extended area shall
|
|
|
|
* appear as if it were zero-filled.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virStorageBackendVolZeroSparseFileLocal(virStorageVolDefPtr vol,
|
|
|
|
off_t size,
|
|
|
|
int fd)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
ret = ftruncate(fd, 0);
|
|
|
|
if (ret == -1) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Failed to truncate volume with "
|
|
|
|
"path '%s' to 0 bytes"),
|
|
|
|
vol->target.path);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ftruncate(fd, size);
|
|
|
|
if (ret == -1) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Failed to truncate volume with "
|
|
|
|
"path '%s' to %ju bytes"),
|
|
|
|
vol->target.path, (uintmax_t)size);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virStorageBackendWipeExtentLocal(virStorageVolDefPtr vol,
|
|
|
|
int fd,
|
|
|
|
off_t extent_start,
|
|
|
|
off_t extent_length,
|
|
|
|
char *writebuf,
|
|
|
|
size_t writebuf_length,
|
|
|
|
size_t *bytes_wiped)
|
|
|
|
{
|
|
|
|
int ret = -1, written = 0;
|
|
|
|
off_t remaining = 0;
|
|
|
|
size_t write_size = 0;
|
|
|
|
|
|
|
|
VIR_DEBUG("extent logical start: %ju len: %ju",
|
|
|
|
(uintmax_t)extent_start, (uintmax_t)extent_length);
|
|
|
|
|
|
|
|
if ((ret = lseek(fd, extent_start, SEEK_SET)) < 0) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Failed to seek to position %ju in volume "
|
|
|
|
"with path '%s'"),
|
|
|
|
(uintmax_t)extent_start, vol->target.path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
remaining = extent_length;
|
|
|
|
while (remaining > 0) {
|
|
|
|
|
|
|
|
write_size = (writebuf_length < remaining) ? writebuf_length : remaining;
|
|
|
|
written = safewrite(fd, writebuf, write_size);
|
|
|
|
if (written < 0) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Failed to write %zu bytes to "
|
|
|
|
"storage volume with path '%s'"),
|
|
|
|
write_size, vol->target.path);
|
|
|
|
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
*bytes_wiped += written;
|
|
|
|
remaining -= written;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fdatasync(fd) < 0) {
|
|
|
|
ret = -errno;
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("cannot sync data to volume with path '%s'"),
|
|
|
|
vol->target.path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_DEBUG("Wrote %zu bytes to volume with path '%s'",
|
|
|
|
*bytes_wiped, vol->target.path);
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virStorageBackendVolWipeLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
|
|
virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
|
|
|
|
virStorageVolDefPtr vol,
|
|
|
|
unsigned int algorithm,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
int ret = -1, fd = -1;
|
|
|
|
struct stat st;
|
|
|
|
char *writebuf = NULL;
|
|
|
|
size_t bytes_wiped = 0;
|
|
|
|
virCommandPtr cmd = NULL;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
|
|
|
VIR_DEBUG("Wiping volume with path '%s' and algorithm %u",
|
|
|
|
vol->target.path, algorithm);
|
|
|
|
|
|
|
|
fd = open(vol->target.path, O_RDWR);
|
|
|
|
if (fd == -1) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Failed to open storage volume with path '%s'"),
|
|
|
|
vol->target.path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fstat(fd, &st) == -1) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Failed to stat storage volume with path '%s'"),
|
|
|
|
vol->target.path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (algorithm != VIR_STORAGE_VOL_WIPE_ALG_ZERO) {
|
|
|
|
const char *alg_char ATTRIBUTE_UNUSED = NULL;
|
|
|
|
switch (algorithm) {
|
|
|
|
case VIR_STORAGE_VOL_WIPE_ALG_NNSA:
|
|
|
|
alg_char = "nnsa";
|
|
|
|
break;
|
|
|
|
case VIR_STORAGE_VOL_WIPE_ALG_DOD:
|
|
|
|
alg_char = "dod";
|
|
|
|
break;
|
|
|
|
case VIR_STORAGE_VOL_WIPE_ALG_BSI:
|
|
|
|
alg_char = "bsi";
|
|
|
|
break;
|
|
|
|
case VIR_STORAGE_VOL_WIPE_ALG_GUTMANN:
|
|
|
|
alg_char = "gutmann";
|
|
|
|
break;
|
|
|
|
case VIR_STORAGE_VOL_WIPE_ALG_SCHNEIER:
|
|
|
|
alg_char = "schneier";
|
|
|
|
break;
|
|
|
|
case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7:
|
|
|
|
alg_char = "pfitzner7";
|
|
|
|
break;
|
|
|
|
case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33:
|
|
|
|
alg_char = "pfitzner33";
|
|
|
|
break;
|
|
|
|
case VIR_STORAGE_VOL_WIPE_ALG_RANDOM:
|
|
|
|
alg_char = "random";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("unsupported algorithm %d"),
|
|
|
|
algorithm);
|
|
|
|
}
|
|
|
|
cmd = virCommandNew(SCRUB);
|
|
|
|
virCommandAddArgList(cmd, "-f", "-p", alg_char,
|
|
|
|
vol->target.path, NULL);
|
|
|
|
|
|
|
|
if (virCommandRun(cmd, NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
} else {
|
|
|
|
if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE)) {
|
|
|
|
ret = virStorageBackendVolZeroSparseFileLocal(vol, st.st_size, fd);
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(writebuf, st.st_blksize) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = virStorageBackendWipeExtentLocal(vol,
|
|
|
|
fd,
|
|
|
|
0,
|
|
|
|
vol->target.allocation,
|
|
|
|
writebuf,
|
|
|
|
st.st_blksize,
|
|
|
|
&bytes_wiped);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virCommandFree(cmd);
|
|
|
|
VIR_FREE(writebuf);
|
|
|
|
VIR_FORCE_CLOSE(fd);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-26 19:17:55 +01:00
|
|
|
#ifdef GLUSTER_CLI
|
|
|
|
int
|
|
|
|
virStorageBackendFindGlusterPoolSources(const char *host,
|
|
|
|
int pooltype,
|
|
|
|
virStoragePoolSourceListPtr list)
|
|
|
|
{
|
|
|
|
char *outbuf = NULL;
|
|
|
|
virCommandPtr cmd = NULL;
|
|
|
|
xmlDocPtr doc = NULL;
|
|
|
|
xmlXPathContextPtr ctxt = NULL;
|
|
|
|
xmlNodePtr *nodes = NULL;
|
|
|
|
virStoragePoolSource *src = NULL;
|
|
|
|
size_t i;
|
|
|
|
int nnodes;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
cmd = virCommandNewArgList(GLUSTER_CLI,
|
|
|
|
"--xml",
|
|
|
|
"--log-file=/dev/null",
|
|
|
|
"volume", "info", "all", NULL);
|
|
|
|
|
|
|
|
virCommandAddArgFormat(cmd, "--remote-host=%s", host);
|
|
|
|
virCommandSetOutputBuffer(cmd, &outbuf);
|
|
|
|
|
|
|
|
if (virCommandRun(cmd, &rc) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (rc != 0) {
|
|
|
|
VIR_INFO("failed to query host '%s' for gluster volumes: %s",
|
|
|
|
host, outbuf);
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(doc = virXMLParseStringCtxt(outbuf, _("(gluster_cli_output)"),
|
|
|
|
&ctxt)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((nnodes = virXPathNodeSet("//volumes/volume", ctxt, &nodes)) <= 0) {
|
|
|
|
VIR_INFO("no gluster volumes available on '%s'", host);
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < nnodes; i++) {
|
|
|
|
ctxt->node = nodes[i];
|
|
|
|
|
|
|
|
if (!(src = virStoragePoolSourceListNewSource(list)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(src->dir = virXPathString("string(//name)", ctxt))) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("failed to extract gluster volume name"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(src->hosts, 1) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
src->nhost = 1;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(src->hosts[0].name, host) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
src->format = pooltype;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(nodes);
|
|
|
|
xmlXPathFreeContext(ctxt);
|
|
|
|
xmlFreeDoc(doc);
|
|
|
|
VIR_FREE(outbuf);
|
|
|
|
virCommandFree(cmd);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#else /* #ifdef GLUSTER_CLI */
|
|
|
|
int
|
|
|
|
virStorageBackendFindGlusterPoolSources(const char *host ATTRIBUTE_UNUSED,
|
|
|
|
int pooltype ATTRIBUTE_UNUSED,
|
|
|
|
virStoragePoolSourceListPtr list ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
VIR_INFO("gluster cli tool not installed");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /* #ifdef GLUSTER_CLI */
|