Similar to the openflags VIR_STORAGE_VOL_OPEN_NOERROR processing, if some
read processing operation fails, check the readflags for the corresponding
error flag being set. If so, rather then causing an error - use VIR_WARN
to flag the error, but return -2 which some callers can use to perform
specific actions.
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
src/storage/storage_backend.c | 107 +++++++++++++++++++++++++++++++-----------
src/storage/storage_backend.h | 11 +++++
2 files changed, 90 insertions(+), 28 deletions(-)
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index c870380..da830d6 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -1393,14 +1393,17 @@ static struct diskType const disk_types[] = {
* virStorageBackendDetectBlockVolFormatFD
* @target: target definition ptr of volume to update
* @fd: fd of storage volume to update,
- * @readflags: unused
+ * @readflags: various VolReadErrorMode flags to handle errors after open
+ * is successful, but some other access/read is not.
*
- * Returns 0 for success, -1 on a legitimate error condition
+ * Returns 0 for success, -1 on a legitimate error condition, -2 if
+ * some sort of error is desired to be ignored (along with appropriate
+ * VIR_WARN of the issue).
*/
static int
virStorageBackendDetectBlockVolFormatFD(virStorageSourcePtr target,
int fd,
- unsigned int readflags ATTRIBUTE_UNUSED)
+ unsigned int readflags)
{
size_t i;
off_t start;
@@ -1412,17 +1415,29 @@ virStorageBackendDetectBlockVolFormatFD(virStorageSourcePtr
target,
start = lseek(fd, 0, SEEK_SET);
if (start < 0) {
- virReportSystemError(errno,
- _("cannot seek to beginning of file
'%s'"),
- target->path);
- return -1;
+ if (readflags & VIR_STORAGE_VOL_SEEK_ERROR) {
+ VIR_WARN("ignoring failed beginning of file lseek for
'%s'",
+ target->path);
+ return -2;
+ } else {
+ 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;
+ if (readflags & VIR_STORAGE_VOL_READ_ERROR) {
+ VIR_WARN("ignoring failed saferead of file '%s'",
+ target->path);
+ return -2;
+ } else {
+ virReportSystemError(errno,
+ _("cannot read beginning of file
'%s'"),
+ target->path);
+ return -1;
+ }
}
for (i = 0; disk_types[i].part_table_type != -1; i++) {
@@ -1591,11 +1606,13 @@ virStorageBackendVolOpen(const char *path, struct stat *sb,
* @target: target definition ptr of volume to update
* @withBlockVolFormat: true if caller determined a block file
* @openflags: various VolOpenCheckMode flags to handle errors on open
- * @readflags: unused
+ * @readflags: various VolReadErrorMode flags to handle errors after open
+ * is successful, but some other access/read is not.
*
* Returns 0 for success, -1 on a legitimate error condition, and -2
* if the openflags used VIR_STORAGE_VOL_OPEN_NOERROR and some sort of
- * open error occurred. It is up to the caller to handle.
+ * open error occurred. It is up to the caller to handle. A -2 may also
+ * be returned if the caller passed a specific readflagsflag.
*/
int
virStorageBackendUpdateVolTargetInfo(virStorageSourcePtr target,
@@ -1625,17 +1642,36 @@ virStorageBackendUpdateVolTargetInfo(virStorageSourcePtr target,
}
if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
- virReportSystemError(errno, _("cannot seek to start of
'%s'"), target->path);
+ if (readflags & VIR_STORAGE_VOL_SEEK_ERROR) {
+ VIR_WARN("ignoring failed beginning of file lseek for
'%s'",
+ target->path);
+ ret = -2;
+ } else {
+ virReportSystemError(errno,
+ _("cannot seek to start of
'%s'"),
+ target->path);
+ ret = -1;
+ }
goto cleanup;
}
if ((len = virFileReadHeaderFD(fd, len, &buf)) < 0) {
- virReportSystemError(errno, _("cannot read header '%s'"),
target->path);
+ if (readflags & VIR_STORAGE_VOL_READ_ERROR) {
+ VIR_WARN("ignoring failed header read for '%s'",
+ target->path);
+ ret = -2;
+ } else {
+ virReportSystemError(errno,
+ _("cannot read header '%s'"),
+ target->path);
+ ret = -1;
+ }
goto cleanup;
}
- if (!(meta = virStorageFileGetMetadataFromBuf(target->path, buf, len,
target->format,
- NULL))) {
+ if (!(meta = virStorageFileGetMetadataFromBuf(target->path,
+ buf, len,
+ target->format, NULL))) {
goto cleanup;
}
@@ -1696,15 +1732,18 @@ virStorageBackendUpdateVolInfo(virStorageVolDefPtr vol,
* @target: target definition ptr of volume to update
* @fd: fd of storage volume to update, via virStorageBackendOpenVol*, or -1
* @sb: details about file (must match @fd, if that is provided)
- * @readflags: unused
+ * @readflags: various VolReadErrorMode flags to handle errors after open
+ * is successful, but some other access/read is not.
*
- * Returns 0 for success, -1 on a legitimate error condition.
+ * Returns 0 for success, -1 on a legitimate error condition, -2 if
+ * some sort of error is desired to be ignored (along with appropriate
+ * VIR_WARN of the issue).
*/
int
virStorageBackendUpdateVolTargetInfoFD(virStorageSourcePtr target,
int fd,
struct stat *sb,
- unsigned int readflags ATTRIBUTE_UNUSED)
+ unsigned int readflags)
{
#if WITH_SELINUX
security_context_t filecon = NULL;
@@ -1733,10 +1772,16 @@ virStorageBackendUpdateVolTargetInfoFD(virStorageSourcePtr
target,
*/
end = lseek(fd, 0, SEEK_END);
if (end == (off_t)-1) {
- virReportSystemError(errno,
- _("cannot seek to end of file '%s'"),
- target->path);
- return -1;
+ if (readflags & VIR_STORAGE_VOL_SEEK_ERROR) {
+ VIR_WARN("Ignoring failed end of file lseek for '%s'",
+ target->path);
+ return -2;
+ } else {
+ virReportSystemError(errno,
+ _("cannot seek to end of file
'%s'"),
+ target->path);
+ return -1;
+ }
}
target->allocation = end;
target->capacity = end;
@@ -1762,10 +1807,16 @@ virStorageBackendUpdateVolTargetInfoFD(virStorageSourcePtr
target,
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;
+ if (readflags & VIR_STORAGE_VOL_FILECON_ERROR) {
+ VIR_WARN("ignore failed get file context of '%s'",
+ target->path);
+ return -2;
+ } else {
+ virReportSystemError(errno,
+ _("cannot get file context of
'%s'"),
+ target->path);
+ return -1;
+ }
}
} else {
if (VIR_STRDUP(target->perms->label, filecon) < 0) {
diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h
index aa9008e..e3ff306 100644
--- a/src/storage/storage_backend.h
+++ b/src/storage/storage_backend.h
@@ -179,6 +179,17 @@ enum {
VIR_STORAGE_VOL_OPEN_DIR = 1 << 4, /* directories okay */
};
+/* VolReadErrorMode flags
+ * If flag is present, then operation won't cause fatal error for
+ * specified operation, rather a VIR_WARN will be issued and a -2 returned
+ * for function call
+ */
+enum {
+ VIR_STORAGE_VOL_SEEK_ERROR = 1 << 0, /* don't error on (l)seek */
+ VIR_STORAGE_VOL_READ_ERROR = 1 << 1, /* don't error on *read */
+ VIR_STORAGE_VOL_FILECON_ERROR = 1 << 2, /* don't error on (f)filecon* */
+};
+
# define VIR_STORAGE_VOL_OPEN_DEFAULT (VIR_STORAGE_VOL_OPEN_REG |\
VIR_STORAGE_VOL_OPEN_BLOCK)
--
2.5.0