Fixed the locking scheme. The need of extra locking was caused by
the fact that hpfs_write_inode() must update directory entry; since HPFS
directories are implemented as b-trees, we must provide protection both
against rename() (to make sure that we update the entry in right directory)
and against rebalancing of the parent.
Old scheme had both deadlocks and races - to start with, we had no
protection against rename()/unlink()/rmdir(), since (a) locking parent
was done without any warranties that it will remain our parent and (b)
check that we still have a directory entry (== have positive nlink) was
done before we tried to lock the parent. Moreover, iget serialization
killed two steps ago gave immediate deadlocks if iget() of parent had
triggered another hpfs_write_inode().
New scheme introduces another per-inode semaphore (hpfs-only,
obviously) protecting the reference to parent. It's taken on
rename/rmdir/unlink victims and inode being moved by rename. Old semaphores
are taken only on parent(s) and only after we grab one(s) of the new kind.
hpfs_write_inode() gets the new semaphore on our inode, checks nlink and
if it's non-zero grabs parent and takes the old semaphore on it.
Order among the semaphores of the same kind is arbitrary - the only
function that might take more than one of the same kind is hpfs_rename()
and it's serialized by VFS.
We might get away with only one semaphore, but then the ordering
issues would bite us big way - we would have to make sure that child is
always locked before parent (hpfs_write_inode() leaves no other choice)
and while that's easy to do for almost all operations, rename() is a bitch -
as always. And per-superblock rwsem giving rename() vs. write_inode()
exclusion on hpfs would make the entire thing too baroque for my taste.
->readdir() takes no locks at all (protection against directory
modifications is provided by VFS exclusion), ditto for ->lookup().
->llseek() on directories switched to use of (VFS) ->i_sem, so
it's safe from directory modifications and ->readdir() is safe from it -
no hpfs locks are needed here.