diff mbox

SCSI bug

Message ID 0905D3D6-635F-4E09-BFD0-2EBE5DA0B0CC@bell.net (mailing list archive)
State Not Applicable
Headers show

Commit Message

John David Anglin Feb. 22, 2016, 12:53 a.m. UTC
On 2016-02-21, at 4:17 PM, Helge Deller wrote:

> I enabled CONFIG_DEBUG_SG, which I had enabled the last few times as well, but it now happened
> for the first time:

I also enabled CONFIG_DEBUG_SG.  I added a bunch of printks and eventually narrowed the bug occurance
to __blk_segment_map_sg.  It seems like clearing the termination bit is somewhat dangerous.  I added the
attached check.  With it, I get the following on boot:

scsi target6:0:2: Beginning Domain Validation                                   
 sdb: sdb1 sdb2 sdb3 sdb4                                                       
scsi target6:0:2: Ending Domain Validation                                      
scsi target6:0:2: FAST-160 WIDE SCSI 320.0 MB/s DT IU QAS RTI WRFLOW PCOMP (6.2)
sd 6:0:2:0: [sdc] 143374738 512-byte logical blocks: (73.4 GB/68.3 GiB)         
sd 6:0:0:0: [sdb] Attached SCSI disk                                            
sd 6:0:2:0: [sdc] Write Protect is off                                          
sd 6:0:2:0: [sdc] Write cache: enabled, read cache: enabled, supports DPO and FA
mptbase: ioc1: Initiating bringup                                               
sd 6:0:2:0: [sdc] Attached SCSI disk                                            
ioc1: LSI53C1030 B2: Capabilities={Initiator,Target}                            
scsi host7: ioc1: LSI53C1030 B2, FwRev=01032341h, Ports=1, MaxQ=255, IRQ=68     
__blk_segment_map_sg: clearing termination bit                                  
------------[ cut here ]------------                                            
kernel BUG at include/linux/scatterlist.h:92!                                   
__blk_segment_map_sg: clearing termination bit                                  
------------[ cut here ]------------                                            
kernel BUG at include/linux/scatterlist.h:92!                                   
CPU: 3 PID: 1026 Comm: systemd-udevd Not tainted 4.2.0-rc2+ #16                 
task: 000000007f77d548 ti: 000000007e4f0000 task.ti: 000000007e4f0000           
                                                                                
     YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI                                           
PSW: 00001000000001000011001000001110 Not tainted                               
r00-03  000000ff0804320e 000000007e4f1130 00000000403623e8 000000007e4f1130     
r04-07  000000004074f010 000000000001c000 0000000000001000 00000000000001a0     
r08-11  000000007e7b3040 0000000000000000 0000000000000000 000000007e6990c0     
r12-15  000000000000001a 0000000000000000 000000007c784790 0000000000000006     
r16-19  0000000042d79220 0000000000001000 0000000000000001 0000000000000000     
r20-23  000000000000002e 00000000705f7367 000000000000001f 0000000000000000     
r24-27  ffffffff87654000 000000000800000e 000000007e6990c0 000000004074f010     
r28-31  000000007e7b3a00 000000007e4f1230 000000007e4f1260 0000000087654321     
sr00-03  0000000000016800 0000000000000000 0000000000000000 0000000000016800    
sr04-07  0000000000000000 0000000000000000 0000000000000000 0000000000000000    
                                                                                
IASQ: 0000000000000000 0000000000000000 IAOQ: 0000000040362608 000000004036260c 
 IIR: 03ffe01f    ISR: 0000000010340000  IOR: 000000f93c4f1260                  
 CPU:        3   CR30: 000000007e4f0000 CR31: ffffffffffffffff                  
 ORIG_R28: 000000000000002e                                                     
 IAOQ[0]: blk_rq_map_sg+0x580/0x6a0                                             
 IAOQ[1]: blk_rq_map_sg+0x584/0x6a0                                             
 RP(r2): blk_rq_map_sg+0x360/0x6a0                                              
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...

Dave
--
John David Anglin	dave.anglin@bell.net

Comments

John David Anglin Feb. 22, 2016, 3:24 a.m. UTC | #1
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 mbox

Patch

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;
 }