Browse Source

[block] Allow SAN retry count to be reconfigured

Allow the SAN retry count to be configured via the ${san-retry}
setting, defaulting to the current value of 10 retries if not
specified.

Note that setting a retry count of zero is inadvisable, since iSCSI
targets in particular will often report spurious errors such as "power
on occurred" for the first few commands.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 7 years ago
parent
commit
6b385c9da3
3 changed files with 61 additions and 17 deletions
  1. 52
    17
      src/core/sanboot.c
  2. 7
    0
      src/include/ipxe/dhcp.h
  3. 2
    0
      src/include/ipxe/sanboot.h

+ 52
- 17
src/core/sanboot.c View File

@@ -65,18 +65,21 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
65 65
 #define SAN_COMMAND_TIMEOUT ( 15 * TICKS_PER_SEC )
66 66
 
67 67
 /**
68
- * Number of times to retry commands
68
+ * Default number of times to retry commands
69 69
  *
70 70
  * We may need to retry commands.  For example, the underlying
71 71
  * connection may be closed by the SAN target due to an inactivity
72 72
  * timeout, or the SAN target may return pointless "error" messages
73 73
  * such as "SCSI power-on occurred".
74 74
  */
75
-#define SAN_COMMAND_MAX_RETRIES 10
75
+#define SAN_DEFAULT_RETRIES 10
76 76
 
77 77
 /** List of SAN devices */
78 78
 LIST_HEAD ( san_devices );
79 79
 
80
+/** Number of times to retry commands */
81
+static unsigned long san_retries = SAN_DEFAULT_RETRIES;
82
+
80 83
 /**
81 84
  * Find SAN device by drive number
82 85
  *
@@ -101,13 +104,13 @@ struct san_device * sandev_find ( unsigned int drive ) {
101 104
 static void sandev_free ( struct refcnt *refcnt ) {
102 105
 	struct san_device *sandev =
103 106
 		container_of ( refcnt, struct san_device, refcnt );
104
-	struct san_path *sanpath;
107
+	unsigned int i;
105 108
 
106 109
 	assert ( ! timer_running ( &sandev->timer ) );
107 110
 	assert ( ! sandev->active );
108 111
 	assert ( list_empty ( &sandev->opened ) );
109
-	list_for_each_entry ( sanpath, &sandev->closed, list )
110
-		uri_put ( sanpath->uri );
112
+	for ( i = 0 ; i < sandev->paths ; i++ )
113
+		uri_put ( sandev->path[i].uri );
111 114
 	free ( sandev );
112 115
 }
113 116
 
@@ -469,14 +472,14 @@ sandev_command ( struct san_device *sandev,
469 472
 		 int ( * command ) ( struct san_device *sandev,
470 473
 				     const union san_command_params *params ),
471 474
 		 const union san_command_params *params ) {
472
-	unsigned int retries;
475
+	unsigned int retries = 0;
473 476
 	int rc;
474 477
 
475 478
 	/* Sanity check */
476 479
 	assert ( ! timer_running ( &sandev->timer ) );
477 480
 
478 481
 	/* (Re)try command */
479
-	for ( retries = 0 ; retries < SAN_COMMAND_MAX_RETRIES ; retries++ ) {
482
+	do {
480 483
 
481 484
 		/* Reopen block device if applicable */
482 485
 		if ( sandev_needs_reopen ( sandev ) &&
@@ -484,23 +487,24 @@ sandev_command ( struct san_device *sandev,
484 487
 			continue;
485 488
 		}
486 489
 
487
-		/* Start expiry timer */
488
-		start_timer_fixed ( &sandev->timer, SAN_COMMAND_TIMEOUT );
489
-
490 490
 		/* Initiate command */
491
-		if ( ( rc = command ( sandev, params ) ) != 0 ) {
492
-			stop_timer ( &sandev->timer );
491
+		if ( ( rc = command ( sandev, params ) ) != 0 )
493 492
 			continue;
494
-		}
493
+
494
+		/* Start expiry timer */
495
+		start_timer_fixed ( &sandev->timer, SAN_COMMAND_TIMEOUT );
495 496
 
496 497
 		/* Wait for command to complete */
497 498
 		while ( timer_running ( &sandev->timer ) )
498 499
 			step();
499 500
 
500
-		/* Exit on success */
501
-		if ( ( rc = sandev->command_rc ) == 0 )
502
-			return 0;
503
-	}
501
+		/* Check command status */
502
+		if ( ( rc = sandev->command_rc ) != 0 )
503
+			continue;
504
+
505
+		return 0;
506
+
507
+	} while ( ++retries <= san_retries );
504 508
 
505 509
 	/* Sanity check */
506 510
 	assert ( ! timer_running ( &sandev->timer ) );
@@ -676,6 +680,7 @@ struct san_device * alloc_sandev ( struct uri **uris, unsigned int count,
676 680
 	intf_init ( &sandev->command, &sandev_command_desc, &sandev->refcnt );
677 681
 	timer_init ( &sandev->timer, sandev_command_expired, &sandev->refcnt );
678 682
 	sandev->priv = ( ( ( void * ) sandev ) + size );
683
+	sandev->paths = count;
679 684
 	INIT_LIST_HEAD ( &sandev->opened );
680 685
 	INIT_LIST_HEAD ( &sandev->closed );
681 686
 	for ( i = 0 ; i < count ; i++ ) {
@@ -767,3 +772,33 @@ unsigned int san_default_drive ( void ) {
767 772
 	/* Otherwise, default to booting from first hard disk */
768 773
 	return SAN_DEFAULT_DRIVE;
769 774
 }
775
+
776
+/** The "san-retries" setting */
777
+const struct setting san_retries_setting __setting ( SETTING_SANBOOT_EXTRA,
778
+						     san-retries ) = {
779
+	.name = "san-retries",
780
+	.description = "SAN retry count",
781
+	.tag = DHCP_EB_SAN_RETRY,
782
+	.type = &setting_type_int8,
783
+};
784
+
785
+/**
786
+ * Apply SAN boot settings
787
+ *
788
+ * @ret rc		Return status code
789
+ */
790
+static int sandev_apply ( void ) {
791
+
792
+	/* Apply "san-retries" setting */
793
+	if ( fetch_uint_setting ( NULL, &san_retries_setting,
794
+				  &san_retries ) < 0 ) {
795
+		san_retries = SAN_DEFAULT_RETRIES;
796
+	}
797
+
798
+	return 0;
799
+}
800
+
801
+/** Settings applicator */
802
+struct settings_applicator sandev_applicator __settings_applicator = {
803
+	.apply = sandev_apply,
804
+};

+ 7
- 0
src/include/ipxe/dhcp.h View File

@@ -433,6 +433,13 @@ struct dhcp_netdev_desc {
433 433
 /** Use cached network settings (obsolete; do not reuse this value) */
434 434
 #define DHCP_EB_USE_CACHED DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xb2 )
435 435
 
436
+/** SAN retry count
437
+ *
438
+ * This is the maximum number of times that SAN operations will be
439
+ * retried.
440
+ */
441
+#define DHCP_EB_SAN_RETRY DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xbb )
442
+
436 443
 /** SAN drive number
437 444
  *
438 445
  * This is the drive number for a SAN-hooked drive.  For BIOS, 0x80 is

+ 2
- 0
src/include/ipxe/sanboot.h View File

@@ -71,6 +71,8 @@ struct san_device {
71 71
 	/** Driver private data */
72 72
 	void *priv;
73 73
 
74
+	/** Number of paths */
75
+	unsigned int paths;
74 76
 	/** Current active path */
75 77
 	struct san_path *active;
76 78
 	/** List of opened SAN paths */

Loading…
Cancel
Save