On Fri, Oct 9, 2015 at 1:51 AM, Jan Beulich <jbeul...@suse.com> wrote:
> >>> On 08.10.15 at 22:57, <ta...@tklengyel.com> wrote: > > --- a/xen/arch/x86/mm/mem_sharing.c > > +++ b/xen/arch/x86/mm/mem_sharing.c > > @@ -1293,6 +1293,37 @@ int relinquish_shared_pages(struct domain *d) > > return rc; > > } > > > > +static int bulk_share(struct domain *d, struct domain *cd, unsigned > long max, > > + struct mem_sharing_op_bulk_share *bulk) > > +{ > > + int rc = 0; > > + shr_handle_t sh, ch; > > + > > + while( bulk->start <= max ) > > + { > > + if ( mem_sharing_nominate_page(d, bulk->start, 0, &sh) != 0 ) > > + goto next; > > + > > + if ( mem_sharing_nominate_page(cd, bulk->start, 0, &ch) != 0 ) > > + goto next; > > + > > + if ( !mem_sharing_share_pages(d, bulk->start, sh, cd, > bulk->start, ch) ) > > + ++(bulk->shared); > > Pointless parentheses. > > Pointless but harmless and I like this style better. > > +next: > > Labels indented by at least one space please. > Ack. > > > + ++(bulk->start); > > + > > + /* Check for continuation if it's not the last iteration. */ > > + if ( bulk->start < max && hypercall_preempt_check() ) > > + { > > + rc = 1; > > + break; > > This could simple be a return statement, avoiding the need for a > local variable (the type of which would need to be changed, see > below). > It's reused in the caller to indicate where the mso copyback happens and rc is of type int in the caller. > > > + } > > + } > > + > > + return rc; > > +} > > So effectively the function right now returns a boolean. If that's > intended, its return type should reflect that (but I then wonder > whether the sense of the values shouldn't be inverted, to have > "true" mean "done"). > It does but it's return is assigned to rc which is used to decide where copyback happens. > > > @@ -1467,6 +1498,59 @@ int > mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg) > > } > > break; > > > > + case XENMEM_sharing_op_bulk_share: > > + { > > + unsigned long max_sgfn, max_cgfn; > > + struct domain *cd; > > + > > + rc = -EINVAL; > > + if ( !mem_sharing_enabled(d) ) > > + goto out; > > + > > + rc = > rcu_lock_live_remote_domain_by_id(mso.u.bulk.client_domain, > > + &cd); > > + if ( rc ) > > + goto out; > > + > > + rc = xsm_mem_sharing_op(XSM_DM_PRIV, d, cd, mso.op); > > + if ( rc ) > > + { > > + rcu_unlock_domain(cd); > > + goto out; > > + } > > + > > + if ( !mem_sharing_enabled(cd) ) > > + { > > + rcu_unlock_domain(cd); > > + rc = -EINVAL; > > + goto out; > > + } > > + > > + max_sgfn = domain_get_maximum_gpfn(d); > > + max_cgfn = domain_get_maximum_gpfn(cd); > > + > > + if ( max_sgfn != max_cgfn || max_sgfn < mso.u.bulk.start ) > > Are both domains required to be paused for this operation? If so, > shouldn't you enforce this? If not, by the time you reach the if() > the values are stale. > It's expected that the user has exclusive tool-side lock on the domains before issuing this hypercall and that the domains are paused already. > > > + { > > + rcu_unlock_domain(cd); > > + rc = -EINVAL; > > + goto out; > > + } > > + > > + rc = bulk_share(d, cd, max_sgfn, &mso.u.bulk); > > + if ( rc ) > > With the boolean nature the use of "rc" here is rather confusing; > I'd suggest avoiding the use of in intermediate variable in this case. > I don't see where the confusion is - rc indicates there is work left to do and hypercall continuation needs to be setup. I could move this block into bulk_share itself. > > > + { > > + if ( __copy_to_guest(arg, &mso, 1) ) > > + rc = -EFAULT; > > + else > > + rc = > hypercall_create_continuation(__HYPERVISOR_memory_op, > > + "lh", > XENMEM_sharing_op, > > + arg); > > + } > > + > > + rcu_unlock_domain(cd); > > + } > > + break; > > + > > case XENMEM_sharing_op_debug_gfn: > > { > > unsigned long gfn = mso.u.debug.u.gfn; > > diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h > > index 320de91..0299746 100644 > > --- a/xen/include/public/memory.h > > +++ b/xen/include/public/memory.h > > @@ -447,6 +447,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_mem_access_op_t); > > #define XENMEM_sharing_op_debug_gref 5 > > #define XENMEM_sharing_op_add_physmap 6 > > #define XENMEM_sharing_op_audit 7 > > +#define XENMEM_sharing_op_bulk_share 8 > > > > #define XENMEM_SHARING_OP_S_HANDLE_INVALID (-10) > > #define XENMEM_SHARING_OP_C_HANDLE_INVALID (-9) > > @@ -482,7 +483,13 @@ struct xen_mem_sharing_op { > > uint64_aligned_t client_gfn; /* IN: the client gfn */ > > uint64_aligned_t client_handle; /* IN: handle to the client > page */ > > domid_t client_domain; /* IN: the client domain id */ > > - } share; > > + } share; > > + struct mem_sharing_op_bulk_share { /* OP_BULK_SHARE */ > > Is the _share suffix really useful here? Even more, if you dropped > it and renamed "shared" below to "done", the same structure could > be used for a hypothetical bulk-unshare operation. > I don't really have a use-case for that at the moment and having it simply as "bulk" is not specific enough IMHO. > > > + domid_t client_domain; /* IN: the client domain > id */ > > + uint64_aligned_t start; /* IN: start gfn (normally > 0) */ > > Marking this as just IN implies that the value doesn't change across > the operation. > In my book IN means it's used strictly only to pass input and it's value may or may not be the same afterwards. > > > + uint64_aligned_t shared; /* OUT: the number of > > + successfully shared > pages */ > > For this to be correct, the value is required to be zero initialized by > the caller at present. Either this needs to be documented, or you > should zero the field on any non-continuation invocation. > Sure, I'll add a comment for that effect - the toolstack already memsets the mso struct to zero but I agree it's better to explicitly state that. Tamas
_______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel