[libvirt RFCv10 05/32] virfile: virFileDiskCopy: prepare for O_DIRECT files without wrapper

Claudio Fontana cfontana at suse.de
Sun May 15 09:49:01 UTC 2022


we will allow to use already open fds that are not empty
for both read and write, as long as they are properly aligned.

Adapt the truncation to take into account the initial offset.

Signed-off-by: Claudio Fontana <cfontana at suse.de>
---
 src/util/virfile.c | 39 +++++++++++++++++----------------------
 1 file changed, 17 insertions(+), 22 deletions(-)

diff --git a/src/util/virfile.c b/src/util/virfile.c
index c529598595..b4eacfe608 100644
--- a/src/util/virfile.c
+++ b/src/util/virfile.c
@@ -4890,12 +4890,6 @@ runIOCopy(const struct runIOParams p)
                 virReportSystemError(errno, _("Unable to write %s"), p.fdoutname);
                 return -3;
             }
-
-            if (!p.isBlockDev && ftruncate(p.fdout, total) < 0) {
-                virReportSystemError(errno, _("Unable to truncate %s"), p.fdoutname);
-                return -4;
-            }
-
             break;
         }
 
@@ -4930,6 +4924,7 @@ off_t
 virFileDiskCopy(int disk_fd, const char *disk_path, int remote_fd, const char *remote_path)
 {
     int ret = -1;
+    off_t off = 0;
     off_t total = 0;
     struct stat sb;
     struct runIOParams p;
@@ -4973,23 +4968,17 @@ virFileDiskCopy(int disk_fd, const char *disk_path, int remote_fd, const char *r
                              (oflags & O_ACCMODE));
         goto cleanup;
     }
-    /* To make the implementation simpler, we give up on any
-     * attempt to use O_DIRECT in a non-trivial manner.  */
     if (!p.isBlockDev && p.isDirect) {
-        off_t off;
-        if (p.isWrite) {
-            /*
-             * note: for write we do not only check that disk_fd is seekable,
-             * we also want to know that the file is empty, so we need SEEK_END.
-             */
-            if ((off = lseek(disk_fd, 0, SEEK_END)) != 0) {
-                virReportSystemError(off < 0 ? errno : EINVAL, "%s",
-                                     _("O_DIRECT write needs empty seekable file"));
-                goto cleanup;
-            }
-        } else if ((off = lseek(disk_fd, 0, SEEK_CUR)) != 0) {
-            virReportSystemError(off < 0 ? errno : EINVAL, "%s",
-                                 _("O_DIRECT read needs entire seekable file"));
+        off = lseek(disk_fd, 0, SEEK_CUR);
+
+        /* Detect wrong uses of O_DIRECT. */
+        if (off < 0) {
+            virReportSystemError(errno, "%s", _("O_DIRECT needs a seekable file"));
+            goto cleanup;
+        }
+        if (virFileDirectAlign(off) != off) {
+            /* we could write some zeroes, but maybe it is safer to just fail */
+            virReportSystemError(EINVAL, "%s", _("O_DIRECT attempted on an open fd that is not aligned"));
             goto cleanup;
         }
     }
@@ -4997,6 +4986,12 @@ virFileDiskCopy(int disk_fd, const char *disk_path, int remote_fd, const char *r
     if (total < 0)
         goto cleanup;
 
+    if (!p.isBlockDev && p.isDirect && p.isWrite) {
+        if (ftruncate(p.fdout, off + total) < 0) {
+            virReportSystemError(errno, _("Unable to truncate %s"), p.fdoutname);
+            goto cleanup;
+        }
+    }
     /* Ensure all data is written */
     if (virFileDataSync(p.fdout) < 0) {
         if (errno != EINVAL && errno != EROFS) {
-- 
2.35.3



More information about the libvir-list mailing list