[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCHv1] grant-table: defer releasing pages acquired in a grant copy
>>> On 13.01.15 at 11:46, <david.vrabel@xxxxxxxxxx> wrote: > --- a/xen/common/grant_table.c > +++ b/xen/common/grant_table.c > @@ -2077,152 +2077,293 @@ __acquire_grant_for_copy( > return rc; > } > > -static void > -__gnttab_copy( > - struct gnttab_copy *op) > +struct gnttab_copy_buf { > + /* guest provided. */ > + domid_t domid; > + bool_t is_ref; > + union { > + grant_ref_t ref; > + xen_pfn_t gfn; > + } u; > + unsigned int offset; So why are the respective parts above not simply an instance of struct gnttab_copy_ptr? > +static int gnttab_copy_lock_domain(struct gnttab_copy *op, > + domid_t domid, unsigned int gref_flag, > + struct gnttab_copy_buf *buf) > { > - struct domain *sd = NULL, *dd = NULL; > - unsigned long s_frame, d_frame; > - struct page_info *s_pg = NULL, *d_pg = NULL; > - char *sp, *dp; > - s16 rc = GNTST_okay; > - int have_d_grant = 0, have_s_grant = 0; > - int src_is_gref, dest_is_gref; > + s16 rc; > > - if ( ((op->source.offset + op->len) > PAGE_SIZE) || > - ((op->dest.offset + op->len) > PAGE_SIZE) ) > - PIN_FAIL(error_out, GNTST_bad_copy_arg, "copy beyond page area.\n"); > + if ( domid != DOMID_SELF && !(op->flags & gref_flag) ) > + PIN_FAIL(out, GNTST_permission_denied, > + "only allow copy-by-mfn for DOMID_SELF.\n"); > > - src_is_gref = op->flags & GNTCOPY_source_gref; > - dest_is_gref = op->flags & GNTCOPY_dest_gref; > + if ( domid == DOMID_SELF ) > + buf->domain = rcu_lock_current_domain(); > + else > + { > + buf->domain = rcu_lock_domain_by_id(domid); > + if ( buf->domain == NULL ) > + PIN_FAIL(out, GNTST_bad_domain, > + "couldn't find %d\n", op->source.domid); > + } > > - if ( (op->source.domid != DOMID_SELF && !src_is_gref ) || > - (op->dest.domid != DOMID_SELF && !dest_is_gref) ) > - PIN_FAIL(error_out, GNTST_permission_denied, > - "only allow copy-by-mfn for DOMID_SELF.\n"); > + buf->domid = domid; > + rc = GNTST_okay; > +out: Labels should be indented by at least one space. > + return rc; > +} > > - if ( op->source.domid == DOMID_SELF ) > - sd = rcu_lock_current_domain(); > - else if ( (sd = rcu_lock_domain_by_id(op->source.domid)) == NULL ) > - PIN_FAIL(error_out, GNTST_bad_domain, > - "couldn't find %d\n", op->source.domid); > +static void gnttab_copy_unlock_domains(struct gnttab_copy_buf *src, > + struct gnttab_copy_buf *dest) > +{ > + if ( src->domain ) > + { > + rcu_unlock_domain(src->domain); > + src->domain = NULL; > + } > + if ( dest->domain ) { Figure brace goes on a separate line. > + rcu_unlock_domain(dest->domain); > + dest->domain = NULL; > + } > +} > > - if ( op->dest.domid == DOMID_SELF ) > - dd = rcu_lock_current_domain(); > - else if ( (dd = rcu_lock_domain_by_id(op->dest.domid)) == NULL ) > - PIN_FAIL(error_out, GNTST_bad_domain, > - "couldn't find %d\n", op->dest.domid); > +static s16 gnttab_copy_lock_domains(struct gnttab_copy *op, > + struct gnttab_copy_buf *src, > + struct gnttab_copy_buf *dest) > +{ > + s16 rc; > > - rc = xsm_grant_copy(XSM_HOOK, sd, dd); > - if ( rc ) > + rc = gnttab_copy_lock_domain(op, op->source.domid, GNTCOPY_source_gref, > src); > + if ( rc < 0 ) > + return rc; > + rc = gnttab_copy_lock_domain(op, op->dest.domid, GNTCOPY_dest_gref, > dest); > + if ( rc < 0 ) > + return rc; > + > + rc = xsm_grant_copy(XSM_HOOK, src->domain, dest->domain); > + if ( rc < 0 ) > { > - rc = GNTST_permission_denied; > - goto error_out; > + gnttab_copy_unlock_domains(src, dest); > + return GNTST_permission_denied; > } > > - if ( src_is_gref ) > + return 0; > +} Wouldn't most of the changes up to here make a nice preparatory cleanup patch, easing review? > +static s16 gnttab_copy_claim_buf( > + struct gnttab_copy *op, > + struct gnttab_copy_ptr *ptr, > + struct gnttab_copy_buf *buf, > + bool_t read_only) > +{ > + unsigned int is_gref; > + s16 rc; > > - if ( dest_is_gref ) > + is_gref = op->flags & (read_only ? GNTCOPY_source_gref : > GNTCOPY_dest_gref); Elsewhere you have this mask passed as gref_flag - perhaps for consistency this should be done here too replacing the read_only parameter)? > +static bool_t gnttab_copy_buf_valid(struct gnttab_copy *op, > + struct gnttab_copy_ptr *p, > + struct gnttab_copy_buf *b, Constify as much of these as possible? > + unsigned int gref_flag) > +{ > + if ( !b->virt ) > + return 0; > + if ( op->flags & gref_flag ) If this is not an "else if" ... > + return b->have_grant && p->u.ref == b->u.ref; > + else ... it's inconsistent to use "else" here. > +static int gnttab_copy_buf(struct gnttab_copy *op, > + struct gnttab_copy_buf *dest, > + struct gnttab_copy_buf *src) > +{ > + s16 rc; > > - put_page_type(d_pg); > - error_out: > - if ( d_pg ) > - put_page(d_pg); > - if ( s_pg ) > - put_page(s_pg); > - if ( have_s_grant ) > - __release_grant_for_copy(sd, op->source.u.ref, 1); > - if ( have_d_grant ) > - __release_grant_for_copy(dd, op->dest.u.ref, 0); > - if ( sd ) > - rcu_unlock_domain(sd); > - if ( dd ) > - rcu_unlock_domain(dd); > - op->status = rc; > + if ( ((op->source.offset + op->len) > PAGE_SIZE) || > + ((op->dest.offset + op->len) > PAGE_SIZE) ) > + PIN_FAIL(out, GNTST_bad_copy_arg, "copy beyond page area.\n"); > + > + if ( op->source.offset < src->offset || > + op->source.offset + op->len > src->offset + src->len ) > + PIN_FAIL(out, GNTST_general_error, > + "copy source out of bounds: %d < %d || %d > %d\n", > + op->source.offset, src->offset, > + op->len, src->len); > + > + if ( op->dest.offset < dest->offset || > + op->dest.offset + op->len > dest->offset + dest->len ) > + PIN_FAIL(out, GNTST_general_error, > + "copy dest out of bounds: %d < %d || %d > %d\n", > + op->dest.offset, dest->offset, > + op->len, dest->len); Indentation appears screwed up here. > +static s16 gnttab_copy_one(struct gnttab_copy *op, > + struct gnttab_copy_buf *dest, > + struct gnttab_copy_buf *src) > +{ > + s16 rc; > + > + if ( !src->domain || op->source.domid != src->domid > + || !dest->domain || op->dest.domid != dest->domid ) While personally I prefer it this way, consistency calls for the || to be at the end of the first line rather than at the beginning of the second one. > + { > + gnttab_copy_release_buf(src, 1); > + gnttab_copy_release_buf(dest, 0); > + gnttab_copy_unlock_domains(src, dest); > + > + rc = gnttab_copy_lock_domains(op, src, dest); > + if ( rc < 0 ) > + goto out; > + } > + > + /* Different source? */ > + if ( !gnttab_copy_buf_valid(op, &op->source, src, GNTCOPY_source_gref) ) > + { > + gnttab_copy_release_buf(src, 1); > + rc = gnttab_copy_claim_buf(op, &op->source, src, 1); > + if ( rc < 0 ) > + goto out; > + } > + > + /* Different dest? */ > + if ( !gnttab_copy_buf_valid(op, &op->dest, dest, GNTCOPY_dest_gref) ) > + { > + gnttab_copy_release_buf(dest, 0); > + rc = gnttab_copy_claim_buf(op, &op->dest, dest, 0); > + if ( rc < 0 ) > + goto out; > + } Aren't these latter two if()-s effectively needed in the else case of the first if()? > +static long gnttab_copy( > XEN_GUEST_HANDLE_PARAM(gnttab_copy_t) uop, unsigned int count) > { > - int i; > + unsigned int i; > struct gnttab_copy op; > + struct gnttab_copy_buf src = { 0, }; > + struct gnttab_copy_buf dest = { 0, }; Just {} will do. Leaving aside those mostly mechanical comments, content wise the patch looks good to me, but I'd hope for at least one other review. Jan _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |