|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v5 01/11] memory: batch processing in acquire_resource()
From: Michal Leszczynski <michal.leszczynski@xxxxxxx>
Allow to acquire large resources by allowing acquire_resource()
to process items in batches, using hypercall continuation.
Be aware that this modifies the behavior of acquire_resource
call with frame_list=NULL. While previously it would return
the size of internal array (32), with this patch it returns
the maximal quantity of frames that could be requested at once,
i.e. UINT_MAX >> MEMOP_EXTENT_SHIFT.
Signed-off-by: Michal Leszczynski <michal.leszczynski@xxxxxxx>
---
xen/common/memory.c | 49 ++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 44 insertions(+), 5 deletions(-)
diff --git a/xen/common/memory.c b/xen/common/memory.c
index 714077c1e5..eb42f883df 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -1046,10 +1046,12 @@ static int acquire_grant_table(struct domain *d,
unsigned int id,
}
static int acquire_resource(
- XEN_GUEST_HANDLE_PARAM(xen_mem_acquire_resource_t) arg)
+ XEN_GUEST_HANDLE_PARAM(xen_mem_acquire_resource_t) arg,
+ unsigned long *start_extent)
{
struct domain *d, *currd = current->domain;
xen_mem_acquire_resource_t xmar;
+ uint32_t total_frames;
/*
* The mfn_list and gfn_list (below) arrays are ok on stack for the
* moment since they are small, but if they need to grow in future
@@ -1069,7 +1071,7 @@ static int acquire_resource(
if ( xmar.nr_frames )
return -EINVAL;
- xmar.nr_frames = ARRAY_SIZE(mfn_list);
+ xmar.nr_frames = UINT_MAX >> MEMOP_EXTENT_SHIFT;
if ( __copy_field_to_guest(arg, &xmar, nr_frames) )
return -EFAULT;
@@ -1077,8 +1079,28 @@ static int acquire_resource(
return 0;
}
+ total_frames = xmar.nr_frames;
+
+ /* Is the size too large for us to encode a continuation? */
+ if ( unlikely(xmar.nr_frames > (UINT_MAX >> MEMOP_EXTENT_SHIFT)) )
+ return -EINVAL;
+
+ if ( *start_extent )
+ {
+ /*
+ * Check whether start_extent is in bounds, as this
+ * value if visible to the calling domain.
+ */
+ if ( *start_extent > xmar.nr_frames )
+ return -EINVAL;
+
+ xmar.frame += *start_extent;
+ xmar.nr_frames -= *start_extent;
+ guest_handle_add_offset(xmar.frame_list, *start_extent);
+ }
+
if ( xmar.nr_frames > ARRAY_SIZE(mfn_list) )
- return -E2BIG;
+ xmar.nr_frames = ARRAY_SIZE(mfn_list);
rc = rcu_lock_remote_domain_by_id(xmar.domid, &d);
if ( rc )
@@ -1135,6 +1157,14 @@ static int acquire_resource(
}
}
+ if ( !rc )
+ {
+ *start_extent += xmar.nr_frames;
+
+ if ( *start_extent != total_frames )
+ rc = -ERESTART;
+ }
+
out:
rcu_unlock_domain(d);
@@ -1599,8 +1629,17 @@ long do_memory_op(unsigned long cmd,
XEN_GUEST_HANDLE_PARAM(void) arg)
#endif
case XENMEM_acquire_resource:
- rc = acquire_resource(
- guest_handle_cast(arg, xen_mem_acquire_resource_t));
+ do {
+ rc = acquire_resource(
+ guest_handle_cast(arg, xen_mem_acquire_resource_t),
+ &start_extent);
+
+ if ( hypercall_preempt_check() )
+ return hypercall_create_continuation(
+ __HYPERVISOR_memory_op, "lh",
+ op | (start_extent << MEMOP_EXTENT_SHIFT), arg);
+ } while ( rc == -ERESTART );
+
break;
default:
--
2.17.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |