[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2] gnttab: defer allocation of status frame tracking array
On 24.12.2020 10:57, Julien Grall wrote: > Hi Jan, > > On 23/12/2020 15:13, Jan Beulich wrote: >> This array can be large when many grant frames are permitted; avoid >> allocating it when it's not going to be used anyway, by doing this only >> in gnttab_populate_status_frames(). >> >> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> >> --- >> v2: Defer allocation to when a domain actually switches to the v2 grant >> API. >> >> --- a/xen/common/grant_table.c >> +++ b/xen/common/grant_table.c >> @@ -1725,6 +1728,17 @@ gnttab_populate_status_frames(struct dom >> /* Make sure, prior version checks are architectural visible */ >> block_speculation(); >> >> + if ( gt->status == ZERO_BLOCK_PTR ) >> + { >> + gt->status = xzalloc_array(grant_status_t *, >> + >> grant_to_status_frames(gt->max_grant_frames)); >> + if ( !gt->status ) >> + { >> + gt->status = ZERO_BLOCK_PTR; >> + return -ENOMEM; >> + } >> + } >> + >> for ( i = nr_status_frames(gt); i < req_status_frames; i++ ) >> { >> if ( (gt->status[i] = alloc_xenheap_page()) == NULL ) >> @@ -1745,18 +1759,23 @@ status_alloc_failed: >> free_xenheap_page(gt->status[i]); >> gt->status[i] = NULL; >> } >> + if ( !nr_status_frames(gt) ) >> + { >> + xfree(gt->status); >> + gt->status = ZERO_BLOCK_PTR; >> + } >> return -ENOMEM; >> } >> >> static int >> gnttab_unpopulate_status_frames(struct domain *d, struct grant_table *gt) >> { >> - unsigned int i; >> + unsigned int i, n = nr_status_frames(gt); >> >> /* Make sure, prior version checks are architectural visible */ >> block_speculation(); >> >> - for ( i = 0; i < nr_status_frames(gt); i++ ) >> + for ( i = 0; i < n; i++ ) >> { >> struct page_info *pg = virt_to_page(gt->status[i]); >> gfn_t gfn = gnttab_get_frame_gfn(gt, true, i); >> @@ -1811,12 +1830,12 @@ gnttab_unpopulate_status_frames(struct d >> page_set_owner(pg, NULL); >> } >> >> - for ( i = 0; i < nr_status_frames(gt); i++ ) >> - { >> - free_xenheap_page(gt->status[i]); >> - gt->status[i] = NULL; >> - } >> gt->nr_status_frames = 0; >> + smp_wmb(); /* Just in case - all accesses should be under lock. */ > > I think gt->status cannot be accessed locklessly. If a entity read > gt->nr_status_frames != 0, then there is no promise the array will be > accessible when trying to access it as it may have been freed. Yet the common principle of (pointer,count) pairs to describe arrays to be updated / accessed in sequences guaranteeing a non-zero count implies a valid pointer could as well be considered to apply here. I.e. when freeing, at least in principle clearing count first would be a sensible thing to do, wouldn't it? Subsequently allocation and consumers could be updated to follow suit ... > So I would drop the barrier here. I certainly can (unless double checking would tell me otherwise), but I'm not convinced this is a good idea. I'd rather have a barrier too many in the code than one too little, even if the "too little" may only be the result of a future change. And this isn't a path where performance considerations would suggest avoiding barriers when they're not strictly needed. Jan
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |