freebsd-skq/sys/cam/scsi
ken 498f14d067 Work around a race condition in devfs by changing the way closes
are handled in most CAM peripheral drivers that are not handled by
GEOM's disk class.

The usual character driver open and close semantics are that the
driver gets N open calls, but only one close, when the last caller
closes the device.

CAM peripheral drivers expect that behavior to be honored to the
letter, and the CAM peripheral driver code (specifically
cam_periph_release_locked_busses()) panics if it is done incorrectly.

Since devfs has to drop its locks while it calls a driver's close
routine, and it does not have a way to delay or prevent open calls
while it is calling the close routine, there is a race.

The sequence of events, simplified a bit, is:

- devfs acquires a lock
- devfs checks the reference count, and if it is 1, continues to close.
- devfs releases the lock

- 2nd process open call on the device happens here

- devfs calls the driver's close routine

- devfs acquires a lock
- devfs decrements the reference count
- devfs releases the lock

- 2nd process close call on the device happens here

At the second close, we get a panic in
cam_periph_release_locked_busses(), complaining that peripheral
has been released when the reference count is already 0.  This is
because we have gotten two closes in a row, which should not
happen.

The fix is to add the D_TRACKCLOSE flag to the driver's cdevsw, so
that we get a close() call for each open().  That does happen
reliably, so we can make sure that our reference counts are
correct.

Note that the sa(4) and pt(4) drivers only allow one context
through the open routine.  So these drivers aren't exposed to the
same race condition.

scsi_ch.c,
scsi_enc.c,
scsi_enc_internal.h,
scsi_pass.c,
scsi_sg.c:
		For these drivers, change the open() routine to
		increment the reference count for every open, and
		just decrement the reference count in the close.

		Call cam_periph_release_locked() in some scenarios
		to avoid additional lock and unlock calls.

scsi_pt.c:	Call cam_periph_release_locked() in some scenarios
		to avoid additional lock and unlock calls.

MFC after:	3 days
2012-05-27 06:11:09 +00:00
..
scsi_all.c MFprojects/zfsd: 2012-05-24 11:07:39 +00:00
scsi_all.h MFprojects/zfsd: 2012-05-24 11:07:39 +00:00
scsi_cd.c Add support for CDRIOCGETBLOCKSIZE and CDRIOCSETBLOCKSIZE IOCTLs to control 2012-01-03 17:04:09 +00:00
scsi_cd.h
scsi_ch.c Work around a race condition in devfs by changing the way closes 2012-05-27 06:11:09 +00:00
scsi_ch.h - fix duplicate "a a" in some comments 2011-11-13 17:06:33 +00:00
scsi_da.c Add support for: 2012-04-29 22:28:15 +00:00
scsi_da.h Add the CAM Target Layer (CTL). 2012-01-12 00:34:33 +00:00
scsi_dvcfg.h
scsi_enc_internal.h MFprojects/zfsd: 2012-05-24 14:07:44 +00:00
scsi_enc_safte.c MFprojects/zfsd: 2012-05-24 14:07:44 +00:00
scsi_enc_ses.c MFprojects/zfsd: 2012-05-24 14:07:44 +00:00
scsi_enc.c Work around a race condition in devfs by changing the way closes 2012-05-27 06:11:09 +00:00
scsi_enc.h MFprojects/zfsd: 2012-05-24 14:07:44 +00:00
scsi_iu.h
scsi_low_pisa.c
scsi_low_pisa.h
scsi_low.c Mark MALLOC_DEFINEs static that have no corresponding MALLOC_DECLAREs. 2011-11-07 06:44:47 +00:00
scsi_low.h
scsi_message.h
scsi_pass.c Work around a race condition in devfs by changing the way closes 2012-05-27 06:11:09 +00:00
scsi_pass.h
scsi_pt.c Work around a race condition in devfs by changing the way closes 2012-05-27 06:11:09 +00:00
scsi_pt.h
scsi_sa.c Remove unneeded checks for CAM_DEV_QFRZN after cam_periph_runccb() call. 2012-01-02 17:02:45 +00:00
scsi_sa.h
scsi_ses.h MFprojects/zfsd: 2012-05-24 14:07:44 +00:00
scsi_sg.c Work around a race condition in devfs by changing the way closes 2012-05-27 06:11:09 +00:00
scsi_sg.h
scsi_targ_bh.c Add the CAM Target Layer (CTL). 2012-01-12 00:34:33 +00:00
scsi_target.c Change targ(4) to use cdevpriv, instead of multiple character devices. 2011-12-13 21:26:33 +00:00
scsi_targetio.h
scsi_xpt.c Limit the ST3146855LW U320 drive to 55 tags to avoid command timeouts 2012-02-15 07:30:23 +00:00
smp_all.c Add Serial Management Protocol (SMP) passthrough support to CAM. 2010-11-30 22:39:46 +00:00
smp_all.h Add Serial Management Protocol (SMP) passthrough support to CAM. 2010-11-30 22:39:46 +00:00