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