Merge tag 'nfsd-5.5' of git://linux-nfs.org/~bfields/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 8 Dec 2019 00:56:00 +0000 (16:56 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 8 Dec 2019 00:56:00 +0000 (16:56 -0800)
Pull nfsd updates from Bruce Fields:
 "This is a relatively quiet cycle for nfsd, mainly various bugfixes.

  Possibly most interesting is Trond's fixes for some callback races
  that were due to my incomplete understanding of rpc client shutdown.
  Unfortunately at the last minute I've started noticing a new
  intermittent failure to send callbacks. As the logic seems basically
  correct, I'm leaving Trond's patches in for now, and hope to find a
  fix in the next week so I don't have to revert those patches"

* tag 'nfsd-5.5' of git://linux-nfs.org/~bfields/linux: (24 commits)
  nfsd: depend on CRYPTO_MD5 for legacy client tracking
  NFSD fixing possible null pointer derefering in copy offload
  nfsd: check for EBUSY from vfs_rmdir/vfs_unink.
  nfsd: Ensure CLONE persists data and metadata changes to the target file
  SUNRPC: Fix backchannel latency metrics
  nfsd: restore NFSv3 ACL support
  nfsd: v4 support requires CRYPTO_SHA256
  nfsd: Fix cld_net->cn_tfm initialization
  lockd: remove __KERNEL__ ifdefs
  sunrpc: remove __KERNEL__ ifdefs
  race in exportfs_decode_fh()
  nfsd: Drop LIST_HEAD where the variable it declares is never used.
  nfsd: document callback_wq serialization of callback code
  nfsd: mark cb path down on unknown errors
  nfsd: Fix races between nfsd4_cb_release() and nfsd4_shutdown_callback()
  nfsd: minor 4.1 callback cleanup
  SUNRPC: Fix svcauth_gss_proxy_init()
  SUNRPC: Trace gssproxy upcall results
  sunrpc: fix crash when cache_head become valid before update
  nfsd: remove private bin2hex implementation
  ...

1  2 
fs/nfsd/nfs4xdr.c
include/linux/sunrpc/clnt.h
include/linux/sunrpc/xprt.h
include/linux/sunrpc/xprtsock.h
include/trace/events/rpcrdma.h
include/trace/events/sunrpc.h
net/sunrpc/xprtsock.c

diff --combined fs/nfsd/nfs4xdr.c
@@@ -2991,9 -2991,18 +2991,9 @@@ nfsd4_encode_dirent_fattr(struct xdr_st
        __be32 nfserr;
        int ignore_crossmnt = 0;
  
 -      dentry = lookup_one_len_unlocked(name, cd->rd_fhp->fh_dentry, namlen);
 +      dentry = lookup_positive_unlocked(name, cd->rd_fhp->fh_dentry, namlen);
        if (IS_ERR(dentry))
                return nfserrno(PTR_ERR(dentry));
 -      if (d_really_is_negative(dentry)) {
 -              /*
 -               * we're not holding the i_mutex here, so there's
 -               * a window where this directory entry could have gone
 -               * away.
 -               */
 -              dput(dentry);
 -              return nfserr_noent;
 -      }
  
        exp_get(exp);
        /*
@@@ -3452,7 -3461,6 +3452,6 @@@ static __be32 nfsd4_encode_splice_read
        struct xdr_stream *xdr = &resp->xdr;
        struct xdr_buf *buf = xdr->buf;
        u32 eof;
-       long len;
        int space_left;
        __be32 nfserr;
        __be32 *p = xdr->p - 2;
        if (xdr->end - xdr->p < 1)
                return nfserr_resource;
  
-       len = maxcount;
        nfserr = nfsd_splice_read(read->rd_rqstp, read->rd_fhp,
                                  file, read->rd_offset, &maxcount, &eof);
        read->rd_length = maxcount;
@@@ -109,8 -109,6 +109,6 @@@ struct rpc_procinfo 
        const char *            p_name;         /* name of procedure */
  };
  
- #ifdef __KERNEL__
  struct rpc_create_args {
        struct net              *net;
        int                     protocol;
@@@ -149,7 -147,6 +147,7 @@@ struct rpc_add_xprt_test 
  #define RPC_CLNT_CREATE_NO_IDLE_TIMEOUT       (1UL << 8)
  #define RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT    (1UL << 9)
  #define RPC_CLNT_CREATE_SOFTERR               (1UL << 10)
 +#define RPC_CLNT_CREATE_REUSEPORT     (1UL << 11)
  
  struct rpc_clnt *rpc_create(struct rpc_create_args *args);
  struct rpc_clnt       *rpc_bind_new_program(struct rpc_clnt *,
@@@ -238,5 -235,4 +236,4 @@@ static inline int rpc_reply_expected(st
                (task->tk_msg.rpc_proc->p_decode != NULL);
  }
  
- #endif /* __KERNEL__ */
  #endif /* _LINUX_SUNRPC_CLNT_H */
@@@ -19,8 -19,6 +19,6 @@@
  #include <linux/sunrpc/xdr.h>
  #include <linux/sunrpc/msg_prot.h>
  
- #ifdef __KERNEL__
  #define RPC_MIN_SLOT_TABLE    (2U)
  #define RPC_DEF_SLOT_TABLE    (16U)
  #define RPC_MAX_SLOT_TABLE_LIMIT      (65536U)
@@@ -207,8 -205,7 +205,8 @@@ struct rpc_xprt 
        unsigned int            min_reqs;       /* min number of slots */
        unsigned int            num_reqs;       /* total slots */
        unsigned long           state;          /* transport state */
 -      unsigned char           resvport   : 1; /* use a reserved port */
 +      unsigned char           resvport   : 1, /* use a reserved port */
 +                              reuseport  : 1; /* reuse port on reconnect */
        atomic_t                swapper;        /* we're swapping over this
                                                   transport */
        unsigned int            bind_index;     /* bind function index */
@@@ -506,6 -503,4 +504,4 @@@ static inline void xprt_inject_disconne
  }
  #endif
  
- #endif /* __KERNEL__*/
  #endif /* _LINUX_SUNRPC_XPRT_H */
@@@ -8,8 -8,6 +8,6 @@@
  #ifndef _LINUX_SUNRPC_XPRTSOCK_H
  #define _LINUX_SUNRPC_XPRTSOCK_H
  
- #ifdef __KERNEL__
  int           init_socket_xprt(void);
  void          cleanup_socket_xprt(void);
  
@@@ -61,7 -59,6 +59,7 @@@ struct sock_xprt 
        struct mutex            recv_mutex;
        struct sockaddr_storage srcaddr;
        unsigned short          srcport;
 +      int                     xprt_err;
  
        /*
         * UDP socket buffer size parameters
@@@ -91,6 -88,4 +89,4 @@@
  #define XPRT_SOCK_WAKE_PENDING        (6)
  #define XPRT_SOCK_WAKE_DISCONNECT     (7)
  
- #endif /* __KERNEL__ */
  #endif /* _LINUX_SUNRPC_XPRTSOCK_H */
@@@ -85,44 -85,6 +85,44 @@@ DECLARE_EVENT_CLASS(xprtrdma_rxprt
                                ),                                      \
                                TP_ARGS(r_xprt))
  
 +DECLARE_EVENT_CLASS(xprtrdma_connect_class,
 +      TP_PROTO(
 +              const struct rpcrdma_xprt *r_xprt,
 +              int rc
 +      ),
 +
 +      TP_ARGS(r_xprt, rc),
 +
 +      TP_STRUCT__entry(
 +              __field(const void *, r_xprt)
 +              __field(int, rc)
 +              __field(int, connect_status)
 +              __string(addr, rpcrdma_addrstr(r_xprt))
 +              __string(port, rpcrdma_portstr(r_xprt))
 +      ),
 +
 +      TP_fast_assign(
 +              __entry->r_xprt = r_xprt;
 +              __entry->rc = rc;
 +              __entry->connect_status = r_xprt->rx_ep.rep_connected;
 +              __assign_str(addr, rpcrdma_addrstr(r_xprt));
 +              __assign_str(port, rpcrdma_portstr(r_xprt));
 +      ),
 +
 +      TP_printk("peer=[%s]:%s r_xprt=%p: rc=%d connect status=%d",
 +              __get_str(addr), __get_str(port), __entry->r_xprt,
 +              __entry->rc, __entry->connect_status
 +      )
 +);
 +
 +#define DEFINE_CONN_EVENT(name)                                               \
 +              DEFINE_EVENT(xprtrdma_connect_class, xprtrdma_##name,   \
 +                              TP_PROTO(                               \
 +                                      const struct rpcrdma_xprt *r_xprt, \
 +                                      int rc                          \
 +                              ),                                      \
 +                              TP_ARGS(r_xprt, rc))
 +
  DECLARE_EVENT_CLASS(xprtrdma_rdch_event,
        TP_PROTO(
                const struct rpc_task *task,
@@@ -371,81 -333,47 +371,81 @@@ TRACE_EVENT(xprtrdma_cm_event
        )
  );
  
 -TRACE_EVENT(xprtrdma_disconnect,
 +TRACE_EVENT(xprtrdma_inline_thresh,
        TP_PROTO(
 -              const struct rpcrdma_xprt *r_xprt,
 -              int status
 +              const struct rpcrdma_xprt *r_xprt
        ),
  
 -      TP_ARGS(r_xprt, status),
 +      TP_ARGS(r_xprt),
  
        TP_STRUCT__entry(
                __field(const void *, r_xprt)
 -              __field(int, status)
 -              __field(int, connected)
 +              __field(unsigned int, inline_send)
 +              __field(unsigned int, inline_recv)
 +              __field(unsigned int, max_send)
 +              __field(unsigned int, max_recv)
                __string(addr, rpcrdma_addrstr(r_xprt))
                __string(port, rpcrdma_portstr(r_xprt))
        ),
  
        TP_fast_assign(
 +              const struct rpcrdma_ep *ep = &r_xprt->rx_ep;
 +
                __entry->r_xprt = r_xprt;
 -              __entry->status = status;
 -              __entry->connected = r_xprt->rx_ep.rep_connected;
 +              __entry->inline_send = ep->rep_inline_send;
 +              __entry->inline_recv = ep->rep_inline_recv;
 +              __entry->max_send = ep->rep_max_inline_send;
 +              __entry->max_recv = ep->rep_max_inline_recv;
                __assign_str(addr, rpcrdma_addrstr(r_xprt));
                __assign_str(port, rpcrdma_portstr(r_xprt));
        ),
  
 -      TP_printk("peer=[%s]:%s r_xprt=%p: status=%d %sconnected",
 -              __get_str(addr), __get_str(port),
 -              __entry->r_xprt, __entry->status,
 -              __entry->connected == 1 ? "still " : "dis"
 +      TP_printk("peer=[%s]:%s r_xprt=%p neg send/recv=%u/%u, calc send/recv=%u/%u",
 +              __get_str(addr), __get_str(port), __entry->r_xprt,
 +              __entry->inline_send, __entry->inline_recv,
 +              __entry->max_send, __entry->max_recv
        )
  );
  
 -DEFINE_RXPRT_EVENT(xprtrdma_conn_start);
 -DEFINE_RXPRT_EVENT(xprtrdma_conn_tout);
 +DEFINE_CONN_EVENT(connect);
 +DEFINE_CONN_EVENT(disconnect);
 +
  DEFINE_RXPRT_EVENT(xprtrdma_create);
  DEFINE_RXPRT_EVENT(xprtrdma_op_destroy);
  DEFINE_RXPRT_EVENT(xprtrdma_remove);
  DEFINE_RXPRT_EVENT(xprtrdma_reinsert);
 -DEFINE_RXPRT_EVENT(xprtrdma_reconnect);
  DEFINE_RXPRT_EVENT(xprtrdma_op_inject_dsc);
  DEFINE_RXPRT_EVENT(xprtrdma_op_close);
 -DEFINE_RXPRT_EVENT(xprtrdma_op_connect);
 +DEFINE_RXPRT_EVENT(xprtrdma_op_setport);
 +
 +TRACE_EVENT(xprtrdma_op_connect,
 +      TP_PROTO(
 +              const struct rpcrdma_xprt *r_xprt,
 +              unsigned long delay
 +      ),
 +
 +      TP_ARGS(r_xprt, delay),
 +
 +      TP_STRUCT__entry(
 +              __field(const void *, r_xprt)
 +              __field(unsigned long, delay)
 +              __string(addr, rpcrdma_addrstr(r_xprt))
 +              __string(port, rpcrdma_portstr(r_xprt))
 +      ),
 +
 +      TP_fast_assign(
 +              __entry->r_xprt = r_xprt;
 +              __entry->delay = delay;
 +              __assign_str(addr, rpcrdma_addrstr(r_xprt));
 +              __assign_str(port, rpcrdma_portstr(r_xprt));
 +      ),
 +
 +      TP_printk("peer=[%s]:%s r_xprt=%p delay=%lu",
 +              __get_str(addr), __get_str(port), __entry->r_xprt,
 +              __entry->delay
 +      )
 +);
 +
  
  TRACE_EVENT(xprtrdma_op_set_cto,
        TP_PROTO(
@@@ -604,8 -532,6 +604,8 @@@ DEFINE_WRCH_EVENT(write)
  DEFINE_WRCH_EVENT(reply);
  
  TRACE_DEFINE_ENUM(rpcrdma_noch);
 +TRACE_DEFINE_ENUM(rpcrdma_noch_pullup);
 +TRACE_DEFINE_ENUM(rpcrdma_noch_mapped);
  TRACE_DEFINE_ENUM(rpcrdma_readch);
  TRACE_DEFINE_ENUM(rpcrdma_areadch);
  TRACE_DEFINE_ENUM(rpcrdma_writech);
@@@ -614,8 -540,6 +614,8 @@@ TRACE_DEFINE_ENUM(rpcrdma_replych)
  #define xprtrdma_show_chunktype(x)                                    \
                __print_symbolic(x,                                     \
                                { rpcrdma_noch, "inline" },             \
 +                              { rpcrdma_noch_pullup, "pullup" },      \
 +                              { rpcrdma_noch_mapped, "mapped" },      \
                                { rpcrdma_readch, "read list" },        \
                                { rpcrdma_areadch, "*read list" },      \
                                { rpcrdma_writech, "write list" },      \
@@@ -743,8 -667,9 +743,8 @@@ TRACE_EVENT(xprtrdma_post_send
                __entry->client_id = rqst->rq_task->tk_client ?
                                     rqst->rq_task->tk_client->cl_clid : -1;
                __entry->req = req;
 -              __entry->num_sge = req->rl_sendctx->sc_wr.num_sge;
 -              __entry->signaled = req->rl_sendctx->sc_wr.send_flags &
 -                                  IB_SEND_SIGNALED;
 +              __entry->num_sge = req->rl_wr.num_sge;
 +              __entry->signaled = req->rl_wr.send_flags & IB_SEND_SIGNALED;
                __entry->status = status;
        ),
  
@@@ -810,31 -735,6 +810,31 @@@ TRACE_EVENT(xprtrdma_post_recvs
        )
  );
  
 +TRACE_EVENT(xprtrdma_post_linv,
 +      TP_PROTO(
 +              const struct rpcrdma_req *req,
 +              int status
 +      ),
 +
 +      TP_ARGS(req, status),
 +
 +      TP_STRUCT__entry(
 +              __field(const void *, req)
 +              __field(int, status)
 +              __field(u32, xid)
 +      ),
 +
 +      TP_fast_assign(
 +              __entry->req = req;
 +              __entry->status = status;
 +              __entry->xid = be32_to_cpu(req->rl_slot.rq_xid);
 +      ),
 +
 +      TP_printk("req=%p xid=0x%08x status=%d",
 +              __entry->req, __entry->xid, __entry->status
 +      )
 +);
 +
  /**
   ** Completion events
   **/
@@@ -1121,32 -1021,66 +1121,32 @@@ DEFINE_REPLY_EVENT(xprtrdma_reply_hdr)
  TRACE_EVENT(xprtrdma_fixup,
        TP_PROTO(
                const struct rpc_rqst *rqst,
 -              int len,
 -              int hdrlen
 +              unsigned long fixup
        ),
  
 -      TP_ARGS(rqst, len, hdrlen),
 +      TP_ARGS(rqst, fixup),
  
        TP_STRUCT__entry(
                __field(unsigned int, task_id)
                __field(unsigned int, client_id)
 -              __field(const void *, base)
 -              __field(int, len)
 -              __field(int, hdrlen)
 -      ),
 -
 -      TP_fast_assign(
 -              __entry->task_id = rqst->rq_task->tk_pid;
 -              __entry->client_id = rqst->rq_task->tk_client->cl_clid;
 -              __entry->base = rqst->rq_rcv_buf.head[0].iov_base;
 -              __entry->len = len;
 -              __entry->hdrlen = hdrlen;
 -      ),
 -
 -      TP_printk("task:%u@%u base=%p len=%d hdrlen=%d",
 -              __entry->task_id, __entry->client_id,
 -              __entry->base, __entry->len, __entry->hdrlen
 -      )
 -);
 -
 -TRACE_EVENT(xprtrdma_fixup_pg,
 -      TP_PROTO(
 -              const struct rpc_rqst *rqst,
 -              int pageno,
 -              const void *pos,
 -              int len,
 -              int curlen
 -      ),
 -
 -      TP_ARGS(rqst, pageno, pos, len, curlen),
 -
 -      TP_STRUCT__entry(
 -              __field(unsigned int, task_id)
 -              __field(unsigned int, client_id)
 -              __field(const void *, pos)
 -              __field(int, pageno)
 -              __field(int, len)
 -              __field(int, curlen)
 +              __field(unsigned long, fixup)
 +              __field(size_t, headlen)
 +              __field(unsigned int, pagelen)
 +              __field(size_t, taillen)
        ),
  
        TP_fast_assign(
                __entry->task_id = rqst->rq_task->tk_pid;
                __entry->client_id = rqst->rq_task->tk_client->cl_clid;
 -              __entry->pos = pos;
 -              __entry->pageno = pageno;
 -              __entry->len = len;
 -              __entry->curlen = curlen;
 +              __entry->fixup = fixup;
 +              __entry->headlen = rqst->rq_rcv_buf.head[0].iov_len;
 +              __entry->pagelen = rqst->rq_rcv_buf.page_len;
 +              __entry->taillen = rqst->rq_rcv_buf.tail[0].iov_len;
        ),
  
 -      TP_printk("task:%u@%u pageno=%d pos=%p len=%d curlen=%d",
 -              __entry->task_id, __entry->client_id,
 -              __entry->pageno, __entry->pos, __entry->len, __entry->curlen
 +      TP_printk("task:%u@%u fixup=%lu xdr=%zu/%u/%zu",
 +              __entry->task_id, __entry->client_id, __entry->fixup,
 +              __entry->headlen, __entry->pagelen, __entry->taillen
        )
  );
  
@@@ -1564,31 -1498,47 +1564,47 @@@ DEFINE_ERROR_EVENT(chunk)
   ** Server-side RDMA API events
   **/
  
TRACE_EVENT(svcrdma_dma_map_page,
DECLARE_EVENT_CLASS(svcrdma_dma_map_class,
        TP_PROTO(
                const struct svcxprt_rdma *rdma,
-               const void *page
+               u64 dma_addr,
+               u32 length
        ),
  
-       TP_ARGS(rdma, page),
+       TP_ARGS(rdma, dma_addr, length),
  
        TP_STRUCT__entry(
-               __field(const void *, page);
+               __field(u64, dma_addr)
+               __field(u32, length)
                __string(device, rdma->sc_cm_id->device->name)
                __string(addr, rdma->sc_xprt.xpt_remotebuf)
        ),
  
        TP_fast_assign(
-               __entry->page = page;
+               __entry->dma_addr = dma_addr;
+               __entry->length = length;
                __assign_str(device, rdma->sc_cm_id->device->name);
                __assign_str(addr, rdma->sc_xprt.xpt_remotebuf);
        ),
  
-       TP_printk("addr=%s device=%s page=%p",
-               __get_str(addr), __get_str(device), __entry->page
+       TP_printk("addr=%s device=%s dma_addr=%llu length=%u",
+               __get_str(addr), __get_str(device),
+               __entry->dma_addr, __entry->length
        )
  );
  
+ #define DEFINE_SVC_DMA_EVENT(name)                                    \
+               DEFINE_EVENT(svcrdma_dma_map_class, svcrdma_##name,     \
+                               TP_PROTO(                               \
+                                       const struct svcxprt_rdma *rdma,\
+                                       u64 dma_addr,                   \
+                                       u32 length                      \
+                               ),                                      \
+                               TP_ARGS(rdma, dma_addr, length))
+ DEFINE_SVC_DMA_EVENT(dma_map_page);
+ DEFINE_SVC_DMA_EVENT(dma_unmap_page);
  TRACE_EVENT(svcrdma_dma_map_rwctx,
        TP_PROTO(
                const struct svcxprt_rdma *rdma,
  #include <linux/net.h>
  #include <linux/tracepoint.h>
  
+ TRACE_DEFINE_ENUM(RPC_AUTH_OK);
+ TRACE_DEFINE_ENUM(RPC_AUTH_BADCRED);
+ TRACE_DEFINE_ENUM(RPC_AUTH_REJECTEDCRED);
+ TRACE_DEFINE_ENUM(RPC_AUTH_BADVERF);
+ TRACE_DEFINE_ENUM(RPC_AUTH_REJECTEDVERF);
+ TRACE_DEFINE_ENUM(RPC_AUTH_TOOWEAK);
+ TRACE_DEFINE_ENUM(RPCSEC_GSS_CREDPROBLEM);
+ TRACE_DEFINE_ENUM(RPCSEC_GSS_CTXPROBLEM);
+ #define rpc_show_auth_stat(status)                                    \
+       __print_symbolic(status,                                        \
+               { RPC_AUTH_OK,                  "AUTH_OK" },            \
+               { RPC_AUTH_BADCRED,             "BADCRED" },            \
+               { RPC_AUTH_REJECTEDCRED,        "REJECTEDCRED" },       \
+               { RPC_AUTH_BADVERF,             "BADVERF" },            \
+               { RPC_AUTH_REJECTEDVERF,        "REJECTEDVERF" },       \
+               { RPC_AUTH_TOOWEAK,             "TOOWEAK" },            \
+               { RPCSEC_GSS_CREDPROBLEM,       "GSS_CREDPROBLEM" },    \
+               { RPCSEC_GSS_CTXPROBLEM,        "GSS_CTXPROBLEM" })     \
  DECLARE_EVENT_CLASS(rpc_task_status,
  
        TP_PROTO(const struct rpc_task *task),
@@@ -165,7 -185,6 +185,7 @@@ DECLARE_EVENT_CLASS(rpc_task_running
  DEFINE_RPC_RUNNING_EVENT(begin);
  DEFINE_RPC_RUNNING_EVENT(run_action);
  DEFINE_RPC_RUNNING_EVENT(complete);
 +DEFINE_RPC_RUNNING_EVENT(end);
  
  DECLARE_EVENT_CLASS(rpc_task_queued,
  
@@@ -778,99 -797,6 +798,99 @@@ TRACE_EVENT(xprt_ping
                        __get_str(addr), __get_str(port), __entry->status)
  );
  
 +DECLARE_EVENT_CLASS(xprt_writelock_event,
 +      TP_PROTO(
 +              const struct rpc_xprt *xprt, const struct rpc_task *task
 +      ),
 +
 +      TP_ARGS(xprt, task),
 +
 +      TP_STRUCT__entry(
 +              __field(unsigned int, task_id)
 +              __field(unsigned int, client_id)
 +              __field(unsigned int, snd_task_id)
 +      ),
 +
 +      TP_fast_assign(
 +              if (task) {
 +                      __entry->task_id = task->tk_pid;
 +                      __entry->client_id = task->tk_client ?
 +                                           task->tk_client->cl_clid : -1;
 +              } else {
 +                      __entry->task_id = -1;
 +                      __entry->client_id = -1;
 +              }
 +              __entry->snd_task_id = xprt->snd_task ?
 +                                      xprt->snd_task->tk_pid : -1;
 +      ),
 +
 +      TP_printk("task:%u@%u snd_task:%u",
 +                      __entry->task_id, __entry->client_id,
 +                      __entry->snd_task_id)
 +);
 +
 +#define DEFINE_WRITELOCK_EVENT(name) \
 +      DEFINE_EVENT(xprt_writelock_event, xprt_##name, \
 +                      TP_PROTO( \
 +                              const struct rpc_xprt *xprt, \
 +                              const struct rpc_task *task \
 +                      ), \
 +                      TP_ARGS(xprt, task))
 +
 +DEFINE_WRITELOCK_EVENT(reserve_xprt);
 +DEFINE_WRITELOCK_EVENT(release_xprt);
 +
 +DECLARE_EVENT_CLASS(xprt_cong_event,
 +      TP_PROTO(
 +              const struct rpc_xprt *xprt, const struct rpc_task *task
 +      ),
 +
 +      TP_ARGS(xprt, task),
 +
 +      TP_STRUCT__entry(
 +              __field(unsigned int, task_id)
 +              __field(unsigned int, client_id)
 +              __field(unsigned int, snd_task_id)
 +              __field(unsigned long, cong)
 +              __field(unsigned long, cwnd)
 +              __field(bool, wait)
 +      ),
 +
 +      TP_fast_assign(
 +              if (task) {
 +                      __entry->task_id = task->tk_pid;
 +                      __entry->client_id = task->tk_client ?
 +                                           task->tk_client->cl_clid : -1;
 +              } else {
 +                      __entry->task_id = -1;
 +                      __entry->client_id = -1;
 +              }
 +              __entry->snd_task_id = xprt->snd_task ?
 +                                      xprt->snd_task->tk_pid : -1;
 +              __entry->cong = xprt->cong;
 +              __entry->cwnd = xprt->cwnd;
 +              __entry->wait = test_bit(XPRT_CWND_WAIT, &xprt->state);
 +      ),
 +
 +      TP_printk("task:%u@%u snd_task:%u cong=%lu cwnd=%lu%s",
 +                      __entry->task_id, __entry->client_id,
 +                      __entry->snd_task_id, __entry->cong, __entry->cwnd,
 +                      __entry->wait ? " (wait)" : "")
 +);
 +
 +#define DEFINE_CONG_EVENT(name) \
 +      DEFINE_EVENT(xprt_cong_event, xprt_##name, \
 +                      TP_PROTO( \
 +                              const struct rpc_xprt *xprt, \
 +                              const struct rpc_task *task \
 +                      ), \
 +                      TP_ARGS(xprt, task))
 +
 +DEFINE_CONG_EVENT(reserve_cong);
 +DEFINE_CONG_EVENT(release_cong);
 +DEFINE_CONG_EVENT(get_cong);
 +DEFINE_CONG_EVENT(put_cong);
 +
  TRACE_EVENT(xs_stream_read_data,
        TP_PROTO(struct rpc_xprt *xprt, ssize_t err, size_t total),
  
@@@ -960,6 -886,41 +980,41 @@@ TRACE_EVENT(svc_recv
                        show_rqstp_flags(__entry->flags))
  );
  
+ #define svc_show_status(status)                               \
+       __print_symbolic(status,                        \
+               { SVC_GARBAGE,  "SVC_GARBAGE" },        \
+               { SVC_SYSERR,   "SVC_SYSERR" },         \
+               { SVC_VALID,    "SVC_VALID" },          \
+               { SVC_NEGATIVE, "SVC_NEGATIVE" },       \
+               { SVC_OK,       "SVC_OK" },             \
+               { SVC_DROP,     "SVC_DROP" },           \
+               { SVC_CLOSE,    "SVC_CLOSE" },          \
+               { SVC_DENIED,   "SVC_DENIED" },         \
+               { SVC_PENDING,  "SVC_PENDING" },        \
+               { SVC_COMPLETE, "SVC_COMPLETE" })
+ TRACE_EVENT(svc_authenticate,
+       TP_PROTO(const struct svc_rqst *rqst, int auth_res, __be32 auth_stat),
+       TP_ARGS(rqst, auth_res, auth_stat),
+       TP_STRUCT__entry(
+               __field(u32, xid)
+               __field(unsigned long, svc_status)
+               __field(unsigned long, auth_stat)
+       ),
+       TP_fast_assign(
+               __entry->xid = be32_to_cpu(rqst->rq_xid);
+               __entry->svc_status = auth_res;
+               __entry->auth_stat = be32_to_cpu(auth_stat);
+       ),
+       TP_printk("xid=0x%08x auth_res=%s auth_stat=%s",
+                       __entry->xid, svc_show_status(__entry->svc_status),
+                       rpc_show_auth_stat(__entry->auth_stat))
+ );
  TRACE_EVENT(svc_process,
        TP_PROTO(const struct svc_rqst *rqst, const char *name),
  
diff --combined net/sunrpc/xprtsock.c
@@@ -1249,21 -1249,19 +1249,21 @@@ static void xs_error_report(struct soc
  {
        struct sock_xprt *transport;
        struct rpc_xprt *xprt;
 -      int err;
  
        read_lock_bh(&sk->sk_callback_lock);
        if (!(xprt = xprt_from_sock(sk)))
                goto out;
  
        transport = container_of(xprt, struct sock_xprt, xprt);
 -      err = -sk->sk_err;
 -      if (err == 0)
 +      transport->xprt_err = -sk->sk_err;
 +      if (transport->xprt_err == 0)
                goto out;
        dprintk("RPC:       xs_error_report client %p, error=%d...\n",
 -                      xprt, -err);
 -      trace_rpc_socket_error(xprt, sk->sk_socket, err);
 +                      xprt, -transport->xprt_err);
 +      trace_rpc_socket_error(xprt, sk->sk_socket, transport->xprt_err);
 +
 +      /* barrier ensures xprt_err is set before XPRT_SOCK_WAKE_ERROR */
 +      smp_mb__before_atomic();
        xs_run_error_worker(transport, XPRT_SOCK_WAKE_ERROR);
   out:
        read_unlock_bh(&sk->sk_callback_lock);
@@@ -1752,7 -1750,7 +1752,7 @@@ static void xs_set_port(struct rpc_xpr
  
  static void xs_set_srcport(struct sock_xprt *transport, struct socket *sock)
  {
 -      if (transport->srcport == 0)
 +      if (transport->srcport == 0 && transport->xprt.reuseport)
                transport->srcport = xs_sock_getport(sock);
  }
  
@@@ -2478,6 -2476,7 +2478,6 @@@ static void xs_wake_write(struct sock_x
  static void xs_wake_error(struct sock_xprt *transport)
  {
        int sockerr;
 -      int sockerr_len = sizeof(sockerr);
  
        if (!test_bit(XPRT_SOCK_WAKE_ERROR, &transport->sock_state))
                return;
                goto out;
        if (!test_and_clear_bit(XPRT_SOCK_WAKE_ERROR, &transport->sock_state))
                goto out;
 -      if (kernel_getsockopt(transport->sock, SOL_SOCKET, SO_ERROR,
 -                              (char *)&sockerr, &sockerr_len) != 0)
 -              goto out;
 +      sockerr = xchg(&transport->xprt_err, 0);
        if (sockerr < 0)
                xprt_wake_pending_tasks(&transport->xprt, sockerr);
  out:
@@@ -2659,6 -2660,8 +2659,8 @@@ static int bc_sendto(struct rpc_rqst *r
                .iov_len        = sizeof(marker),
        };
  
+       req->rq_xtime = ktime_get();
        len = kernel_sendmsg(transport->sock, &msg, &iov, 1, iov.iov_len);
        if (len != iov.iov_len)
                return -EAGAIN;
@@@ -2684,7 -2687,6 +2686,6 @@@ static int bc_send_request(struct rpc_r
        struct svc_xprt *xprt;
        int len;
  
-       dprintk("sending request with xid: %08x\n", ntohl(req->rq_xid));
        /*
         * Get the server socket associated with this callback xprt
         */