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 <cfont...@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

Reply via email to