[BLOCK] blk_rq_map_sg: force clear termination bit
authorJens Axboe <jens.axboe@oracle.com>
Tue, 23 Oct 2007 07:49:25 +0000 (09:49 +0200)
committerJens Axboe <jens.axboe@oracle.com>
Tue, 23 Oct 2007 07:49:25 +0000 (09:49 +0200)
Since blk_rq_map_sg() sets the termination bit at the end of the sg
table, we could see it prematurely on the next mapping unless we
force drivers to do a full sg_init_table() prior to each mapping. So
force clear the termination bit to avoid having to put that clear in
the driver for every mapping.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
block/ll_rw_blk.c

index fb8fb8852c3b478a80741ee2a7d95343332e43a8..de5ba479c2245b9e747558757fb6444eebc6745e 100644 (file)
@@ -1351,8 +1351,20 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
 new_segment:
                        if (!sg)
                                sg = sglist;
-                       else
+                       else {
+                               /*
+                                * If the driver previously mapped a shorter
+                                * list, we could see a termination bit
+                                * prematurely unless it fully inits the sg
+                                * table on each mapping. We KNOW that there
+                                * must be more entries here or the driver
+                                * would be buggy, so force clear the
+                                * termination bit to avoid doing a full
+                                * sg_init_table() in drivers for each command.
+                                */
+                               sg->page_link &= ~0x02;
                                sg = sg_next(sg);
+                       }
 
                        sg_set_page(sg, bvec->bv_page);
                        sg->length = nbytes;