SOLARIS: Avoid vcache locks when flushing pages for RO vnodes
We have multiple code paths that hold the following locks at the same
time:
- avc->lock for a vcache
- The page lock for a page in 'avc'
In order to avoid deadlocks, we need a consistent ordering for obtaining
these two locks. The code in afs_putpage() currently obtains avc->lock
before the page lock (Obtain*Lock is called before pvn_vplist_dirty).
The code in afs_getpages() also obtains avc->lock before the page lock,
but it does so in a loop for all requested pages (via pvn_getpages()).
On the second iteration of that loop, it obtains avc->lock, and the page
from the first iteration of the loop is still locked. Thus, it obtains a
page lock before locking avc->lock in some cases.
Since we have two code paths that obtain those two locks in a different
order, a deadlock can occur. Fixing this properly requires changing at
least one of those code paths, so the locks are taken in a consistent
order. However, doing so is complex and will be done in a separate
future commit.
For this commit, we can avoid the deadlock for RO volumes by simply
avoiding taking avc->lock in afs_putpages() at all while the pages are
locked. Normally, we lock avc->lock because pvn_vplist_dirty() will call
afs_putapage() for each dirty page (and afs_putapage() requires
avc->lock held). But for RO volumes, we will have no dirty pages
(because RO volumes cannot be written to from a client), and so
afs_putapage() will never be called.
So to avoid this deadlock issue for RO volumes, avoid taking avc->lock
across the pvn_vplist_dirty() call in afs_putpage(). We now pass a dummy
pageout callback function to pvn_vplist_dirty() instead, which should
never be called, and which panics if it ever is.
We still need to hold avc->lock a few other times during afs_putpage()
for other minor reasons, but none of these hold page locks at the same
time, so the deadlock issue is still avoided.
[mmeffie: comments, and fix missing write lock, fix lock releases]
[adeason: revised commit message]
Reviewed-on: https://gerrit.openafs.org/12247
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Andrew Deason <adeason@dson.org>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
(cherry picked from commit
5e09a694ec2c0cd20f5dee500eff6bc3dd04c097)
Change-Id: I5d4e4ddba12c09dc549edeee3cad7de40582ac65
Reviewed-on: https://gerrit.openafs.org/12900
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Mark Vitale <mvitale@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>