linux-stable-rt/drivers/s390/scsi
Martin Peschke 86e8dfc560 [SCSI] zfcp: fix cleanup of dismissed error recovery actions
Calling zfcp_erp_strategy_check_action() after zfcp_erp_action_to_running()
in zfcp_erp_strategy() might cause an unbalanced up() for erp_ready_sem,
which makes the zfcp recovery fail somewhere along the way:

erp thread processing erp_action:
|
|	someone waking up erp thread for erp_action
|	|
|	|		someone else dismissing erp_action:
|	|		|
V	V		V

	write_lock_irqsave(&adapter->erp_lock, flags);
	...
	if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) {
		zfcp_erp_action_to_ready(erp_action);
		up(&adapter->erp_ready_sem);	/* first up() for erp_action */
	}
	write_unlock_irqrestore(&adapter->erp_lock, flags);

write_lock_irqsave(&adapter->erp_lock, flags);
...
zfcp_erp_action_to_running(erp_action);
write_unlock_restore(&adapter->erp_lock, flags);
/* processing erp_action */

			write_lock_irqsave(&adapter->erp_lock, flags);
			...
			erp_action->status |= ZFCP_STATUS_ERP_DISMISSED;
			if (zfcp_erp_action_exists(erp_action) ==
						ZFCP_ERP_ACTION_RUNNING) {
				zfcp_erp_action_to_ready(erp_action);
				up(&adapter->erp_ready_sem);
				/* second, unbalanced up() for erp_action */
			}
			...
			write_unlock_restore(&adapter->erp_lock, flags);

write_lock_irqsave(&adapter->erp_lock, flags);
if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) {
	zfcp_erp_action_dequeue(erp_action);
	retval = ZFCP_ERP_DISMISSED;
}
...
write_unlock_restore(&adapter->erp_lock, flags);
down(&adapter->erp_ready_sem);
/* this down() is meant to balance the first up() */

The erp thread must not dismiss an erp_action after moving that action to
erp_running_head. Instead it should just go through the down() operation,
which balances the first up(), and run through zfcp_erp_strategy one more
time for the second up(), which eventually cleans up erp_action. Which
is similar to the normal processing of an event for erp_action doing
something asynchronously (e.g. waiting for the completion of an fsf_req).

This only works if we make sure that a dismissed erp_action is passed to
zfcp_erp_strategy() prior to the other action, which caused actions to be
dismissed. Therefore the patch implements this rule: running actions go to
the head of the ready list; new actions go to the tail of the ready list;
the erp thread picks actions to be processed from the ready list's head.

Signed-off-by: Martin Peschke <mp3@de.ibm.com>
Acked-by: Swen Schillig <swen@vnet.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
2007-11-16 13:03:21 -06:00
..
Makefile
zfcp_aux.c SG: Change sg_set_page() to take length and offset argument 2007-10-24 11:20:47 +02:00
zfcp_ccw.c Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6 2007-10-15 08:19:33 -07:00
zfcp_dbf.c [S390] Get rid of a bunch of sparse warnings again. 2007-10-12 16:13:06 +02:00
zfcp_def.h SG: s390-scsi: missing size parameter in zfcp_address_to_sg() 2007-10-29 09:18:03 +01:00
zfcp_erp.c [SCSI] zfcp: fix cleanup of dismissed error recovery actions 2007-11-16 13:03:21 -06:00
zfcp_ext.h [SCSI] zfcp: whitespace cleanup 2007-10-12 14:47:21 -04:00
zfcp_fsf.c [SCSI] zfcp: whitespace cleanup 2007-10-12 14:47:21 -04:00
zfcp_fsf.h [SCSI] zfcp: whitespace cleanup 2007-10-12 14:47:21 -04:00
zfcp_qdio.c zfcp: sg chaining support 2007-10-16 11:21:00 +02:00
zfcp_scsi.c [SCSI] zfcp: whitespace cleanup 2007-10-12 14:47:21 -04:00
zfcp_sysfs_adapter.c
zfcp_sysfs_driver.c
zfcp_sysfs_port.c
zfcp_sysfs_unit.c [SCSI] zfcp: whitespace cleanup 2007-10-12 14:47:21 -04:00