Browse Source

[block] Retry any SAN device operation

The SCSI layer currently implements a retry loop in order to retry
commands that fail due to spurious "error" conditions such as "power
on occurred".  Move this retry loop to the generic SAN device layer:
this allow for retries due to other transient error conditions such as
an iSCSI target having dropped the connection due to inactivity.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 7 years ago
parent
commit
d9886f1961
2 changed files with 36 additions and 43 deletions
  1. 35
    19
      src/core/sanboot.c
  2. 1
    24
      src/drivers/block/scsi.c

+ 35
- 19
src/core/sanboot.c View File

64
  */
64
  */
65
 #define SAN_COMMAND_TIMEOUT ( 15 * TICKS_PER_SEC )
65
 #define SAN_COMMAND_TIMEOUT ( 15 * TICKS_PER_SEC )
66
 
66
 
67
+/**
68
+ * Number of times to retry commands
69
+ *
70
+ * We may need to retry commands.  For example, the underlying
71
+ * connection may be closed by the SAN target due to an inactivity
72
+ * timeout, or the SAN target may return pointless "error" messages
73
+ * such as "SCSI power-on occurred".
74
+ */
75
+#define SAN_COMMAND_MAX_RETRIES 10
76
+
67
 /** List of SAN devices */
77
 /** List of SAN devices */
68
 LIST_HEAD ( san_devices );
78
 LIST_HEAD ( san_devices );
69
 
79
 
331
 		 int ( * command ) ( struct san_device *sandev,
341
 		 int ( * command ) ( struct san_device *sandev,
332
 				     const union san_command_params *params ),
342
 				     const union san_command_params *params ),
333
 		 const union san_command_params *params ) {
343
 		 const union san_command_params *params ) {
344
+	unsigned int retries;
334
 	int rc;
345
 	int rc;
335
 
346
 
336
 	/* Sanity check */
347
 	/* Sanity check */
337
 	assert ( ! timer_running ( &sandev->timer ) );
348
 	assert ( ! timer_running ( &sandev->timer ) );
338
 
349
 
339
-	/* Reopen block device if applicable */
340
-	if ( sandev_needs_reopen ( sandev ) &&
341
-	     ( ( rc = sandev_reopen ( sandev ) ) != 0 ) ) {
342
-	     goto err_reopen;
343
-	}
350
+	/* (Re)try command */
351
+	for ( retries = 0 ; retries < SAN_COMMAND_MAX_RETRIES ; retries++ ) {
344
 
352
 
345
-	/* Start expiry timer */
346
-	start_timer_fixed ( &sandev->timer, SAN_COMMAND_TIMEOUT );
353
+		/* Reopen block device if applicable */
354
+		if ( sandev_needs_reopen ( sandev ) &&
355
+		     ( ( rc = sandev_reopen ( sandev ) ) != 0 ) ) {
356
+			continue;
357
+		}
347
 
358
 
348
-	/* Initiate command */
349
-	if ( ( rc = command ( sandev, params ) ) != 0 )
350
-		goto err_op;
359
+		/* Start expiry timer */
360
+		start_timer_fixed ( &sandev->timer, SAN_COMMAND_TIMEOUT );
351
 
361
 
352
-	/* Wait for command to complete */
353
-	while ( timer_running ( &sandev->timer ) )
354
-		step();
362
+		/* Initiate command */
363
+		if ( ( rc = command ( sandev, params ) ) != 0 ) {
364
+			stop_timer ( &sandev->timer );
365
+			continue;
366
+		}
355
 
367
 
356
-	/* Collect return status */
357
-	rc = sandev->command_rc;
368
+		/* Wait for command to complete */
369
+		while ( timer_running ( &sandev->timer ) )
370
+			step();
358
 
371
 
359
-	return rc;
372
+		/* Exit on success */
373
+		if ( ( rc = sandev->command_rc ) == 0 )
374
+			return 0;
375
+	}
376
+
377
+	/* Sanity check */
378
+	assert ( ! timer_running ( &sandev->timer ) );
360
 
379
 
361
- err_op:
362
-	stop_timer ( &sandev->timer );
363
- err_reopen:
364
 	return rc;
380
 	return rc;
365
 }
381
 }
366
 
382
 

+ 1
- 24
src/drivers/block/scsi.c View File

40
  *
40
  *
41
  */
41
  */
42
 
42
 
43
-/** Maximum number of command retries */
44
-#define SCSICMD_MAX_RETRIES 10
45
-
46
 /* Error numbers generated by SCSI sense data */
43
 /* Error numbers generated by SCSI sense data */
47
 #define EIO_NO_SENSE __einfo_error ( EINFO_EIO_NO_SENSE )
44
 #define EIO_NO_SENSE __einfo_error ( EINFO_EIO_NO_SENSE )
48
 #define EINFO_EIO_NO_SENSE \
45
 #define EINFO_EIO_NO_SENSE \
283
 	/** Command tag */
280
 	/** Command tag */
284
 	uint32_t tag;
281
 	uint32_t tag;
285
 
282
 
286
-	/** Retry count */
287
-	unsigned int retries;
288
-
289
 	/** Private data */
283
 	/** Private data */
290
 	uint8_t priv[0];
284
 	uint8_t priv[0];
291
 };
285
 };
449
  * @v rc		Reason for close
443
  * @v rc		Reason for close
450
  */
444
  */
451
 static void scsicmd_done ( struct scsi_command *scsicmd, int rc ) {
445
 static void scsicmd_done ( struct scsi_command *scsicmd, int rc ) {
452
-	struct scsi_device *scsidev = scsicmd->scsidev;
453
 
446
 
454
 	/* Restart SCSI interface */
447
 	/* Restart SCSI interface */
455
 	intf_restart ( &scsicmd->scsi, rc );
448
 	intf_restart ( &scsicmd->scsi, rc );
456
 
449
 
457
-	/* SCSI targets have an annoying habit of returning occasional
458
-	 * pointless "error" messages such as "power-on occurred", so
459
-	 * we have to be prepared to retry commands.
460
-	 */
461
-	if ( ( rc != 0 ) && ( scsicmd->retries++ < SCSICMD_MAX_RETRIES ) ) {
462
-		/* Retry command */
463
-		DBGC ( scsidev, "SCSI %p tag %08x failed: %s\n",
464
-		       scsidev, scsicmd->tag, strerror ( rc ) );
465
-		DBGC ( scsidev, "SCSI %p tag %08x retrying (retry %d)\n",
466
-		       scsidev, scsicmd->tag, scsicmd->retries );
467
-		if ( ( rc = scsicmd_command ( scsicmd ) ) == 0 )
468
-			return;
469
-	}
470
-
471
-	/* If we didn't (successfully) reissue the command, hand over
472
-	 * to the command completion handler.
473
-	 */
450
+	/* Hand over to the command completion handler */
474
 	scsicmd->type->done ( scsicmd, rc );
451
 	scsicmd->type->done ( scsicmd, rc );
475
 }
452
 }
476
 
453
 

Loading…
Cancel
Save