virStorageBackendVolDownloadLocal and virStorageBackendVolUploadLocal
use virFDStreamOpenFile function to work with the volume fd.
virFDStreamOpenFile calls virFDStreamOpenFileInternal that implements
handling of the non-blocking I/O. If a file is not a character device and
not a fifo, it uses libvirt_iohelper.
On FreeBSD, it doesn't work as expected because disks are exposed as
character devices.
To overcome this, introduce a forceIOHelper flag to
virFDStreamOpenFileInternal that forces using libvirt_iohelper. And
introduce virFDStreamOpenBlockDevice that calls
virFDStreamOpenFileInternal with the forceIOHelper set to true.
---
src/fdstream.c | 26 ++++++++++++++++++++------
src/fdstream.h | 5 +++++
src/libvirt_private.syms | 1 +
src/storage/storage_backend.c | 6 ++++--
4 files changed, 30 insertions(+), 8 deletions(-)
diff --git a/src/fdstream.c b/src/fdstream.c
index d236318..4cf152a 100644
--- a/src/fdstream.c
+++ b/src/fdstream.c
@@ -577,7 +577,8 @@ virFDStreamOpenFileInternal(virStreamPtr st,
unsigned long long offset,
unsigned long long length,
int oflags,
- int mode)
+ int mode,
+ bool forceIOHelper)
{
int fd = -1;
int childfd = -1;
@@ -623,8 +624,8 @@ virFDStreamOpenFileInternal(virStreamPtr st,
* the I/O so we just have a fifo. Or use AIO :-(
*/
if ((st->flags & VIR_STREAM_NONBLOCK) &&
- (!S_ISCHR(sb.st_mode) &&
- !S_ISFIFO(sb.st_mode))) {
+ ((!S_ISCHR(sb.st_mode) &&
+ !S_ISFIFO(sb.st_mode)) || forceIOHelper)) {
int fds[2] = { -1, -1 };
if ((oflags & O_ACCMODE) == O_RDWR) {
@@ -703,7 +704,7 @@ int virFDStreamOpenFile(virStreamPtr st,
}
return virFDStreamOpenFileInternal(st, path,
offset, length,
- oflags, 0);
+ oflags, 0, false);
}
int virFDStreamCreateFile(virStreamPtr st,
@@ -715,7 +716,8 @@ int virFDStreamCreateFile(virStreamPtr st,
{
return virFDStreamOpenFileInternal(st, path,
offset, length,
- oflags | O_CREAT, mode);
+ oflags | O_CREAT, mode,
+ false);
}
#ifdef HAVE_CFMAKERAW
@@ -730,7 +732,8 @@ int virFDStreamOpenPTY(virStreamPtr st,
if (virFDStreamOpenFileInternal(st, path,
offset, length,
- oflags | O_CREAT, 0) < 0)
+ oflags | O_CREAT, 0,
+ false) < 0)
return -1;
fdst = st->privateData;
@@ -770,6 +773,17 @@ int virFDStreamOpenPTY(virStreamPtr st,
}
#endif /* !HAVE_CFMAKERAW */
+int virFDStreamOpenBlockDevice(virStreamPtr st,
+ const char *path,
+ unsigned long long offset,
+ unsigned long long length,
+ int oflags)
+{
+ return virFDStreamOpenFileInternal(st, path,
+ offset, length,
+ oflags, 0, true);
+}
+
int virFDStreamSetInternalCloseCb(virStreamPtr st,
virFDStreamInternalCloseCb cb,
void *opaque,
diff --git a/src/fdstream.h b/src/fdstream.h
index 69d8328..2c913ea 100644
--- a/src/fdstream.h
+++ b/src/fdstream.h
@@ -56,6 +56,11 @@ int virFDStreamOpenPTY(virStreamPtr st,
unsigned long long offset,
unsigned long long length,
int oflags);
+int virFDStreamOpenBlockDevice(virStreamPtr st,
+ const char *path,
+ unsigned long long offset,
+ unsigned long long length,
+ int oflags);
int virFDStreamSetInternalCloseCb(virStreamPtr st,
virFDStreamInternalCloseCb cb,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 08111d4..ab7a39e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -823,6 +823,7 @@ virStreamClass;
virFDStreamConnectUNIX;
virFDStreamCreateFile;
virFDStreamOpen;
+virFDStreamOpenBlockDevice;
virFDStreamOpenFile;
virFDStreamOpenPTY;
virFDStreamSetInternalCloseCb;
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index 9c775c9..00cfe74 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -1718,7 +1718,8 @@ virStorageBackendVolUploadLocal(virConnectPtr conn
ATTRIBUTE_UNUSED,
/* Not using O_CREAT because the file is required to already exist at
* this point */
- return virFDStreamOpenFile(stream, vol->target.path, offset, len, O_WRONLY);
+ return virFDStreamOpenBlockDevice(stream, vol->target.path,
+ offset, len, O_WRONLY);
}
int
@@ -1732,7 +1733,8 @@ virStorageBackendVolDownloadLocal(virConnectPtr conn
ATTRIBUTE_UNUSED,
{
virCheckFlags(0, -1);
- return virFDStreamOpenFile(stream, vol->target.path, offset, len, O_RDONLY);
+ return virFDStreamOpenBlockDevice(stream, vol->target.path,
+ offset, len, O_RDONLY);
}
--
1.9.0