02 Aug, 2014

1 commit

  • A memory allocation failure could cause nfsd_startup_generic to fail, in
    which case nfsd_users wouldn't be incorrectly left elevated.

    After nfsd restarts nfsd_startup_generic will then succeed without doing
    anything--the first consequence is likely nfs4_start_net finding a bad
    laundry_wq and crashing.

    Signed-off-by: Kinglong Mee
    Fixes: 4539f14981ce "nfsd: replace boolean nfsd_up flag by users counter"
    Cc: stable@vger.kernel.org
    Signed-off-by: J. Bruce Fields

    Kinglong Mee
     

01 Aug, 2014

36 commits

  • ...to better match other functions that deal with open/lock stateids.

    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • When we remove the client_mutex, we'll have a potential race between
    FREE_STATEID and CLOSE.

    The root of the problem is that we are walking the st_locks list,
    dropping the spinlock and then trying to release the persistent
    reference to the lockstateid. In between, a FREE_STATEID call can come
    along and take the lock, find the stateid and then try to put the
    reference. That leads to a double put.

    Fix this by not releasing the cl_lock in order to release each lock
    stateid. Use put_generic_stateid_locked to unhash them and gather them
    onto a list, and free_ol_stateid_reaplist to free any that end up on the
    list.

    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • Releasing an openowner is a bit inefficient as it can potentially thrash
    the cl_lock if you have a lot of stateids attached to it. Once we remove
    the client_mutex, it'll also potentially be dangerous to do this.

    Add some functions to make it easier to defer the part of putting a
    generic stateid reference that needs to be done outside the cl_lock while
    doing the parts that must be done while holding it under a single lock.

    First we unhash each open stateid. Then we call
    put_generic_stateid_locked which will put the reference to an
    nfs4_ol_stateid. If it turns out to be the last reference, it'll go
    ahead and remove the stid from the IDR tree and put it onto the reaplist
    using the st_locks list_head.

    Then, after dropping the lock we'll call free_ol_stateid_reaplist to
    walk the list of stateids that are fully unhashed and ready to be freed,
    and free each of them. This function can sleep, so it must be done
    outside any spinlocks.

    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • Once we remove the client_mutex, it'll be possible for the sc_type of a
    lock stateid to change after it's found and checked, but before we can
    go to destroy it. If that happens, we can end up putting the persistent
    reference to the stateid more than once, and unhash it more than once.

    Fix this by unhashing the lock stateid prior to dropping the cl_lock but
    after finding it.

    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • Reduce the cl_lock trashing in destroy_lockowner. Unhash all of the
    lockstateids on the lockowner's list. Put the reference under the lock
    and see if it was the last one. If so, then add it to a private list
    to be destroyed after we drop the lock.

    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • Once we remove the client_mutex, we'll need to properly protect
    the stateowner reference counts using the cl_lock.

    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • Do more within the main loop, and simplify the function a bit. Also,
    there's no need to take a stateowner reference unless we're going to call
    release_lockowner.

    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • Preparation for removing the client_mutex.

    Convert the open owner hash table into a per-client table and protect it
    using the nfs4_client->cl_lock spin lock.

    Signed-off-by: Trond Myklebust
    Signed-off-by: J. Bruce Fields

    Trond Myklebust
     
  • Once we remove client mutex protection, we'll need to ensure that
    stateowner lookup and creation are atomic between concurrent compounds.
    Ensure that alloc_init_lock_stateowner checks the hashtable under the
    client_lock before adding a new element.

    Signed-off-by: Trond Myklebust
    Signed-off-by: J. Bruce Fields

    Trond Myklebust
     
  • Once we remove client mutex protection, we'll need to ensure that
    stateowner lookup and creation are atomic between concurrent compounds.
    Ensure that alloc_init_open_stateowner checks the hashtable under the
    client_lock before adding a new element.

    Signed-off-by: Trond Myklebust
    Signed-off-by: J. Bruce Fields

    Trond Myklebust
     
  • Once we remove client_mutex protection, it'll be possible to have an
    in-flight operation using an openstateid when a CLOSE call comes in.
    If that happens, we can't just put the sc_file reference and clear its
    pointer without risking an oops.

    Fix this by ensuring that v4.0 CLOSE operations wait for the refcount
    to drop before proceeding to do so.

    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • Change it so that only openstateids hold persistent references to
    openowners. References can still be held by compounds in progress.

    With this, we can get rid of NFS4_OO_NEW. It's possible that we
    will create a new openowner in the process of doing the open, but
    something later fails. In the meantime, another task could find
    that openowner and start using it on a successful open. If that
    occurs we don't necessarily want to tear it down, just put the
    reference that the failing compound holds.

    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • Ensure that lockowner references are only held by lockstateids and
    operations that are in-progress. With this, we can get rid of
    release_lockowner_if_empty, which will be racy once we remove
    client_mutex protection.

    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • A necessary step toward client_mutex removal.

    Signed-off-by: Trond Myklebust
    Signed-off-by: J. Bruce Fields

    Trond Myklebust
     
  • Allow stateowners to be unhashed and destroyed when the last reference
    is put. The unhashing must be idempotent. In a future patch, we'll add
    some locking around it, but for now it's only protected by the
    client_mutex.

    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • Ensure that when finding or creating a lockowner, that we get a
    reference to it. For now, we also take an extra reference when a
    lockowner is created that can be put when release_lockowner is called,
    but we'll remove that in a later patch once we change how references are
    held.

    Since we no longer destroy lockowners in the event of an error in
    nfsd4_lock, we must change how the seqid gets bumped in the lk_is_new
    case. Instead of doing so on creation, do it manually in nfsd4_lock.

    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • We don't want to rely on the client_mutex for protection in the case of
    NFSv4 open owners. Instead, we add a mutex that will only be taken for
    NFSv4.0 state mutating operations, and that will be released once the
    entire compound is done.

    Also, ensure that nfsd4_cstate_assign_replay/nfsd4_cstate_clear_replay
    take a reference to the stateowner when they are using it for NFSv4.0
    open and lock replay caching.

    Signed-off-by: Trond Myklebust
    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • The way stateowners are managed today is somewhat awkward. They need to
    be explicitly destroyed, even though the stateids reference them. This
    will be particularly problematic when we remove the client_mutex.

    We may create a new stateowner and attempt to open a file or set a lock,
    and have that fail. In the meantime, another RPC may come in that uses
    that same stateowner and succeed. We can't have the first task tearing
    down the stateowner in that situation.

    To fix this, we need to change how stateowners are tracked altogether.
    Refcount them and only destroy them once all stateids that reference
    them have been destroyed. This patch starts by adding the refcounting
    necessary to do that.

    Signed-off-by: Trond Myklebust
    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • Allow nfs4_find_stateid_by_type to take the stateid reference, while
    still holding the &cl->cl_lock. Necessary step toward client_mutex
    removal.

    Signed-off-by: Trond Myklebust
    Signed-off-by: J. Bruce Fields

    Trond Myklebust
     
  • Allow nfs4_lookup_stateid to take the stateid reference, instead
    of having all the callers do so.

    Signed-off-by: Trond Myklebust
    Signed-off-by: J. Bruce Fields

    Trond Myklebust
     
  • Allow nfs4_preprocess_seqid_op to take the stateid reference, instead
    of having all the callers do so.

    Signed-off-by: Trond Myklebust
    Signed-off-by: J. Bruce Fields

    Trond Myklebust
     
  • Ensure that all the callers put the open stateid after use.
    Necessary step toward client_mutex removal.

    Signed-off-by: Trond Myklebust
    Signed-off-by: J. Bruce Fields

    Trond Myklebust
     
  • Ensure that nfsd4_open_confirm() keeps a reference to the open
    stateid until it is done working with it.

    Necessary step toward client_mutex removal.

    Signed-off-by: Trond Myklebust
    Signed-off-by: J. Bruce Fields

    Trond Myklebust
     
  • Prepare nfsd4_close for a future where nfs4_preprocess_seqid_op()
    hands it a fully referenced open stateid. Necessary step toward
    client_mutex removal.

    Signed-off-by: Trond Myklebust
    Signed-off-by: J. Bruce Fields

    Trond Myklebust
     
  • Ensure that nfsd4_process_open2() keeps a reference to the open
    stateid until it is done working with it. Necessary step toward
    client_mutex removal.

    Signed-off-by: Trond Myklebust
    Signed-off-by: J. Bruce Fields

    Trond Myklebust
     
  • Ensure that nfsd4_process_open2() keeps a reference to the delegation
    stateid until it is done working with it. Necessary step toward
    client_mutex removal.

    Signed-off-by: Trond Myklebust
    Signed-off-by: J. Bruce Fields

    Trond Myklebust
     
  • Ensure that nfs4_open_delegation() keeps a reference to the delegation
    stateid until it is done working with it. Necessary step toward
    client_mutex removal.

    Signed-off-by: Trond Myklebust
    Signed-off-by: J. Bruce Fields

    Trond Myklebust
     
  • Ensure that nfsd4_locku() keeps a reference to the lock stateid
    until it is done working with it. Necessary step toward client_mutex
    removal.

    Signed-off-by: Trond Myklebust
    Signed-off-by: J. Bruce Fields

    Trond Myklebust
     
  • Ensure that nfsd4_lock() references the lock stateid while it is
    manipulating it. Not currently necessary, but will be once the
    client_mutex is removed.

    Signed-off-by: Trond Myklebust
    Signed-off-by: J. Bruce Fields

    Trond Myklebust
     
  • Hold the cl_lock over the bulk of these functions. In addition to
    ensuring that they aren't freed prematurely, this will also help prevent
    a potential race that could be introduced later. Once we remove the
    client_mutex, it'll be possible for FREE_STATEID and CLOSE to race and
    for both to try to put the "persistent" reference to the stateid.

    Signed-off-by: Trond Myklebust
    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • Preparation for removal of the client_mutex.

    Currently, no lock aside from the client_mutex is held when calling
    find_lock_state. Ensure that the cl_lock is held by adding a lockdep
    assertion.

    Once we remove the client_mutex, it'll be possible for another thread to
    race in and insert a lock state for the same file after we search but
    before we insert a new one. Ensure that doesn't happen by redoing the
    search after allocating a new stid that we plan to insert. If one is
    found just put the one that was allocated.

    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • Change to using the clp->cl_lock for this. For now, there's a lot of
    cl_lock thrashing, but in later patches we'll eliminate that and close
    the potential races that can occur when releasing the cl_lock while
    walking the lists. For now, the client_mutex prevents those races.

    Signed-off-by: Trond Myklebust
    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • Releasing locks when we unhash the stateid instead of doing so only when
    the stateid is actually released will be problematic in later patches
    when we need to protect the unhashing with spinlocks. Move it into the
    sc_free operation instead.

    Signed-off-by: Jeff Layton
    Reviewed-by: Christoph Hellwig
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • Currently, this is serialized by the client_mutex, which is slated for
    removal. Add finer-grained locking here. Also, do some cleanup around
    find_stateid to prepare for taking references.

    Signed-off-by: Trond Myklebust
    Signed-off-by: Benny Halevy
    Signed-off-by: Jeff Layton
    Reviewed-by: Christoph Hellwig
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     
  • All stateids are associated with a nfs4_file. Let's consolidate.
    Replace delegation->dl_file with the dl_stid.sc_file, and
    nfs4_ol_stateid->st_file with st_stid.sc_file.

    Signed-off-by: Trond Myklebust
    Reviewed-by: Christoph Hellwig
    Signed-off-by: J. Bruce Fields

    Trond Myklebust
     
  • When we remove the client_mutex, we'll need to be able to ensure that
    these objects aren't destroyed while we're not holding locks.

    Add a ->free() callback to the struct nfs4_stid, so that we can
    release a reference to the stid without caring about the contents.

    Signed-off-by: Trond Myklebust
    Reviewed-by: Christoph Hellwig
    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Trond Myklebust
     

30 Jul, 2014

3 commits