libs/guest: Drop guest_data in write_batch() and fill iov directly

There is no need to store the page pointers simply to transcribe the same
information into iov later.  Drop the guest_data intermediate array.

These days, linux has a maximum limit of 1024 iovs.  Libc under the hood will
subdivide the submission if necessary, which is why our general case of 1026
submissions works.

xenforeignmemory_map() maps the requested guest memory contiguously, and
except for PV pagetable frames, we submit contiguously into the stream.  When
safe to do, merge adjacent vectors by extending iov_len, reducing the
likelihood that libc needs to subdivide the submission.

Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
This commit is contained in:
Frediano Ziglio authored and Andrew Cooper committed 2026-07-10 19:35:49 +01:00
1 parent 85bdb67eaa
commit fdeba9d55f
1 file changed
+11 -22
+11 -22
View File
@@ -88,7 +88,6 @@ static int write_batch(struct xc_sr_context *ctx)
xc_interface *xch = ctx->xch;
xen_pfn_t *mfns = NULL, *types = NULL;
void *guest_mapping = NULL;
void **guest_data = NULL;
void **local_pages = NULL;
int *errors = NULL, rc = -1;
unsigned int i, p, nr_pages = 0, nr_pages_mapped = 0;
@@ -118,8 +117,6 @@ static int write_batch(struct xc_sr_context *ctx)
types = malloc(nr_pfns * sizeof(*types));
/* Errors from attempting to map the gfns. */
errors = malloc(nr_pfns * sizeof(*errors));
/* Pointers to page data to send. Mapped gfns or local allocations. */
guest_data = calloc(nr_pfns, sizeof(*guest_data));
/* Pointers to locally allocated pages. Need freeing. */
local_pages = calloc(nr_pfns, sizeof(*local_pages));
/* iovec[] for writev(). */
@@ -127,7 +124,7 @@ static int write_batch(struct xc_sr_context *ctx)
/* page_data record PFNs list */
rec_pfns = malloc(nr_pfns * sizeof(*rec_pfns));
if ( !mfns || !types || !errors || !guest_data || !local_pages || !iov || !rec_pfns )
if ( !mfns || !types || !errors || !local_pages || !iov || !rec_pfns )
{
ERROR("Unable to allocate arrays for a batch of %u pages",
nr_pfns);
@@ -218,8 +215,17 @@ static int write_batch(struct xc_sr_context *ctx)
else
goto err;
}
else if ( iov[iovcnt - 1].iov_base + iov[iovcnt - 1].iov_len !=
page )
{
iov[iovcnt].iov_base = page;
iov[iovcnt].iov_len = PAGE_SIZE;
iovcnt++;
}
else
guest_data[i] = page;
{
iov[iovcnt - 1].iov_len += PAGE_SIZE;
}
rc = -1;
++p;
@@ -231,28 +237,12 @@ static int write_batch(struct xc_sr_context *ctx)
for ( i = 0; i < nr_pfns; ++i )
rec_pfns[i] = ((uint64_t)(types[i]) << 32) | ctx->save.batch_pfns[i];
if ( nr_pages )
{
for ( i = 0; i < nr_pfns; ++i )
{
if ( guest_data[i] )
{
iov[iovcnt].iov_base = guest_data[i];
iov[iovcnt].iov_len = PAGE_SIZE;
iovcnt++;
--nr_pages;
}
}
}
if ( writev_exact(ctx->fd, iov, iovcnt) )
{
PERROR("Failed to write page data to stream");
goto err;
}
/* Sanity check we have sent all the pages we expected to. */
assert(nr_pages == 0);
rc = ctx->save.nr_batch_pfns = 0;
err:
@@ -263,7 +253,6 @@ static int write_batch(struct xc_sr_context *ctx)
free(rec_pfns);
free(iov);
free(local_pages);
free(guest_data);
free(errors);
free(types);
free(mfns);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.