Procházet zdrojové kódy

[scsi] Avoid duplicate calls to scsicmd_close()

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>
tags/v1.20.1
Michael Brown před 7 roky
rodič
revize
9db9221ea0
1 změnil soubory, kde provedl 7 přidání a 8 odebrání
  1. 7
    8
      src/drivers/block/scsi.c

+ 7
- 8
src/drivers/block/scsi.c Zobrazit soubor

@@ -371,8 +371,7 @@ static void scsicmd_free ( struct refcnt *refcnt ) {
371 371
 	struct scsi_command *scsicmd =
372 372
 		container_of ( refcnt, struct scsi_command, refcnt );
373 373
 
374
-	/* Remove from list of commands */
375
-	list_del ( &scsicmd->list );
374
+	/* Drop reference to SCSI device */
376 375
 	scsidev_put ( scsicmd->scsidev );
377 376
 
378 377
 	/* Free command */
@@ -395,6 +394,10 @@ static void scsicmd_close ( struct scsi_command *scsicmd, int rc ) {
395 394
 
396 395
 	/* Shut down interfaces */
397 396
 	intfs_shutdown ( rc, &scsicmd->scsi, &scsicmd->block, NULL );
397
+
398
+	/* Remove from list of commands and drop list's reference */
399
+	list_del ( &scsicmd->list );
400
+	scsicmd_put ( scsicmd );
398 401
 }
399 402
 
400 403
 /**
@@ -733,9 +736,8 @@ static int scsidev_command ( struct scsi_device *scsidev,
733 736
 	if ( ( rc = scsicmd_command ( scsicmd ) ) != 0 )
734 737
 		goto err_command;
735 738
 
736
-	/* Attach to parent interface, mortalise self, and return */
739
+	/* Attach to parent interface, transfer reference to list, and return */
737 740
 	intf_plug_plug ( &scsicmd->block, block );
738
-	ref_put ( &scsicmd->refcnt );
739 741
 	return 0;
740 742
 
741 743
  err_command:
@@ -843,11 +845,8 @@ static void scsidev_close ( struct scsi_device *scsidev, int rc ) {
843 845
 			 NULL );
844 846
 
845 847
 	/* Shut down any remaining commands */
846
-	list_for_each_entry_safe ( scsicmd, tmp, &scsidev->cmds, list ) {
847
-		scsicmd_get ( scsicmd );
848
+	list_for_each_entry_safe ( scsicmd, tmp, &scsidev->cmds, list )
848 849
 		scsicmd_close ( scsicmd, rc );
849
-		scsicmd_put ( scsicmd );
850
-	}
851 850
 }
852 851
 
853 852
 /** SCSI device block interface operations */

Načítá se…
Zrušit
Uložit