Whamcloud - gitweb
LU-16412 llite: check truncated page in ->readpage() 33/49433/5
authorQian Yingjin <qian@ddn.com>
Mon, 19 Dec 2022 06:57:39 +0000 (01:57 -0500)
committerQian Yingjin <qian@ddn.com>
Tue, 17 Jan 2023 14:06:09 +0000 (09:06 -0500)
commit4d3f6c052d78a771797a37a3d08dc6bbf0b323f1
tree2ccaa8ece3016cbad8fd5681f24da9d686ad1d70
parent601ed56575a304c15ccb6d98a252162e64ef95e9
LU-16412 llite: check truncated page in ->readpage()

The page end offset calculation in filemap_get_read_batch() was
off by one. This bug was introduced in commit v5.11-10234-gcbd59c48ae
("mm/filemap: use head pages in generic_file_buffered_read")

When a read is submitted with end offset 1048575, it calculates
the end page index for read of 256 where it should be 255. This
results in the readpage() call for the page with index 256 is over
stripe boundary and may not be covered by a DLM extent lock.

This happens in a corner race case: filemap_get_read_batch()
batches the page with index 256 for read, but later this page is
removed from page cache due to the lock protected it being revoked,
but has a reference count due to the batch.  This results in this
page in the read path is not covered by any DLM lock.

The solution is simple. We can check whether the page was
truncated and removed from page cache in ->readpage() by the
address_sapce pointer of the page. If it was truncated, return
AOP_TRUNCATED_PAGE to the upper caller.  This will cause the
kernel to retry to batch pages and the truncated page will not
be added as it was already removed from page cache of the file.

Add sanityn/test_95 to verify it.

Test-Parameters: testlist=sanityn env=ONLY=95 clientdistro=ubuntu2204
Signed-off-by: Qian Yingjin <qian@ddn.com>
Change-Id: I192df92b1d1b79057055430cc81cb7cc760cc9ed
lustre/include/obd_support.h
lustre/llite/rw.c
lustre/llite/rw26.c
lustre/tests/sanityn.sh