[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
SCSI locking
(I was tempted to call this `Locking and the Single-threaded driver', but
I feared no-one would get the pun)
I've just collected an email from Doug Ledford on linux-kernel and
mangled it slightly into linux/Documentation/drivers/scsi/locking.txt.
Doug, the current plan is to move all the linux/drivers/scsi/README.foo
files into linux/Documentation/drivers/scsi/foo.txt.
--- cut ---
Locking in the SCSI device layer
================================
If you wish to manipulate the locks in the individual driver, the following
rules must be followed for Linux 2.2. The mid-level code is destined to be
rewritten, so this probably does not apply to Linux 2.3.
1. If you drop the global io_request_lock, then you must either be
prepared to have your code re-entered or you must provide some alternate
form of locking. Note possible deadlock issues here are *very*
abundant. The global io_request_lock is the *only* thing the mid-level
SCSI code uses to make sure it doesn't call into your code
re-entrantly. And even then it's not a total guarantee. Be aware that
the mid-level SCSI code can call back into your code from the
scsi_done() routine, so an interrupt can generate calls into the
queue_command() routine, queue() routine, or the reset() routine. Be
prepared for such calls when doing your own locking.
2. You must *always* re-aquire the spin lock on the io_request_lock
before you make any calls into the mid-level code. The mid-level code
expects that all low level drivers will be holding this lock when they
call into it for anything other than init functions and relies upon that
to perform it's own locking. Failure to do this will result in the
mid-level code eventually hosing things horribly.
3. Be prepared to handle deadlocks if you drop the lock and do your own
locking. My experimental code in this area used a custom
recursion-allowed-on-the-same-cpu spin lock for this purpose. It's
still in the aic7xxx driver, but ifdef'ed out at the moment. In
general, realize that if you use any of your own locks, then you must
drop all of your own locks before trying to re-aquire the global
io_request_lock, etc. Be aware of all possible entry points in your
driver and any interdependancies when doing this as well (such as "If I
drop the io_request_lock in my driver and spin in the queue routine,
then what happens if I get an interrupt? Will the interrupt handler
call scsi_done() and result in another command in the queue routine, and
if so, what will happen when it hits my locking and will it trounce on
variables, etc?").
Now, having said things so wordly to express the warning I would give
people, the short version is that the mid-level code not only uses the
global io_request_lock spinlock to guarantee that the low level driver
is treated as a single threaded driver, it also does it's own internal
locking with it. So, dropping the lock has more implications than
simply in the low level driver. It also means that SMP programming is
much more fickle once you drop that lock. The design was to be failsafe
for 2.2, and fix it properly in 2.3. The alternative was SCSI race
conditions all through 2.2.
[This document is based on an email from Doug Ledford sent to linux-kernel]
--- cut ---
--
Matthew Wilcox <willy@bofh.ai>
"I decry the current tendency to seek patents on algorithms. There are
better ways to earn a living than to prevent other people from making use of
one's contributions to computer science." -- Donald E. Knuth, TAoCP vol 3
-
Kernel-doc, Linux kernel documentation list.
http://mail.nl.linux.org/lists/