[libvirt] [PATCH v2 3/5] storage: Handle readflags errors

John Ferlan jferlan at redhat.com
Tue Nov 24 20:57:14 UTC 2015


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 at 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




More information about the libvir-list mailing list