--- /dev/null
+From 149a4fddd0a72d526abbeac0c8deaab03559836a Mon Sep 17 00:00:00 2001
+From: Benjamin Coddington <bcodding@redhat.com>
+Date: Mon, 18 Jul 2016 10:41:57 -0400
+Subject: nfs: don't create zero-length requests
+
+From: Benjamin Coddington <bcodding@redhat.com>
+
+commit 149a4fddd0a72d526abbeac0c8deaab03559836a upstream.
+
+NFS doesn't expect requests with wb_bytes set to zero and may make
+unexpected decisions about how to handle that request at the page IO layer.
+Skip request creation if we won't have any wb_bytes in the request.
+
+Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
+Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
+Reviewed-by: Weston Andros Adamson <dros@primarydata.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/write.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/fs/nfs/write.c
++++ b/fs/nfs/write.c
+@@ -1261,6 +1261,9 @@ int nfs_updatepage(struct file *file, st
+ dprintk("NFS: nfs_updatepage(%pD2 %d@%lld)\n",
+ file, count, (long long)(page_file_offset(page) + offset));
+
++ if (!count)
++ goto out;
++
+ if (nfs_can_extend_write(file, page, inode)) {
+ count = max(count + offset, nfs_page_length(page));
+ offset = 0;
+@@ -1271,7 +1274,7 @@ int nfs_updatepage(struct file *file, st
+ nfs_set_pageerror(page);
+ else
+ __set_page_dirty_nobuffers(page);
+-
++out:
+ dprintk("NFS: nfs_updatepage returns %d (isize %lld)\n",
+ status, (long long)i_size_read(inode));
+ return status;
--- /dev/null
+From dd257933fa4b9fea66a1195f8a15111029810abc Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@redhat.com>
+Date: Thu, 11 Aug 2016 10:37:39 -0400
+Subject: nfsd: don't return an unhashed lock stateid after taking mutex
+
+From: Jeff Layton <jlayton@redhat.com>
+
+commit dd257933fa4b9fea66a1195f8a15111029810abc upstream.
+
+nfsd4_lock will take the st_mutex before working with the stateid it
+gets, but between the time when we drop the cl_lock and take the mutex,
+the stateid could become unhashed (a'la FREE_STATEID). If that happens
+the lock stateid returned to the client will be forgotten.
+
+Fix this by first moving the st_mutex acquisition into
+lookup_or_create_lock_state. Then, have it check to see if the lock
+stateid is still hashed after taking the mutex. If it's not, then put
+the stateid and try the find/create again.
+
+Signed-off-by: Jeff Layton <jlayton@redhat.com>
+Tested-by: Alexey Kodanev <alexey.kodanev@oracle.com>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfsd/nfs4state.c | 25 ++++++++++++++++++++-----
+ 1 file changed, 20 insertions(+), 5 deletions(-)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -5502,7 +5502,7 @@ static __be32
+ lookup_or_create_lock_state(struct nfsd4_compound_state *cstate,
+ struct nfs4_ol_stateid *ost,
+ struct nfsd4_lock *lock,
+- struct nfs4_ol_stateid **lst, bool *new)
++ struct nfs4_ol_stateid **plst, bool *new)
+ {
+ __be32 status;
+ struct nfs4_file *fi = ost->st_stid.sc_file;
+@@ -5510,7 +5510,9 @@ lookup_or_create_lock_state(struct nfsd4
+ struct nfs4_client *cl = oo->oo_owner.so_client;
+ struct inode *inode = d_inode(cstate->current_fh.fh_dentry);
+ struct nfs4_lockowner *lo;
++ struct nfs4_ol_stateid *lst;
+ unsigned int strhashval;
++ bool hashed;
+
+ lo = find_lockowner_str(cl, &lock->lk_new_owner);
+ if (!lo) {
+@@ -5526,12 +5528,27 @@ lookup_or_create_lock_state(struct nfsd4
+ goto out;
+ }
+
+- *lst = find_or_create_lock_stateid(lo, fi, inode, ost, new);
+- if (*lst == NULL) {
++retry:
++ lst = find_or_create_lock_stateid(lo, fi, inode, ost, new);
++ if (lst == NULL) {
+ status = nfserr_jukebox;
+ goto out;
+ }
++
++ mutex_lock(&lst->st_mutex);
++
++ /* See if it's still hashed to avoid race with FREE_STATEID */
++ spin_lock(&cl->cl_lock);
++ hashed = !list_empty(&lst->st_perfile);
++ spin_unlock(&cl->cl_lock);
++
++ if (!hashed) {
++ mutex_unlock(&lst->st_mutex);
++ nfs4_put_stid(&lst->st_stid);
++ goto retry;
++ }
+ status = nfs_ok;
++ *plst = lst;
+ out:
+ nfs4_put_stateowner(&lo->lo_owner);
+ return status;
+@@ -5598,8 +5615,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struc
+ goto out;
+ status = lookup_or_create_lock_state(cstate, open_stp, lock,
+ &lock_stp, &new);
+- if (status == nfs_ok)
+- mutex_lock(&lock_stp->st_mutex);
+ } else {
+ status = nfs4_preprocess_seqid_op(cstate,
+ lock->lk_old_lock_seqid,
--- /dev/null
+From 42691398be08bd1fe99326911a0aa31f2c041d53 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Thu, 11 Aug 2016 10:37:30 -0400
+Subject: nfsd: Fix race between FREE_STATEID and LOCK
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+commit 42691398be08bd1fe99326911a0aa31f2c041d53 upstream.
+
+When running LTP's nfslock01 test, the Linux client can send a LOCK
+and a FREE_STATEID request at the same time. The outcome is:
+
+Frame 324 R OPEN stateid [2,O]
+
+Frame 115004 C LOCK lockowner_is_new stateid [2,O] offset 672000 len 64
+Frame 115008 R LOCK stateid [1,L]
+Frame 115012 C WRITE stateid [0,L] offset 672000 len 64
+Frame 115016 R WRITE NFS4_OK
+Frame 115019 C LOCKU stateid [1,L] offset 672000 len 64
+Frame 115022 R LOCKU NFS4_OK
+Frame 115025 C FREE_STATEID stateid [2,L]
+Frame 115026 C LOCK lockowner_is_new stateid [2,O] offset 672128 len 64
+Frame 115029 R FREE_STATEID NFS4_OK
+Frame 115030 R LOCK stateid [3,L]
+Frame 115034 C WRITE stateid [0,L] offset 672128 len 64
+Frame 115038 R WRITE NFS4ERR_BAD_STATEID
+
+In other words, the server returns stateid L in a successful LOCK
+reply, but it has already released it. Subsequent uses of stateid L
+fail.
+
+To address this, protect the generation check in nfsd4_free_stateid
+with the st_mutex. This should guarantee that only one of two
+outcomes occurs: either LOCK returns a fresh valid stateid, or
+FREE_STATEID returns NFS4ERR_LOCKS_HELD.
+
+Reported-by: Alexey Kodanev <alexey.kodanev@oracle.com>
+Fix-suggested-by: Jeff Layton <jlayton@redhat.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Tested-by: Alexey Kodanev <alexey.kodanev@oracle.com>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfsd/nfs4state.c | 40 ++++++++++++++++++++++++++++------------
+ 1 file changed, 28 insertions(+), 12 deletions(-)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -4882,6 +4882,32 @@ nfsd4_test_stateid(struct svc_rqst *rqst
+ return nfs_ok;
+ }
+
++static __be32
++nfsd4_free_lock_stateid(stateid_t *stateid, struct nfs4_stid *s)
++{
++ struct nfs4_ol_stateid *stp = openlockstateid(s);
++ __be32 ret;
++
++ mutex_lock(&stp->st_mutex);
++
++ ret = check_stateid_generation(stateid, &s->sc_stateid, 1);
++ if (ret)
++ goto out;
++
++ ret = nfserr_locks_held;
++ if (check_for_locks(stp->st_stid.sc_file,
++ lockowner(stp->st_stateowner)))
++ goto out;
++
++ release_lock_stateid(stp);
++ ret = nfs_ok;
++
++out:
++ mutex_unlock(&stp->st_mutex);
++ nfs4_put_stid(s);
++ return ret;
++}
++
+ __be32
+ nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_free_stateid *free_stateid)
+@@ -4889,7 +4915,6 @@ nfsd4_free_stateid(struct svc_rqst *rqst
+ stateid_t *stateid = &free_stateid->fr_stateid;
+ struct nfs4_stid *s;
+ struct nfs4_delegation *dp;
+- struct nfs4_ol_stateid *stp;
+ struct nfs4_client *cl = cstate->session->se_client;
+ __be32 ret = nfserr_bad_stateid;
+
+@@ -4908,18 +4933,9 @@ nfsd4_free_stateid(struct svc_rqst *rqst
+ ret = nfserr_locks_held;
+ break;
+ case NFS4_LOCK_STID:
+- ret = check_stateid_generation(stateid, &s->sc_stateid, 1);
+- if (ret)
+- break;
+- stp = openlockstateid(s);
+- ret = nfserr_locks_held;
+- if (check_for_locks(stp->st_stid.sc_file,
+- lockowner(stp->st_stateowner)))
+- break;
+- WARN_ON(!unhash_lock_stateid(stp));
++ atomic_inc(&s->sc_count);
+ spin_unlock(&cl->cl_lock);
+- nfs4_put_stid(s);
+- ret = nfs_ok;
++ ret = nfsd4_free_lock_stateid(stateid, s);
+ goto out;
+ case NFS4_REVOKED_DELEG_STID:
+ dp = delegstateid(s);
mips-kvm-add-missing-gfn-range-check.patch
mips-kvm-fix-gfn-range-check-in-kseg0-tlb-faults.patch
mips-kvm-propagate-kseg0-mapped-tlb-fault-errors.patch
+nfs-don-t-create-zero-length-requests.patch
+nfsd-fix-race-between-free_stateid-and-lock.patch
+nfsd-don-t-return-an-unhashed-lock-stateid-after-taking-mutex.patch