• Neil Brown's avatar
    [PATCH] md: modify locking when accessing subdevices in md · 53a7c0ec
    Neil Brown authored
    Each md personality keeps a list of devices that are currently active in the
    array (mdk_rdev_t).  As these can potentially be removed at any time, some
    locking is needed when accessing entries in the list.  Currently this involves
    a spinlock, but all the spinlocking this imposed in unplug_slaves bothered me.
    
    So, I have changed it to use rcu locking.  This is more appropriate as objects
    are removed only very rarely, and there is no cost in waiting a little while
    for a remove to succeed.
    
    Also, all changes to the list of devices are performed by the per-array thread
    (calling md_check_recovery) and so are completely single threaded, so no
    locking between writers is needed at all.
    
    Finally, devices are never added or removed while resync is happening, so
    resync doesn't need to worry about locking at all.
    
    So with this patch, the spinlocking is replaced with rcu read locking and
    synchronize_kernel.  The rcu_read_lock is held while dereferencing a possible
    device, and the nr_pending count is atomically incremented if the device is to
    be held outside of the rcu_read_lock.
    
    When removing a device, if the nr_pending count appears to be zero, we set the
    list entry to NULL and call synchronize_kernel().  If the count is still zero
    after this, we have a safe removal.  If it is non-zero, then someone has just
    started using it so we put the pointer back and fail the removal.  When the
    new user finally drops it's reference, that will cause the per-array thread to
    wake up again and retry the removal.
    Signed-off-by: default avatarNeil Brown <neilb@cse.unsw.edu.au>
    Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
    53a7c0ec
raid5.c 50.5 KB