Commit 5d47738a authored by Pavel Emelyanov's avatar Pavel Emelyanov

pagemap: Support async pages reading by chunks (v2)

When we collect all the read_page requests into one big preadv
call, the latter one may not read all the data in one go and
return less bytes read, than requested.

This is valid and already met in a bug :) So advance the iovec
set with the ret value and continue reading.

v2: Compilation fix on arm-s
    A little bit more debugging

https://github.com/xemul/criu/issues/271

travis-ci: success for series starting with [1/2] pagemap: Support async pages reading by chunks (v2)
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent 6267e267
......@@ -397,6 +397,31 @@ static void free_pagemaps(struct page_read *pr)
xfree(pr->pmes);
}
static void advance_piov(struct page_read_iov *piov, ssize_t len)
{
ssize_t olen = len;
int onr = piov->nr;
piov->from += len;
while (len) {
struct iovec *cur = piov->to;
if (cur->iov_len <= len) {
piov->to++;
piov->nr--;
len -= cur->iov_len;
continue;
}
cur->iov_base += len;
cur->iov_len -= len;
break;
}
pr_debug("Advanced iov %zu bytes, %d->%d iovs, %zu tail\n",
olen, onr, piov->nr, len);
}
static int process_async_reads(struct page_read *pr)
{
int fd, ret = 0;
......@@ -404,19 +429,40 @@ static int process_async_reads(struct page_read *pr)
fd = img_raw_fd(pr->pi);
list_for_each_entry_safe(piov, n, &pr->async, l) {
int ret;
ssize_t ret;
off_t start = piov->from;
struct iovec *iovs = piov->to;
pr_debug("Read piov iovs %d, from %ju, len %ju, first %p:%zu\n",
piov->nr, piov->from, piov->end - piov->from,
piov->to->iov_base, piov->to->iov_len);
more:
ret = preadv(fd, piov->to, piov->nr, piov->from);
if (ret != piov->end - piov->from) {
pr_err("Can't read async pr bytes\n");
return -1;
if (ret < 0) {
pr_err("Can't read async pr bytes (%zd / %ju read, %ju off, %d iovs)\n",
ret, piov->end - piov->from, piov->from, piov->nr);
return -1;
}
/*
* The preadv() can return less than requested. It's
* valid and doesn't mean error or EOF. We should advance
* the iovecs and continue
*
* Modify the piov in-place, we're going to drop this one
* anyway.
*/
advance_piov(piov, ret);
goto more;
}
if (opts.auto_dedup && punch_hole(pr, piov->from, ret, false))
if (opts.auto_dedup && punch_hole(pr, start, ret, false))
return -1;
list_del(&piov->l);
xfree(piov->to);
xfree(iovs);
xfree(piov);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment