/** * Shut down an object interface * * @v intf Object interface * @v rc Reason for close * * Blocks further operations from being received via the interface, * executes a close operation on the destination interface, and * unplugs the interface. */ void intf_shutdown ( struct interface *intf, int rc ) { 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 ); /* Unplug interface */ intf_unplug ( intf ); }
/** * Send redirection event * * @v intf Data transfer interface * @v type New location type * @v args Remaining arguments depend upon location type * @ret rc Return status code */ int xfer_vredirect ( struct interface *intf, int type, va_list args ) { struct interface tmp = INTF_INIT ( null_intf_desc ); struct interface *dest; xfer_vredirect_TYPE ( void * ) *op = intf_get_dest_op_no_passthru ( intf, xfer_vredirect, &dest ); void *object = intf_object ( dest ); int rc; DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " redirect\n", INTF_INTF_DBG ( intf, dest ) ); if ( op ) { rc = op ( object, type, args ); } else { /* Default is to reopen the interface as instructed, * then send xfer_window_changed() messages to both * new child and parent interfaces. Since our * original child interface is likely to be closed and * unplugged as a result of the call to * xfer_vreopen(), we create a temporary interface in * order to be able to send xfer_window_changed() to * the parent. */ intf_plug ( &tmp, dest ); rc = xfer_vreopen ( dest, type, args ); if ( rc == 0 ) { xfer_window_changed ( dest ); xfer_window_changed ( &tmp ); } intf_unplug ( &tmp ); } if ( rc != 0 ) { DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " redirect " "failed: %s\n", INTF_INTF_DBG ( intf, dest ), strerror ( rc ) ); } intf_put ( dest ); return rc; }