Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[interface] Unplug interface before calling intf_close() in intf_shut…
…down()

The call to intf_close() may result in the original interface being
reopened.  For example: when reading the capacity of a 2TB+ disk via
iSCSI, the SCSI layer will respond to the intf_close() from the READ
CAPACITY (10) command by immediately issuing a READ CAPACITY (16)
command.  The iSCSI layer happens to reuse the same interface for the
new command (since it allows only a single concurrent command).

Currently, intf_shutdown() unplugs the interface after the call to
intf_close() returns.  In the above scenario, this results in
unplugging the just-reopened interface.

Fix by transferring the interface destination (and its reference) to a
temporary interface, and so effectively performing the unplug before
making the call to intf_close().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed Jan 25, 2017
1 parent 5ff1383 commit f450c75
Showing 1 changed file with 9 additions and 4 deletions.
13 changes: 9 additions & 4 deletions src/core/interface.c
Expand Up @@ -271,18 +271,23 @@ void intf_close ( struct interface *intf, int rc ) {
* unplugs the interface.
*/
void intf_shutdown ( struct interface *intf, int rc ) {
struct interface tmp;

DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " shutting down (%s)\n",
INTF_DBG ( intf ), strerror ( rc ) );

/* Block further operations */
intf_nullify ( intf );

/* Notify destination of close */
intf_close ( intf, rc );
/* Transfer destination to temporary interface */
tmp.dest = intf->dest;
intf->dest = &null_intf;

/* Notify destination of close via temporary interface */
intf_close ( &tmp, rc );

/* Unplug interface */
intf_unplug ( intf );
/* Unplug temporary interface */
intf_unplug ( &tmp );
}

/**
Expand Down

0 comments on commit f450c75

Please sign in to comment.