2015-04-16 09:24:19 +00:00
|
|
|
/*
|
|
|
|
* qemu_blockjob.h: helper functions for QEMU block jobs
|
|
|
|
*
|
|
|
|
* Copyright (C) 2006-2015 Red Hat, Inc.
|
|
|
|
* Copyright (C) 2006 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
|
|
|
|
* License along with this library. If not, see
|
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2019-06-18 16:12:37 +00:00
|
|
|
#pragma once
|
2015-04-16 09:24:19 +00:00
|
|
|
|
2019-06-18 16:12:37 +00:00
|
|
|
#include "internal.h"
|
|
|
|
#include "qemu_conf.h"
|
2015-04-16 09:24:19 +00:00
|
|
|
|
2019-01-17 15:34:11 +00:00
|
|
|
/**
|
|
|
|
* This enum has to map all known block job states from enum virDomainBlockJobType
|
|
|
|
* to the same values. All internal blockjobs can be mapped after and don't
|
|
|
|
* need to have stable values.
|
|
|
|
*/
|
|
|
|
typedef enum {
|
2019-01-23 19:38:41 +00:00
|
|
|
/* Mapped to public enum */
|
2019-01-17 15:34:11 +00:00
|
|
|
QEMU_BLOCKJOB_STATE_COMPLETED = VIR_DOMAIN_BLOCK_JOB_COMPLETED,
|
|
|
|
QEMU_BLOCKJOB_STATE_FAILED = VIR_DOMAIN_BLOCK_JOB_FAILED,
|
|
|
|
QEMU_BLOCKJOB_STATE_CANCELLED = VIR_DOMAIN_BLOCK_JOB_CANCELED,
|
|
|
|
QEMU_BLOCKJOB_STATE_READY = VIR_DOMAIN_BLOCK_JOB_READY,
|
2019-01-23 19:38:41 +00:00
|
|
|
/* Additional enum values local to qemu */
|
|
|
|
QEMU_BLOCKJOB_STATE_NEW,
|
2019-01-17 15:34:11 +00:00
|
|
|
QEMU_BLOCKJOB_STATE_RUNNING,
|
2018-12-07 16:40:30 +00:00
|
|
|
QEMU_BLOCKJOB_STATE_CONCLUDED, /* job has finished, but it's unknown
|
|
|
|
whether it has failed or not */
|
2019-02-11 13:36:24 +00:00
|
|
|
QEMU_BLOCKJOB_STATE_ABORTING,
|
|
|
|
QEMU_BLOCKJOB_STATE_PIVOTING,
|
2019-01-17 15:34:11 +00:00
|
|
|
QEMU_BLOCKJOB_STATE_LAST
|
|
|
|
} qemuBlockjobState;
|
2020-01-09 10:39:55 +00:00
|
|
|
G_STATIC_ASSERT((int)QEMU_BLOCKJOB_STATE_NEW == VIR_DOMAIN_BLOCK_JOB_LAST);
|
2019-01-17 15:34:11 +00:00
|
|
|
|
2018-11-30 15:55:08 +00:00
|
|
|
VIR_ENUM_DECL(qemuBlockjobState);
|
|
|
|
|
2018-11-23 11:45:32 +00:00
|
|
|
/**
|
|
|
|
* This enum has to map all known block job types from enum virDomainBlockJobType
|
|
|
|
* to the same values. All internal blockjobs can be mapped after and don't
|
|
|
|
* need to have stable values.
|
|
|
|
*/
|
|
|
|
typedef enum {
|
2019-01-23 19:38:41 +00:00
|
|
|
/* Mapped to public enum */
|
2018-11-23 11:45:32 +00:00
|
|
|
QEMU_BLOCKJOB_TYPE_NONE = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN,
|
|
|
|
QEMU_BLOCKJOB_TYPE_PULL = VIR_DOMAIN_BLOCK_JOB_TYPE_PULL,
|
|
|
|
QEMU_BLOCKJOB_TYPE_COPY = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY,
|
|
|
|
QEMU_BLOCKJOB_TYPE_COMMIT = VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT,
|
|
|
|
QEMU_BLOCKJOB_TYPE_ACTIVE_COMMIT = VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT,
|
2019-10-18 13:10:33 +00:00
|
|
|
QEMU_BLOCKJOB_TYPE_BACKUP = VIR_DOMAIN_BLOCK_JOB_TYPE_BACKUP,
|
2019-01-23 19:38:41 +00:00
|
|
|
/* Additional enum values local to qemu */
|
2018-11-23 11:45:32 +00:00
|
|
|
QEMU_BLOCKJOB_TYPE_INTERNAL,
|
2019-06-10 16:13:09 +00:00
|
|
|
QEMU_BLOCKJOB_TYPE_CREATE,
|
2019-11-26 13:55:05 +00:00
|
|
|
QEMU_BLOCKJOB_TYPE_BROKEN,
|
2018-11-23 11:45:32 +00:00
|
|
|
QEMU_BLOCKJOB_TYPE_LAST
|
|
|
|
} qemuBlockJobType;
|
2020-01-09 10:39:55 +00:00
|
|
|
G_STATIC_ASSERT((int)QEMU_BLOCKJOB_TYPE_INTERNAL == VIR_DOMAIN_BLOCK_JOB_TYPE_LAST);
|
2018-10-17 06:57:08 +00:00
|
|
|
|
2018-11-30 15:55:08 +00:00
|
|
|
VIR_ENUM_DECL(qemuBlockjob);
|
|
|
|
|
2019-07-22 11:39:24 +00:00
|
|
|
|
|
|
|
typedef struct _qemuBlockJobPullData qemuBlockJobPullData;
|
|
|
|
typedef qemuBlockJobPullData *qemuBlockJobDataPullPtr;
|
|
|
|
|
|
|
|
struct _qemuBlockJobPullData {
|
|
|
|
virStorageSourcePtr base;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-07-22 11:39:24 +00:00
|
|
|
typedef struct _qemuBlockJobCommitData qemuBlockJobCommitData;
|
|
|
|
typedef qemuBlockJobCommitData *qemuBlockJobDataCommitPtr;
|
|
|
|
|
|
|
|
struct _qemuBlockJobCommitData {
|
|
|
|
virStorageSourcePtr topparent;
|
|
|
|
virStorageSourcePtr top;
|
|
|
|
virStorageSourcePtr base;
|
2019-12-10 16:25:38 +00:00
|
|
|
bool deleteCommittedImages;
|
2019-07-22 11:39:24 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-06-10 16:13:09 +00:00
|
|
|
typedef struct _qemuBlockJobCreateData qemuBlockJobCreateData;
|
|
|
|
typedef qemuBlockJobCreateData *qemuBlockJobDataCreatePtr;
|
|
|
|
|
|
|
|
struct _qemuBlockJobCreateData {
|
|
|
|
bool storage;
|
|
|
|
virStorageSourcePtr src;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-07-22 11:59:01 +00:00
|
|
|
typedef struct _qemuBlockJobCopyData qemuBlockJobCopyData;
|
|
|
|
typedef qemuBlockJobCopyData *qemuBlockJobDataCopyPtr;
|
|
|
|
|
|
|
|
struct _qemuBlockJobCopyData {
|
|
|
|
bool shallownew;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-10-16 07:39:32 +00:00
|
|
|
typedef struct _qemuBlockJobBackupData qemuBlockJobBackupData;
|
|
|
|
typedef qemuBlockJobBackupData *qemuBlockJobDataBackupPtr;
|
|
|
|
|
|
|
|
struct _qemuBlockJobBackupData {
|
|
|
|
virStorageSourcePtr store;
|
|
|
|
char *bitmap;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2018-10-17 06:57:08 +00:00
|
|
|
typedef struct _qemuBlockJobData qemuBlockJobData;
|
|
|
|
typedef qemuBlockJobData *qemuBlockJobDataPtr;
|
|
|
|
|
|
|
|
struct _qemuBlockJobData {
|
2018-11-14 15:47:50 +00:00
|
|
|
virObject parent;
|
|
|
|
|
2019-01-17 16:01:55 +00:00
|
|
|
char *name;
|
|
|
|
|
2018-11-21 14:36:47 +00:00
|
|
|
virDomainDiskDefPtr disk; /* may be NULL, if blockjob does not correspond to any disk */
|
2019-03-19 06:54:12 +00:00
|
|
|
virStorageSourcePtr chain; /* Reference to the chain the job operates on. */
|
|
|
|
virStorageSourcePtr mirrorChain; /* reference to 'mirror' part of the job */
|
2018-11-21 14:36:47 +00:00
|
|
|
|
2020-01-31 12:00:29 +00:00
|
|
|
unsigned int jobflags; /* per job flags */
|
|
|
|
bool jobflagsmissing; /* job flags were not stored */
|
|
|
|
|
2019-07-22 11:39:24 +00:00
|
|
|
union {
|
|
|
|
qemuBlockJobPullData pull;
|
2019-07-22 11:39:24 +00:00
|
|
|
qemuBlockJobCommitData commit;
|
2019-06-10 16:13:09 +00:00
|
|
|
qemuBlockJobCreateData create;
|
2019-07-22 11:59:01 +00:00
|
|
|
qemuBlockJobCopyData copy;
|
2019-10-16 07:39:32 +00:00
|
|
|
qemuBlockJobBackupData backup;
|
2019-07-22 11:39:24 +00:00
|
|
|
} data;
|
|
|
|
|
2018-11-23 11:45:32 +00:00
|
|
|
int type; /* qemuBlockJobType */
|
2019-01-17 15:34:11 +00:00
|
|
|
int state; /* qemuBlockjobState */
|
2018-10-17 06:57:08 +00:00
|
|
|
char *errmsg;
|
|
|
|
bool synchronous; /* API call is waiting for this job */
|
2018-11-22 14:05:50 +00:00
|
|
|
|
2019-02-12 13:02:27 +00:00
|
|
|
int newstate; /* qemuBlockjobState, subset of events emitted by qemu */
|
2019-07-05 07:02:21 +00:00
|
|
|
|
2019-11-26 13:55:05 +00:00
|
|
|
int brokentype; /* the previous type of a broken blockjob qemuBlockJobType */
|
|
|
|
|
2019-07-05 07:02:21 +00:00
|
|
|
bool invalidData; /* the job data (except name) is not valid */
|
2018-12-11 17:13:35 +00:00
|
|
|
bool reconnected; /* internal field for tracking whether job is live after reconnect to qemu */
|
2018-10-17 06:57:08 +00:00
|
|
|
};
|
2019-10-04 16:14:10 +00:00
|
|
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuBlockJobData, virObjectUnref);
|
2018-10-17 06:57:08 +00:00
|
|
|
|
2019-07-01 15:36:38 +00:00
|
|
|
int
|
|
|
|
qemuBlockJobRegister(qemuBlockJobDataPtr job,
|
|
|
|
virDomainObjPtr vm,
|
2019-05-15 08:58:42 +00:00
|
|
|
virDomainDiskDefPtr disk,
|
|
|
|
bool savestatus)
|
2019-07-01 15:36:38 +00:00
|
|
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
|
|
|
|
|
|
|
qemuBlockJobDataPtr
|
|
|
|
qemuBlockJobDataNew(qemuBlockJobType type,
|
|
|
|
const char *name)
|
|
|
|
ATTRIBUTE_NONNULL(2);
|
2018-10-17 06:57:08 +00:00
|
|
|
|
2018-11-19 15:48:09 +00:00
|
|
|
qemuBlockJobDataPtr
|
2018-11-29 16:35:52 +00:00
|
|
|
qemuBlockJobDiskNew(virDomainObjPtr vm,
|
|
|
|
virDomainDiskDefPtr disk,
|
2019-01-17 16:01:55 +00:00
|
|
|
qemuBlockJobType type,
|
|
|
|
const char *jobname)
|
2019-07-19 06:47:39 +00:00
|
|
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4);
|
2018-11-19 15:48:09 +00:00
|
|
|
|
|
|
|
qemuBlockJobDataPtr
|
2019-07-22 11:39:24 +00:00
|
|
|
qemuBlockJobDiskNewPull(virDomainObjPtr vm,
|
|
|
|
virDomainDiskDefPtr disk,
|
2020-01-30 13:02:55 +00:00
|
|
|
virStorageSourcePtr base,
|
|
|
|
unsigned int jobflags);
|
2019-07-22 11:39:24 +00:00
|
|
|
|
|
|
|
qemuBlockJobDataPtr
|
2019-07-22 11:39:24 +00:00
|
|
|
qemuBlockJobDiskNewCommit(virDomainObjPtr vm,
|
|
|
|
virDomainDiskDefPtr disk,
|
|
|
|
virStorageSourcePtr topparent,
|
|
|
|
virStorageSourcePtr top,
|
2019-12-10 16:25:38 +00:00
|
|
|
virStorageSourcePtr base,
|
2020-01-30 13:02:55 +00:00
|
|
|
bool delete_imgs,
|
|
|
|
unsigned int jobflags);
|
2019-07-22 11:39:24 +00:00
|
|
|
|
|
|
|
qemuBlockJobDataPtr
|
2019-06-10 16:13:09 +00:00
|
|
|
qemuBlockJobNewCreate(virDomainObjPtr vm,
|
|
|
|
virStorageSourcePtr src,
|
|
|
|
virStorageSourcePtr chain,
|
|
|
|
bool storage);
|
|
|
|
|
|
|
|
qemuBlockJobDataPtr
|
2019-07-22 11:59:01 +00:00
|
|
|
qemuBlockJobDiskNewCopy(virDomainObjPtr vm,
|
|
|
|
virDomainDiskDefPtr disk,
|
|
|
|
virStorageSourcePtr mirror,
|
|
|
|
bool shallow,
|
2020-01-30 13:02:55 +00:00
|
|
|
bool reuse,
|
|
|
|
unsigned int jobflags);
|
2019-07-22 11:59:01 +00:00
|
|
|
|
|
|
|
qemuBlockJobDataPtr
|
2019-10-16 07:39:32 +00:00
|
|
|
qemuBlockJobDiskNewBackup(virDomainObjPtr vm,
|
|
|
|
virDomainDiskDefPtr disk,
|
|
|
|
virStorageSourcePtr store,
|
|
|
|
const char *bitmap);
|
|
|
|
|
|
|
|
qemuBlockJobDataPtr
|
2018-11-19 15:48:09 +00:00
|
|
|
qemuBlockJobDiskGetJob(virDomainDiskDefPtr disk)
|
|
|
|
ATTRIBUTE_NONNULL(1);
|
|
|
|
|
|
|
|
void
|
2019-05-15 08:58:42 +00:00
|
|
|
qemuBlockJobStarted(qemuBlockJobDataPtr job,
|
|
|
|
virDomainObjPtr vm)
|
|
|
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
2018-11-19 15:48:09 +00:00
|
|
|
|
2019-01-17 15:34:11 +00:00
|
|
|
bool
|
|
|
|
qemuBlockJobIsRunning(qemuBlockJobDataPtr job)
|
|
|
|
ATTRIBUTE_NONNULL(1);
|
|
|
|
|
2018-11-19 15:48:09 +00:00
|
|
|
void
|
2018-11-29 16:35:52 +00:00
|
|
|
qemuBlockJobStartupFinalize(virDomainObjPtr vm,
|
|
|
|
qemuBlockJobDataPtr job);
|
2018-11-19 15:48:09 +00:00
|
|
|
|
2018-12-11 17:13:35 +00:00
|
|
|
int
|
|
|
|
qemuBlockJobRefreshJobs(virQEMUDriverPtr driver,
|
|
|
|
virDomainObjPtr vm);
|
|
|
|
|
2020-03-26 12:22:18 +00:00
|
|
|
void
|
|
|
|
qemuBlockJobUpdate(virDomainObjPtr vm,
|
|
|
|
qemuBlockJobDataPtr job,
|
|
|
|
int asyncJob);
|
2015-04-16 09:24:19 +00:00
|
|
|
|
2018-10-19 07:14:54 +00:00
|
|
|
void qemuBlockJobSyncBegin(qemuBlockJobDataPtr job);
|
2018-11-27 17:06:28 +00:00
|
|
|
void qemuBlockJobSyncEnd(virDomainObjPtr vm,
|
|
|
|
qemuBlockJobDataPtr job,
|
|
|
|
int asyncJob);
|
qemuBlockJobSync*: introduce sync block job helpers
qemuBlockJobSyncBegin and qemuBlockJobSyncEnd delimit a region of code
where block job events are processed "synchronously".
qemuBlockJobSyncWait and qemuBlockJobSyncWaitWithTimeout wait for an
event generated by a block job.
The Wait* functions may be called multiple times while the synchronous
block job is active. Any pending block job event will be processed by
only when Wait* or End is called. disk->blockJobStatus is reset by
these functions, so if it is needed a pointer to a
virConnectDomainEventBlockJobStatus variable should be passed as the
last argument. It is safe to pass NULL if you do not care about the
block job status.
All functions assume the VM object is locked. The Wait* functions will
unlock the object for as long as they are waiting. They will return -1
and report an error if the domain exits before an event is received.
Typical use is as follows:
virQEMUDriverPtr driver;
virDomainObjPtr vm; /* locked */
virDomainDiskDefPtr disk;
virConnectDomainEventBlockJobStatus status;
qemuBlockJobSyncBegin(disk);
... start block job ...
if (qemuBlockJobSyncWait(driver, vm, disk, &status) < 0) {
/* domain died while waiting for event */
ret = -1;
goto error;
}
... possibly start other block jobs
or wait for further events ...
qemuBlockJobSyncEnd(driver, vm, disk, NULL);
To perform other tasks periodically while waiting for an event:
virQEMUDriverPtr driver;
virDomainObjPtr vm; /* locked */
virDomainDiskDefPtr disk;
virConnectDomainEventBlockJobStatus status;
unsigned long long timeout = 500 * 1000ull; /* milliseconds */
qemuBlockJobSyncBegin(disk);
... start block job ...
do {
... do other task ...
if (qemuBlockJobSyncWaitWithTimeout(driver, vm, disk,
timeout, &status) < 0) {
/* domain died while waiting for event */
ret = -1;
goto error;
}
} while (status == -1);
qemuBlockJobSyncEnd(driver, vm, disk, NULL);
Signed-off-by: Michael Chapman <mike@very.puzzling.org>
2015-04-16 09:24:20 +00:00
|
|
|
|
2018-11-19 15:48:09 +00:00
|
|
|
qemuBlockJobDataPtr
|
|
|
|
qemuBlockJobGetByDisk(virDomainDiskDefPtr disk)
|
2019-10-14 12:25:14 +00:00
|
|
|
ATTRIBUTE_NONNULL(1) G_GNUC_WARN_UNUSED_RESULT;
|
2018-12-10 15:56:53 +00:00
|
|
|
|
|
|
|
qemuBlockjobState
|
|
|
|
qemuBlockjobConvertMonitorStatus(int monitorstatus);
|