]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[block] Allow SAN retry count to be reconfigured
authorMichael Brown <mcb30@ipxe.org>
Mon, 27 Mar 2017 10:06:16 +0000 (13:06 +0300)
committerMichael Brown <mcb30@ipxe.org>
Mon, 27 Mar 2017 12:41:22 +0000 (15:41 +0300)
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>
src/core/sanboot.c
src/include/ipxe/dhcp.h
src/include/ipxe/sanboot.h

index 90bf763bde237b8b2254c44c7bf378047a569e8b..c7279ad363c2f52e426f93ee76c9a254f5a4eb53 100644 (file)
@@ -65,18 +65,21 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #define SAN_COMMAND_TIMEOUT ( 15 * TICKS_PER_SEC )
 
 /**
- * Number of times to retry commands
+ * Default number of times to retry commands
  *
  * We may need to retry commands.  For example, the underlying
  * connection may be closed by the SAN target due to an inactivity
  * timeout, or the SAN target may return pointless "error" messages
  * such as "SCSI power-on occurred".
  */
-#define SAN_COMMAND_MAX_RETRIES 10
+#define SAN_DEFAULT_RETRIES 10
 
 /** List of SAN devices */
 LIST_HEAD ( san_devices );
 
+/** Number of times to retry commands */
+static unsigned long san_retries = SAN_DEFAULT_RETRIES;
+
 /**
  * Find SAN device by drive number
  *
@@ -101,13 +104,13 @@ struct san_device * sandev_find ( unsigned int drive ) {
 static void sandev_free ( struct refcnt *refcnt ) {
        struct san_device *sandev =
                container_of ( refcnt, struct san_device, refcnt );
-       struct san_path *sanpath;
+       unsigned int i;
 
        assert ( ! timer_running ( &sandev->timer ) );
        assert ( ! sandev->active );
        assert ( list_empty ( &sandev->opened ) );
-       list_for_each_entry ( sanpath, &sandev->closed, list )
-               uri_put ( sanpath->uri );
+       for ( i = 0 ; i < sandev->paths ; i++ )
+               uri_put ( sandev->path[i].uri );
        free ( sandev );
 }
 
@@ -469,14 +472,14 @@ sandev_command ( struct san_device *sandev,
                 int ( * command ) ( struct san_device *sandev,
                                     const union san_command_params *params ),
                 const union san_command_params *params ) {
-       unsigned int retries;
+       unsigned int retries = 0;
        int rc;
 
        /* Sanity check */
        assert ( ! timer_running ( &sandev->timer ) );
 
        /* (Re)try command */
-       for ( retries = 0 ; retries < SAN_COMMAND_MAX_RETRIES ; retries++ ) {
+       do {
 
                /* Reopen block device if applicable */
                if ( sandev_needs_reopen ( sandev ) &&
@@ -484,23 +487,24 @@ sandev_command ( struct san_device *sandev,
                        continue;
                }
 
-               /* Start expiry timer */
-               start_timer_fixed ( &sandev->timer, SAN_COMMAND_TIMEOUT );
-
                /* Initiate command */
-               if ( ( rc = command ( sandev, params ) ) != 0 ) {
-                       stop_timer ( &sandev->timer );
+               if ( ( rc = command ( sandev, params ) ) != 0 )
                        continue;
-               }
+
+               /* Start expiry timer */
+               start_timer_fixed ( &sandev->timer, SAN_COMMAND_TIMEOUT );
 
                /* Wait for command to complete */
                while ( timer_running ( &sandev->timer ) )
                        step();
 
-               /* Exit on success */
-               if ( ( rc = sandev->command_rc ) == 0 )
-                       return 0;
-       }
+               /* Check command status */
+               if ( ( rc = sandev->command_rc ) != 0 )
+                       continue;
+
+               return 0;
+
+       } while ( ++retries <= san_retries );
 
        /* Sanity check */
        assert ( ! timer_running ( &sandev->timer ) );
@@ -676,6 +680,7 @@ struct san_device * alloc_sandev ( struct uri **uris, unsigned int count,
        intf_init ( &sandev->command, &sandev_command_desc, &sandev->refcnt );
        timer_init ( &sandev->timer, sandev_command_expired, &sandev->refcnt );
        sandev->priv = ( ( ( void * ) sandev ) + size );
+       sandev->paths = count;
        INIT_LIST_HEAD ( &sandev->opened );
        INIT_LIST_HEAD ( &sandev->closed );
        for ( i = 0 ; i < count ; i++ ) {
@@ -767,3 +772,33 @@ unsigned int san_default_drive ( void ) {
        /* Otherwise, default to booting from first hard disk */
        return SAN_DEFAULT_DRIVE;
 }
+
+/** The "san-retries" setting */
+const struct setting san_retries_setting __setting ( SETTING_SANBOOT_EXTRA,
+                                                    san-retries ) = {
+       .name = "san-retries",
+       .description = "SAN retry count",
+       .tag = DHCP_EB_SAN_RETRY,
+       .type = &setting_type_int8,
+};
+
+/**
+ * Apply SAN boot settings
+ *
+ * @ret rc             Return status code
+ */
+static int sandev_apply ( void ) {
+
+       /* Apply "san-retries" setting */
+       if ( fetch_uint_setting ( NULL, &san_retries_setting,
+                                 &san_retries ) < 0 ) {
+               san_retries = SAN_DEFAULT_RETRIES;
+       }
+
+       return 0;
+}
+
+/** Settings applicator */
+struct settings_applicator sandev_applicator __settings_applicator = {
+       .apply = sandev_apply,
+};
index 23f16aaa74216d2eb33a33543e44e38190aaa6ba..0f662d633a11142a66447906ce3e4e0066a8c604 100644 (file)
@@ -433,6 +433,13 @@ struct dhcp_netdev_desc {
 /** Use cached network settings (obsolete; do not reuse this value) */
 #define DHCP_EB_USE_CACHED DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xb2 )
 
+/** SAN retry count
+ *
+ * This is the maximum number of times that SAN operations will be
+ * retried.
+ */
+#define DHCP_EB_SAN_RETRY DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xbb )
+
 /** SAN drive number
  *
  * This is the drive number for a SAN-hooked drive.  For BIOS, 0x80 is
index a8b0291de9e83e5d304e6573b672e29e98f06bcd..64b665a52a176cf1fa558bf02f7a62a45abc8c41 100644 (file)
@@ -71,6 +71,8 @@ struct san_device {
        /** Driver private data */
        void *priv;
 
+       /** Number of paths */
+       unsigned int paths;
        /** Current active path */
        struct san_path *active;
        /** List of opened SAN paths */