Merge tag 'nfs-for-5.17-1' of git://git.linux-nfs.org/projects/anna/linux-nfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 25 Jan 2022 18:16:03 +0000 (20:16 +0200)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 25 Jan 2022 18:16:03 +0000 (20:16 +0200)
Pull NFS client updates from Anna Schumaker:
 "New Features:

   - Basic handling for case insensitive filesystems

   - Initial support for fs_locations and server trunking

  Bugfixes and Cleanups:

   - Cleanups to how the "struct cred *" is handled for the
     nfs_access_entry

   - Ensure the server has an up to date ctimes before hardlinking or
     renaming

   - Update 'blocks used' after writeback, fallocate, and clone

   - nfs_atomic_open() fixes

   - Improvements to sunrpc tracing

   - Various null check & indenting related cleanups

   - Some improvements to the sunrpc sysfs code:
      - Use default_groups in kobj_type
      - Fix some potential races and reference leaks

   - A few tracepoint cleanups in xprtrdma"

[ This should have gone in during the merge window, but didn't. The
  original pull request - sent during the merge window - had gotten
  marked as spam and discarded due missing DKIM headers in the email
  from Anna.   - Linus ]

* tag 'nfs-for-5.17-1' of git://git.linux-nfs.org/projects/anna/linux-nfs: (35 commits)
  SUNRPC: Don't dereference xprt->snd_task if it's a cookie
  xprtrdma: Remove definitions of RPCDBG_FACILITY
  xprtrdma: Remove final dprintk call sites from xprtrdma
  sunrpc: Fix potential race conditions in rpc_sysfs_xprt_state_change()
  net/sunrpc: fix reference count leaks in rpc_sysfs_xprt_state_change
  NFSv4.1 test and add 4.1 trunking transport
  SUNRPC allow for unspecified transport time in rpc_clnt_add_xprt
  NFSv4 handle port presence in fs_location server string
  NFSv4 expose nfs_parse_server_name function
  NFSv4.1 query for fs_location attr on a new file system
  NFSv4 store server support for fs_location attribute
  NFSv4 remove zero number of fs_locations entries error check
  NFSv4: nfs_atomic_open() can race when looking up a non-regular file
  NFSv4: Handle case where the lookup of a directory fails
  NFSv42: Fallocate and clone should also request 'blocks used'
  NFSv4: Allow writebacks to request 'blocks used'
  SUNRPC: use default_groups in kobj_type
  NFS: use default_groups in kobj_type
  NFS: Fix the verifier for case sensitive filesystem in nfs_atomic_open()
  NFS: Add a helper to remove case-insensitive aliases
  ...

1  2 
fs/nfs/client.c
fs/nfs/dir.c
fs/nfs/nfs4state.c
include/linux/nfs_fs.h
include/linux/nfs_fs_sb.h
include/trace/events/sunrpc.h

diff --combined fs/nfs/client.c
@@@ -183,6 -183,8 +183,6 @@@ struct nfs_client *nfs_alloc_client(con
        clp->cl_net = get_net(cl_init->net);
  
        clp->cl_principal = "*";
 -      nfs_fscache_get_client_cookie(clp);
 -
        return clp;
  
  error_cleanup:
@@@ -236,6 -238,8 +236,6 @@@ static void pnfs_init_server(struct nfs
   */
  void nfs_free_client(struct nfs_client *clp)
  {
 -      nfs_fscache_release_client_cookie(clp);
 -
        /* -EIO all pending I/O */
        if (!IS_ERR(clp->cl_rpcclient))
                rpc_shutdown_client(clp->cl_rpcclient);
@@@ -856,6 -860,13 +856,13 @@@ static int nfs_probe_fsinfo(struct nfs_
                        server->namelen = pathinfo.max_namelen;
        }
  
+       if (clp->rpc_ops->discover_trunking != NULL &&
+                       (server->caps & NFS_CAP_FS_LOCATIONS)) {
+               error = clp->rpc_ops->discover_trunking(server, mntfh);
+               if (error < 0)
+                       return error;
+       }
        return 0;
  }
  
diff --combined fs/nfs/dir.c
@@@ -18,7 -18,6 +18,7 @@@
   *  6 Jun 1999        Cache readdir lookups in the page cache. -DaveM
   */
  
 +#include <linux/compat.h>
  #include <linux/module.h>
  #include <linux/time.h>
  #include <linux/errno.h>
@@@ -1325,6 -1324,14 +1325,14 @@@ void nfs_clear_verifier_delegated(struc
  EXPORT_SYMBOL_GPL(nfs_clear_verifier_delegated);
  #endif /* IS_ENABLED(CONFIG_NFS_V4) */
  
+ static int nfs_dentry_verify_change(struct inode *dir, struct dentry *dentry)
+ {
+       if (nfs_server_capable(dir, NFS_CAP_CASE_INSENSITIVE) &&
+           d_really_is_negative(dentry))
+               return dentry->d_time == inode_peek_iversion_raw(dir);
+       return nfs_verify_change_attribute(dir, dentry->d_time);
+ }
  /*
   * A check for whether or not the parent directory has changed.
   * In the case it has, we assume that the dentries are untrustworthy
@@@ -1338,7 -1345,7 +1346,7 @@@ static int nfs_check_verifier(struct in
                return 1;
        if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONE)
                return 0;
-       if (!nfs_verify_change_attribute(dir, dentry->d_time))
+       if (!nfs_dentry_verify_change(dir, dentry))
                return 0;
        /* Revalidate nfsi->cache_change_attribute before we declare a match */
        if (nfs_mapping_need_revalidate_inode(dir)) {
                if (__nfs_revalidate_inode(NFS_SERVER(dir), dir) < 0)
                        return 0;
        }
-       if (!nfs_verify_change_attribute(dir, dentry->d_time))
+       if (!nfs_dentry_verify_change(dir, dentry))
                return 0;
        return 1;
  }
@@@ -1437,6 -1444,9 +1445,9 @@@ int nfs_neg_need_reval(struct inode *di
                return 0;
        if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG)
                return 1;
+       /* Case insensitive server? Revalidate negative dentries */
+       if (nfs_server_capable(dir, NFS_CAP_CASE_INSENSITIVE))
+               return 1;
        return !nfs_check_verifier(dir, dentry, flags & LOOKUP_RCU);
  }
  
@@@ -1537,7 -1547,7 +1548,7 @@@ out
         * If the lookup failed despite the dentry change attribute being
         * a match, then we should revalidate the directory cache.
         */
-       if (!ret && nfs_verify_change_attribute(dir, dentry->d_time))
+       if (!ret && nfs_dentry_verify_change(dir, dentry))
                nfs_mark_dir_for_revalidate(dir);
        return nfs_lookup_revalidate_done(dir, dentry, inode, ret);
  }
@@@ -1776,8 -1786,11 +1787,11 @@@ struct dentry *nfs_lookup(struct inode 
        dir_verifier = nfs_save_change_attribute(dir);
        trace_nfs_lookup_enter(dir, dentry, flags);
        error = NFS_PROTO(dir)->lookup(dir, dentry, fhandle, fattr);
-       if (error == -ENOENT)
+       if (error == -ENOENT) {
+               if (nfs_server_capable(dir, NFS_CAP_CASE_INSENSITIVE))
+                       dir_verifier = inode_peek_iversion_raw(dir);
                goto no_entry;
+       }
        if (error < 0) {
                res = ERR_PTR(error);
                goto out;
  }
  EXPORT_SYMBOL_GPL(nfs_lookup);
  
+ void nfs_d_prune_case_insensitive_aliases(struct inode *inode)
+ {
+       /* Case insensitive server? Revalidate dentries */
+       if (inode && nfs_server_capable(inode, NFS_CAP_CASE_INSENSITIVE))
+               d_prune_aliases(inode);
+ }
+ EXPORT_SYMBOL_GPL(nfs_d_prune_case_insensitive_aliases);
  #if IS_ENABLED(CONFIG_NFS_V4)
  static int nfs4_lookup_revalidate(struct dentry *, unsigned int);
  
@@@ -1867,6 -1888,7 +1889,7 @@@ int nfs_atomic_open(struct inode *dir, 
        struct iattr attr = { .ia_valid = ATTR_OPEN };
        struct inode *inode;
        unsigned int lookup_flags = 0;
+       unsigned long dir_verifier;
        bool switched = false;
        int created = 0;
        int err;
                switch (err) {
                case -ENOENT:
                        d_splice_alias(NULL, dentry);
-                       nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+                       if (nfs_server_capable(dir, NFS_CAP_CASE_INSENSITIVE))
+                               dir_verifier = inode_peek_iversion_raw(dir);
+                       else
+                               dir_verifier = nfs_save_change_attribute(dir);
+                       nfs_set_verifier(dentry, dir_verifier);
                        break;
                case -EISDIR:
                case -ENOTDIR:
  
  no_open:
        res = nfs_lookup(dir, dentry, lookup_flags);
+       if (!res) {
+               inode = d_inode(dentry);
+               if ((lookup_flags & LOOKUP_DIRECTORY) && inode &&
+                   !S_ISDIR(inode->i_mode))
+                       res = ERR_PTR(-ENOTDIR);
+               else if (inode && S_ISREG(inode->i_mode))
+                       res = ERR_PTR(-EOPENSTALE);
+       } else if (!IS_ERR(res)) {
+               inode = d_inode(res);
+               if ((lookup_flags & LOOKUP_DIRECTORY) && inode &&
+                   !S_ISDIR(inode->i_mode)) {
+                       dput(res);
+                       res = ERR_PTR(-ENOTDIR);
+               } else if (inode && S_ISREG(inode->i_mode)) {
+                       dput(res);
+                       res = ERR_PTR(-EOPENSTALE);
+               }
+       }
        if (switched) {
                d_lookup_done(dentry);
                if (!res)
@@@ -2186,8 -2230,10 +2231,10 @@@ static void nfs_dentry_remove_handle_er
        switch (error) {
        case -ENOENT:
                d_delete(dentry);
-               fallthrough;
+               nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+               break;
        case 0:
+               nfs_d_prune_case_insensitive_aliases(d_inode(dentry));
                nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
        }
  }
@@@ -2380,6 -2426,8 +2427,8 @@@ nfs_link(struct dentry *old_dentry, str
  
        trace_nfs_link_enter(inode, dir, dentry);
        d_drop(dentry);
+       if (S_ISREG(inode->i_mode))
+               nfs_sync_inode(inode);
        error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
        if (error == 0) {
                nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
@@@ -2469,6 -2517,8 +2518,8 @@@ int nfs_rename(struct user_namespace *m
                }
        }
  
+       if (S_ISREG(old_inode->i_mode))
+               nfs_sync_inode(old_inode);
        task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry, NULL);
        if (IS_ERR(task)) {
                error = PTR_ERR(task);
@@@ -2529,7 -2579,7 +2580,7 @@@ MODULE_PARM_DESC(nfs_access_max_cachesi
  
  static void nfs_access_free_entry(struct nfs_access_entry *entry)
  {
-       put_cred(entry->cred);
+       put_group_info(entry->group_info);
        kfree_rcu(entry, rcu_head);
        smp_mb__before_atomic();
        atomic_long_dec(&nfs_access_nr_entries);
@@@ -2655,6 -2705,43 +2706,43 @@@ void nfs_access_zap_cache(struct inode 
  }
  EXPORT_SYMBOL_GPL(nfs_access_zap_cache);
  
+ static int access_cmp(const struct cred *a, const struct nfs_access_entry *b)
+ {
+       struct group_info *ga, *gb;
+       int g;
+       if (uid_lt(a->fsuid, b->fsuid))
+               return -1;
+       if (uid_gt(a->fsuid, b->fsuid))
+               return 1;
+       if (gid_lt(a->fsgid, b->fsgid))
+               return -1;
+       if (gid_gt(a->fsgid, b->fsgid))
+               return 1;
+       ga = a->group_info;
+       gb = b->group_info;
+       if (ga == gb)
+               return 0;
+       if (ga == NULL)
+               return -1;
+       if (gb == NULL)
+               return 1;
+       if (ga->ngroups < gb->ngroups)
+               return -1;
+       if (ga->ngroups > gb->ngroups)
+               return 1;
+       for (g = 0; g < ga->ngroups; g++) {
+               if (gid_lt(ga->gid[g], gb->gid[g]))
+                       return -1;
+               if (gid_gt(ga->gid[g], gb->gid[g]))
+                       return 1;
+       }
+       return 0;
+ }
  static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, const struct cred *cred)
  {
        struct rb_node *n = NFS_I(inode)->access_cache.rb_node;
        while (n != NULL) {
                struct nfs_access_entry *entry =
                        rb_entry(n, struct nfs_access_entry, rb_node);
-               int cmp = cred_fscmp(cred, entry->cred);
+               int cmp = access_cmp(cred, entry);
  
                if (cmp < 0)
                        n = n->rb_left;
        return NULL;
  }
  
- static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *cred, struct nfs_access_entry *res, bool may_block)
+ static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *cred, u32 *mask, bool may_block)
  {
        struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_access_entry *cache;
                spin_lock(&inode->i_lock);
                retry = false;
        }
-       res->cred = cache->cred;
-       res->mask = cache->mask;
+       *mask = cache->mask;
        list_move_tail(&cache->lru, &nfsi->access_cache_entry_lru);
        err = 0;
  out:
@@@ -2717,7 -2803,7 +2804,7 @@@ out_zap
        return -ENOENT;
  }
  
- static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cred, struct nfs_access_entry *res)
+ static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cred, u32 *mask)
  {
        /* Only check the most recently returned cache entry,
         * but do it without locking.
        lh = rcu_dereference(list_tail_rcu(&nfsi->access_cache_entry_lru));
        cache = list_entry(lh, struct nfs_access_entry, lru);
        if (lh == &nfsi->access_cache_entry_lru ||
-           cred_fscmp(cred, cache->cred) != 0)
+           access_cmp(cred, cache) != 0)
                cache = NULL;
        if (cache == NULL)
                goto out;
        if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_ACCESS))
                goto out;
-       res->cred = cache->cred;
-       res->mask = cache->mask;
+       *mask = cache->mask;
        err = 0;
  out:
        rcu_read_unlock();
        return err;
  }
  
- int nfs_access_get_cached(struct inode *inode, const struct cred *cred, struct
nfs_access_entry *res, bool may_block)
+ int nfs_access_get_cached(struct inode *inode, const struct cred *cred,
                        u32 *mask, bool may_block)
  {
        int status;
  
-       status = nfs_access_get_cached_rcu(inode, cred, res);
+       status = nfs_access_get_cached_rcu(inode, cred, mask);
        if (status != 0)
-               status = nfs_access_get_cached_locked(inode, cred, res,
+               status = nfs_access_get_cached_locked(inode, cred, mask,
                    may_block);
  
        return status;
  }
  EXPORT_SYMBOL_GPL(nfs_access_get_cached);
  
- static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *set)
+ static void nfs_access_add_rbtree(struct inode *inode,
+                                 struct nfs_access_entry *set,
+                                 const struct cred *cred)
  {
        struct nfs_inode *nfsi = NFS_I(inode);
        struct rb_root *root_node = &nfsi->access_cache;
        while (*p != NULL) {
                parent = *p;
                entry = rb_entry(parent, struct nfs_access_entry, rb_node);
-               cmp = cred_fscmp(set->cred, entry->cred);
+               cmp = access_cmp(cred, entry);
  
                if (cmp < 0)
                        p = &parent->rb_left;
@@@ -2796,13 -2883,16 +2884,16 @@@ found
        nfs_access_free_entry(entry);
  }
  
- void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
+ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set,
+                         const struct cred *cred)
  {
        struct nfs_access_entry *cache = kmalloc(sizeof(*cache), GFP_KERNEL);
        if (cache == NULL)
                return;
        RB_CLEAR_NODE(&cache->rb_node);
-       cache->cred = get_cred(set->cred);
+       cache->fsuid = cred->fsuid;
+       cache->fsgid = cred->fsgid;
+       cache->group_info = get_group_info(cred->group_info);
        cache->mask = set->mask;
  
        /* The above field assignments must be visible
         * use rcu_assign_pointer, so just force the memory barrier.
         */
        smp_wmb();
-       nfs_access_add_rbtree(inode, cache);
+       nfs_access_add_rbtree(inode, cache, cred);
  
        /* Update accounting */
        smp_mb__before_atomic();
@@@ -2875,7 -2965,7 +2966,7 @@@ static int nfs_do_access(struct inode *
  
        trace_nfs_access_enter(inode);
  
-       status = nfs_access_get_cached(inode, cred, &cache, may_block);
+       status = nfs_access_get_cached(inode, cred, &cache.mask, may_block);
        if (status == 0)
                goto out_cached;
  
                cache.mask |= NFS_ACCESS_DELETE | NFS_ACCESS_LOOKUP;
        else
                cache.mask |= NFS_ACCESS_EXECUTE;
-       cache.cred = cred;
-       status = NFS_PROTO(inode)->access(inode, &cache);
+       status = NFS_PROTO(inode)->access(inode, &cache, cred);
        if (status != 0) {
                if (status == -ESTALE) {
                        if (!S_ISDIR(inode->i_mode))
                }
                goto out;
        }
-       nfs_access_add_cache(inode, &cache);
+       nfs_access_add_cache(inode, &cache, cred);
  out_cached:
        cache_mask = nfs_access_calc_mask(cache.mask, inode->i_mode);
        if ((mask & ~cache_mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) != 0)
diff --combined fs/nfs/nfs4state.c
@@@ -2098,7 -2098,8 +2098,8 @@@ static int nfs4_try_migration(struct nf
        }
  
        inode = d_inode(server->super->s_root);
-       result = nfs4_proc_get_locations(inode, locations, page, cred);
+       result = nfs4_proc_get_locations(server, NFS_FH(inode), locations,
+                                        page, cred);
        if (result) {
                dprintk("<-- %s: failed to retrieve fs_locations: %d\n",
                        __func__, result);
        }
  
        result = -NFS4ERR_NXIO;
+       if (!locations->nlocations)
+               goto out;
        if (!(locations->fattr.valid & NFS_ATTR_FATTR_V4_LOCATIONS)) {
                dprintk("<-- %s: No fs_locations data, migration skipped\n",
                        __func__);
@@@ -2693,6 -2697,6 +2697,6 @@@ static int nfs4_run_state_manager(void 
        allow_signal(SIGKILL);
        nfs4_state_manager(clp);
        nfs_put_client(clp);
 -      module_put_and_exit(0);
 +      module_put_and_kthread_exit(0);
        return 0;
  }
diff --combined include/linux/nfs_fs.h
@@@ -61,7 -61,9 +61,9 @@@
  struct nfs_access_entry {
        struct rb_node          rb_node;
        struct list_head        lru;
-       const struct cred *     cred;
+       kuid_t                  fsuid;
+       kgid_t                  fsgid;
+       struct group_info       *group_info;
        __u32                   mask;
        struct rcu_head         rcu_head;
  };
@@@ -275,6 -277,7 +277,6 @@@ struct nfs4_copy_state 
  #define NFS_INO_ACL_LRU_SET   (2)             /* Inode is on the LRU list */
  #define NFS_INO_INVALIDATING  (3)             /* inode is being invalidated */
  #define NFS_INO_FSCACHE               (5)             /* inode can be cached by FS-Cache */
 -#define NFS_INO_FSCACHE_LOCK  (6)             /* FS-Cache cookie management lock */
  #define NFS_INO_FORCE_READDIR (7)             /* force readdirplus */
  #define NFS_INO_LAYOUTCOMMIT  (9)             /* layoutcommit required */
  #define NFS_INO_LAYOUTCOMMITTING (10)         /* layoutcommit inflight */
@@@ -395,7 -398,7 +397,7 @@@ extern int nfs_post_op_update_inode_for
  extern int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fattr *fattr);
  extern int nfs_getattr(struct user_namespace *, const struct path *,
                       struct kstat *, u32, unsigned int);
- extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *);
+ extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *, const struct cred *);
  extern void nfs_access_set_mask(struct nfs_access_entry *, u32);
  extern int nfs_permission(struct user_namespace *, struct inode *, int);
  extern int nfs_open(struct inode *, struct file *);
@@@ -532,8 -535,8 +534,8 @@@ extern int nfs_instantiate(struct dentr
                        struct nfs_fattr *fattr);
  extern int nfs_may_open(struct inode *inode, const struct cred *cred, int openflags);
  extern void nfs_access_zap_cache(struct inode *inode);
- extern int nfs_access_get_cached(struct inode *inode, const struct cred *cred, struct nfs_access_entry *res,
-                                bool may_block);
+ extern int nfs_access_get_cached(struct inode *inode, const struct cred *cred,
+                                u32 *mask, bool may_block);
  
  /*
   * linux/fs/nfs/symlink.c
@@@ -120,6 -120,11 +120,6 @@@ struct nfs_client 
         * This is used to generate the mv0 callback address.
         */
        char                    cl_ipaddr[48];
 -
 -#ifdef CONFIG_NFS_FSCACHE
 -      struct fscache_cookie   *fscache;       /* client index cache cookie */
 -#endif
 -
        struct net              *cl_net;
        struct list_head        pending_cb_stateids;
  };
@@@ -189,8 -194,8 +189,8 @@@ struct nfs_server 
        struct nfs_auth_info    auth_info;      /* parsed auth flavors */
  
  #ifdef CONFIG_NFS_FSCACHE
 -      struct nfs_fscache_key  *fscache_key;   /* unique key for superblock */
 -      struct fscache_cookie   *fscache;       /* superblock cookie */
 +      struct fscache_volume   *fscache;       /* superblock cookie */
 +      char                    *fscache_uniq;  /* Uniquifier (or NULL) */
  #endif
  
        u32                     pnfs_blksize;   /* layout_blksize attr */
  #define NFS_CAP_ACLS          (1U << 3)
  #define NFS_CAP_ATOMIC_OPEN   (1U << 4)
  #define NFS_CAP_LGOPEN                (1U << 5)
+ #define NFS_CAP_CASE_INSENSITIVE      (1U << 6)
+ #define NFS_CAP_CASE_PRESERVING       (1U << 7)
  #define NFS_CAP_POSIX_LOCK    (1U << 14)
  #define NFS_CAP_UIDGID_NOMAP  (1U << 15)
  #define NFS_CAP_STATEID_NFSV41        (1U << 16)
  #define NFS_CAP_COPY_NOTIFY   (1U << 27)
  #define NFS_CAP_XATTR         (1U << 28)
  #define NFS_CAP_READ_PLUS     (1U << 29)
+ #define NFS_CAP_FS_LOCATIONS  (1U << 30)
  #endif
@@@ -794,6 -794,9 +794,9 @@@ RPC_SHOW_SOCKE
  
  RPC_SHOW_SOCK
  
+ #include <trace/events/net_probe_common.h>
  /*
   * Now redefine the EM() and EMe() macros to map the enums to the strings
   * that will be printed in the output.
@@@ -816,27 -819,32 +819,32 @@@ DECLARE_EVENT_CLASS(xs_socket_event
                        __field(unsigned int, socket_state)
                        __field(unsigned int, sock_state)
                        __field(unsigned long long, ino)
-                       __string(dstaddr,
-                               xprt->address_strings[RPC_DISPLAY_ADDR])
-                       __string(dstport,
-                               xprt->address_strings[RPC_DISPLAY_PORT])
+                       __array(__u8, saddr, sizeof(struct sockaddr_in6))
+                       __array(__u8, daddr, sizeof(struct sockaddr_in6))
                ),
  
                TP_fast_assign(
                        struct inode *inode = SOCK_INODE(socket);
+                       const struct sock *sk = socket->sk;
+                       const struct inet_sock *inet = inet_sk(sk);
+                       memset(__entry->saddr, 0, sizeof(struct sockaddr_in6));
+                       memset(__entry->daddr, 0, sizeof(struct sockaddr_in6));
+                       TP_STORE_ADDR_PORTS(__entry, inet, sk);
                        __entry->socket_state = socket->state;
                        __entry->sock_state = socket->sk->sk_state;
                        __entry->ino = (unsigned long long)inode->i_ino;
-                       __assign_str(dstaddr,
-                               xprt->address_strings[RPC_DISPLAY_ADDR]);
-                       __assign_str(dstport,
-                               xprt->address_strings[RPC_DISPLAY_PORT]);
                ),
  
                TP_printk(
-                       "socket:[%llu] dstaddr=%s/%s "
+                       "socket:[%llu] srcaddr=%pISpc dstaddr=%pISpc "
                        "state=%u (%s) sk_state=%u (%s)",
-                       __entry->ino, __get_str(dstaddr), __get_str(dstport),
+                       __entry->ino,
+                       __entry->saddr,
+                       __entry->daddr,
                        __entry->socket_state,
                        rpc_show_socket_state(__entry->socket_state),
                        __entry->sock_state,
@@@ -866,29 -874,33 +874,33 @@@ DECLARE_EVENT_CLASS(xs_socket_event_don
                        __field(unsigned int, socket_state)
                        __field(unsigned int, sock_state)
                        __field(unsigned long long, ino)
-                       __string(dstaddr,
-                               xprt->address_strings[RPC_DISPLAY_ADDR])
-                       __string(dstport,
-                               xprt->address_strings[RPC_DISPLAY_PORT])
+                       __array(__u8, saddr, sizeof(struct sockaddr_in6))
+                       __array(__u8, daddr, sizeof(struct sockaddr_in6))
                ),
  
                TP_fast_assign(
                        struct inode *inode = SOCK_INODE(socket);
+                       const struct sock *sk = socket->sk;
+                       const struct inet_sock *inet = inet_sk(sk);
+                       memset(__entry->saddr, 0, sizeof(struct sockaddr_in6));
+                       memset(__entry->daddr, 0, sizeof(struct sockaddr_in6));
+                       TP_STORE_ADDR_PORTS(__entry, inet, sk);
                        __entry->socket_state = socket->state;
                        __entry->sock_state = socket->sk->sk_state;
                        __entry->ino = (unsigned long long)inode->i_ino;
                        __entry->error = error;
-                       __assign_str(dstaddr,
-                               xprt->address_strings[RPC_DISPLAY_ADDR]);
-                       __assign_str(dstport,
-                               xprt->address_strings[RPC_DISPLAY_PORT]);
                ),
  
                TP_printk(
-                       "error=%d socket:[%llu] dstaddr=%s/%s "
+                       "error=%d socket:[%llu] srcaddr=%pISpc dstaddr=%pISpc "
                        "state=%u (%s) sk_state=%u (%s)",
                        __entry->error,
-                       __entry->ino, __get_str(dstaddr), __get_str(dstport),
+                       __entry->ino,
+                       __entry->saddr,
+                       __entry->daddr,
                        __entry->socket_state,
                        rpc_show_socket_state(__entry->socket_state),
                        __entry->sock_state,
@@@ -953,7 -965,8 +965,8 @@@ TRACE_EVENT(rpc_socket_nospace
                { BIT(XPRT_REMOVE),             "REMOVE" },             \
                { BIT(XPRT_CONGESTED),          "CONGESTED" },          \
                { BIT(XPRT_CWND_WAIT),          "CWND_WAIT" },          \
-               { BIT(XPRT_WRITE_SPACE),        "WRITE_SPACE" })
+               { BIT(XPRT_WRITE_SPACE),        "WRITE_SPACE" },        \
+               { BIT(XPRT_SND_IS_COOKIE),      "SND_IS_COOKIE" })
  
  DECLARE_EVENT_CLASS(rpc_xprt_lifetime_class,
        TP_PROTO(
@@@ -1150,8 -1163,11 +1163,11 @@@ DECLARE_EVENT_CLASS(xprt_writelock_even
                        __entry->task_id = -1;
                        __entry->client_id = -1;
                }
-               __entry->snd_task_id = xprt->snd_task ?
-                                       xprt->snd_task->tk_pid : -1;
+               if (xprt->snd_task &&
+                   !test_bit(XPRT_SND_IS_COOKIE, &xprt->state))
+                       __entry->snd_task_id = xprt->snd_task->tk_pid;
+               else
+                       __entry->snd_task_id = -1;
        ),
  
        TP_printk(SUNRPC_TRACE_TASK_SPECIFIER
@@@ -1196,8 -1212,12 +1212,12 @@@ DECLARE_EVENT_CLASS(xprt_cong_event
                        __entry->task_id = -1;
                        __entry->client_id = -1;
                }
-               __entry->snd_task_id = xprt->snd_task ?
-                                       xprt->snd_task->tk_pid : -1;
+               if (xprt->snd_task &&
+                   !test_bit(XPRT_SND_IS_COOKIE, &xprt->state))
+                       __entry->snd_task_id = xprt->snd_task->tk_pid;
+               else
+                       __entry->snd_task_id = -1;
                __entry->cong = xprt->cong;
                __entry->cwnd = xprt->cwnd;
                __entry->wait = test_bit(XPRT_CWND_WAIT, &xprt->state);
@@@ -1744,11 -1764,10 +1764,11 @@@ TRACE_EVENT(svc_xprt_create_err
                const char *program,
                const char *protocol,
                struct sockaddr *sap,
 +              size_t salen,
                const struct svc_xprt *xprt
        ),
  
 -      TP_ARGS(program, protocol, sap, xprt),
 +      TP_ARGS(program, protocol, sap, salen, xprt),
  
        TP_STRUCT__entry(
                __field(long, error)
                __entry->error = PTR_ERR(xprt);
                __assign_str(program, program);
                __assign_str(protocol, protocol);
 -              memcpy(__entry->addr, sap, sizeof(__entry->addr));
 +              memcpy(__entry->addr, sap, min(salen, sizeof(__entry->addr)));
        ),
  
        TP_printk("addr=%pISpc program=%s protocol=%s error=%ld",
                __entry->error)
  );
  
 -TRACE_EVENT(svc_xprt_do_enqueue,
 +TRACE_EVENT(svc_xprt_enqueue,
        TP_PROTO(struct svc_xprt *xprt, struct svc_rqst *rqst),
  
        TP_ARGS(xprt, rqst),
@@@ -1816,6 -1835,7 +1836,6 @@@ DECLARE_EVENT_CLASS(svc_xprt_event
                        ), \
                        TP_ARGS(xprt))
  
 -DEFINE_SVC_XPRT_EVENT(received);
  DEFINE_SVC_XPRT_EVENT(no_write_space);
  DEFINE_SVC_XPRT_EVENT(close);
  DEFINE_SVC_XPRT_EVENT(detach);
@@@ -1902,6 -1922,27 +1922,6 @@@ TRACE_EVENT(svc_alloc_arg_err
        TP_printk("pages=%u", __entry->pages)
  );
  
 -TRACE_EVENT(svc_handle_xprt,
 -      TP_PROTO(struct svc_xprt *xprt, int len),
 -
 -      TP_ARGS(xprt, len),
 -
 -      TP_STRUCT__entry(
 -              __field(int, len)
 -              __field(unsigned long, flags)
 -              __string(addr, xprt->xpt_remotebuf)
 -      ),
 -
 -      TP_fast_assign(
 -              __entry->len = len;
 -              __entry->flags = xprt->xpt_flags;
 -              __assign_str(addr, xprt->xpt_remotebuf);
 -      ),
 -
 -      TP_printk("addr=%s len=%d flags=%s", __get_str(addr),
 -              __entry->len, show_svc_xprt_flags(__entry->flags))
 -);
 -
  TRACE_EVENT(svc_stats_latency,
        TP_PROTO(const struct svc_rqst *rqst),
  
@@@ -2125,17 -2166,17 +2145,17 @@@ DECLARE_EVENT_CLASS(svcsock_accept_clas
        TP_STRUCT__entry(
                __field(long, status)
                __string(service, service)
 -              __array(unsigned char, addr, sizeof(struct sockaddr_in6))
 +              __field(unsigned int, netns_ino)
        ),
  
        TP_fast_assign(
                __entry->status = status;
                __assign_str(service, service);
 -              memcpy(__entry->addr, &xprt->xpt_local, sizeof(__entry->addr));
 +              __entry->netns_ino = xprt->xpt_net->ns.inum;
        ),
  
 -      TP_printk("listener=%pISpc service=%s status=%ld",
 -              __entry->addr, __get_str(service), __entry->status
 +      TP_printk("addr=listener service=%s status=%ld",
 +              __get_str(service), __entry->status
        )
  );