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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list