On 25.08.2022 14:10, Juergen Gross wrote: > On 25.08.22 13:58, Jan Beulich wrote: >> On 25.08.2022 13:40, Juergen Gross wrote: >>> --- a/drivers/xen/privcmd.c >>> +++ b/drivers/xen/privcmd.c >>> @@ -581,7 +581,7 @@ static int lock_pages( >>> struct privcmd_dm_op_buf kbufs[], unsigned int num, >>> struct page *pages[], unsigned int nr_pages, unsigned int *pinned) >>> { >>> - unsigned int i; >>> + unsigned int i, off = 0; >>> >>> for (i = 0; i < num; i++) { >>> unsigned int requested; >>> @@ -589,19 +589,23 @@ static int lock_pages( >>> >>> requested = DIV_ROUND_UP( >>> offset_in_page(kbufs[i].uptr) + kbufs[i].size, >>> - PAGE_SIZE); >>> + PAGE_SIZE) - off; >>> if (requested > nr_pages) >>> return -ENOSPC; >>> >>> page_count = pin_user_pages_fast( >>> - (unsigned long) kbufs[i].uptr, >>> + (unsigned long)kbufs[i].uptr + off * PAGE_SIZE, >>> requested, FOLL_WRITE, pages); >>> - if (page_count < 0) >>> - return page_count; >>> + if (page_count <= 0) >>> + return page_count ? : -EFAULT; >>> >>> *pinned += page_count; >>> nr_pages -= page_count; >>> pages += page_count; >>> + >>> + off = requested - page_count; >>> + if (off) >>> + i--; >>> } >> >> Initially I thought this would go wrong only on the 3rd iteration, but >> meanwhile I think it's wrong already on the 2nd. What I think you need >> is >> >> if (page_count < requested) >> i--; >> off += page_count; >> >> or with the i++ from the loop header absorbed here >> >> if (page_count == requested) >> i++; >> off += page_count; >> >> Plus of course off needs resetting to zero whenever i advances. I.e. >> >> if (page_count == requested) { >> i++; >> off = 0; >> } else { >> off += page_count; >> } > > Yeah, or: > > off = (page_count == requested) ? 0 : off + page_count; > i += !off; I wasn't daring to suggest something like that ;-) Jan