mirror of https://gitee.com/openkylin/libvirt.git
virfdstream: Allow sparse stream vol-download
When handling sparse stream, a thread is executed. This thread runs a read() or write() loop (depending what API is called; in this case it's virStorageVolDownload() and this the thread run read() loop). The read() is handled in virFDStreamThreadDoRead() which is then data/hole section aware, meaning it uses virFileInData() to detect data and hole sections and sends TYPE_DATA or TYPE_HOLE virStream messages accordingly. However, virFileInData() does not work with block devices. Simply because block devices don't have data and hole sections. What we can do though, is to mimic being always in a DATA section. Partially resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1852528 Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com>
This commit is contained in:
parent
c2e1c414ef
commit
6e0306fa26
|
@ -398,6 +398,7 @@ struct _virFDStreamThreadData {
|
|||
size_t length;
|
||||
bool doRead;
|
||||
bool sparse;
|
||||
bool isBlock;
|
||||
int fdin;
|
||||
char *fdinname;
|
||||
int fdout;
|
||||
|
@ -421,6 +422,7 @@ virFDStreamThreadDataFree(virFDStreamThreadDataPtr data)
|
|||
static ssize_t
|
||||
virFDStreamThreadDoRead(virFDStreamDataPtr fdst,
|
||||
bool sparse,
|
||||
bool isBlock,
|
||||
const int fdin,
|
||||
const int fdout,
|
||||
const char *fdinname,
|
||||
|
@ -437,8 +439,20 @@ virFDStreamThreadDoRead(virFDStreamDataPtr fdst,
|
|||
ssize_t got;
|
||||
|
||||
if (sparse && *dataLen == 0) {
|
||||
if (virFileInData(fdin, &inData, §ionLen) < 0)
|
||||
return -1;
|
||||
if (isBlock) {
|
||||
/* Block devices are always in data section by definition. The
|
||||
* @sectionLen is slightly more tricky. While we could try and get
|
||||
* how much bytes is there left until EOF, we can pretend there is
|
||||
* always X bytes left and let the saferead() below hit EOF (which
|
||||
* is then handled gracefully anyway). Worst case scenario, this
|
||||
* branch is called more than once.
|
||||
* X was chosen to be 1MiB but it has ho special meaning. */
|
||||
inData = 1;
|
||||
sectionLen = 1 * 1024 * 1024;
|
||||
} else {
|
||||
if (virFileInData(fdin, &inData, §ionLen) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (length &&
|
||||
sectionLen > length - total)
|
||||
|
@ -568,6 +582,7 @@ virFDStreamThread(void *opaque)
|
|||
virStreamPtr st = data->st;
|
||||
size_t length = data->length;
|
||||
bool sparse = data->sparse;
|
||||
bool isBlock = data->isBlock;
|
||||
VIR_AUTOCLOSE fdin = data->fdin;
|
||||
char *fdinname = data->fdinname;
|
||||
VIR_AUTOCLOSE fdout = data->fdout;
|
||||
|
@ -604,7 +619,7 @@ virFDStreamThread(void *opaque)
|
|||
}
|
||||
|
||||
if (doRead)
|
||||
got = virFDStreamThreadDoRead(fdst, sparse,
|
||||
got = virFDStreamThreadDoRead(fdst, sparse, isBlock,
|
||||
fdin, fdout,
|
||||
fdinname, fdoutname,
|
||||
length, total,
|
||||
|
@ -1271,6 +1286,7 @@ virFDStreamOpenFileInternal(virStreamPtr st,
|
|||
threadData->st = virObjectRef(st);
|
||||
threadData->length = length;
|
||||
threadData->sparse = sparse;
|
||||
threadData->isBlock = !!S_ISBLK(sb.st_mode);
|
||||
|
||||
if ((oflags & O_ACCMODE) == O_RDONLY) {
|
||||
threadData->fdin = fd;
|
||||
|
|
Loading…
Reference in New Issue