summaryrefslogtreecommitdiffstats
path: root/src/arch
diff options
context:
space:
mode:
authorMichael Brown2017-03-26 14:12:11 +0200
committerMichael Brown2017-03-26 15:06:02 +0200
commitbb5a54b79a414082d0b39d478a8b3332c56d68e5 (patch)
treec022d5b8ed56be56414eb007273aeacd57c44d37 /src/arch
parent[block] Add dummy SAN device (diff)
downloadipxe-bb5a54b79a414082d0b39d478a8b3332c56d68e5.tar.gz
ipxe-bb5a54b79a414082d0b39d478a8b3332c56d68e5.tar.xz
ipxe-bb5a54b79a414082d0b39d478a8b3332c56d68e5.zip
[block] Add basic multipath support
Add basic support for multipath block devices. The "sanboot" and "sanhook" commands now accept a list of SAN URIs. We open all URIs concurrently. The first connection to become available for issuing block device commands is marked as the active path and used for all subsequent commands; all other connections are then closed. Whenever the active path fails, we reopen all URIs and repeat the process. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/x86/interface/pcbios/int13.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/src/arch/x86/interface/pcbios/int13.c b/src/arch/x86/interface/pcbios/int13.c
index 23cfefca..c322440e 100644
--- a/src/arch/x86/interface/pcbios/int13.c
+++ b/src/arch/x86/interface/pcbios/int13.c
@@ -833,6 +833,7 @@ static int int13_extended_seek ( struct san_device *sandev,
*/
static int int13_device_path_info ( struct san_device *sandev,
struct edd_device_path_information *dpi ) {
+ struct san_path *sanpath;
struct device *device;
struct device_description *desc;
unsigned int i;
@@ -843,9 +844,11 @@ static int int13_device_path_info ( struct san_device *sandev,
if ( sandev_needs_reopen ( sandev ) &&
( ( rc = sandev_reopen ( sandev ) ) != 0 ) )
return rc;
+ sanpath = sandev->active;
+ assert ( sanpath != NULL );
/* Get underlying hardware device */
- device = identify_device ( &sandev->block );
+ device = identify_device ( &sanpath->block );
if ( ! device ) {
DBGC ( sandev, "INT13 drive %02x cannot identify hardware "
"device\n", sandev->drive );
@@ -869,7 +872,7 @@ static int int13_device_path_info ( struct san_device *sandev,
}
/* Get EDD block device description */
- if ( ( rc = edd_describe ( &sandev->block, &dpi->interface_type,
+ if ( ( rc = edd_describe ( &sanpath->block, &dpi->interface_type,
&dpi->device_path ) ) != 0 ) {
DBGC ( sandev, "INT13 drive %02x cannot identify block device: "
"%s\n", sandev->drive, strerror ( rc ) );
@@ -1199,14 +1202,16 @@ static void int13_unhook_vector ( void ) {
/**
* Hook INT 13 SAN device
*
- * @v uri URI
* @v drive Drive number
+ * @v uris List of URIs
+ * @v count Number of URIs
* @ret drive Drive number, or negative error
*
* Registers the drive with the INT 13 emulation subsystem, and hooks
* the INT 13 interrupt vector (if not already hooked).
*/
-static int int13_hook ( struct uri *uri, unsigned int drive ) {
+static int int13_hook ( unsigned int drive, struct uri **uris,
+ unsigned int count ) {
struct san_device *sandev;
struct int13_data *int13;
unsigned int natural_drive;
@@ -1223,7 +1228,7 @@ static int int13_hook ( struct uri *uri, unsigned int drive ) {
drive = natural_drive;
/* Allocate SAN device */
- sandev = alloc_sandev ( uri, sizeof ( *int13 ) );
+ sandev = alloc_sandev ( uris, count, sizeof ( *int13 ) );
if ( ! sandev ) {
rc = -ENOMEM;
goto err_alloc;
@@ -1525,6 +1530,7 @@ static union xbft_table __bss16 ( xbftab ) __attribute__ (( aligned ( 16 ) ));
*/
static int int13_describe ( unsigned int drive ) {
struct san_device *sandev;
+ struct san_path *sanpath;
struct segoff xbft_address;
int rc;
@@ -1539,6 +1545,8 @@ static int int13_describe ( unsigned int drive ) {
if ( sandev_needs_reopen ( sandev ) &&
( ( rc = sandev_reopen ( sandev ) ) != 0 ) )
return rc;
+ sanpath = sandev->active;
+ assert ( sanpath != NULL );
/* Clear table */
memset ( &xbftab, 0, sizeof ( xbftab ) );
@@ -1550,7 +1558,7 @@ static int int13_describe ( unsigned int drive ) {
sizeof ( xbftab.acpi.oem_table_id ) );
/* Fill in remaining parameters */
- if ( ( rc = acpi_describe ( &sandev->block, &xbftab.acpi,
+ if ( ( rc = acpi_describe ( &sanpath->block, &xbftab.acpi,
sizeof ( xbftab ) ) ) != 0 ) {
DBGC ( sandev, "INT13 drive %02x could not create ACPI "
"description: %s\n", sandev->drive, strerror ( rc ) );