cascardo/linux.git
9 years agonfsd: Protect session creation and client confirm using client_lock
Jeff Layton [Wed, 30 Jul 2014 12:27:07 +0000 (08:27 -0400)]
nfsd: Protect session creation and client confirm using client_lock

In particular, we want to ensure that the move_to_confirmed() is
protected by the nn->client_lock spin lock, so that we can use that when
looking up the clientid etc. instead of relying on the client_mutex.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Protect unconfirmed client creation using client_lock
Trond Myklebust [Wed, 30 Jul 2014 12:27:06 +0000 (08:27 -0400)]
nfsd: Protect unconfirmed client creation using client_lock

...instead of relying on the client_mutex.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Move create_client() call outside the lock
Trond Myklebust [Wed, 30 Jul 2014 12:27:05 +0000 (08:27 -0400)]
nfsd: Move create_client() call outside the lock

For efficiency reasons, and because we want to use spin locks instead
of relying on the client_mutex.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Don't require client_lock in free_client
Trond Myklebust [Wed, 30 Jul 2014 12:27:04 +0000 (08:27 -0400)]
nfsd: Don't require client_lock in free_client

The struct nfs_client is supposed to be invisible and unreferenced
before it gets here.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Ensure that the laundromat unhashes the client before releasing locks
Trond Myklebust [Wed, 30 Jul 2014 12:27:03 +0000 (08:27 -0400)]
nfsd: Ensure that the laundromat unhashes the client before releasing locks

If we leave the client on the confirmed/unconfirmed tables, and leave
the sessions visible on the sessionid_hashtbl, then someone might
find them before we've had a chance to destroy them.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Ensure struct nfs4_client is unhashed before we try to destroy it
Trond Myklebust [Wed, 30 Jul 2014 12:27:02 +0000 (08:27 -0400)]
nfsd: Ensure struct nfs4_client is unhashed before we try to destroy it

When we remove the client_mutex protection, we will need to ensure
that it can't be found by other threads while we're destroying it.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd4: fix out of date comment
J. Bruce Fields [Thu, 31 Jul 2014 20:10:08 +0000 (16:10 -0400)]
nfsd4: fix out of date comment

Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agoNFSD: Decrease nfsd_users in nfsd_startup_generic fail
Kinglong Mee [Wed, 30 Jul 2014 13:26:05 +0000 (21:26 +0800)]
NFSD: Decrease nfsd_users in nfsd_startup_generic fail

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 <kinglongmee@gmail.com>
Fixes: 4539f14981ce "nfsd: replace boolean nfsd_up flag by users counter"
Cc: stable@vger.kernel.org
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: rename unhash_generic_stateid to unhash_ol_stateid
Jeff Layton [Wed, 30 Jul 2014 01:34:43 +0000 (21:34 -0400)]
nfsd: rename unhash_generic_stateid to unhash_ol_stateid

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

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: don't thrash the cl_lock while freeing an open stateid
Jeff Layton [Wed, 30 Jul 2014 01:34:42 +0000 (21:34 -0400)]
nfsd: don't thrash the cl_lock while freeing an open stateid

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 <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: reduce cl_lock thrashing in release_openowner
Jeff Layton [Wed, 30 Jul 2014 01:34:41 +0000 (21:34 -0400)]
nfsd: reduce cl_lock thrashing in release_openowner

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 <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: close potential race in nfsd4_free_stateid
Jeff Layton [Wed, 30 Jul 2014 01:34:40 +0000 (21:34 -0400)]
nfsd: close potential race in nfsd4_free_stateid

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 <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: optimize destroy_lockowner cl_lock thrashing
Jeff Layton [Wed, 30 Jul 2014 01:34:39 +0000 (21:34 -0400)]
nfsd: optimize destroy_lockowner cl_lock thrashing

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 <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: add locking to stateowner release
Jeff Layton [Wed, 30 Jul 2014 01:34:38 +0000 (21:34 -0400)]
nfsd: add locking to stateowner release

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 <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: clean up and reorganize release_lockowner
Jeff Layton [Wed, 30 Jul 2014 01:34:37 +0000 (21:34 -0400)]
nfsd: clean up and reorganize release_lockowner

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 <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Move the open owner hash table into struct nfs4_client
Trond Myklebust [Wed, 30 Jul 2014 01:34:36 +0000 (21:34 -0400)]
nfsd: Move the open owner hash table into struct nfs4_client

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 <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Protect adding/removing lock owners using client_lock
Trond Myklebust [Wed, 30 Jul 2014 01:34:35 +0000 (21:34 -0400)]
nfsd: Protect adding/removing lock owners using client_lock

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 <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Protect adding/removing open state owners using client_lock
Trond Myklebust [Wed, 30 Jul 2014 01:34:34 +0000 (21:34 -0400)]
nfsd: Protect adding/removing open state owners using client_lock

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 <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: don't allow CLOSE to proceed until refcount on stateid drops
Jeff Layton [Wed, 30 Jul 2014 01:34:33 +0000 (21:34 -0400)]
nfsd: don't allow CLOSE to proceed until refcount on stateid drops

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 <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: make openstateids hold references to their openowners
Jeff Layton [Wed, 30 Jul 2014 01:34:32 +0000 (21:34 -0400)]
nfsd: make openstateids hold references to their openowners

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 <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: clean up refcounting for lockowners
Jeff Layton [Wed, 30 Jul 2014 01:34:31 +0000 (21:34 -0400)]
nfsd: clean up refcounting for lockowners

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 <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Make lock stateid take a reference to the lockowner
Trond Myklebust [Wed, 30 Jul 2014 01:34:30 +0000 (21:34 -0400)]
nfsd: Make lock stateid take a reference to the lockowner

A necessary step toward client_mutex removal.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: add an operation for unhashing a stateowner
Jeff Layton [Wed, 30 Jul 2014 01:34:29 +0000 (21:34 -0400)]
nfsd: add an operation for unhashing a stateowner

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 <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: clean up lockowner refcounting when finding them
Jeff Layton [Wed, 30 Jul 2014 01:34:28 +0000 (21:34 -0400)]
nfsd: clean up lockowner refcounting when finding them

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 <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Add a mutex to protect the NFSv4.0 open owner replay cache
Jeff Layton [Wed, 30 Jul 2014 01:34:27 +0000 (21:34 -0400)]
nfsd: Add a mutex to protect the NFSv4.0 open owner replay cache

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 <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Add reference counting to state owners
Jeff Layton [Wed, 30 Jul 2014 01:34:26 +0000 (21:34 -0400)]
nfsd: Add reference counting to state owners

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 <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Migrate the stateid reference into nfs4_find_stateid_by_type()
Trond Myklebust [Wed, 30 Jul 2014 01:34:25 +0000 (21:34 -0400)]
nfsd: Migrate the stateid reference into nfs4_find_stateid_by_type()

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 <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Migrate the stateid reference into nfs4_lookup_stateid()
Trond Myklebust [Wed, 30 Jul 2014 01:34:24 +0000 (21:34 -0400)]
nfsd: Migrate the stateid reference into nfs4_lookup_stateid()

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

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Migrate the stateid reference into nfs4_preprocess_seqid_op
Trond Myklebust [Wed, 30 Jul 2014 01:34:23 +0000 (21:34 -0400)]
nfsd: Migrate the stateid reference into nfs4_preprocess_seqid_op

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

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Add reference counting to nfs4_preprocess_confirmed_seqid_op
Trond Myklebust [Wed, 30 Jul 2014 01:34:22 +0000 (21:34 -0400)]
nfsd: Add reference counting to nfs4_preprocess_confirmed_seqid_op

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

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: nfsd4_open_confirm() must reference the open stateid
Trond Myklebust [Wed, 30 Jul 2014 01:34:21 +0000 (21:34 -0400)]
nfsd: nfsd4_open_confirm() must reference the open stateid

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 <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Prepare nfsd4_close() for open stateid referencing
Trond Myklebust [Wed, 30 Jul 2014 01:34:20 +0000 (21:34 -0400)]
nfsd: Prepare nfsd4_close() for open stateid referencing

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 <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: nfsd4_process_open2() must reference the open stateid
Trond Myklebust [Wed, 30 Jul 2014 01:34:19 +0000 (21:34 -0400)]
nfsd: nfsd4_process_open2() must reference the open stateid

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 <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: nfsd4_process_open2() must reference the delegation stateid
Trond Myklebust [Wed, 30 Jul 2014 01:34:18 +0000 (21:34 -0400)]
nfsd: nfsd4_process_open2() must reference the delegation stateid

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 <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Ensure that nfs4_open_delegation() references the delegation stateid
Trond Myklebust [Wed, 30 Jul 2014 01:34:17 +0000 (21:34 -0400)]
nfsd: Ensure that nfs4_open_delegation() references the delegation stateid

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 <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: nfsd4_locku() must reference the lock stateid
Trond Myklebust [Wed, 30 Jul 2014 01:34:16 +0000 (21:34 -0400)]
nfsd: nfsd4_locku() must reference the lock stateid

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 <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Add reference counting to lock stateids
Trond Myklebust [Wed, 30 Jul 2014 01:34:15 +0000 (21:34 -0400)]
nfsd: Add reference counting to lock stateids

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 <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: ensure atomicity in nfsd4_free_stateid and nfsd4_validate_stateid
Jeff Layton [Wed, 30 Jul 2014 01:34:14 +0000 (21:34 -0400)]
nfsd: ensure atomicity in nfsd4_free_stateid and nfsd4_validate_stateid

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 <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: clean up races in lock stateid searching and creation
Jeff Layton [Wed, 30 Jul 2014 01:34:13 +0000 (21:34 -0400)]
nfsd: clean up races in lock stateid searching and creation

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 <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Add locking to protect the state owner lists
Jeff Layton [Wed, 30 Jul 2014 01:34:12 +0000 (21:34 -0400)]
nfsd: Add locking to protect the state owner lists

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 <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: do filp_close in sc_free callback for lock stateids
Jeff Layton [Wed, 30 Jul 2014 01:34:11 +0000 (21:34 -0400)]
nfsd: do filp_close in sc_free callback for lock stateids

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 <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd4: use cl_lock to synchronize all stateid idr calls
Jeff Layton [Wed, 30 Jul 2014 01:34:10 +0000 (21:34 -0400)]
nfsd4: use cl_lock to synchronize all stateid idr calls

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 <trond.myklebust@primarydata.com>
Signed-off-by: Benny Halevy <bhalevy@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Add a struct nfs4_file field to struct nfs4_stid
Trond Myklebust [Wed, 30 Jul 2014 01:34:08 +0000 (21:34 -0400)]
nfsd: Add a struct nfs4_file field to struct nfs4_stid

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 <trond.myklebust@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Add reference counting to the lock and open stateids
Trond Myklebust [Wed, 30 Jul 2014 01:34:06 +0000 (21:34 -0400)]
nfsd: Add reference counting to the lock and open stateids

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 <trond.myklebust@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: print status when nfsd4_open fails to open file it just created
Jeff Layton [Wed, 30 Jul 2014 01:37:44 +0000 (21:37 -0400)]
nfsd: print status when nfsd4_open fails to open file it just created

It's possible for nfsd to fail opening a file that it has just created.
When that happens, we throw a WARN but it doesn't include any info about
the error code. Print the status code to give us a bit more info.

Our QA group hit some of these warnings under some very heavy stress
testing. My suspicion is that they hit the file-max limit, but it's hard
to know for sure. Go ahead and add a -ENFILE mapping to
nfserr_serverfault to make the error more distinct (and correct).

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agoSUNRPC: Allow svc_reserve() to notify TCP socket that space has been freed
Trond Myklebust [Fri, 25 Jul 2014 03:59:33 +0000 (23:59 -0400)]
SUNRPC: Allow svc_reserve() to notify TCP socket that space has been freed

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agoSUNRPC: svc_tcp_write_space: don't clear SOCK_NOSPACE prematurely
Trond Myklebust [Fri, 25 Jul 2014 03:59:32 +0000 (23:59 -0400)]
SUNRPC: svc_tcp_write_space: don't clear SOCK_NOSPACE prematurely

If requests are queued in the socket inbuffer waiting for an
svc_tcp_has_wspace() requirement to be satisfied, then we do not want
to clear the SOCK_NOSPACE flag until we've satisfied that requirement.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agoSUNRPC: Reduce contention in svc_xprt_enqueue()
Trond Myklebust [Fri, 25 Jul 2014 03:59:31 +0000 (23:59 -0400)]
SUNRPC: Reduce contention in svc_xprt_enqueue()

Ensure that all calls to svc_xprt_enqueue() except svc_xprt_received()
check the value of XPT_BUSY, before attempting to grab spinlocks etc.
This is to avoid situations such as the following "perf" trace,
which shows heavy contention on the pool spinlock:

    54.15%            nfsd  [kernel.kallsyms]        [k] _raw_spin_lock_bh
                      |
                      --- _raw_spin_lock_bh
                         |
                         |--71.43%-- svc_xprt_enqueue
                         |          |
                         |          |--50.31%-- svc_reserve
                         |          |
                         |          |--31.35%-- svc_xprt_received
                         |          |
                         |          |--18.34%-- svc_tcp_data_ready
...

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: remove dl_fh field from struct nfs4_delegation
Jeff Layton [Fri, 25 Jul 2014 11:34:27 +0000 (07:34 -0400)]
nfsd: remove dl_fh field from struct nfs4_delegation

Now that the nfs4_file has a filehandle in it, we no longer need to
keep a per-delegation copy of it. Switch to using the one in the
nfs4_file instead.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: give block_delegation and delegation_blocked its own spinlock
Jeff Layton [Fri, 25 Jul 2014 11:34:26 +0000 (07:34 -0400)]
nfsd: give block_delegation and delegation_blocked its own spinlock

The state lock can be fairly heavily contended, and there's no reason
that nfs4_file lookups and delegation_blocked should be mutually
exclusive.  Let's give the new block_delegation code its own spinlock.
It does mean that we'll need to take a different lock in the delegation
break code, but that's not generally as critical to performance.

Cc: Neil Brown <neilb@suse.de>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: clean up nfs4_set_delegation
Jeff Layton [Fri, 25 Jul 2014 11:34:25 +0000 (07:34 -0400)]
nfsd: clean up nfs4_set_delegation

Move the alloc_init_deleg call into nfs4_set_delegation and change the
function to return a pointer to the delegation or an IS_ERR return. This
allows us to skip allocating a delegation if the file has already
experienced a lease conflict.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: clean up arguments to nfs4_open_delegation
Jeff Layton [Fri, 25 Jul 2014 11:34:24 +0000 (07:34 -0400)]
nfsd: clean up arguments to nfs4_open_delegation

No need to pass in a net pointer since we can derive that.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: drop unused stp arg to alloc_init_deleg
Jeff Layton [Fri, 25 Jul 2014 11:34:23 +0000 (07:34 -0400)]
nfsd: drop unused stp arg to alloc_init_deleg

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Convert delegation counter to an atomic_long_t type
Trond Myklebust [Fri, 25 Jul 2014 11:34:22 +0000 (07:34 -0400)]
nfsd: Convert delegation counter to an atomic_long_t type

We want to convert to an atomic type so that we don't need to lock
across the call to alloc_init_deleg(). Then convert to a long type so
that we match the size of 'max_delegations'.

None of this is a problem today, but it will be once we remove
client_mutex protection.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: ensure that clp->cl_revoked list is protected by clp->cl_lock
Jeff Layton [Fri, 25 Jul 2014 11:34:21 +0000 (07:34 -0400)]
nfsd: ensure that clp->cl_revoked list is protected by clp->cl_lock

Currently, both destroy_revoked_delegation and revoke_delegation
manipulate the cl_revoked list without any locking aside from the
client_mutex. Ensure that the clp->cl_lock is held when manipulating it,
except for the list walking in destroy_client. At that point, the client
should no longer be in use, and so it should be safe to walk the list
without any locking. That also means that we don't need to do the
list_splice_init there either.

Also, the fact that revoke_delegation deletes dl_recall_lru list_head
without any locking makes it difficult to know whether it's doing so
safely in all cases. Move the list_del_init calls into the callers, and
add a WARN_ON in the event that t's passed a delegation that has a
non-empty list_head.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: fully unhash delegations when revoking them
Jeff Layton [Fri, 25 Jul 2014 11:34:20 +0000 (07:34 -0400)]
nfsd: fully unhash delegations when revoking them

Ensure that the delegations cannot be found by the laundromat etc once
we add them to the various 'revoke' lists.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: simplify stateid allocation and file handling
Trond Myklebust [Fri, 25 Jul 2014 11:34:19 +0000 (07:34 -0400)]
nfsd: simplify stateid allocation and file handling

Don't allow stateids to clear the open file pointer until they are
being destroyed. In a later patches we'll want to rely on the fact that
we have a valid file pointer when dealing with the stateid and this
will save us from having to do a lot of NULL pointer checks before
doing so.

Also, move to allocating stateids with kzalloc and get rid of the
explicit zeroing of fields.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Do not let nfs4_file pin the struct inode
Jeff Layton [Wed, 23 Jul 2014 20:17:41 +0000 (16:17 -0400)]
nfsd: Do not let nfs4_file pin the struct inode

Remove the fi_inode field in struct nfs4_file in order to remove the
possibility of struct nfs4_file pinning the inode when it does not have
any open state.

The only place we still need to get to an inode is in check_for_locks,
so change it to use find_any_file and use the inode from any that it
finds. If it doesn't find one, then just assume there aren't any.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: nfs4_check_fh - make it actually check the filehandle
Trond Myklebust [Wed, 23 Jul 2014 20:17:40 +0000 (16:17 -0400)]
nfsd: nfs4_check_fh - make it actually check the filehandle

...instead of just checking the inode that corresponds to it.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Use the filehandle to look up the struct nfs4_file instead of inode
Trond Myklebust [Wed, 23 Jul 2014 20:17:39 +0000 (16:17 -0400)]
nfsd: Use the filehandle to look up the struct nfs4_file instead of inode

This makes more sense anyway since an inode pointer value can change
even when the filehandle doesn't.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Store the filehandle with the struct nfs4_file
Trond Myklebust [Wed, 23 Jul 2014 20:17:38 +0000 (16:17 -0400)]
nfsd: Store the filehandle with the struct nfs4_file

For use when we may not have a struct inode.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd4: convert comma to semicolon
Himangi Saraogi [Wed, 23 Jul 2014 14:42:31 +0000 (20:12 +0530)]
nfsd4: convert comma to semicolon

Replace a comma between expression statements by a semicolon. This changes
the semantics of the code, but given the current indentation appears to be
what is intended.

A simplified version of the Coccinelle semantic patch that performs this
transformation is as follows:
// <smpl>
@r@
expression e1,e2;
@@

 e1
-,
+;
 e2;
// </smpl>

Signed-off-by: Himangi Saraogi <himangi774@gmail.com>
Acked-by: Julia Lawall <julia.lawall@lip6.fr>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agosvcrdma: Double the default credit limit
Chuck Lever [Tue, 22 Jul 2014 21:48:04 +0000 (17:48 -0400)]
svcrdma: Double the default credit limit

The RDMA credit limit controls how many concurrent RPCs are allowed
per connection.

An NFS/RDMA client and server exchange their credit limits in the
RPC/RDMA headers. The Linux client and the Solaris client and server
allow 32 credits. The Linux server allows only 16, which limits its
performance.

Set the server's default credit limit to 32, like the other well-
known implementations, so the out-of-the-shrinkwrap performance of
the Linux server is better.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: ensure that st_access_bmap and st_deny_bmap are initialized to 0
Jeff Layton [Wed, 23 Jul 2014 17:46:49 +0000 (13:46 -0400)]
nfsd: ensure that st_access_bmap and st_deny_bmap are initialized to 0

Open stateids must be initialized with the st_access_bmap and
st_deny_bmap set to 0, so that nfs4_get_vfs_file can properly record
their state in old_access_bmap and old_deny_bmap.

This bug was introduced in commit baeb4ff0e502 (nfsd: make deny mode
enforcement more efficient and close races in it) and was causing the
refcounts to end up incorrect when nfs4_get_vfs_file returned an error
after bumping the refcounts. This made it impossible to unmount the
underlying filesystem after running pynfs tests that involve deny modes.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agosvcrdma: Add zero padding if the client doesn't send it
Chuck Lever [Tue, 22 Jul 2014 20:00:40 +0000 (16:00 -0400)]
svcrdma: Add zero padding if the client doesn't send it

See RFC 5666 section 3.7: clients don't have to send zero XDR
padding.

BugLink: https://bugzilla.linux-nfs.org/show_bug.cgi?id=246
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: bump dl_time when unhashing delegation
Jeff Layton [Tue, 22 Jul 2014 17:52:06 +0000 (13:52 -0400)]
nfsd: bump dl_time when unhashing delegation

There's a potential race between a lease break and DELEGRETURN call.

Suppose a lease break comes in and queues the workqueue job for a
delegation, but it doesn't run just yet. Then, a DELEGRETURN comes in
finds the delegation and calls destroy_delegation on it to unhash it and
put its primary reference.

Next, the workqueue job runs and queues the delegation back onto the
del_recall_lru list, issues the CB_RECALL and puts the final reference.
With that, the final reference to the delegation is put, but it's still
on the LRU list.

When we go to unhash a delegation, it's because we intend to get rid of
it soon afterward, so we don't want lease breaks to mess with it once
that occurs. Fix this by bumping the dl_time whenever we unhash a
delegation, to ensure that lease breaks don't monkey with it.

I believe this is a regression due to commit 02e1215f9f7 (nfsd: Avoid
taking state_lock while holding inode lock in nfsd_break_one_deleg).
Prior to that, the state_lock was held in the lm_break callback itself,
and that would have prevented this race.

Cc: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Move the delegation reference counter into the struct nfs4_stid
Trond Myklebust [Mon, 21 Jul 2014 13:34:58 +0000 (09:34 -0400)]
nfsd: Move the delegation reference counter into the struct nfs4_stid

We will want to add reference counting to the lock stateid and open
stateids too in later patches.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: fix race that grants unrecallable delegation
Jeff Layton [Mon, 21 Jul 2014 13:34:57 +0000 (09:34 -0400)]
nfsd: fix race that grants unrecallable delegation

If nfs4_setlease succesfully acquires a new delegation, then another
task breaks the delegation before we reach hash_delegation_locked, then
the breaking task will see an empty fi_delegations list and do nothing.
The client will receive an open reply incorrectly granting a delegation
and will never receive a recall.

Move more of the delegation fields to be protected by the fi_lock. It's
more granular than the state_lock and in later patches we'll want to
be able to rely on it in addition to the state_lock.

Attempt to acquire a delegation. If that succeeds, take the spinlocks
and then check to see if the file has had a conflict show up since then.
If it has, then we assume that the lease is no longer valid and that
we shouldn't hand out a delegation.

There's also one more potential (but very unlikely) problem. If the
lease is broken before the delegation is hashed, then it could leak.
In the event that the fi_delegations list is empty, reset the
fl_break_time to jiffies so that it's cleaned up ASAP by
the normal lease handling code.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd4: CREATE_SESSION should update backchannel immediately
J. Bruce Fields [Fri, 18 Jul 2014 19:06:47 +0000 (15:06 -0400)]
nfsd4: CREATE_SESSION should update backchannel immediately

nfsd4_probe_callback kicks off some work that will eventually run
nfsd4_process_cb_update and update the session flags.  In theory we
could process a following SEQUENCE call before that update happens
resulting in flags that don't accurately represent, for example, the
lack of a backchannel.

Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agoSUNRPC: xdr_get_next_encode_buffer should be declared static
Trond Myklebust [Sat, 12 Jul 2014 22:01:02 +0000 (18:01 -0400)]
SUNRPC: xdr_get_next_encode_buffer should be declared static

Quell another sparse warning.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agosvcrdma: Select NFSv4.1 backchannel transport based on forward channel
Chuck Lever [Wed, 16 Jul 2014 19:38:32 +0000 (15:38 -0400)]
svcrdma: Select NFSv4.1 backchannel transport based on forward channel

The current code always selects XPRT_TRANSPORT_BC_TCP for the back
channel, even when the forward channel was not TCP (eg, RDMA). When
a 4.1 mount is attempted with RDMA, the server panics in the TCP BC
code when trying to send CB_NULL.

Instead, construct the transport protocol number from the forward
channel transport or'd with XPRT_TRANSPORT_BC. Transports that do
not support bi-directional RPC will not have registered a "BC"
transport, causing create_backchannel_client() to fail immediately.

Fixes: https://bugzilla.linux-nfs.org/show_bug.cgi?id=265
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd4: zero op arguments beyond the 8th compound op
J. Bruce Fields [Thu, 17 Jul 2014 20:20:39 +0000 (16:20 -0400)]
nfsd4: zero op arguments beyond the 8th compound op

The first 8 ops of the compound are zeroed since they're a part of the
argument that's zeroed by the

memset(rqstp->rq_argp, 0, procp->pc_argsize);

in svc_process_common().  But we handle larger compounds by allocating
the memory on the fly in nfsd4_decode_compound().  Other than code
recently fixed by 01529e3f8179 "NFSD: Fix memory leak in encoding denied
lock", I don't know of any examples of code depending on this
initialization. But it definitely seems possible, and I'd rather be
safe.

Compounds this long are unusual so I'm much more worried about failure
in this poorly tested cases than about an insignificant performance hit.

Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: silence sparse warning about accessing credentials
Jeff Layton [Tue, 15 Jul 2014 16:59:36 +0000 (12:59 -0400)]
nfsd: silence sparse warning about accessing credentials

sparse says:

    fs/nfsd/auth.c:31:38: warning: incorrect type in argument 1 (different address spaces)
    fs/nfsd/auth.c:31:38:    expected struct cred const *cred
    fs/nfsd/auth.c:31:38:    got struct cred const [noderef] <asn:4>*real_cred

Add a new accessor for the ->real_cred and use that to fetch the
pointer. Accessing current->real_cred directly is actually quite safe
since we know that they can't go away so this is mostly a cosmetic fixup
to silence sparse.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Ensure stateids remain unique until they are freed
Trond Myklebust [Wed, 16 Jul 2014 14:31:59 +0000 (10:31 -0400)]
nfsd: Ensure stateids remain unique until they are freed

Add an extra delegation state to allow the stateid to remain in the idr
tree until the last reference has been released. This will be necessary
to ensure uniqueness once the client_mutex is removed.

[jlayton: reset the sc_type under the state_lock in unhash_delegation]

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: nfs4_alloc_init_lease should take a nfs4_file arg
Jeff Layton [Wed, 16 Jul 2014 14:31:58 +0000 (10:31 -0400)]
nfsd: nfs4_alloc_init_lease should take a nfs4_file arg

No need to pass the delegation pointer in here as it's only used to get
the nfs4_file pointer.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Avoid taking state_lock while holding inode lock in nfsd_break_one_deleg
Jeff Layton [Wed, 16 Jul 2014 14:31:57 +0000 (10:31 -0400)]
nfsd: Avoid taking state_lock while holding inode lock in nfsd_break_one_deleg

state_lock is a heavily contended global lock. We don't want to grab
that while simultaneously holding the inode->i_lock.

Add a new per-nfs4_file lock that we can use to protect the
per-nfs4_file delegation list. Hold that while walking the list in the
break_deleg callback and queue the workqueue job for each one.

The workqueue job can then take the state_lock and do the list
manipulations without the i_lock being held prior to starting the
rpc call.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: eliminate nfsd4_init_callback
Jeff Layton [Wed, 16 Jul 2014 14:31:56 +0000 (10:31 -0400)]
nfsd: eliminate nfsd4_init_callback

It's just an obfuscated INIT_WORK call. Just make the work_func_t a
non-static symbol and use a normal INIT_WORK call.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agoNFSD: Fix bad checking of space for padding in splice read
Kinglong Mee [Wed, 9 Jul 2014 13:51:27 +0000 (21:51 +0800)]
NFSD: Fix bad checking of space for padding in splice read

Note that the caller has already reserved space for count and eof, so
xdr->p has already moved past them, only the padding remains.

Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
Fixes dc97618ddd (nfsd4: separate splice and readv cases)
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agoNFSD: Check acl returned from get_acl/posix_acl_from_mode
Kinglong Mee [Wed, 9 Jul 2014 13:54:16 +0000 (21:54 +0800)]
NFSD: Check acl returned from get_acl/posix_acl_from_mode

Commit 4ac7249ea5 (nfsd: use get_acl and ->set_acl)
don't check the acl returned from get_acl()/posix_acl_from_mode().

Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agosvcrdma: send_write() must not overflow the device's max sge
Steve Wise [Wed, 9 Jul 2014 18:49:15 +0000 (13:49 -0500)]
svcrdma: send_write() must not overflow the device's max sge

Function send_write() must stop creating sges when it reaches the device
max and return the amount sent in the RDMA Write to the caller.

Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: cleanup and rename nfs4_check_open
Jeff Layton [Thu, 10 Jul 2014 18:07:35 +0000 (14:07 -0400)]
nfsd: cleanup and rename nfs4_check_open

Rename it to better describe what it does, and have it just return the
stateid instead of a __be32 (which is now always nfs_ok). Also, do the
search for an existing stateid after the delegation check, to reduce
cleanup if the delegation check returns error.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: make deny mode enforcement more efficient and close races in it
Jeff Layton [Thu, 10 Jul 2014 18:07:34 +0000 (14:07 -0400)]
nfsd: make deny mode enforcement more efficient and close races in it

The current enforcement of deny modes is both inefficient and scattered
across several places, which makes it hard to guarantee atomicity. The
inefficiency is a problem now, and the lack of atomicity will mean races
once the client_mutex is removed.

First, we address the inefficiency. We have to track deny modes on a
per-stateid basis to ensure that open downgrades are sane, but when the
server goes to enforce them it has to walk the entire list of stateids
and check against each one.

Instead of doing that, maintain a per-nfs4_file deny mode. When a file
is opened, we simply set any deny bits in that mode that were specified
in the OPEN call. We can then use that unified deny mode to do a simple
check to see whether there are any conflicts without needing to walk the
entire stateid list.

The only time we'll need to walk the entire list of stateids is when a
stateid that has a deny mode on it is being released, or one is having
its deny mode downgraded. In that case, we must walk the entire list and
recalculate the fi_share_deny field. Since deny modes are pretty rare
today, this should be very rare under normal workloads.

To address the potential for races once the client_mutex is removed,
protect fi_share_deny with the fi_lock. In nfs4_get_vfs_file, check to
make sure that any deny mode we want to apply won't conflict with
existing access. If that's ok, then have nfs4_file_get_access check that
new access to the file won't conflict with existing deny modes.

If that also passes, then get file access references, set the correct
access and deny bits in the stateid, and update the fi_share_deny field.
If opening the file or truncating it fails, then unwind the whole mess
and return the appropriate error.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: always hold the fi_lock when bumping fi_access refcounts
Jeff Layton [Thu, 10 Jul 2014 18:07:33 +0000 (14:07 -0400)]
nfsd: always hold the fi_lock when bumping fi_access refcounts

Once we remove the client_mutex, there's an unlikely but possible race
that could occur. It will be possible for nfs4_file_put_access to race
with nfs4_file_get_access. The refcount will go to zero (briefly) and
then bumped back to one. If that happens we set ourselves up for a
use-after-free and the potential for a lock to race onto the i_flock
list as a filp is being torn down.

Ensure that we can safely bump the refcount on the file by holding the
fi_lock whenever that's done. The only place it currently isn't is in
get_lock_access.

In order to ensure atomicity with finding the file, use the
find_*_file_locked variants and then call get_lock_access to get new
access references on the nfs4_file under the same lock.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: clean up reset_union_bmap_deny
Jeff Layton [Thu, 10 Jul 2014 18:07:32 +0000 (14:07 -0400)]
nfsd: clean up reset_union_bmap_deny

Fix the "deny" argument type, and start the loop at 1. The 0 iteration
is always a noop.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: set stateid access and deny bits in nfs4_get_vfs_file
Jeff Layton [Thu, 10 Jul 2014 18:07:31 +0000 (14:07 -0400)]
nfsd: set stateid access and deny bits in nfs4_get_vfs_file

Cleanup -- ensure that the stateid bits are set at the same time that
the file access refcounts are incremented. Keeping them coherent like
this makes it easier to ensure that we account for all of the
references.

Since the initialization of the st_*_bmap fields is done when it's
hashed, we go ahead and hash the stateid before getting access to the
file and unhash it if that function returns error. This will be
necessary anyway in a follow-on patch that will overhaul deny mode
handling.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: shrink st_access_bmap and st_deny_bmap
Jeff Layton [Thu, 10 Jul 2014 18:07:30 +0000 (14:07 -0400)]
nfsd: shrink st_access_bmap and st_deny_bmap

We never use anything above bit #3, so an unsigned long for each is
wasteful. Shrink them to a char each, and add some WARN_ON_ONCE calls if
we try to set or clear bits that would go outside those sizes.

Note too that because atomic bitops work on unsigned longs, we have to
abandon their use here. That shouldn't be a problem though since we
don't really care about the atomicity in this code anyway. Using them
was just a convenient way to flip bits.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: remove nfs4_file_put_fd
Jeff Layton [Thu, 10 Jul 2014 18:07:29 +0000 (14:07 -0400)]
nfsd: remove nfs4_file_put_fd

...and replace it with a simple swap call.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: refactor nfs4_file_get_access and nfs4_file_put_access
Jeff Layton [Thu, 10 Jul 2014 18:07:28 +0000 (14:07 -0400)]
nfsd: refactor nfs4_file_get_access and nfs4_file_put_access

Have them take NFS4_SHARE_ACCESS_* flags instead of an open mode. This
spares the callers from having to convert it themselves.

This also allows us to simplify these functions as we no longer need
to do the access_to_omode conversion in either one.

Note too that this patch eliminates the WARN_ON in
__nfs4_file_get_access. It's valid for now, but in a later patch we'll
be bumping the refcounts prior to opening the file in order to close
some races, at which point we'll need to remove it anyway.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: clean up helper __release_lock_stateid
Trond Myklebust [Thu, 10 Jul 2014 18:07:27 +0000 (14:07 -0400)]
nfsd: clean up helper __release_lock_stateid

Use filp_close instead of open coding. filp_close does a bit more than
just release the locks and put the filp. It also calls ->flush and
dnotify_flush, both of which should be done here anyway.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Add locking to the nfs4_file->fi_fds[] array
Trond Myklebust [Thu, 10 Jul 2014 18:07:26 +0000 (14:07 -0400)]
nfsd: Add locking to the nfs4_file->fi_fds[] array

Preparation for removal of the client_mutex, which currently protects
this array. While we don't actually need the find_*_file_locked variants
just yet, a later patch will. So go ahead and add them now to reduce
future churn in this code.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Add fine grained protection for the nfs4_file->fi_stateids list
Trond Myklebust [Thu, 10 Jul 2014 18:07:25 +0000 (14:07 -0400)]
nfsd: Add fine grained protection for the nfs4_file->fi_stateids list

Access to this list is currently serialized by the client_mutex. Add
finer grained locking around this list in preparation for its removal.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: reduce some spinlocking in put_client_renew
Jeff Layton [Tue, 8 Jul 2014 18:02:50 +0000 (14:02 -0400)]
nfsd: reduce some spinlocking in put_client_renew

No need to take the lock unless the count goes to 0.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: close potential race between delegation break and laundromat
Jeff Layton [Tue, 8 Jul 2014 18:02:49 +0000 (14:02 -0400)]
nfsd: close potential race between delegation break and laundromat

Bruce says:

    There's also a preexisting expire_client/laundromat vs break race:

    - expire_client/laundromat adds a delegation to its local
      reaplist using the same dl_recall_lru field that a delegation
      uses to track its position on the recall lru and drops the
      state lock.

    - a concurrent break_lease adds the delegation to the lru.

    - expire/client/laundromat then walks it reaplist and sees the
      lru head as just another delegation on the list....

Fix this race by checking the dl_time under the state_lock. If we find
that it's not 0, then we know that it has already been queued to the LRU
list and that we shouldn't queue it again.

In the case of destroy_client, we must also ensure that we don't hit
similar races by ensuring that we don't move any delegations to the
reaplist with a dl_time of 0. Just bump the dl_time by one before we
drop the state_lock. We're destroying the delegations anyway, so a 1s
difference there won't matter.

The fault injection code also requires a bit of surgery here:

First, in the case of nfsd_forget_client_delegations, we must prevent
the same sort of race vs. the delegation break callback. For that, we
just increment the dl_time to ensure that a delegation callback can't
race in while we're working on it.

We can't do that for nfsd_recall_client_delegations, as we need to have
it actually queue the delegation, and that won't happen if we increment
the dl_time. The state lock is held over that function, so we don't need
to worry about these sorts of races there.

There is one other potential bug nfsd_recall_client_delegations though.
Entries on the victims list are not dequeued before calling
nfsd_break_one_deleg. That's a potential list corruptor, so ensure that
we do that there.

Reported-by: "J. Bruce Fields" <bfields@fieldses.org>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agoNFSD: Fix memory leak in encoding denied lock
Kinglong Mee [Mon, 7 Jul 2014 14:10:56 +0000 (22:10 +0800)]
NFSD: Fix memory leak in encoding denied lock

Commit 8c7424cff6 (nfsd4: don't try to encode conflicting owner if low on space)
forgot free conf->data in nfsd4_encode_lockt and before sign conf->data to NULL
in nfsd4_encode_lock_denied.

Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Convert nfs4_check_open_reclaim() to work with lookup_clientid()
Trond Myklebust [Mon, 30 Jun 2014 15:48:47 +0000 (11:48 -0400)]
nfsd: Convert nfs4_check_open_reclaim() to work with lookup_clientid()

lookup_clientid is preferable to find_confirmed_client since it's able
to use the cached client in the compound state.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Always use lookup_clientid() in nfsd4_process_open1
Trond Myklebust [Mon, 30 Jun 2014 15:48:46 +0000 (11:48 -0400)]
nfsd: Always use lookup_clientid() in nfsd4_process_open1

In later patches, we'll be moving the stateowner table into the
nfs4_client, and by doing this we ensure that we have a cached
nfs4_client pointer.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Convert nfsd4_process_open1() to work with lookup_clientid()
Trond Myklebust [Mon, 30 Jun 2014 15:48:45 +0000 (11:48 -0400)]
nfsd: Convert nfsd4_process_open1() to work with lookup_clientid()

...and have alloc_init_open_stateowner just use the cstate->clp pointer
instead of passing in a clp separately. This allows us to use the
cached nfs4_client pointer in the cstate instead of having to look it
up again.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: Allow struct nfsd4_compound_state to cache the nfs4_client
Jeff Layton [Mon, 30 Jun 2014 15:48:44 +0000 (11:48 -0400)]
nfsd: Allow struct nfsd4_compound_state to cache the nfs4_client

We want to use the nfsd4_compound_state to cache the nfs4_client in
order to optimise away extra lookups of the clid.

In the v4.0 case, we use this to ensure that we only have to look up the
client at most once per compound for each call into lookup_clientid. For
v4.1+ we set the pointer in the cstate during SEQUENCE processing so we
should never need to do a search for it.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: add a nfserrno mapping for -E2BIG to nfserr_fbig
Jeff Layton [Thu, 3 Jul 2014 19:15:54 +0000 (15:15 -0400)]
nfsd: add a nfserrno mapping for -E2BIG to nfserr_fbig

I saw this pop up with some pynfs testing:

    [  123.609992] nfsd: non-standard errno: -7

...and -7 is -E2BIG. I think what happened is that XFS returned -E2BIG
due to some xattr operations with the ACL10 pynfs TEST (I guess it has
limited xattr size?).

Add a better mapping for that error since it's possible that we'll need
it. How about we convert it to NFSERR_FBIG? As Bruce points out, they
both have "BIG" in the name so it must be good.

Also, turn the printk in this function into a WARN() so that we can get
a bit more information about situations that don't have proper mappings.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
9 years agonfsd: properly convert return from commit_metadata to __be32
Jeff Layton [Thu, 3 Jul 2014 11:54:19 +0000 (07:54 -0400)]
nfsd: properly convert return from commit_metadata to __be32

Commit 2a7420c03e504 (nfsd: Ensure that nfsd_create_setattr commits
files to stable storage), added a couple of calls to commit_metadata,
but doesn't convert their return codes to __be32 in the appropriate
places.

Cc: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>