[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v9 02/11] xen/domain: Add vmtrace_size domain creation parameter
On 03.02.2021 17:04, Andrew Cooper wrote: > On 02/02/2021 09:04, Jan Beulich wrote: >> On 02.02.2021 00:26, Andrew Cooper wrote: >>> --- a/xen/common/domain.c >>> +++ b/xen/common/domain.c >>> @@ -132,6 +132,56 @@ static void vcpu_info_reset(struct vcpu *v) >>> v->vcpu_info_mfn = INVALID_MFN; >>> } >>> >>> +static void vmtrace_free_buffer(struct vcpu *v) >>> +{ >>> + const struct domain *d = v->domain; >>> + struct page_info *pg = v->vmtrace.pg; >>> + unsigned int i; >>> + >>> + if ( !pg ) >>> + return; >>> + >>> + v->vmtrace.pg = NULL; >>> + >>> + for ( i = 0; i < (d->vmtrace_size >> PAGE_SHIFT); i++ ) >>> + { >>> + put_page_alloc_ref(&pg[i]); >>> + put_page_and_type(&pg[i]); >>> + } >>> +} >>> + >>> +static int vmtrace_alloc_buffer(struct vcpu *v) >>> +{ >>> + struct domain *d = v->domain; >>> + struct page_info *pg; >>> + unsigned int i; >>> + >>> + if ( !d->vmtrace_size ) >>> + return 0; >>> + >>> + pg = alloc_domheap_pages(d, get_order_from_bytes(d->vmtrace_size), >>> + MEMF_no_refcount); >>> + if ( !pg ) >>> + return -ENOMEM; >>> + >>> + for ( i = 0; i < (d->vmtrace_size >> PAGE_SHIFT); i++ ) >>> + if ( unlikely(!get_page_and_type(&pg[i], d, PGT_writable_page)) ) >>> + goto refcnt_err; >>> + >>> + /* >>> + * We must only let vmtrace_free_buffer() take any action in the >>> success >>> + * case when we've taken all the refs it intends to drop. >>> + */ >>> + v->vmtrace.pg = pg; >>> + return 0; >>> + >>> + refcnt_err: >>> + while ( i-- ) >>> + put_page_and_type(&pg[i]); >>> + >>> + return -ENODATA; >> Would you mind at least logging how many pages may be leaked >> here? I also don't understand why you don't call >> put_page_alloc_ref() in the loop - that's fine to do prior to >> the put_page_and_type(), and will at least limit the leak. >> The buffer size here typically isn't insignificant, and it >> may be helpful to not unnecessarily defer the freeing to >> relinquish_resources() (assuming we will make that one also >> traverse the list of "extra" pages, but I understand that's >> not going to happen for 4.15 anymore anyway). >> >> Additionally, while I understand you're not in favor of the >> comments we have on all three similar code paths, I think >> replicating their comments here would help easily spotting >> (by grep-ing e.g. for "fishy") all instances that will need >> adjusting once we have figured a better overall solution. > > How is: > > for ( i = 0; i < (d->vmtrace_size >> PAGE_SHIFT); i++ ) > if ( unlikely(!get_page_and_type(&pg[i], d, PGT_writable_page)) ) > /* > * The domain can't possibly know about this page yet, so > failure > * here is a clear indication of something fishy going on. > */ > goto refcnt_err; > > /* > * We must only let vmtrace_free_buffer() take any action in the success > * case when we've taken all the refs it intends to drop. > */ > v->vmtrace.pg = pg; > return 0; > > refcnt_err: > /* > * We can theoretically reach this point if someone has taken 2^43 > refs on > * the frames in the time the above loop takes to execute, or > someone has > * made a blind decrease reservation hypercall and managed to pick the > * right mfn. Free the memory we safely can, and leak the rest. > */ > while ( i-- ) > { > put_page_alloc_ref(&pg[i]); > put_page_and_type(&pg[i]); > } > > return -ENODATA; > > this? Much better, thanks. Remains the question of logging the suspected leak of perhaps many pages. But either way Acked-by: Jan Beulich <jbeulich@xxxxxxxx> Jan
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |