fdstream: introduce virFDStreamOpenBlockDevice

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 disk devices (including
ZFS volumes) are exposed as character devices, and ZFS volumes do not
support open(2) with O_NONBLOCK.

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.
This commit is contained in:
Roman Bogorodskiy 2014-08-15 12:11:35 +04:00
parent eb626b49fd
commit f5b4c14155
4 changed files with 30 additions and 8 deletions

View File

@ -577,7 +577,8 @@ virFDStreamOpenFileInternal(virStreamPtr st,
unsigned long long offset, unsigned long long offset,
unsigned long long length, unsigned long long length,
int oflags, int oflags,
int mode) int mode,
bool forceIOHelper)
{ {
int fd = -1; int fd = -1;
int childfd = -1; int childfd = -1;
@ -623,8 +624,8 @@ virFDStreamOpenFileInternal(virStreamPtr st,
* the I/O so we just have a fifo. Or use AIO :-( * the I/O so we just have a fifo. Or use AIO :-(
*/ */
if ((st->flags & VIR_STREAM_NONBLOCK) && if ((st->flags & VIR_STREAM_NONBLOCK) &&
(!S_ISCHR(sb.st_mode) && ((!S_ISCHR(sb.st_mode) &&
!S_ISFIFO(sb.st_mode))) { !S_ISFIFO(sb.st_mode)) || forceIOHelper)) {
int fds[2] = { -1, -1 }; int fds[2] = { -1, -1 };
if ((oflags & O_ACCMODE) == O_RDWR) { if ((oflags & O_ACCMODE) == O_RDWR) {
@ -703,7 +704,7 @@ int virFDStreamOpenFile(virStreamPtr st,
} }
return virFDStreamOpenFileInternal(st, path, return virFDStreamOpenFileInternal(st, path,
offset, length, offset, length,
oflags, 0); oflags, 0, false);
} }
int virFDStreamCreateFile(virStreamPtr st, int virFDStreamCreateFile(virStreamPtr st,
@ -715,7 +716,8 @@ int virFDStreamCreateFile(virStreamPtr st,
{ {
return virFDStreamOpenFileInternal(st, path, return virFDStreamOpenFileInternal(st, path,
offset, length, offset, length,
oflags | O_CREAT, mode); oflags | O_CREAT, mode,
false);
} }
#ifdef HAVE_CFMAKERAW #ifdef HAVE_CFMAKERAW
@ -730,7 +732,8 @@ int virFDStreamOpenPTY(virStreamPtr st,
if (virFDStreamOpenFileInternal(st, path, if (virFDStreamOpenFileInternal(st, path,
offset, length, offset, length,
oflags | O_CREAT, 0) < 0) oflags | O_CREAT, 0,
false) < 0)
return -1; return -1;
fdst = st->privateData; fdst = st->privateData;
@ -770,6 +773,17 @@ int virFDStreamOpenPTY(virStreamPtr st,
} }
#endif /* !HAVE_CFMAKERAW */ #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, int virFDStreamSetInternalCloseCb(virStreamPtr st,
virFDStreamInternalCloseCb cb, virFDStreamInternalCloseCb cb,
void *opaque, void *opaque,

View File

@ -56,6 +56,11 @@ int virFDStreamOpenPTY(virStreamPtr st,
unsigned long long offset, unsigned long long offset,
unsigned long long length, unsigned long long length,
int oflags); int oflags);
int virFDStreamOpenBlockDevice(virStreamPtr st,
const char *path,
unsigned long long offset,
unsigned long long length,
int oflags);
int virFDStreamSetInternalCloseCb(virStreamPtr st, int virFDStreamSetInternalCloseCb(virStreamPtr st,
virFDStreamInternalCloseCb cb, virFDStreamInternalCloseCb cb,

View File

@ -823,6 +823,7 @@ virStreamClass;
virFDStreamConnectUNIX; virFDStreamConnectUNIX;
virFDStreamCreateFile; virFDStreamCreateFile;
virFDStreamOpen; virFDStreamOpen;
virFDStreamOpenBlockDevice;
virFDStreamOpenFile; virFDStreamOpenFile;
virFDStreamOpenPTY; virFDStreamOpenPTY;
virFDStreamSetInternalCloseCb; virFDStreamSetInternalCloseCb;

View File

@ -1718,7 +1718,8 @@ virStorageBackendVolUploadLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
/* Not using O_CREAT because the file is required to already exist at /* Not using O_CREAT because the file is required to already exist at
* this point */ * this point */
return virFDStreamOpenFile(stream, vol->target.path, offset, len, O_WRONLY); return virFDStreamOpenBlockDevice(stream, vol->target.path,
offset, len, O_WRONLY);
} }
int int
@ -1732,7 +1733,8 @@ virStorageBackendVolDownloadLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
{ {
virCheckFlags(0, -1); virCheckFlags(0, -1);
return virFDStreamOpenFile(stream, vol->target.path, offset, len, O_RDONLY); return virFDStreamOpenBlockDevice(stream, vol->target.path,
offset, len, O_RDONLY);
} }