Message ID | 87eeh2erm0.fsf@mail.parknet.co.jp (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Fix zero_user_segments() with start > end | expand |
On Sat, Feb 27, 2021 at 01:11:35AM +0900, OGAWA Hirofumi wrote: > zero_user_segments() is used from __block_write_begin_int(), for > example like the following > > zero_user_segments(page, 4096, 1024, 512, 918) > > But new zero_user_segments() implements for HIGMEM + TRANSPARENT_HUGEPAGE > doesn't handle "start > end" case correctly, and hits BUG_ON(). (we > can fix __block_write_begin_int() instead though, it is the old and > multiple usage) Why don't we just take out the BUG_ON instead? The function doesn't actually do the wrong thing. > Also it calls kmap_atomic() unnecessary while start == end == 0. I'm OK with that. It always used to do that. > Cc: <stable@vger.kernel.org> > Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> Fixes: 0060ef3b4e6d ("mm: support THPs in zero_user_segments")
Matthew Wilcox <willy@infradead.org> writes: > On Sat, Feb 27, 2021 at 01:11:35AM +0900, OGAWA Hirofumi wrote: >> zero_user_segments() is used from __block_write_begin_int(), for >> example like the following >> >> zero_user_segments(page, 4096, 1024, 512, 918) >> >> But new zero_user_segments() implements for HIGMEM + TRANSPARENT_HUGEPAGE >> doesn't handle "start > end" case correctly, and hits BUG_ON(). (we >> can fix __block_write_begin_int() instead though, it is the old and >> multiple usage) > > Why don't we just take out the BUG_ON instead? The function doesn't > actually do the wrong thing. end1 is underflow with if (start1 >= PAGE_SIZE) { start1 -= PAGE_SIZE; end1 -= PAGE_SIZE; } >> Also it calls kmap_atomic() unnecessary while start == end == 0. > > I'm OK with that. It always used to do that. Old one is only one page, so it is always necessary if start1/end1 or start2/end2 is valid range. But this one is multiple pages, so there are completely unnecessary pages possibly. >> Cc: <stable@vger.kernel.org> >> Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> > > Fixes: 0060ef3b4e6d ("mm: support THPs in zero_user_segments") OK.
diff --git a/mm/highmem.c b/mm/highmem.c index 874b732..86f2b94 100644 --- a/mm/highmem.c 2021-02-20 12:56:49.037165666 +0900 +++ b/mm/highmem.c 2021-02-20 22:03:08.369361223 +0900 @@ -368,20 +368,24 @@ void zero_user_segments(struct page *pag BUG_ON(end1 > page_size(page) || end2 > page_size(page)); + if (start1 >= end1) + start1 = end1 = 0; + if (start2 >= end2) + start2 = end2 = 0; + for (i = 0; i < compound_nr(page); i++) { void *kaddr = NULL; - if (start1 < PAGE_SIZE || start2 < PAGE_SIZE) - kaddr = kmap_atomic(page + i); - if (start1 >= PAGE_SIZE) { start1 -= PAGE_SIZE; end1 -= PAGE_SIZE; } else { unsigned this_end = min_t(unsigned, end1, PAGE_SIZE); - if (end1 > start1) + if (end1 > start1) { + kaddr = kmap_atomic(page + i); memset(kaddr + start1, 0, this_end - start1); + } end1 -= this_end; start1 = 0; } @@ -392,8 +396,11 @@ void zero_user_segments(struct page *pag } else { unsigned this_end = min_t(unsigned, end2, PAGE_SIZE); - if (end2 > start2) + if (end2 > start2) { + if (!kaddr) + kaddr = kmap_atomic(page + i); memset(kaddr + start2, 0, this_end - start2); + } end2 -= this_end; start2 = 0; }
zero_user_segments() is used from __block_write_begin_int(), for example like the following zero_user_segments(page, 4096, 1024, 512, 918) But new zero_user_segments() implements for HIGMEM + TRANSPARENT_HUGEPAGE doesn't handle "start > end" case correctly, and hits BUG_ON(). (we can fix __block_write_begin_int() instead though, it is the old and multiple usage) Also it calls kmap_atomic() unnecessary while start == end == 0. Cc: <stable@vger.kernel.org> Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> --- mm/highmem.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)