Merge tag 'nfs-for-4.15-1' of git://git.linux-nfs.org/projects/anna/linux-nfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 17 Nov 2017 22:18:00 +0000 (14:18 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 17 Nov 2017 22:18:00 +0000 (14:18 -0800)
Pull NFS client updates from Anna Schumaker:
 "Stable bugfixes:
   - Revalidate "." and ".." correctly on open
   - Avoid RCU usage in tracepoints
   - Fix ugly referral attributes
   - Fix a typo in nomigration mount option
   - Revert "NFS: Move the flock open mode check into nfs_flock()"

  Features:
   - Implement a stronger send queue accounting system for NFS over RDMA
   - Switch some atomics to the new refcount_t type

  Other bugfixes and cleanups:
   - Clean up access mode bits
   - Remove special-case revalidations in nfs_opendir()
   - Improve invalidating NFS over RDMA memory for async operations that
     time out
   - Handle NFS over RDMA replies with a worqueue
   - Handle NFS over RDMA sends with a workqueue
   - Fix up replaying interrupted requests
   - Remove dead NFS over RDMA definitions
   - Update NFS over RDMA copyright information
   - Be more consistent with bool initialization and comparisons
   - Mark expected switch fall throughs
   - Various sunrpc tracepoint cleanups
   - Fix various OPEN races
   - Fix a typo in nfs_rename()
   - Use common error handling code in nfs_lock_and_join_request()
   - Check that some structures are properly cleaned up during
     net_exit()
   - Remove net pointer from dprintk()s"

* tag 'nfs-for-4.15-1' of git://git.linux-nfs.org/projects/anna/linux-nfs: (62 commits)
  NFS: Revert "NFS: Move the flock open mode check into nfs_flock()"
  NFS: Fix typo in nomigration mount option
  nfs: Fix ugly referral attributes
  NFS: super: mark expected switch fall-throughs
  sunrpc: remove net pointer from messages
  nfs: remove net pointer from messages
  sunrpc: exit_net cleanup check added
  nfs client: exit_net cleanup check added
  nfs/write: Use common error handling code in nfs_lock_and_join_requests()
  NFSv4: Replace closed stateids with the "invalid special stateid"
  NFSv4: nfs_set_open_stateid must not trigger state recovery for closed state
  NFSv4: Check the open stateid when searching for expired state
  NFSv4: Clean up nfs4_delegreturn_done
  NFSv4: cleanup nfs4_close_done
  NFSv4: Retry NFS4ERR_OLD_STATEID errors in layoutreturn
  pNFS: Retry NFS4ERR_OLD_STATEID errors in layoutreturn-on-close
  NFSv4: Don't try to CLOSE if the stateid 'other' field has changed
  NFSv4: Retry CLOSE and DELEGRETURN on NFS4ERR_OLD_STATEID.
  NFS: Fix a typo in nfs_rename()
  NFSv4: Fix open create exclusive when the server reboots
  ...

20 files changed:
1  2 
fs/nfs/cache_lib.c
fs/nfs/cache_lib.h
fs/nfs/callback.c
fs/nfs/callback_proc.c
fs/nfs/delegation.h
fs/nfs/dir.c
fs/nfs/flexfilelayout/flexfilelayout.h
fs/nfs/inode.c
fs/nfs/nfs3proc.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4trace.h
include/linux/nfs_fs.h
include/linux/nfs_fs_sb.h
include/trace/events/sunrpc.h
net/sunrpc/sched.c
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/backchannel.c
net/sunrpc/xprtrdma/fmr_ops.c
net/sunrpc/xprtrdma/frwr_ops.c
net/sunrpc/xprtsock.c

diff --combined fs/nfs/cache_lib.c
index b60627bcfc6234bf0f2a44c808b3fee3c461b1df,6167f13025d75454063fb7e217ac8f4aeec911c7..ef67295684325b08dfbf45f18e23bb753a6c60b2
@@@ -1,4 -1,3 +1,4 @@@
 +// SPDX-License-Identifier: GPL-2.0
  /*
   * linux/fs/nfs/cache_lib.c
   *
@@@ -67,7 -66,7 +67,7 @@@ out
   */
  void nfs_cache_defer_req_put(struct nfs_cache_defer_req *dreq)
  {
-       if (atomic_dec_and_test(&dreq->count))
+       if (refcount_dec_and_test(&dreq->count))
                kfree(dreq);
  }
  
@@@ -87,7 -86,7 +87,7 @@@ static struct cache_deferred_req *nfs_d
  
        dreq = container_of(req, struct nfs_cache_defer_req, req);
        dreq->deferred_req.revisit = nfs_dns_cache_revisit;
-       atomic_inc(&dreq->count);
+       refcount_inc(&dreq->count);
  
        return &dreq->deferred_req;
  }
@@@ -99,7 -98,7 +99,7 @@@ struct nfs_cache_defer_req *nfs_cache_d
        dreq = kzalloc(sizeof(*dreq), GFP_KERNEL);
        if (dreq) {
                init_completion(&dreq->completion);
-               atomic_set(&dreq->count, 1);
+               refcount_set(&dreq->count, 1);
                dreq->req.defer = nfs_dns_cache_defer;
        }
        return dreq;
diff --combined fs/nfs/cache_lib.h
index 4e6236a86cf7c73950647ec1aab79d57391fd401,02b378c2eeefa6f8b3ad5fcd29feb7ec9f5fb537..220ee409abc46d80d5144414efb135a3eda265fd
@@@ -1,4 -1,3 +1,4 @@@
 +/* SPDX-License-Identifier: GPL-2.0 */
  /*
   * Helper routines for the NFS client caches
   *
@@@ -16,7 -15,7 +16,7 @@@ struct nfs_cache_defer_req 
        struct cache_req req;
        struct cache_deferred_req deferred_req;
        struct completion completion;
-       atomic_t count;
+       refcount_t count;
  };
  
  extern int nfs_cache_upcall(struct cache_detail *cd, char *entry_name);
diff --combined fs/nfs/callback.c
index cd9d992feb2e155eac9d57b51bb22a7a0f1f85c4,387369c2107b9e5645e8377d4e9a79d9f53a20bb..509dc5adeb8f79e9f5508274e32039547873ed45
@@@ -1,4 -1,3 +1,4 @@@
 +// SPDX-License-Identifier: GPL-2.0
  /*
   * linux/fs/nfs/callback.c
   *
@@@ -49,15 -48,15 +49,15 @@@ static int nfs4_callback_up_net(struct 
        if (ret <= 0)
                goto out_err;
        nn->nfs_callback_tcpport = ret;
-       dprintk("NFS: Callback listener port = %u (af %u, net %p)\n",
-                       nn->nfs_callback_tcpport, PF_INET, net);
+       dprintk("NFS: Callback listener port = %u (af %u, net %x)\n",
+               nn->nfs_callback_tcpport, PF_INET, net->ns.inum);
  
        ret = svc_create_xprt(serv, "tcp", net, PF_INET6,
                                nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
        if (ret > 0) {
                nn->nfs_callback_tcpport6 = ret;
-               dprintk("NFS: Callback listener port = %u (af %u, net %p)\n",
-                               nn->nfs_callback_tcpport6, PF_INET6, net);
+               dprintk("NFS: Callback listener port = %u (af %u, net %x\n",
+                       nn->nfs_callback_tcpport6, PF_INET6, net->ns.inum);
        } else if (ret != -EAFNOSUPPORT)
                goto out_err;
        return 0;
@@@ -185,7 -184,7 +185,7 @@@ static void nfs_callback_down_net(u32 m
        if (--nn->cb_users[minorversion])
                return;
  
-       dprintk("NFS: destroy per-net callback data; net=%p\n", net);
+       dprintk("NFS: destroy per-net callback data; net=%x\n", net->ns.inum);
        svc_shutdown_net(serv, net);
  }
  
@@@ -198,7 -197,7 +198,7 @@@ static int nfs_callback_up_net(int mino
        if (nn->cb_users[minorversion]++)
                return 0;
  
-       dprintk("NFS: create per-net callback data; net=%p\n", net);
+       dprintk("NFS: create per-net callback data; net=%x\n", net->ns.inum);
  
        ret = svc_bind(serv, net);
        if (ret < 0) {
@@@ -223,7 -222,7 +223,7 @@@ err_socks
  err_bind:
        nn->cb_users[minorversion]--;
        dprintk("NFS: Couldn't create callback socket: err = %d; "
-                       "net = %p\n", ret, net);
+                       "net = %x\n", ret, net->ns.inum);
        return ret;
  }
  
diff --combined fs/nfs/callback_proc.c
index 19151f6c0e97e32d4f58245a75c0b237194911b0,a82abff80dff4ec51276e8fcefbcc095b9766981..2435af56b87e4472a725f7ef1c6e3b252dd82ae9
@@@ -1,4 -1,3 +1,4 @@@
 +// SPDX-License-Identifier: GPL-2.0
  /*
   * linux/fs/nfs/callback_proc.c
   *
@@@ -440,7 -439,7 +440,7 @@@ static bool referring_call_exists(struc
                                  uint32_t nrclists,
                                  struct referring_call_list *rclists)
  {
-       bool status = 0;
+       bool status = false;
        int i, j;
        struct nfs4_session *session;
        struct nfs4_slot_table *tbl;
diff --combined fs/nfs/delegation.h
index ddaf2644cf13a15aa8bf1dd18046460013132ba7,fe9f3882adaedf2e3d415e79e1d96e30ec8d0b39..185a09f37a89b22228bdffacdb51604f4b9a3f7b
@@@ -1,4 -1,3 +1,4 @@@
 +/* SPDX-License-Identifier: GPL-2.0 */
  /*
   * linux/fs/nfs/delegation.h
   *
@@@ -62,6 -61,7 +62,7 @@@ int nfs4_proc_delegreturn(struct inode 
  int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid, fmode_t type);
  int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state, const nfs4_stateid *stateid);
  bool nfs4_copy_delegation_stateid(struct inode *inode, fmode_t flags, nfs4_stateid *dst, struct rpc_cred **cred);
+ bool nfs4_refresh_delegation_stateid(nfs4_stateid *dst, struct inode *inode);
  
  void nfs_mark_delegation_referenced(struct nfs_delegation *delegation);
  int nfs4_have_delegation(struct inode *inode, fmode_t flags);
diff --combined fs/nfs/dir.c
index f439f1c450086fa7349790989cf1823683204e77,927fd2768eadeeb4ce57ab7438e802e640cac9ea..e51ae52ed14ff5ef6bc28dd4d9e60d1f33a9fb6c
@@@ -118,13 -118,6 +118,6 @@@ nfs_opendir(struct inode *inode, struc
                goto out;
        }
        filp->private_data = ctx;
-       if (filp->f_path.dentry == filp->f_path.mnt->mnt_root) {
-               /* This is a mountpoint, so d_revalidate will never
-                * have been called, so we need to refresh the
-                * inode (for close-open consistency) ourselves.
-                */
-               __nfs_revalidate_inode(NFS_SERVER(inode), inode);
-       }
  out:
        put_rpccred(cred);
        return res;
@@@ -253,7 -246,7 +246,7 @@@ int nfs_readdir_search_for_pos(struct n
        desc->cache_entry_index = index;
        return 0;
  out_eof:
-       desc->eof = 1;
+       desc->eof = true;
        return -EBADCOOKIE;
  }
  
@@@ -307,7 -300,7 +300,7 @@@ int nfs_readdir_search_for_cookie(struc
        if (array->eof_index >= 0) {
                status = -EBADCOOKIE;
                if (*desc->dir_cookie == array->last_cookie)
-                       desc->eof = 1;
+                       desc->eof = true;
        }
  out:
        return status;
@@@ -761,7 -754,7 +754,7 @@@ int nfs_do_filldir(nfs_readdir_descript
                ent = &array->array[i];
                if (!dir_emit(desc->ctx, ent->string.name, ent->string.len,
                    nfs_compat_user_ino64(ent->ino), ent->d_type)) {
-                       desc->eof = 1;
+                       desc->eof = true;
                        break;
                }
                desc->ctx->pos++;
                        ctx->duped = 1;
        }
        if (array->eof_index >= 0)
-               desc->eof = 1;
+               desc->eof = true;
  
        kunmap(desc->page);
        cache_page_release(desc);
@@@ -873,7 -866,7 +866,7 @@@ static int nfs_readdir(struct file *fil
                if (res == -EBADCOOKIE) {
                        res = 0;
                        /* This means either end of directory */
-                       if (*desc->dir_cookie && desc->eof == 0) {
+                       if (*desc->dir_cookie && !desc->eof) {
                                /* Or that the server has 'lost' a cookie */
                                res = uncached_readdir(desc);
                                if (res == 0)
@@@ -1081,7 -1074,7 +1074,7 @@@ static int nfs_lookup_revalidate(struc
        int error;
  
        if (flags & LOOKUP_RCU) {
 -              parent = ACCESS_ONCE(dentry->d_parent);
 +              parent = READ_ONCE(dentry->d_parent);
                dir = d_inode_rcu(parent);
                if (!dir)
                        return -ECHILD;
@@@ -1168,7 -1161,7 +1161,7 @@@ out_set_verifier
        nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
   out_valid:
        if (flags & LOOKUP_RCU) {
 -              if (parent != ACCESS_ONCE(dentry->d_parent))
 +              if (parent != READ_ONCE(dentry->d_parent))
                        return -ECHILD;
        } else
                dput(parent);
@@@ -1241,8 -1234,7 +1234,7 @@@ static int nfs_weak_revalidate(struct d
                return 0;
        }
  
-       if (nfs_mapping_need_revalidate_inode(inode))
-               error = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
+       error = nfs_lookup_verify_inode(inode, flags);
        dfprintk(LOOKUPCACHE, "NFS: %s: inode %lu is %s\n",
                        __func__, inode->i_ino, error ? "invalid" : "valid");
        return !error;
@@@ -1393,6 -1385,7 +1385,7 @@@ static int nfs4_lookup_revalidate(struc
  
  const struct dentry_operations nfs4_dentry_operations = {
        .d_revalidate   = nfs4_lookup_revalidate,
+       .d_weak_revalidate      = nfs_weak_revalidate,
        .d_delete       = nfs_dentry_delete,
        .d_iput         = nfs_dentry_iput,
        .d_automount    = nfs_d_automount,
@@@ -1582,7 -1575,7 +1575,7 @@@ static int nfs4_lookup_revalidate(struc
                struct inode *dir;
  
                if (flags & LOOKUP_RCU) {
 -                      parent = ACCESS_ONCE(dentry->d_parent);
 +                      parent = READ_ONCE(dentry->d_parent);
                        dir = d_inode_rcu(parent);
                        if (!dir)
                                return -ECHILD;
                        ret = -ECHILD;
                if (!(flags & LOOKUP_RCU))
                        dput(parent);
 -              else if (parent != ACCESS_ONCE(dentry->d_parent))
 +              else if (parent != READ_ONCE(dentry->d_parent))
                        return -ECHILD;
                goto out;
        }
@@@ -2064,7 -2057,7 +2057,7 @@@ out
                 * should mark the directories for revalidation.
                 */
                d_move(old_dentry, new_dentry);
-               nfs_set_verifier(new_dentry,
+               nfs_set_verifier(old_dentry,
                                        nfs_save_change_attribute(new_dir));
        } else if (error == -ENOENT)
                nfs_dentry_handle_enoent(old_dentry);
@@@ -2369,15 -2362,15 +2362,15 @@@ void nfs_access_add_cache(struct inode 
  }
  EXPORT_SYMBOL_GPL(nfs_access_add_cache);
  
- #define NFS_MAY_READ (NFS4_ACCESS_READ)
- #define NFS_MAY_WRITE (NFS4_ACCESS_MODIFY | \
-               NFS4_ACCESS_EXTEND | \
-               NFS4_ACCESS_DELETE)
- #define NFS_FILE_MAY_WRITE (NFS4_ACCESS_MODIFY | \
-               NFS4_ACCESS_EXTEND)
+ #define NFS_MAY_READ (NFS_ACCESS_READ)
+ #define NFS_MAY_WRITE (NFS_ACCESS_MODIFY | \
+               NFS_ACCESS_EXTEND | \
+               NFS_ACCESS_DELETE)
+ #define NFS_FILE_MAY_WRITE (NFS_ACCESS_MODIFY | \
+               NFS_ACCESS_EXTEND)
  #define NFS_DIR_MAY_WRITE NFS_MAY_WRITE
- #define NFS_MAY_LOOKUP (NFS4_ACCESS_LOOKUP)
- #define NFS_MAY_EXECUTE (NFS4_ACCESS_EXECUTE)
+ #define NFS_MAY_LOOKUP (NFS_ACCESS_LOOKUP)
+ #define NFS_MAY_EXECUTE (NFS_ACCESS_EXECUTE)
  static int
  nfs_access_calc_mask(u32 access_result, umode_t umode)
  {
@@@ -2425,9 -2418,14 +2418,14 @@@ static int nfs_do_access(struct inode *
        if (!may_block)
                goto out;
  
-       /* Be clever: ask server to check for all possible rights */
-       cache.mask = NFS_MAY_LOOKUP | NFS_MAY_EXECUTE
-                    | NFS_MAY_WRITE | NFS_MAY_READ;
+       /*
+        * Determine which access bits we want to ask for...
+        */
+       cache.mask = NFS_ACCESS_READ | NFS_ACCESS_MODIFY | NFS_ACCESS_EXTEND;
+       if (S_ISDIR(inode->i_mode))
+               cache.mask |= NFS_ACCESS_DELETE | NFS_ACCESS_LOOKUP;
+       else
+               cache.mask |= NFS_ACCESS_EXECUTE;
        cache.cred = cred;
        status = NFS_PROTO(inode)->access(inode, &cache);
        if (status != 0) {
index 679cb087ef3f228b833def767d33bf266e238902,ca35426ac3b4a586558aba00c8d431b42eb4530e..411798346e48360c85a0db1c47d2eb5edb79001f
@@@ -1,4 -1,3 +1,4 @@@
 +/* SPDX-License-Identifier: GPL-2.0 */
  /*
   * NFSv4 flexfile layout driver data structures.
   *
@@@ -14,6 -13,7 +14,7 @@@
  #define FF_FLAGS_NO_IO_THRU_MDS  2
  #define FF_FLAGS_NO_READ_IO      4
  
+ #include <linux/refcount.h>
  #include "../pnfs.h"
  
  /* XXX: Let's filter out insanely large mirror count for now to avoid oom
@@@ -82,7 -82,7 +83,7 @@@ struct nfs4_ff_layout_mirror 
        nfs4_stateid                    stateid;
        struct rpc_cred __rcu           *ro_cred;
        struct rpc_cred __rcu           *rw_cred;
-       atomic_t                        ref;
+       refcount_t                      ref;
        spinlock_t                      lock;
        unsigned long                   flags;
        struct nfs4_ff_layoutstat       read_stat;
diff --combined fs/nfs/inode.c
index 1629056aa2c9a0c5a7dc1393fb552337fbe02996,e5fcc1f095aec2ff336c62c6b72a54a6ff7f5b8f..38b93d54c02e2d64111e5ff522795badf27fdcf7
@@@ -85,9 -85,9 +85,9 @@@ int nfs_wait_bit_killable(struct wait_b
  }
  EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);
  
 -int nfs_wait_atomic_killable(atomic_t *p)
 +int nfs_wait_atomic_killable(atomic_t *p, unsigned int mode)
  {
 -      return nfs_wait_killable(TASK_KILLABLE);
 +      return nfs_wait_killable(mode);
  }
  
  /**
@@@ -783,7 -783,7 +783,7 @@@ EXPORT_SYMBOL_GPL(nfs_getattr)
  
  static void nfs_init_lock_context(struct nfs_lock_context *l_ctx)
  {
-       atomic_set(&l_ctx->count, 1);
+       refcount_set(&l_ctx->count, 1);
        l_ctx->lockowner = current->files;
        INIT_LIST_HEAD(&l_ctx->list);
        atomic_set(&l_ctx->io_count, 0);
@@@ -797,7 -797,7 +797,7 @@@ static struct nfs_lock_context *__nfs_f
        do {
                if (pos->lockowner != current->files)
                        continue;
-               atomic_inc(&pos->count);
+               refcount_inc(&pos->count);
                return pos;
        } while ((pos = list_entry(pos->list.next, typeof(*pos), list)) != head);
        return NULL;
@@@ -836,7 -836,7 +836,7 @@@ void nfs_put_lock_context(struct nfs_lo
        struct nfs_open_context *ctx = l_ctx->open_context;
        struct inode *inode = d_inode(ctx->dentry);
  
-       if (!atomic_dec_and_lock(&l_ctx->count, &inode->i_lock))
+       if (!refcount_dec_and_lock(&l_ctx->count, &inode->i_lock))
                return;
        list_del(&l_ctx->list);
        spin_unlock(&inode->i_lock);
@@@ -913,7 -913,7 +913,7 @@@ EXPORT_SYMBOL_GPL(alloc_nfs_open_contex
  struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
  {
        if (ctx != NULL)
-               atomic_inc(&ctx->lock_context.count);
+               refcount_inc(&ctx->lock_context.count);
        return ctx;
  }
  EXPORT_SYMBOL_GPL(get_nfs_open_context);
@@@ -924,11 -924,11 +924,11 @@@ static void __put_nfs_open_context(stru
        struct super_block *sb = ctx->dentry->d_sb;
  
        if (!list_empty(&ctx->list)) {
-               if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock))
+               if (!refcount_dec_and_lock(&ctx->lock_context.count, &inode->i_lock))
                        return;
                list_del(&ctx->list);
                spin_unlock(&inode->i_lock);
-       } else if (!atomic_dec_and_test(&ctx->lock_context.count))
+       } else if (!refcount_dec_and_test(&ctx->lock_context.count))
                return;
        if (inode != NULL)
                NFS_PROTO(inode)->close_context(ctx, is_sync);
@@@ -2084,8 -2084,12 +2084,12 @@@ static int nfs_net_init(struct net *net
  
  static void nfs_net_exit(struct net *net)
  {
+       struct nfs_net *nn = net_generic(net, nfs_net_id);
        nfs_fs_proc_net_exit(net);
        nfs_cleanup_cb_ident_idr(net);
+       WARN_ON_ONCE(!list_empty(&nn->nfs_client_list));
+       WARN_ON_ONCE(!list_empty(&nn->nfs_volume_list));
  }
  
  static struct pernet_operations nfs_net_ops = {
diff --combined fs/nfs/nfs3proc.c
index bc673fb47fb38fcd4830de96d1f0e7967ce94eb6,44bf961d581253b47a6d7662f16c06db2a4309b6..49f848fd1f04779108d86a5eee618e21d11304e6
@@@ -1,4 -1,3 +1,4 @@@
 +// SPDX-License-Identifier: GPL-2.0
  /*
   *  linux/fs/nfs/nfs3proc.c
   *
@@@ -188,6 -187,7 +188,7 @@@ static int nfs3_proc_access(struct inod
  {
        struct nfs3_accessargs  arg = {
                .fh             = NFS_FH(inode),
+               .access         = entry->mask,
        };
        struct nfs3_accessres   res;
        struct rpc_message msg = {
                .rpc_resp       = &res,
                .rpc_cred       = entry->cred,
        };
-       int mode = entry->mask;
        int status = -ENOMEM;
  
        dprintk("NFS call  access\n");
-       if (mode & MAY_READ)
-               arg.access |= NFS3_ACCESS_READ;
-       if (S_ISDIR(inode->i_mode)) {
-               if (mode & MAY_WRITE)
-                       arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND | NFS3_ACCESS_DELETE;
-               if (mode & MAY_EXEC)
-                       arg.access |= NFS3_ACCESS_LOOKUP;
-       } else {
-               if (mode & MAY_WRITE)
-                       arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND;
-               if (mode & MAY_EXEC)
-                       arg.access |= NFS3_ACCESS_EXECUTE;
-       }
        res.fattr = nfs_alloc_fattr();
        if (res.fattr == NULL)
                goto out;
diff --combined fs/nfs/nfs4_fs.h
index dcfcf7fd7438f9a3248d110d149de8f7e652cf07,dcfd1afc8d1f577d6fcf7ef55d31c1621669175b..b374f680830ca34e5cdd7a4f3fb35d69ae7a2c06
@@@ -1,4 -1,3 +1,4 @@@
 +/* SPDX-License-Identifier: GPL-2.0 */
  /*
   * linux/fs/nfs/nfs4_fs.h
   *
@@@ -145,7 -144,7 +145,7 @@@ struct nfs4_lock_state 
        unsigned long           ls_flags;
        struct nfs_seqid_counter        ls_seqid;
        nfs4_stateid            ls_stateid;
-       atomic_t                ls_count;
+       refcount_t              ls_count;
        fl_owner_t              ls_owner;
  };
  
@@@ -162,6 -161,7 +162,7 @@@ enum 
        NFS_STATE_POSIX_LOCKS,          /* Posix locks are supported */
        NFS_STATE_RECOVERY_FAILED,      /* OPEN stateid state recovery failed */
        NFS_STATE_MAY_NOTIFY_LOCK,      /* server may CB_NOTIFY_LOCK */
+       NFS_STATE_CHANGE_WAIT,          /* A state changing operation is outstanding */
  };
  
  struct nfs4_state {
        unsigned int n_rdwr;            /* Number of read/write references */
        fmode_t state;                  /* State on the server (R,W, or RW) */
        atomic_t count;
+       wait_queue_head_t waitq;
  };
  
  
@@@ -458,6 -460,10 +461,10 @@@ extern int nfs4_set_lock_state(struct n
  extern int nfs4_select_rw_stateid(struct nfs4_state *, fmode_t,
                const struct nfs_lock_context *, nfs4_stateid *,
                struct rpc_cred **);
+ extern bool nfs4_refresh_open_stateid(nfs4_stateid *dst,
+               struct nfs4_state *state);
+ extern bool nfs4_copy_open_stateid(nfs4_stateid *dst,
+               struct nfs4_state *state);
  
  extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask);
  extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task);
@@@ -465,7 -471,7 +472,7 @@@ extern void nfs_increment_open_seqid(in
  extern void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid);
  extern void nfs_release_seqid(struct nfs_seqid *seqid);
  extern void nfs_free_seqid(struct nfs_seqid *seqid);
- extern int nfs4_setup_sequence(const struct nfs_client *client,
+ extern int nfs4_setup_sequence(struct nfs_client *client,
                                struct nfs4_sequence_args *args,
                                struct nfs4_sequence_res *res,
                                struct rpc_task *task);
@@@ -475,6 -481,7 +482,7 @@@ extern int nfs4_sequence_done(struct rp
  extern void nfs4_free_lock_state(struct nfs_server *server, struct nfs4_lock_state *lsp);
  
  extern const nfs4_stateid zero_stateid;
+ extern const nfs4_stateid invalid_stateid;
  
  /* nfs4super.c */
  struct nfs_mount_info;
diff --combined fs/nfs/nfs4trace.h
index e7c6275519b09d856ab50223edbaa8bf5f0517ed,06ac7156c44b91a49c3ae953cb7f36f5b171a19d..a275fba93170c2ba190987e8b546f194868e4394
@@@ -1,4 -1,3 +1,4 @@@
 +/* SPDX-License-Identifier: GPL-2.0 */
  /*
   * Copyright (c) 2013 Trond Myklebust <Trond.Myklebust@netapp.com>
   */
@@@ -202,17 -201,13 +202,13 @@@ DECLARE_EVENT_CLASS(nfs4_clientid_event
                TP_ARGS(clp, error),
  
                TP_STRUCT__entry(
-                       __string(dstaddr,
-                               rpc_peeraddr2str(clp->cl_rpcclient,
-                                       RPC_DISPLAY_ADDR))
+                       __string(dstaddr, clp->cl_hostname)
                        __field(int, error)
                ),
  
                TP_fast_assign(
                        __entry->error = error;
-                       __assign_str(dstaddr,
-                               rpc_peeraddr2str(clp->cl_rpcclient,
-                                               RPC_DISPLAY_ADDR));
+                       __assign_str(dstaddr, clp->cl_hostname);
                ),
  
                TP_printk(
@@@ -1066,6 -1061,8 +1062,8 @@@ DECLARE_EVENT_CLASS(nfs4_inode_stateid_
  
  DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_setattr);
  DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_delegreturn);
+ DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_open_stateid_update);
+ DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_open_stateid_update_wait);
  
  DECLARE_EVENT_CLASS(nfs4_getattr_event,
                TP_PROTO(
@@@ -1133,9 -1130,7 +1131,7 @@@ DECLARE_EVENT_CLASS(nfs4_inode_callback
                        __field(dev_t, dev)
                        __field(u32, fhandle)
                        __field(u64, fileid)
-                       __string(dstaddr, clp ?
-                               rpc_peeraddr2str(clp->cl_rpcclient,
-                                       RPC_DISPLAY_ADDR) : "unknown")
+                       __string(dstaddr, clp ? clp->cl_hostname : "unknown")
                ),
  
                TP_fast_assign(
                                __entry->fileid = 0;
                                __entry->dev = 0;
                        }
-                       __assign_str(dstaddr, clp ?
-                               rpc_peeraddr2str(clp->cl_rpcclient,
-                                       RPC_DISPLAY_ADDR) : "unknown")
+                       __assign_str(dstaddr, clp ? clp->cl_hostname : "unknown")
                ),
  
                TP_printk(
@@@ -1192,9 -1185,7 +1186,7 @@@ DECLARE_EVENT_CLASS(nfs4_inode_stateid_
                        __field(dev_t, dev)
                        __field(u32, fhandle)
                        __field(u64, fileid)
-                       __string(dstaddr, clp ?
-                               rpc_peeraddr2str(clp->cl_rpcclient,
-                                       RPC_DISPLAY_ADDR) : "unknown")
+                       __string(dstaddr, clp ? clp->cl_hostname : "unknown")
                        __field(int, stateid_seq)
                        __field(u32, stateid_hash)
                ),
                                __entry->fileid = 0;
                                __entry->dev = 0;
                        }
-                       __assign_str(dstaddr, clp ?
-                               rpc_peeraddr2str(clp->cl_rpcclient,
-                                       RPC_DISPLAY_ADDR) : "unknown")
+                       __assign_str(dstaddr, clp ? clp->cl_hostname : "unknown")
                        __entry->stateid_seq =
                                be32_to_cpu(stateid->seqid);
                        __entry->stateid_hash =
diff --combined include/linux/nfs_fs.h
index f0015f801a7845890332dbafda8279dc1a34b53c,e6706913e6c2f90f6187119d9daac231c8850f25..38187c68063dad5fa34b3731946c9767c684dc3b
@@@ -1,4 -1,3 +1,4 @@@
 +/* SPDX-License-Identifier: GPL-2.0 */
  /*
   *  linux/include/linux/nfs_fs.h
   *
@@@ -23,6 -22,7 +23,7 @@@
  #include <linux/mm.h>
  #include <linux/pagemap.h>
  #include <linux/rbtree.h>
+ #include <linux/refcount.h>
  #include <linux/rwsem.h>
  #include <linux/wait.h>
  
@@@ -56,7 -56,7 +57,7 @@@ struct nfs_access_entry 
  };
  
  struct nfs_lock_context {
-       atomic_t count;
+       refcount_t count;
        struct list_head list;
        struct nfs_open_context *open_context;
        fl_owner_t lockowner;
@@@ -184,6 -184,16 +185,16 @@@ struct nfs_inode 
        struct inode            vfs_inode;
  };
  
+ /*
+  * Access bit flags
+  */
+ #define NFS_ACCESS_READ        0x0001
+ #define NFS_ACCESS_LOOKUP      0x0002
+ #define NFS_ACCESS_MODIFY      0x0004
+ #define NFS_ACCESS_EXTEND      0x0008
+ #define NFS_ACCESS_DELETE      0x0010
+ #define NFS_ACCESS_EXECUTE     0x0020
  /*
   * Cache validity bit flags
   */
index 286b71c418b415af4b158f93a16a12c9a9813f8c,efcfe9ded9ea1b5e03a7a8c38b4e896cf44c9485..4e735be53e704a56a33f8576b75023dafd60f158
@@@ -1,4 -1,3 +1,4 @@@
 +/* SPDX-License-Identifier: GPL-2.0 */
  #ifndef _NFS_FS_SB
  #define _NFS_FS_SB
  
@@@ -10,6 -9,7 +10,7 @@@
  #include <linux/sunrpc/xprt.h>
  
  #include <linux/atomic.h>
+ #include <linux/refcount.h>
  
  struct nfs4_session;
  struct nfs_iostats;
@@@ -25,7 -25,7 +26,7 @@@ struct nfs41_impl_id
   * The nfs_client identifies our client state to the server.
   */
  struct nfs_client {
-       atomic_t                cl_count;
+       refcount_t              cl_count;
        atomic_t                cl_mds_count;
        int                     cl_cons_state;  /* current construction state (-ve: init error) */
  #define NFS_CS_READY          0               /* ready to be used */
index 25a7739514cd8494409797cfd940764804d8219b,d7c6dc739f6650246d50e865678f861c3facb7dc..ecbdbfe86eb6620350fe5eca369906cd3ea60823
@@@ -1,4 -1,3 +1,4 @@@
 +/* SPDX-License-Identifier: GPL-2.0 */
  #undef TRACE_SYSTEM
  #define TRACE_SYSTEM sunrpc
  
@@@ -71,6 -70,36 +71,36 @@@ TRACE_EVENT(rpc_connect_status
                __entry->status)
  );
  
+ TRACE_EVENT(rpc_request,
+       TP_PROTO(const struct rpc_task *task),
+       TP_ARGS(task),
+       TP_STRUCT__entry(
+               __field(unsigned int, task_id)
+               __field(unsigned int, client_id)
+               __field(int, version)
+               __field(bool, async)
+               __string(progname, task->tk_client->cl_program->name)
+               __string(procname, rpc_proc_name(task))
+       ),
+       TP_fast_assign(
+               __entry->task_id = task->tk_pid;
+               __entry->client_id = task->tk_client->cl_clid;
+               __entry->version = task->tk_client->cl_vers;
+               __entry->async = RPC_IS_ASYNC(task);
+               __assign_str(progname, task->tk_client->cl_program->name)
+               __assign_str(procname, rpc_proc_name(task))
+       ),
+       TP_printk("task:%u@%u %sv%d %s (%ssync)",
+               __entry->task_id, __entry->client_id,
+               __get_str(progname), __entry->version,
+               __get_str(procname), __entry->async ? "a": ""
+               )
+ );
  DECLARE_EVENT_CLASS(rpc_task_running,
  
        TP_PROTO(const struct rpc_clnt *clnt, const struct rpc_task *task, const void *action),
@@@ -342,21 -371,21 +372,21 @@@ DECLARE_EVENT_CLASS(rpc_xprt_event
        TP_ARGS(xprt, xid, status),
  
        TP_STRUCT__entry(
-               __field(__be32, xid)
+               __field(u32, xid)
                __field(int, status)
                __string(addr, xprt->address_strings[RPC_DISPLAY_ADDR])
                __string(port, xprt->address_strings[RPC_DISPLAY_PORT])
        ),
  
        TP_fast_assign(
-               __entry->xid = xid;
+               __entry->xid = be32_to_cpu(xid);
                __entry->status = status;
                __assign_str(addr, xprt->address_strings[RPC_DISPLAY_ADDR]);
                __assign_str(port, xprt->address_strings[RPC_DISPLAY_PORT]);
        ),
  
-       TP_printk("peer=[%s]:%s xid=0x%x status=%d", __get_str(addr),
-                       __get_str(port), be32_to_cpu(__entry->xid),
+       TP_printk("peer=[%s]:%s xid=0x%08x status=%d", __get_str(addr),
+                       __get_str(port), __entry->xid,
                        __entry->status)
  );
  
@@@ -417,7 -446,7 +447,7 @@@ TRACE_EVENT(xs_tcp_data_recv
        TP_STRUCT__entry(
                __string(addr, xs->xprt.address_strings[RPC_DISPLAY_ADDR])
                __string(port, xs->xprt.address_strings[RPC_DISPLAY_PORT])
-               __field(__be32, xid)
+               __field(u32, xid)
                __field(unsigned long, flags)
                __field(unsigned long, copied)
                __field(unsigned int, reclen)
        TP_fast_assign(
                __assign_str(addr, xs->xprt.address_strings[RPC_DISPLAY_ADDR]);
                __assign_str(port, xs->xprt.address_strings[RPC_DISPLAY_PORT]);
-               __entry->xid = xs->tcp_xid;
+               __entry->xid = be32_to_cpu(xs->tcp_xid);
                __entry->flags = xs->tcp_flags;
                __entry->copied = xs->tcp_copied;
                __entry->reclen = xs->tcp_reclen;
                __entry->offset = xs->tcp_offset;
        ),
  
-       TP_printk("peer=[%s]:%s xid=0x%x flags=%s copied=%lu reclen=%u offset=%lu",
-                       __get_str(addr), __get_str(port), be32_to_cpu(__entry->xid),
+       TP_printk("peer=[%s]:%s xid=0x%08x flags=%s copied=%lu reclen=%u offset=%lu",
+                       __get_str(addr), __get_str(port), __entry->xid,
                        rpc_show_sock_xprt_flags(__entry->flags),
                        __entry->copied, __entry->reclen, __entry->offset)
  );
@@@ -457,20 -486,20 +487,20 @@@ TRACE_EVENT(svc_recv
  
        TP_STRUCT__entry(
                __field(struct sockaddr *, addr)
-               __field(__be32, xid)
+               __field(u32, xid)
                __field(int, status)
                __field(unsigned long, flags)
        ),
  
        TP_fast_assign(
                __entry->addr = (struct sockaddr *)&rqst->rq_addr;
-               __entry->xid = status > 0 ? rqst->rq_xid : 0;
+               __entry->xid = status > 0 ? be32_to_cpu(rqst->rq_xid) : 0;
                __entry->status = status;
                __entry->flags = rqst->rq_flags;
        ),
  
-       TP_printk("addr=%pIScp xid=0x%x status=%d flags=%s", __entry->addr,
-                       be32_to_cpu(__entry->xid), __entry->status,
+       TP_printk("addr=%pIScp xid=0x%08x status=%d flags=%s", __entry->addr,
+                       __entry->xid, __entry->status,
                        show_rqstp_flags(__entry->flags))
  );
  
@@@ -481,21 -510,21 +511,21 @@@ DECLARE_EVENT_CLASS(svc_rqst_event
        TP_ARGS(rqst),
  
        TP_STRUCT__entry(
-               __field(__be32, xid)
+               __field(u32, xid)
                __field(unsigned long, flags)
                __dynamic_array(unsigned char, addr, rqst->rq_addrlen)
        ),
  
        TP_fast_assign(
-               __entry->xid = rqst->rq_xid;
+               __entry->xid = be32_to_cpu(rqst->rq_xid);
                __entry->flags = rqst->rq_flags;
                memcpy(__get_dynamic_array(addr),
                        &rqst->rq_addr, rqst->rq_addrlen);
        ),
  
-       TP_printk("addr=%pIScp rq_xid=0x%x flags=%s",
+       TP_printk("addr=%pIScp rq_xid=0x%08x flags=%s",
                (struct sockaddr *)__get_dynamic_array(addr),
-               be32_to_cpu(__entry->xid),
+               __entry->xid,
                show_rqstp_flags(__entry->flags))
  );
  
@@@ -515,7 -544,7 +545,7 @@@ DECLARE_EVENT_CLASS(svc_rqst_status
  
        TP_STRUCT__entry(
                __field(struct sockaddr *, addr)
-               __field(__be32, xid)
+               __field(u32, xid)
                __field(int, dropme)
                __field(int, status)
                __field(unsigned long, flags)
  
        TP_fast_assign(
                __entry->addr = (struct sockaddr *)&rqst->rq_addr;
-               __entry->xid = rqst->rq_xid;
+               __entry->xid = be32_to_cpu(rqst->rq_xid);
                __entry->status = status;
                __entry->flags = rqst->rq_flags;
        ),
  
-       TP_printk("addr=%pIScp rq_xid=0x%x status=%d flags=%s",
-               __entry->addr, be32_to_cpu(__entry->xid),
+       TP_printk("addr=%pIScp rq_xid=0x%08x status=%d flags=%s",
+               __entry->addr, __entry->xid,
                __entry->status, show_rqstp_flags(__entry->flags))
  );
  
@@@ -678,18 -707,19 +708,19 @@@ DECLARE_EVENT_CLASS(svc_deferred_event
        TP_ARGS(dr),
  
        TP_STRUCT__entry(
-               __field(__be32, xid)
+               __field(u32, xid)
                __dynamic_array(unsigned char, addr, dr->addrlen)
        ),
  
        TP_fast_assign(
-               __entry->xid = *(__be32 *)(dr->args + (dr->xprt_hlen>>2));
+               __entry->xid = be32_to_cpu(*(__be32 *)(dr->args +
+                                                      (dr->xprt_hlen>>2)));
                memcpy(__get_dynamic_array(addr), &dr->addr, dr->addrlen);
        ),
  
-       TP_printk("addr=%pIScp xid=0x%x",
+       TP_printk("addr=%pIScp xid=0x%08x",
                (struct sockaddr *)__get_dynamic_array(addr),
-               be32_to_cpu(__entry->xid))
+               __entry->xid)
  );
  
  DEFINE_EVENT(svc_deferred_event, svc_drop_deferred,
diff --combined net/sunrpc/sched.c
index 5dea47eb31bba79adac47e9e13c8af32dfd20659,f9db5fe52d3674253b3b7d0d1ee2f4c57775588a..b1b49edd7c4d16429250b34d819a1ea81ff5964e
@@@ -44,7 -44,7 +44,7 @@@ static mempool_t      *rpc_buffer_mempool __
  
  static void                   rpc_async_schedule(struct work_struct *);
  static void                    rpc_release_task(struct rpc_task *task);
 -static void __rpc_queue_timer_fn(unsigned long ptr);
 +static void __rpc_queue_timer_fn(struct timer_list *t);
  
  /*
   * RPC tasks sit here while waiting for conditions to improve.
@@@ -228,7 -228,7 +228,7 @@@ static void __rpc_init_priority_wait_qu
        queue->maxpriority = nr_queues - 1;
        rpc_reset_waitqueue_priority(queue);
        queue->qlen = 0;
 -      setup_timer(&queue->timer_list.timer, __rpc_queue_timer_fn, (unsigned long)queue);
 +      timer_setup(&queue->timer_list.timer, __rpc_queue_timer_fn, 0);
        INIT_LIST_HEAD(&queue->timer_list.list);
        rpc_assign_waitqueue_name(queue, qname);
  }
@@@ -274,10 -274,9 +274,9 @@@ static inline void rpc_task_set_debugin
  
  static void rpc_set_active(struct rpc_task *task)
  {
-       trace_rpc_task_begin(task->tk_client, task, NULL);
        rpc_task_set_debuginfo(task);
        set_bit(RPC_TASK_ACTIVE, &task->tk_runstate);
+       trace_rpc_task_begin(task->tk_client, task, NULL);
  }
  
  /*
@@@ -635,9 -634,9 +634,9 @@@ void rpc_wake_up_status(struct rpc_wait
  }
  EXPORT_SYMBOL_GPL(rpc_wake_up_status);
  
 -static void __rpc_queue_timer_fn(unsigned long ptr)
 +static void __rpc_queue_timer_fn(struct timer_list *t)
  {
 -      struct rpc_wait_queue *queue = (struct rpc_wait_queue *)ptr;
 +      struct rpc_wait_queue *queue = from_timer(queue, t, timer_list.timer);
        struct rpc_task *task, *n;
        unsigned long expires, now, timeo;
  
diff --combined net/sunrpc/xprt.c
index 6160d17a31c4e32c426ce7fc9c9d03f3cbee5a97,02a9bacb239bbc969c946107c663da0a75c929e8..333b9d697ae5373d00c6001b9c7f75f3d6c0ed91
@@@ -696,9 -696,9 +696,9 @@@ xprt_schedule_autodisconnect(struct rpc
  }
  
  static void
 -xprt_init_autodisconnect(unsigned long data)
 +xprt_init_autodisconnect(struct timer_list *t)
  {
 -      struct rpc_xprt *xprt = (struct rpc_xprt *)data;
 +      struct rpc_xprt *xprt = from_timer(xprt, t, timer);
  
        spin_lock(&xprt->transport_lock);
        if (!list_empty(&xprt->recv))
@@@ -1139,6 -1139,7 +1139,7 @@@ void xprt_alloc_slot(struct rpc_xprt *x
        case -EAGAIN:
                xprt_add_backlog(xprt, task);
                dprintk("RPC:       waiting for request slot\n");
+               /* fall through */
        default:
                task->tk_status = -EAGAIN;
        }
@@@ -1333,7 -1334,7 +1334,7 @@@ void xprt_release(struct rpc_task *task
                rpc_count_iostats(task, task->tk_client->cl_metrics);
        spin_lock(&xprt->recv_lock);
        if (!list_empty(&req->rq_list)) {
 -              list_del(&req->rq_list);
 +              list_del_init(&req->rq_list);
                xprt_wait_on_pinned_rqst(req);
        }
        spin_unlock(&xprt->recv_lock);
@@@ -1422,9 -1423,10 +1423,9 @@@ found
                xprt->idle_timeout = 0;
        INIT_WORK(&xprt->task_cleanup, xprt_autoclose);
        if (xprt_has_timer(xprt))
 -              setup_timer(&xprt->timer, xprt_init_autodisconnect,
 -                          (unsigned long)xprt);
 +              timer_setup(&xprt->timer, xprt_init_autodisconnect, 0);
        else
 -              init_timer(&xprt->timer);
 +              timer_setup(&xprt->timer, NULL, 0);
  
        if (strlen(args->servername) > RPC_MAXNETNAMELEN) {
                xprt_destroy(xprt);
        return xprt;
  }
  
 +static void xprt_destroy_cb(struct work_struct *work)
 +{
 +      struct rpc_xprt *xprt =
 +              container_of(work, struct rpc_xprt, task_cleanup);
 +
 +      rpc_xprt_debugfs_unregister(xprt);
 +      rpc_destroy_wait_queue(&xprt->binding);
 +      rpc_destroy_wait_queue(&xprt->pending);
 +      rpc_destroy_wait_queue(&xprt->sending);
 +      rpc_destroy_wait_queue(&xprt->backlog);
 +      kfree(xprt->servername);
 +      /*
 +       * Tear down transport state and free the rpc_xprt
 +       */
 +      xprt->ops->destroy(xprt);
 +}
 +
  /**
   * xprt_destroy - destroy an RPC transport, killing off all requests.
   * @xprt: transport to destroy
@@@ -1470,19 -1455,22 +1471,19 @@@ static void xprt_destroy(struct rpc_xpr
  {
        dprintk("RPC:       destroying transport %p\n", xprt);
  
 -      /* Exclude transport connect/disconnect handlers */
 +      /*
 +       * Exclude transport connect/disconnect handlers and autoclose
 +       */
        wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_UNINTERRUPTIBLE);
  
        del_timer_sync(&xprt->timer);
  
 -      rpc_xprt_debugfs_unregister(xprt);
 -      rpc_destroy_wait_queue(&xprt->binding);
 -      rpc_destroy_wait_queue(&xprt->pending);
 -      rpc_destroy_wait_queue(&xprt->sending);
 -      rpc_destroy_wait_queue(&xprt->backlog);
 -      cancel_work_sync(&xprt->task_cleanup);
 -      kfree(xprt->servername);
        /*
 -       * Tear down transport state and free the rpc_xprt
 +       * Destroy sockets etc from the system workqueue so they can
 +       * safely flush receive work running on rpciod.
         */
 -      xprt->ops->destroy(xprt);
 +      INIT_WORK(&xprt->task_cleanup, xprt_destroy_cb);
 +      schedule_work(&xprt->task_cleanup);
  }
  
  static void xprt_destroy_kref(struct kref *kref)
index 823a781ec89cf6401f6c4988e5895072579e1ece,088c9cc259d7e0c6ca7d840275e9b7f8ea5cdc14..8b818bb3518a9694a4e5f2bba2c7fe25de9c9cae
@@@ -1,4 -1,3 +1,4 @@@
 +// SPDX-License-Identifier: GPL-2.0
  /*
   * Copyright (c) 2015 Oracle.  All rights reserved.
   *
@@@ -43,7 -42,7 +43,7 @@@ static int rpcrdma_bc_setup_rqst(struc
        req = rpcrdma_create_req(r_xprt);
        if (IS_ERR(req))
                return PTR_ERR(req);
-       req->rl_backchannel = true;
+       __set_bit(RPCRDMA_REQ_F_BACKCHANNEL, &req->rl_flags);
  
        rb = rpcrdma_alloc_regbuf(RPCRDMA_HDRBUF_SIZE,
                                  DMA_TO_DEVICE, GFP_KERNEL);
@@@ -223,8 -222,8 +223,8 @@@ int rpcrdma_bc_marshal_reply(struct rpc
        *p++ = xdr_zero;
        *p = xdr_zero;
  
-       if (!rpcrdma_prepare_send_sges(&r_xprt->rx_ia, req, RPCRDMA_HDRLEN_MIN,
-                                      &rqst->rq_snd_buf, rpcrdma_noch))
+       if (rpcrdma_prepare_send_sges(r_xprt, req, RPCRDMA_HDRLEN_MIN,
+                                     &rqst->rq_snd_buf, rpcrdma_noch))
                return -EIO;
        return 0;
  }
index fa759dd2b0f3de787d6bc127cd32961646db9f6a,30bf713080f1e0d1fc06cdf3d2cc308485e795a6..29fc84c7ff98ff49b272deeb3b1a46759b794ca2
@@@ -1,4 -1,3 +1,4 @@@
 +// SPDX-License-Identifier: GPL-2.0
  /*
   * Copyright (c) 2015 Oracle.  All rights reserved.
   * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
@@@ -306,28 -305,9 +306,9 @@@ out_reset
        }
  }
  
- /* Use a slow, safe mechanism to invalidate all memory regions
-  * that were registered for "req".
-  */
- static void
- fmr_op_unmap_safe(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req,
-                 bool sync)
- {
-       struct rpcrdma_mw *mw;
-       while (!list_empty(&req->rl_registered)) {
-               mw = rpcrdma_pop_mw(&req->rl_registered);
-               if (sync)
-                       fmr_op_recover_mr(mw);
-               else
-                       rpcrdma_defer_mr_recovery(mw);
-       }
- }
  const struct rpcrdma_memreg_ops rpcrdma_fmr_memreg_ops = {
        .ro_map                         = fmr_op_map,
        .ro_unmap_sync                  = fmr_op_unmap_sync,
-       .ro_unmap_safe                  = fmr_op_unmap_safe,
        .ro_recover_mr                  = fmr_op_recover_mr,
        .ro_open                        = fmr_op_open,
        .ro_maxpages                    = fmr_op_maxpages,
index 35d7517ef0e6e0af54fea8b6c02ad69d4cfb8304,404166ac958feda6a566c2380c29628841058bc8..773e66e10a15974518ab30089b9812f467bbf6fe
@@@ -1,4 -1,3 +1,4 @@@
 +// SPDX-License-Identifier: GPL-2.0
  /*
   * Copyright (c) 2015 Oracle.  All rights reserved.
   * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
@@@ -420,7 -419,6 +420,6 @@@ frwr_op_map(struct rpcrdma_xprt *r_xprt
                         IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE :
                         IB_ACCESS_REMOTE_READ;
  
-       rpcrdma_set_signaled(&r_xprt->rx_ep, &reg_wr->wr);
        rc = ib_post_send(ia->ri_id->qp, &reg_wr->wr, &bad_wr);
        if (rc)
                goto out_senderr;
@@@ -508,12 -506,6 +507,6 @@@ frwr_op_unmap_sync(struct rpcrdma_xprt 
        f->fr_cqe.done = frwr_wc_localinv_wake;
        reinit_completion(&f->fr_linv_done);
  
-       /* Initialize CQ count, since there is always a signaled
-        * WR being posted here.  The new cqcount depends on how
-        * many SQEs are about to be consumed.
-        */
-       rpcrdma_init_cqcount(&r_xprt->rx_ep, count);
        /* Transport disconnect drains the receive CQ before it
         * replaces the QP. The RPC reply handler won't call us
         * unless ri_id->qp is a valid pointer.
@@@ -546,7 -538,6 +539,6 @@@ reset_mrs
        /* Find and reset the MRs in the LOCAL_INV WRs that did not
         * get posted.
         */
-       rpcrdma_init_cqcount(&r_xprt->rx_ep, -count);
        while (bad_wr) {
                f = container_of(bad_wr, struct rpcrdma_frmr,
                                 fr_invwr);
        goto unmap;
  }
  
- /* Use a slow, safe mechanism to invalidate all memory regions
-  * that were registered for "req".
-  */
- static void
- frwr_op_unmap_safe(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req,
-                  bool sync)
- {
-       struct rpcrdma_mw *mw;
-       while (!list_empty(&req->rl_registered)) {
-               mw = rpcrdma_pop_mw(&req->rl_registered);
-               if (sync)
-                       frwr_op_recover_mr(mw);
-               else
-                       rpcrdma_defer_mr_recovery(mw);
-       }
- }
  const struct rpcrdma_memreg_ops rpcrdma_frwr_memreg_ops = {
        .ro_map                         = frwr_op_map,
        .ro_unmap_sync                  = frwr_op_unmap_sync,
-       .ro_unmap_safe                  = frwr_op_unmap_safe,
        .ro_recover_mr                  = frwr_op_recover_mr,
        .ro_open                        = frwr_op_open,
        .ro_maxpages                    = frwr_op_maxpages,
diff --combined net/sunrpc/xprtsock.c
index 4dad5da388d6101a25ac3f2d3cbfdb2ac9f311aa,684e356b40e4c329a785909a8d27162896ccd938..9cc850c2719e7da3216f3fdba66b752e99152b76
@@@ -1,4 -1,3 +1,4 @@@
 +// SPDX-License-Identifier: GPL-2.0
  /*
   * linux/net/sunrpc/xprtsock.c
   *
@@@ -552,6 -551,7 +552,7 @@@ static int xs_local_send_request(struc
        default:
                dprintk("RPC:       sendmsg returned unrecognized error %d\n",
                        -status);
+               /* fall through */
        case -EPIPE:
                xs_close(xprt);
                status = -ENOTCONN;
@@@ -1611,6 -1611,7 +1612,7 @@@ static void xs_tcp_state_change(struct 
                xprt->connect_cookie++;
                clear_bit(XPRT_CONNECTED, &xprt->state);
                xs_tcp_force_close(xprt);
+               /* fall through */
        case TCP_CLOSING:
                /*
                 * If the server closed down the connection, make sure that
@@@ -2368,6 -2369,7 +2370,7 @@@ static int xs_tcp_finish_connecting(str
        switch (ret) {
        case 0:
                xs_set_srcport(transport, sock);
+               /* fall through */
        case -EINPROGRESS:
                /* SYN_SENT! */
                if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
@@@ -2419,6 -2421,7 +2422,7 @@@ static void xs_tcp_setup_socket(struct 
        default:
                printk("%s: connect returned unhandled error %d\n",
                        __func__, status);
+               /* fall through */
        case -EADDRNOTAVAIL:
                /* We're probably in TIME_WAIT. Get rid of existing socket,
                 * and retry