Skip to content
  • NeilBrown's avatar
    md: fix some lockdep issues between md and sysfs. · ef286f6f
    NeilBrown authored
    ======
    This fix is related to
        http://bugzilla.kernel.org/show_bug.cgi?id=15142
    
    
    but does not address that exact issue.
    ======
    
    sysfs does like attributes being removed while they are being accessed
    (i.e. read or written) and waits for the access to complete.
    
    As accessing some md attributes takes the same lock that is held while
    removing those attributes a deadlock can occur.
    
    This patch addresses 3 issues in md that could lead to this deadlock.
    
    Two relate to calling flush_scheduled_work while the lock is held.
    This is probably a bad idea in general and as we use schedule_work to
    delete various sysfs objects it is particularly bad.
    
    In one case flush_scheduled_work is called from md_alloc (called by
    md_probe) called from do_md_run which holds the lock.  This call is
    only present to ensure that ->gendisk is set.  However we can be sure
    that gendisk is always set (though possibly we couldn't when that code
    was originally written.  This is because do_md_run is called in three
    different contexts:
      1/ from md_ioctl.  This requires that md_open has succeeded, and it
         fails if ->gendisk is not set.
      2/ from writing a sysfs attribute.  This can only happen if the
         mddev has been registered in sysfs which happens in md_alloc
         after ->gendisk has been set.
      3/ from autorun_array which is only called by autorun_devices, which
         checks for ->gendisk to be set before calling autorun_array.
    So the call to md_probe in do_md_run can be removed, and the check on
    ->gendisk can also go.
    
    
    In the other case flush_scheduled_work is being called in do_md_stop,
    purportedly to wait for all md_delayed_delete calls (which delete the
    component rdevs) to complete.  However there really isn't any need to
    wait for them - they have already been disconnected in all important
    ways.
    
    The third issue is that raid5->stop() removes some attribute names
    while the lock is held.  There is already some infrastructure in place
    to delay attribute removal until after the lock is released (using
    schedule_work).  So extend that infrastructure to remove the
    raid5_attrs_group.
    
    This does not address all lockdep issues related to the sysfs
    "s_active" lock.  The rest can be address by splitting that lockdep
    context between symlinks and non-symlinks which hopefully will happen.
    
    Signed-off-by: default avatarNeilBrown <neilb@suse.de>
    ef286f6f