diff options
author | Michael Brown | 2017-03-07 17:11:22 +0100 |
---|---|---|
committer | Michael Brown | 2017-03-07 17:11:22 +0100 |
commit | d9886f1961f9970b4354442e84b98727b69cd73a (patch) | |
tree | f3327344ff70be0e1dde0b079cd2d7b455389546 /src/core | |
parent | [efi] Refactor to use centralised SAN device abstraction (diff) | |
download | ipxe-d9886f1961f9970b4354442e84b98727b69cd73a.tar.gz ipxe-d9886f1961f9970b4354442e84b98727b69cd73a.tar.xz ipxe-d9886f1961f9970b4354442e84b98727b69cd73a.zip |
[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>
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/sanboot.c | 54 |
1 files changed, 35 insertions, 19 deletions
diff --git a/src/core/sanboot.c b/src/core/sanboot.c index 42a30839..85d0bc7f 100644 --- a/src/core/sanboot.c +++ b/src/core/sanboot.c @@ -64,6 +64,16 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); */ #define SAN_COMMAND_TIMEOUT ( 15 * TICKS_PER_SEC ) +/** + * 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 + /** List of SAN devices */ LIST_HEAD ( san_devices ); @@ -331,36 +341,42 @@ 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; int rc; /* Sanity check */ assert ( ! timer_running ( &sandev->timer ) ); - /* Reopen block device if applicable */ - if ( sandev_needs_reopen ( sandev ) && - ( ( rc = sandev_reopen ( sandev ) ) != 0 ) ) { - goto err_reopen; - } + /* (Re)try command */ + for ( retries = 0 ; retries < SAN_COMMAND_MAX_RETRIES ; retries++ ) { - /* Start expiry timer */ - start_timer_fixed ( &sandev->timer, SAN_COMMAND_TIMEOUT ); + /* Reopen block device if applicable */ + if ( sandev_needs_reopen ( sandev ) && + ( ( rc = sandev_reopen ( sandev ) ) != 0 ) ) { + continue; + } - /* Initiate command */ - if ( ( rc = command ( sandev, params ) ) != 0 ) - goto err_op; + /* Start expiry timer */ + start_timer_fixed ( &sandev->timer, SAN_COMMAND_TIMEOUT ); - /* Wait for command to complete */ - while ( timer_running ( &sandev->timer ) ) - step(); + /* Initiate command */ + if ( ( rc = command ( sandev, params ) ) != 0 ) { + stop_timer ( &sandev->timer ); + continue; + } - /* Collect return status */ - rc = sandev->command_rc; + /* Wait for command to complete */ + while ( timer_running ( &sandev->timer ) ) + step(); - return rc; + /* Exit on success */ + if ( ( rc = sandev->command_rc ) == 0 ) + return 0; + } + + /* Sanity check */ + assert ( ! timer_running ( &sandev->timer ) ); - err_op: - stop_timer ( &sandev->timer ); - err_reopen: return rc; } |