linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] lib/scatterlist: Fix to calculate the last_pg properly
@ 2023-01-09 14:47 Yishai Hadas
  2023-01-09 18:08 ` Logan Gunthorpe
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Yishai Hadas @ 2023-01-09 14:47 UTC (permalink / raw)
  To: linux-kernel, linux-block, linux-mm, jgg, axboe, logang
  Cc: hch, alex.williamson, yishaih, leonro, maorg

The last_pg is wrong, it is actually the first page of the last
scatterlist element. To get the last page of the last scatterlist
element we have to add prv->length. So it is checking mergability
against the wrong page, Further, a SG element is not guaranteed to end
on a page boundary, so we have to check the sub page location also for
merge eligibility.

Fix the above by checking physical contiguity, compute the actual last
page and then call pages_are_mergable().

Fixes: 1567b49d1a40 ("lib/scatterlist: add check when merging zone device pages")
Reported-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Yishai Hadas <yishaih@nvidia.com>
---
 lib/scatterlist.c | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index f72aa50c6654..2377917893e7 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -470,22 +470,29 @@ int sg_alloc_append_table_from_pages(struct sg_append_table *sgt_append,
 		return -EOPNOTSUPP;
 
 	if (sgt_append->prv) {
+		unsigned long paddr =
+			(page_to_pfn(sg_page(sgt_append->prv)) * PAGE_SIZE +
+			 sgt_append->prv->offset + sgt_append->prv->length) /
+			PAGE_SIZE;
+
 		if (WARN_ON(offset))
 			return -EINVAL;
 
 		/* Merge contiguous pages into the last SG */
 		prv_len = sgt_append->prv->length;
-		last_pg = sg_page(sgt_append->prv);
-		while (n_pages && pages_are_mergeable(pages[0], last_pg)) {
-			if (sgt_append->prv->length + PAGE_SIZE > max_segment)
-				break;
-			sgt_append->prv->length += PAGE_SIZE;
-			last_pg = pages[0];
-			pages++;
-			n_pages--;
+		if (page_to_pfn(pages[0]) == paddr) {
+			last_pg = pfn_to_page(paddr - PAGE_SIZE);
+			while (n_pages && pages_are_mergeable(pages[0], last_pg)) {
+				if (sgt_append->prv->length + PAGE_SIZE > max_segment)
+					break;
+				sgt_append->prv->length += PAGE_SIZE;
+				last_pg = pages[0];
+				pages++;
+				n_pages--;
+			}
+			if (!n_pages)
+				goto out;
 		}
-		if (!n_pages)
-			goto out;
 	}
 
 	/* compute number of contiguous chunks */
-- 
2.18.1



^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2023-01-11 13:28 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-09 14:47 [PATCH] lib/scatterlist: Fix to calculate the last_pg properly Yishai Hadas
2023-01-09 18:08 ` Logan Gunthorpe
2023-01-10  3:18 ` Jens Axboe
2023-01-11  0:03   ` Andrew Morton
2023-01-11 13:28     ` Jason Gunthorpe
2023-01-10  5:08 ` Matthew Wilcox
2023-01-10  8:01   ` Yishai Hadas
2023-01-10 13:53     ` Jason Gunthorpe
2023-01-10 15:05       ` Yishai Hadas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox