File 19931-gnttblop-preempt.patch of Package xen
# HG changeset patch
# User Keir Fraser <keir.fraser@citrix.com>
# Date 1247483884 -3600
# Node ID 09dbdf12c33decf5a3ae7cf6f5fa7babc34683e9
# Parent 0d4406bc5cb7b0369dacfa5607550758fac672de
Eliminate grant_table_op restriction
Eliminate the hard-coded, arbitrarily chosen limit of 512 grant table
ops a domain may submit at a time, and instead check for necessary
preemption after each individual element got processed, invoking the
hypercall continuation logic when necessary.
Signed-off-by: Jan Beulich <jbeulich@novell.com>
--- a/xen/common/compat/grant_table.c
+++ b/xen/common/compat/grant_table.c
@@ -35,7 +35,9 @@ int compat_grant_table_op(unsigned int c
{
int rc = 0;
unsigned int i;
+ XEN_GUEST_HANDLE(void) cnt_uop;
+ set_xen_guest_handle(cnt_uop, NULL);
switch ( cmd )
{
#define CASE(name) \
@@ -79,7 +81,7 @@ int compat_grant_table_op(unsigned int c
return do_grant_table_op(cmd, cmp_uop, count);
}
- if ( count > 512 )
+ if ( (int)count < 0 )
rc = -EINVAL;
for ( i = 0; i < count && rc == 0; )
@@ -128,6 +130,7 @@ int compat_grant_table_op(unsigned int c
rc = gnttab_setup_table(guest_handle_cast(nat.uop, gnttab_setup_table_t), 1);
}
}
+ ASSERT(rc <= 0);
if ( rc == 0 )
{
#define XLAT_gnttab_setup_table_HNDL_frame_list(_d_, _s_) \
@@ -163,12 +166,19 @@ int compat_grant_table_op(unsigned int c
}
if ( rc == 0 )
rc = gnttab_transfer(guest_handle_cast(nat.uop, gnttab_transfer_t), n);
- if ( rc == 0 )
+ if ( rc > 0 )
+ {
+ ASSERT(rc < n);
+ i -= n - rc;
+ n = rc;
+ }
+ if ( rc >= 0 )
{
XEN_GUEST_HANDLE(gnttab_transfer_compat_t) xfer;
xfer = guest_handle_cast(cmp_uop, gnttab_transfer_compat_t);
guest_handle_add_offset(xfer, i);
+ cnt_uop = guest_handle_cast(xfer, void);
while ( n-- )
{
guest_handle_add_offset(xfer, -1);
@@ -201,12 +211,19 @@ int compat_grant_table_op(unsigned int c
}
if ( rc == 0 )
rc = gnttab_copy(guest_handle_cast(nat.uop, gnttab_copy_t), n);
- if ( rc == 0 )
+ if ( rc > 0 )
+ {
+ ASSERT(rc < n);
+ i -= n - rc;
+ n = rc;
+ }
+ if ( rc >= 0 )
{
XEN_GUEST_HANDLE(gnttab_copy_compat_t) copy;
copy = guest_handle_cast(cmp_uop, gnttab_copy_compat_t);
guest_handle_add_offset(copy, i);
+ cnt_uop = guest_handle_cast(copy, void);
while ( n-- )
{
guest_handle_add_offset(copy, -1);
@@ -222,6 +239,14 @@ int compat_grant_table_op(unsigned int c
}
}
+ if ( rc > 0 )
+ {
+ ASSERT(i < count);
+ ASSERT(!guest_handle_is_null(cnt_uop));
+ rc = hypercall_create_continuation(__HYPERVISOR_grant_table_op,
+ "ihi", cmd, cnt_uop, count - i);
+ }
+
return rc;
}
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -29,6 +29,7 @@
#include <xen/lib.h>
#include <xen/sched.h>
#include <xen/mm.h>
+#include <xen/event.h>
#include <xen/trace.h>
#include <xen/guest_access.h>
#include <xen/domain_page.h>
@@ -464,6 +465,8 @@ gnttab_map_grant_ref(
for ( i = 0; i < count; i++ )
{
+ if (i && hypercall_preempt_check())
+ return i;
if ( unlikely(__copy_from_guest_offset(&op, uop, i, 1)) )
return -EFAULT;
__gnttab_map_grant_ref(&op);
@@ -721,6 +724,9 @@ gnttab_unmap_grant_ref(
count -= c;
done += c;
+
+ if (count && hypercall_preempt_check())
+ return done;
}
return 0;
@@ -780,6 +786,9 @@ gnttab_unmap_and_replace(
count -= c;
done += c;
+
+ if (count && hypercall_preempt_check())
+ return done;
}
return 0;
@@ -1085,6 +1094,9 @@ gnttab_transfer(
for ( i = 0; i < count; i++ )
{
+ if (i && hypercall_preempt_check())
+ return i;
+
/* Read from caller address space. */
if ( unlikely(__copy_from_guest_offset(&gop, uop, i, 1)) )
{
@@ -1476,6 +1488,8 @@ gnttab_copy(
for ( i = 0; i < count; i++ )
{
+ if (i && hypercall_preempt_check())
+ return i;
if ( unlikely(__copy_from_guest_offset(&op, uop, i, 1)) )
return -EFAULT;
__gnttab_copy(&op);
@@ -1492,7 +1506,7 @@ do_grant_table_op(
long rc;
struct domain *d = current->domain;
- if ( count > 512 )
+ if ( (int)count < 0 )
return -EINVAL;
domain_lock(d);
@@ -1507,6 +1521,11 @@ do_grant_table_op(
if ( unlikely(!guest_handle_okay(map, count)) )
goto out;
rc = gnttab_map_grant_ref(map, count);
+ if ( rc > 0 )
+ {
+ guest_handle_add_offset(map, rc);
+ uop = guest_handle_cast(map, void);
+ }
break;
}
case GNTTABOP_unmap_grant_ref:
@@ -1516,6 +1535,11 @@ do_grant_table_op(
if ( unlikely(!guest_handle_okay(unmap, count)) )
goto out;
rc = gnttab_unmap_grant_ref(unmap, count);
+ if ( rc > 0 )
+ {
+ guest_handle_add_offset(unmap, rc);
+ uop = guest_handle_cast(unmap, void);
+ }
break;
}
case GNTTABOP_unmap_and_replace:
@@ -1528,12 +1552,18 @@ do_grant_table_op(
if ( unlikely(!replace_grant_supported()) )
goto out;
rc = gnttab_unmap_and_replace(unmap, count);
+ if ( rc > 0 )
+ {
+ guest_handle_add_offset(unmap, rc);
+ uop = guest_handle_cast(unmap, void);
+ }
break;
}
case GNTTABOP_setup_table:
{
rc = gnttab_setup_table(
guest_handle_cast(uop, gnttab_setup_table_t), count);
+ ASSERT(rc <= 0);
break;
}
case GNTTABOP_transfer:
@@ -1543,6 +1573,11 @@ do_grant_table_op(
if ( unlikely(!guest_handle_okay(transfer, count)) )
goto out;
rc = gnttab_transfer(transfer, count);
+ if ( rc > 0 )
+ {
+ guest_handle_add_offset(transfer, rc);
+ uop = guest_handle_cast(transfer, void);
+ }
break;
}
case GNTTABOP_copy:
@@ -1552,12 +1587,18 @@ do_grant_table_op(
if ( unlikely(!guest_handle_okay(copy, count)) )
goto out;
rc = gnttab_copy(copy, count);
+ if ( rc > 0 )
+ {
+ guest_handle_add_offset(copy, rc);
+ uop = guest_handle_cast(copy, void);
+ }
break;
}
case GNTTABOP_query_size:
{
rc = gnttab_query_size(
guest_handle_cast(uop, gnttab_query_size_t), count);
+ ASSERT(rc <= 0);
break;
}
default:
@@ -1567,6 +1608,13 @@ do_grant_table_op(
out:
domain_unlock(d);
+
+ if ( rc > 0 )
+ {
+ ASSERT(rc < count);
+ rc = hypercall_create_continuation(__HYPERVISOR_grant_table_op,
+ "ihi", cmd, uop, count - rc);
+ }
return rc;
}