block: blk-merge: don't merge the pages with non-contiguous descriptors

blk_rq_map_sg() function merges the physically contiguous pages to use same
scatter-gather node without checking if their page descriptors are
contiguous or not.

Now when dma_map_sg() is called on the scatter gather list, it would
take the base page pointer from each node (one by one) and iterates
through all of the pages in same sg node by keep incrementing the base
page pointer with the assumption that physically contiguous pages will
have their page descriptor address contiguous which may not be true
if SPARSEMEM config is enabled. So here we may end referring to invalid
page descriptor.

Following table shows the example of physically contiguous pages but
their page descriptor addresses non-contiguous.
-------------------------------------------
| Page Descriptor    |   Physical Address |
------------------------------------------
| 0xc1e43fdc         |   0xdffff000       |
| 0xc2052000         |   0xe0000000       |
-------------------------------------------

With this patch, relevant blk-merge functions will also check if the
physically contiguous pages are having page descriptors address contiguous
or not? If not then, these pages are separated to be in different
scatter-gather nodes.

CRs-Fixed: 392141
Change-Id: I3601565e5569a69f06fb3af99061c4d4c23af241
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
This commit is contained in:
Subhash Jadavani
2013-01-10 17:49:09 +05:30
parent aa12e9cfd6
commit 6e25ce37a4
+6
View File
@@ -42,6 +42,9 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
goto new_segment;
if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv))
goto new_segment;
if ((bvprv->bv_page != bv->bv_page) &&
(bvprv->bv_page + 1) != bv->bv_page)
goto new_segment;
seg_size += bv->bv_len;
bvprv = bv;
@@ -141,6 +144,9 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
goto new_segment;
if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bvec))
goto new_segment;
if ((bvprv->bv_page != bvec->bv_page) &&
((bvprv->bv_page + 1) != bvec->bv_page))
goto new_segment;
sg->length += nbytes;
} else {