Commit c1f0b1f5 authored by Adrian Reber's avatar Adrian Reber Committed by Andrei Vagin

page-pipe: correctly split page-pipe-buffers

Combining pre-copy (pre-dump) and post-copy (lazy-pages) mode showed a
problem in the function page_pipe_split_ppb(). The function is used to
split the page-pipe-buffer so that it only contains the IOVs request
from the restore side during lazy restore.

Unfortunately it only splits the leading IOVs out of the
page-pipe-buffer and not the trailing:

Before split for requested address 0x7f27284d1000:

 page-pipe: ppb->iov 0x7f0f74d93040
 page-pipe: 		0x7f27282bb000 1
 page-pipe: 		0x7f27284d1000 1
 page-pipe: 		0x7f27284dd000 2

After split:

 page-pipe: ppb->iov 0x7f0f74d93050
 page-pipe: 		0x7f27284d1000 1
 page-pipe: 		0x7f27284dd000 2

and:

 page-pipe: ppb->iov 0x7f0f74d93040
 page-pipe: 		0x7f27282bb000 1

This patch keeps on splitting the page-pipe-buffer until it contains
only the requested address with the requested length.

After split (still trying to load 0x7f27284d1000):

 page-pipe: ppb->iov 0x7f0f74d93050
 page-pipe: 		0x7f27284d1000 1

and:

 page-pipe: ppb->iov 0x7f0f74d93040
 page-pipe: 		0x7f27282bb000 1

and:

 page-pipe: ppb->iov 0x7f0f74d93060
 page-pipe: 		0x7f27284dd000 2

v2:
 - moved declarations to the declaration block
Signed-off-by: 's avatarAdrian Reber <areber@redhat.com>
Acked-by: 's avatarMike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent 976cb5f8
......@@ -374,6 +374,8 @@ static int page_pipe_split_iov(struct page_pipe *pp, struct page_pipe_buf *ppb,
static int page_pipe_split_ppb(struct page_pipe *pp, struct page_pipe_buf *ppb,
struct iovec *iov, unsigned long len)
{
struct page_pipe_buf *ppb_tmp;
struct iovec *iov_tmp = iov;
struct page_pipe_buf *ppb_new;
int ret;
......@@ -393,6 +395,34 @@ static int page_pipe_split_ppb(struct page_pipe *pp, struct page_pipe_buf *ppb,
list_move(&ppb->l, &pp->bufs);
/*
* Only the leading iov's are split from the page_pipe_buffer.
* The complete page_pipe_buffer at the start of the page_pipe
* list will be deleted and therefore it is necessary to also
* move unrelated iov's to their own page_pipe_buffers.
*/
if (ppb->nr_segs <= len / PAGE_SIZE)
return 0;
/* Move to the iov after the current request */
iov += len / PAGE_SIZE;
ret = page_pipe_split_ppb(pp, ppb, iov, len);
if (ret)
return -1;
/*
* Rotate until correct head pointer. The function transmitting
* the page data expects that the head points to the right
* page_pipe_buffer. The complete first page_pipe_buffer is
* deleted even it contains additional elements.
*/
ppb_tmp = list_first_entry(&pp->bufs, struct page_pipe_buf, l);
while (ppb_tmp->iov != iov_tmp) {
list_rotate_left(&pp->bufs);
ppb_tmp = list_first_entry(&pp->bufs, struct page_pipe_buf, l);
}
return 0;
}
......
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