• Alexander Viro's avatar
    [PATCH] hpfs: fix locking scheme · 9c96c8be
    Alexander Viro authored
    	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.
    9c96c8be
hpfs_fn.h 10.8 KB