Re: [PATCH v1 16/36] fs: hugetlbfs: cleanup folio in adjust_range_hwpoison()
David Hildenbrand <[email protected]>
| Newsgroups | com.zx2c4.lists.wireguard,dev.linux.lists.iommu,dev.linux.lists.virtualization,org.freedesktop.lists.dri-devel,org.freedesktop.lists.intel-gfx,org.infradead.lists.linux-arm-kernel,org.infradead.lists.linux-riscv,org.kernel.vger.io-uring,org.kernel.vger.kvm,org.kernel.vger.linux-crypto,org.kernel.vger.linux-ide,org.kernel.vger.linux-kernel,org.kernel.vger.linux-kselftest,org.kernel.vger.linux-mips,org.kernel.vger.linux-mmc,org.kernel.vger.linux-s390,org.kernel.vger.linux-scsi,org.kernel.vger.netdev,org.kvack.linux-mm |
|---|---|
| Message-ID | <[email protected]> |
> > Lord above. > > Also semantics of 'if bytes == 0, then check first page anyway' which you do > capture. Yeah, I think bytes == 0 would not make any sense, though. Staring briefly at the single caller, that seems to be the case (bytes != 0). > > OK think I have convinced myself this is right, so hopefully no deeply subtle > off-by-one issues here :P > > Anyway, LGTM, so: > > Reviewed-by: Lorenzo Stoakes <[email protected]> > >> --- >> fs/hugetlbfs/inode.c | 33 +++++++++++---------------------- >> 1 file changed, 11 insertions(+), 22 deletions(-) >> >> diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c >> index c5a46d10afaa0..6ca1f6b45c1e5 100644 >> --- a/fs/hugetlbfs/inode.c >> +++ b/fs/hugetlbfs/inode.c >> @@ -198,31 +198,20 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, >> static size_t adjust_range_hwpoison(struct folio *folio, size_t offset, >> size_t bytes) >> { >> - struct page *page; >> - size_t n = 0; >> - size_t res = 0; >> - >> - /* First page to start the loop. */ >> - page = folio_page(folio, offset / PAGE_SIZE); >> - offset %= PAGE_SIZE; >> - while (1) { >> - if (is_raw_hwpoison_page_in_hugepage(page)) >> - break; >> + struct page *page = folio_page(folio, offset / PAGE_SIZE); >> + size_t safe_bytes; >> + >> + if (is_raw_hwpoison_page_in_hugepage(page)) >> + return 0; >> + /* Safe to read the remaining bytes in this page. */ >> + safe_bytes = PAGE_SIZE - (offset % PAGE_SIZE); >> + page++; >> >> - /* Safe to read n bytes without touching HWPOISON subpage. */ >> - n = min(bytes, (size_t)PAGE_SIZE - offset); >> - res += n; >> - bytes -= n; >> - if (!bytes || !n) >> + for (; safe_bytes < bytes; safe_bytes += PAGE_SIZE, page++) > > OK this is quite subtle - so if safe_bytes == bytes, this means we've confirmed > that all requested bytes are safe. > > So offset=0, bytes = 4096 would fail this (as safe_bytes == 4096). > > Maybe worth putting something like: > > /* > * Now we check page-by-page in the folio to see if any bytes we don't > * yet know to be safe are contained within posioned pages or not. > */ > > Above the loop. Or something like this. "Check each remaining page as long as we are not done yet." > >> + if (is_raw_hwpoison_page_in_hugepage(page)) >> break; >> - offset += n; >> - if (offset == PAGE_SIZE) { >> - page++; >> - offset = 0; >> - } >> - } >> >> - return res; >> + return min(safe_bytes, bytes); > > Yeah given above analysis this seems correct. > > You must have torn your hair out over this :) I could resist the urge to clean that up, yes. I'll also drop the "The implementation borrows the iteration logic from copy_page_to_iter*." part, because I suspect this comment no longer makes sense. Thanks! -- Cheers David / dhildenb