Skip to content

Commit

Permalink
[scsi] Avoid duplicate calls to scsicmd_close()
Browse files Browse the repository at this point in the history
When a SCSI device is closed in error, the shutdown of the device's
block data interface will probably lead to any outstanding commands
being closed (by whichever object is currently connected to the block
data interface).  However, commands remain in the list of outstanding
commands until the final reference is dropped.  The result is that
scsidev_close() will make a second call to scsicmd_close() for each
command.  This is harmless, but produces confusing debug messages.

Fix by treating the outstanding command list as holding an explicit
reference to each command, and removing the command from the list of
outstanding commands in scsicmd_close().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed Mar 9, 2017
1 parent 9423a85 commit 9db9221
Showing 1 changed file with 7 additions and 8 deletions.
15 changes: 7 additions & 8 deletions src/drivers/block/scsi.c
Expand Up @@ -371,8 +371,7 @@ static void scsicmd_free ( struct refcnt *refcnt ) {
struct scsi_command *scsicmd =
container_of ( refcnt, struct scsi_command, refcnt );

/* Remove from list of commands */
list_del ( &scsicmd->list );
/* Drop reference to SCSI device */
scsidev_put ( scsicmd->scsidev );

/* Free command */
Expand All @@ -395,6 +394,10 @@ static void scsicmd_close ( struct scsi_command *scsicmd, int rc ) {

/* Shut down interfaces */
intfs_shutdown ( rc, &scsicmd->scsi, &scsicmd->block, NULL );

/* Remove from list of commands and drop list's reference */
list_del ( &scsicmd->list );
scsicmd_put ( scsicmd );
}

/**
Expand Down Expand Up @@ -733,9 +736,8 @@ static int scsidev_command ( struct scsi_device *scsidev,
if ( ( rc = scsicmd_command ( scsicmd ) ) != 0 )
goto err_command;

/* Attach to parent interface, mortalise self, and return */
/* Attach to parent interface, transfer reference to list, and return */
intf_plug_plug ( &scsicmd->block, block );
ref_put ( &scsicmd->refcnt );
return 0;

err_command:
Expand Down Expand Up @@ -843,11 +845,8 @@ static void scsidev_close ( struct scsi_device *scsidev, int rc ) {
NULL );

/* Shut down any remaining commands */
list_for_each_entry_safe ( scsicmd, tmp, &scsidev->cmds, list ) {
scsicmd_get ( scsicmd );
list_for_each_entry_safe ( scsicmd, tmp, &scsidev->cmds, list )
scsicmd_close ( scsicmd, rc );
scsicmd_put ( scsicmd );
}
}

/** SCSI device block interface operations */
Expand Down

0 comments on commit 9db9221

Please sign in to comment.