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(a)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 be5418c70f..745e8e5836 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