]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[interface] Unplug interface before calling intf_close() in intf_shutdown()
authorMichael Brown <mcb30@ipxe.org>
Wed, 25 Jan 2017 10:19:02 +0000 (10:19 +0000)
committerMichael Brown <mcb30@ipxe.org>
Wed, 25 Jan 2017 11:29:29 +0000 (11:29 +0000)
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>
src/core/interface.c

index a700d2e4d6ff376afaaae0360b7c9122b33d95c5..f7802be071c0d94c2fb064b3cad16348956e6a04 100644 (file)
@@ -271,6 +271,7 @@ 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 ) );
@@ -278,11 +279,15 @@ void intf_shutdown ( struct interface *intf, int 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 );
 }
 
 /**