Message ID | 0905D3D6-635F-4E09-BFD0-2EBE5DA0B0CC@bell.net (mailing list archive) |
---|---|
State | Not Applicable |
Headers | show |
On 2016-02-21, at 7:53 PM, John David Anglin wrote: > Backtrace: > [<000000004046f4b0>] scsi_init_sgtable+0x70/0xb8 > [<000000004046f564>] scsi_init_io+0x6c/0x220 > [<000000000811c5c0>] sd_setup_read_write_cmnd+0x58/0x968 [sd_mod] > [<000000000811cf14>] sd_init_command+0x44/0x130 [sd_mod] > [<000000004046f81c>] scsi_setup_cmnd+0x104/0x1b0 > [<000000004046fab8>] scsi_prep_fn+0x100/0x1a0 > [<000000004035b9b0>] blk_peek_request+0x1b8/0x298 > [<0000000040471028>] scsi_request_fn+0xf8/0xa90 > [<0000000040357244>] __blk_run_queue+0x4c/0x70 > [<00000000403802c4>] cfq_insert_request+0x2dc/0x580 > [<0000000040356404>] __elv_add_request+0x1b4/0x300 > > We have in blk-merge.c: > > 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. > */ > if (sg_is_last (*sg)) > printk ("__blk_segment_map_sg: clearing termination bi > t\n"); > sg_unmark_end(*sg); > *sg = sg_next(*sg); > BUG_ON (!*sg); > } > > The comment suggests there must be more entries... I'm thinking with the split the scsi driver needs to provide one or two extra entires in the sg list. Dave -- John David Anglin dave.anglin@bell.net -- To unsubscribe from this list: send the line "unsubscribe linux-parisc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/block/blk-merge.c b/block/blk-merge.c index d9c3a75..f893ecf 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -327,8 +327,11 @@ new_segment: * termination bit to avoid doing a full * sg_init_table() in drivers for each command. */ + if (sg_is_last (*sg)) + printk ("__blk_segment_map_sg: clearing termination bit\n"); sg_unmark_end(*sg); *sg = sg_next(*sg); + BUG_ON (!*sg); } sg_set_page(*sg, bvec->bv_page, nbytes, bvec->bv_offset); @@ -392,6 +395,9 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq, if (rq->bio) nsegs = __blk_bios_map_sg(q, rq->bio, sglist, &sg); + if (!sg) + return nsegs; + if (unlikely(rq->cmd_flags & REQ_COPY_USER) && (blk_rq_bytes(rq) & q->dma_pad_mask)) { unsigned int pad_len = @@ -415,8 +421,7 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq, rq->extra_len += q->dma_drain_size; } - if (sg) - sg_mark_end(sg); + sg_mark_end(sg); return nsegs; } @@ -439,6 +444,14 @@ static inline int ll_new_hw_segment(struct request_queue *q, * counters. */ req->nr_phys_segments += nr_phys_segs; + +#if 0 +if (req->nr_phys_segments != __blk_recalc_rq_segments(req->q, req->bio, false)) + printk("ll_new_hw_segment: MISMATCH IN MERGE: got %d, should get %d\n", + req->nr_phys_segments, + __blk_recalc_rq_segments(req->q, req->bio, false)); +#endif + return 1; no_merge: @@ -545,6 +558,14 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req, /* Merge is OK... */ req->nr_phys_segments = total_phys_segments; + +#if 0 +if (req->nr_phys_segments != __blk_recalc_rq_segments(req->q, req->bio, false)) + printk("MISMATCH IN MERGE: got %d, should get %d\n", + req->nr_phys_segments, + __blk_recalc_rq_segments(req->q, req->bio, false)); +#endif + return 1; }