From: Colin Ian King colin.king@canonical.com
mainline inclusion from mainline-5.8-rc6 commit 912288442cb2f431bf3c8cb097a5de83bc6dbac1 category: bugfix bugzilla: 51800 CVE: NA
---------------------------
Currently the header size calculations are using an assignment operator instead of a += operator when accumulating the header size leading to incorrect sizes. Fix this by using the correct operator.
Addresses-Coverity: ("Unused value") Fixes: 302d3deb2068 ("xprtrdma: Prevent inline overflow") Signed-off-by: Colin Ian King colin.king@canonical.com Reviewed-by: Chuck Lever chuck.lever@oracle.com Signed-off-by: Anna Schumaker Anna.Schumaker@Netapp.com Signed-off-by: Liu Jian liujian56@huawei.com
Conflicts: net/sunrpc/xprtrdma/rpc_rdma.c Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/sunrpc/xprtrdma/rpc_rdma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index f2eaf264726be..10805313aa960 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c @@ -72,7 +72,7 @@ static unsigned int rpcrdma_max_call_header_size(unsigned int maxsegs)
/* Maximum Read list size */ maxsegs += 2; /* segment for head and tail buffers */ - size = maxsegs * rpcrdma_readchunk_maxsz * sizeof(__be32); + size += maxsegs * rpcrdma_readchunk_maxsz * sizeof(__be32);
/* Minimal Read chunk size */ size += sizeof(__be32); /* segment count */ @@ -98,7 +98,7 @@ static unsigned int rpcrdma_max_reply_header_size(unsigned int maxsegs)
/* Maximum Write list size */ maxsegs += 2; /* segment for head and tail buffers */ - size = sizeof(__be32); /* segment count */ + size += sizeof(__be32); /* segment count */ size += maxsegs * rpcrdma_segment_maxsz * sizeof(__be32); size += sizeof(__be32); /* list discriminator */
From: Dan Aloni dan@kernelim.com
mainline inclusion from mainline-5.9-rc1 commit 4a400f0d08308e3e446a07d3f4590f243e44b7db category: bugfix bugzilla: 51800 CVE: NA
---------------------------
Better to unregister the file system before destroying the kmem_cache cache of the inodes, so that the inodes are freed before we are trying to destroy it. Otherwise, kmem_cache yells that some objects are live.
Signed-off-by: Dan Aloni dan@kernelim.com Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Liu Jian liujian56@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/sunrpc/rpc_pipe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 285eab5b43c86..9dd11fdf1cdae 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -1508,6 +1508,6 @@ int register_rpc_pipefs(void) void unregister_rpc_pipefs(void) { rpc_clients_notifier_unregister(); - kmem_cache_destroy(rpc_inode_cachep); unregister_filesystem(&rpc_pipe_fs_type); + kmem_cache_destroy(rpc_inode_cachep); }
From: Chuck Lever chuck.lever@oracle.com
mainline inclusion from mainline-5.0-rc1 commit 236b0943d1f21335a0fc4324f3bcc455cf99dfb7 category: bugfix bugzilla: 51800 CVE: NA
---------------------------
For better observability of parsing errors, return the error code generated in the decoders to the upper layer consumer.
Signed-off-by: Chuck Lever chuck.lever@oracle.com Signed-off-by: Anna Schumaker Anna.Schumaker@Netapp.com Signed-off-by: Liu Jian liujian56@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/sunrpc/xprtrdma/rpc_rdma.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 10805313aa960..465995996fb0c 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c @@ -1256,7 +1256,6 @@ void rpcrdma_complete_rqst(struct rpcrdma_rep *rep) out_badheader: trace_xprtrdma_reply_hdr(rep); r_xprt->rx_stats.bad_reply_count++; - status = -EIO; goto out; }
From: Chuck Lever chuck.lever@oracle.com
mainline inclusion from mainline-5.8-rc3 commit 7b2182ec381f8ea15c7eb1266d6b5d7da620ad93 category: bugfix bugzilla: 51800 CVE: NA
---------------------------
The RPC client currently doesn't handle ERR_CHUNK replies correctly. rpcrdma_complete_rqst() incorrectly passes a negative number to xprt_complete_rqst() as the number of bytes copied. Instead, set task->tk_status to the error value, and return zero bytes copied.
In these cases, return -EIO rather than -EREMOTEIO. The RPC client's finite state machine doesn't know what to do with -EREMOTEIO.
Additional clean ups: - Don't double-count RDMA_ERROR replies - Remove a stale comment
Signed-off-by: Chuck Lever chuck.lever@oracle.com Cc: stable@kernel.vger.org Signed-off-by: Anna Schumaker Anna.Schumaker@Netapp.com Signed-off-by: Liu Jian liujian56@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/sunrpc/xprtrdma/rpc_rdma.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 465995996fb0c..33b3376afce97 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c @@ -1203,8 +1203,7 @@ rpcrdma_decode_error(struct rpcrdma_xprt *r_xprt, struct rpcrdma_rep *rep, rqst->rq_task->tk_pid, __func__, be32_to_cpup(p)); }
- r_xprt->rx_stats.bad_reply_count++; - return -EREMOTEIO; + return -EIO; }
/* Perform XID lookup, reconstruction of the RPC reply, and @@ -1249,13 +1248,11 @@ void rpcrdma_complete_rqst(struct rpcrdma_rep *rep) spin_unlock(&xprt->recv_lock); return;
-/* If the incoming reply terminated a pending RPC, the next - * RPC call will post a replacement receive buffer as it is - * being marshaled. - */ out_badheader: trace_xprtrdma_reply_hdr(rep); r_xprt->rx_stats.bad_reply_count++; + rqst->rq_task->tk_status = status; + status = 0; goto out; }
From: Yihao Wu wuyihao@linux.alibaba.com
mainline inclusion from mainline-5.7-rc3 commit 43e33924c38e8faeb0c12035481cb150e602e39d category: bugfix bugzilla: 51810 CVE: NA
-------------------------------------------------
Deleting list entry within hlist_for_each_entry_safe is not safe unless next pointer (tmp) is protected too. It's not, because once hash_lock is released, cache_clean may delete the entry that tmp points to. Then cache_purge can walk to a deleted entry and tries to double free it.
Fix this bug by holding only the deleted entry's reference.
Suggested-by: NeilBrown neilb@suse.de Signed-off-by: Yihao Wu wuyihao@linux.alibaba.com Reviewed-by: NeilBrown neilb@suse.de [ cel: removed unused variable ] Signed-off-by: Chuck Lever chuck.lever@oracle.com (cherry picked from commit 43e33924c38e8faeb0c12035481cb150e602e39d) Signed-off-by: Yufen Wang wangyufen@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/sunrpc/cache.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 62b2bd8e1efc5..e2d3cf801c310 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -487,7 +487,6 @@ void cache_purge(struct cache_detail *detail) { struct cache_head *ch = NULL; struct hlist_head *head = NULL; - struct hlist_node *tmp = NULL; int i = 0;
write_lock(&detail->hash_lock); @@ -499,7 +498,9 @@ void cache_purge(struct cache_detail *detail) dprintk("RPC: %d entries in %s cache\n", detail->entries, detail->name); for (i = 0; i < detail->hash_size; i++) { head = &detail->hash_table[i]; - hlist_for_each_entry_safe(ch, tmp, head, cache_list) { + while (!hlist_empty(head)) { + ch = hlist_entry(head->first, struct cache_head, + cache_list); hlist_del_init(&ch->cache_list); detail->entries--;
From: Chuck Lever chuck.lever@oracle.com
mainline inclusion from mainline-5.7-rc3 commit 6221f1d9b63fed6260273e59a2b89ab30537a811 category: bugfix bugzilla: 51810 CVE: NA
------------------------------------------------- Currently, after the forward channel connection goes away, backchannel operations are causing soft lockups on the server because call_transmit_status's SOFTCONN logic ignores ENOTCONN. Such backchannel Calls are aggressively retried until the client reconnects.
Backchannel Calls should use RPC_TASK_NOCONNECT rather than RPC_TASK_SOFTCONN. If there is no forward connection, the server is not capable of establishing a connection back to the client, thus that backchannel request should fail before the server attempts to send it. Commit 58255a4e3ce5 ("NFSD: NFSv4 callback client should use RPC_TASK_SOFTCONN") was merged several years before RPC_TASK_NOCONNECT was available.
Because setup_callback_client() explicitly sets NOPING, the NFSv4.0 callback connection depends on the first callback RPC to initiate a connection to the client. Thus NFSv4.0 needs to continue to use RPC_TASK_SOFTCONN.
Suggested-by: Trond Myklebust trondmy@hammerspace.com Signed-off-by: Chuck Lever chuck.lever@oracle.com Cc: stable@vger.kernel.org # v4.20+ (cherry picked from commit 6221f1d9b63fed6260273e59a2b89ab30537a811) Signed-off-by: Yufen Wang wangyufen@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/nfsd/nfs4callback.c | 4 +++- net/sunrpc/svc_xprt.c | 2 ++ net/sunrpc/xprtrdma/svc_rdma_backchannel.c | 2 ++ net/sunrpc/xprtsock.c | 1 + 4 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index ebbb0285addb0..b601e5915e6f7 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -1160,6 +1160,7 @@ nfsd4_run_cb_work(struct work_struct *work) container_of(work, struct nfsd4_callback, cb_work); struct nfs4_client *clp = cb->cb_clp; struct rpc_clnt *clnt; + int flags;
if (cb->cb_need_restart) { cb->cb_need_restart = false; @@ -1188,7 +1189,8 @@ nfsd4_run_cb_work(struct work_struct *work) }
cb->cb_msg.rpc_cred = clp->cl_cb_cred; - rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN, + flags = clp->cl_minorversion ? RPC_TASK_NOCONNECT : RPC_TASK_SOFTCONN; + rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | flags, cb->cb_ops ? &nfsd4_cb_ops : &nfsd4_cb_probe_ops, cb); }
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 2c8c3193dca7a..0f89fc6c92e2f 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -1016,6 +1016,8 @@ static void svc_delete_xprt(struct svc_xprt *xprt)
dprintk("svc: svc_delete_xprt(%p)\n", xprt); xprt->xpt_ops->xpo_detach(xprt); + if (xprt->xpt_bc_xprt) + xprt->xpt_bc_xprt->ops->close(xprt->xpt_bc_xprt);
spin_lock_bh(&serv->sv_lock); list_del_init(&xprt->xpt_list); diff --git a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c index d183d4aee822c..fc6ea5b7e32c8 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c +++ b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c @@ -248,6 +248,8 @@ static void xprt_rdma_bc_close(struct rpc_xprt *xprt) { dprintk("svcrdma: %s: xprt %p\n", __func__, xprt); + + xprt_disconnect_done(xprt); xprt->cwnd = RPC_CWNDSHIFT; }
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index bb796f03507f4..bd5a7da70ae0f 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -2753,6 +2753,7 @@ static int bc_send_request(struct rpc_task *task)
static void bc_close(struct rpc_xprt *xprt) { + xprt_disconnect_done(xprt); }
/*
From: Xiongfeng Wang wangxiongfeng2@huawei.com
mainline inclusion from mainline-5.8-rc1 commit 746c6237ece641da79df09abcf87bc29f6f9665b category: bugfix bugzilla: 51810 CVE: NA
------------------------------------------------- When I cat parameter '/sys/module/sunrpc/parameters/pool_mode', it displays as follows. It is better to add a newline for easy reading.
[root@hulk-202 ~]# cat /sys/module/sunrpc/parameters/pool_mode global[root@hulk-202 ~]#
Signed-off-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: J. Bruce Fields bfields@redhat.com (cherry picked from commit 746c6237ece641da79df09abcf87bc29f6f9665b) Signed-off-by: Yufen Wang wangyufen@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/sunrpc/svc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 429da1b3e62a2..536bf369b9732 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -87,15 +87,15 @@ param_get_pool_mode(char *buf, const struct kernel_param *kp) switch (*ip) { case SVC_POOL_AUTO: - return strlcpy(buf, "auto", 20); + return strlcpy(buf, "auto\n", 20); case SVC_POOL_GLOBAL: - return strlcpy(buf, "global", 20); + return strlcpy(buf, "global\n", 20); case SVC_POOL_PERCPU: - return strlcpy(buf, "percpu", 20); + return strlcpy(buf, "percpu\n", 20); case SVC_POOL_PERNODE: - return strlcpy(buf, "pernode", 20); + return strlcpy(buf, "pernode\n", 20); default: - return sprintf(buf, "%d", *ip); + return sprintf(buf, "%d\n", *ip); } }
From: Roberto Bergantinos Corpas rbergant@redhat.com
mainline inclusion from mainline-5.10-rc1 commit 27a1e8a0f79e643d4dedb46f71e76bdee3801877 category: bugfix bugzilla: 51817 CVE: NA
------------------------------------------------- Its possible that using AUTH_SYS and mountd manage-gids option a user may hit the 8k RPC channel buffer limit. This have been observed on field, causing unanswered RPCs on clients after mountd fails to write on channel :
rpc.mountd[11231]: auth_unix_gid: error writing reply
Userland nfs-utils uses a buffer size of 32k (RPC_CHAN_BUF_SIZE), so lets match those two.
Signed-off-by: Roberto Bergantinos Corpas rbergant@redhat.com Signed-off-by: J. Bruce Fields bfields@redhat.com (cherry picked from commit 27a1e8a0f79e643d4dedb46f71e76bdee3801877) Signed-off-by: Baisong Zhong zhongbaisong@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/sunrpc/cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index e2d3cf801c310..afab8fce92054 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -870,7 +870,7 @@ static ssize_t cache_do_downcall(char *kaddr, const char __user *buf, static ssize_t cache_slow_downcall(const char __user *buf, size_t count, struct cache_detail *cd) { - static char write_buf[8192]; /* protected by queue_io_mutex */ + static char write_buf[32768]; /* protected by queue_io_mutex */ ssize_t ret = -EINVAL;
if (count >= sizeof(write_buf))
From: Artur Molchanov arturmolchanov@gmail.com
mainline inclusion from mainline-5.10-rc1 commit c09f56b8f68d4d536bff518227aea323b835b2ce category: bugfix bugzilla: 51817 CVE: NA
------------------------------------------------- Fix returning value for sysctl sunrpc.transports. Return error code from sysctl proc_handler function proc_do_xprt instead of number of the written bytes. Otherwise sysctl returns random garbage for this key.
Since v1: - Handle negative returned value from memory_read_from_buffer as an error
Signed-off-by: Artur Molchanov arturmolchanov@gmail.com Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields bfields@redhat.com (cherry picked from commit c09f56b8f68d4d536bff518227aea323b835b2ce) Signed-off-by: Baisong Zhong zhongbaisong@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/sunrpc/sysctl.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c index 0bea8ff8b0d38..c39b90ac24020 100644 --- a/net/sunrpc/sysctl.c +++ b/net/sunrpc/sysctl.c @@ -69,7 +69,13 @@ static int proc_do_xprt(struct ctl_table *table, int write, return 0; } len = svc_print_xprts(tmpbuf, sizeof(tmpbuf)); - return simple_read_from_buffer(buffer, *lenp, ppos, tmpbuf, len); + *lenp = simple_read_from_buffer(buffer, *lenp, ppos, tmpbuf, len); + + if (*lenp < 0) { + *lenp = 0; + return -EINVAL; + } + return 0; }
static int
From: Dan Carpenter dan.carpenter@oracle.com
mainline inclusion from mainline-5.10-rc4 commit d435c05ab0197ee302290e1cee3f2d9c9024a64f category: bugfix bugzilla: 51817 CVE: NA
------------------------------------------------- You can't write to this file because the permissions are 0444. But it sort of looked like you could do a write and it would result in a read. Then it looked like proc_sys_call_handler() just ignored it. Which is confusing. It's more clear if the "write" just returns zero.
Also, the "lenp" pointer is never NULL so that check can be removed.
Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: J. Bruce Fields bfields@redhat.com (cherry picked from commit d435c05ab0197ee302290e1cee3f2d9c9024a64f) Signed-off-by: Baisong Zhong zhongbaisong@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/sunrpc/sysctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c index c39b90ac24020..dee2983ecfd00 100644 --- a/net/sunrpc/sysctl.c +++ b/net/sunrpc/sysctl.c @@ -64,7 +64,7 @@ static int proc_do_xprt(struct ctl_table *table, int write, char tmpbuf[256]; size_t len;
- if ((*ppos && !write) || !*lenp) { + if (write || *ppos) { *lenp = 0; return 0; }
From: Trond Myklebust trondmy@gmail.com
mainline inclusion from mainline-5.2-rc1 commit 83dd59a0b9afc3b1a2642fb5c9b0585b1c08768f category: bugfix bugzilla: NA CVE: NA
------------------------------------------------- RPC server procedures are normally expected to return a __be32 encoded status value of type 'enum rpc_accept_stat', however at least one function wants to return an authentication status of type 'enum rpc_auth_stat' in the case where authentication fails. This patch adds functionality to allow this.
Fixes: a4e187d83d88 ("NFS: Don't drop CB requests with invalid principals") Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: J. Bruce Fields bfields@redhat.com (cherry picked from commit 83dd59a0b9afc3b1a2642fb5c9b0585b1c08768f) Signed-off-by: Qiheng Lin linqiheng@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/nfs/callback_xdr.c | 2 +- include/linux/sunrpc/svc.h | 2 ++ net/sunrpc/svc.c | 27 ++++++++++++++++++++++----- 3 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index a87a562734077..57558a8d92e9b 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c @@ -991,7 +991,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp)
out_invalidcred: pr_warn_ratelimited("NFS: NFSv4 callback contains invalid cred\n"); - return rpc_autherr_badcred; + return svc_return_autherr(rqstp, rpc_autherr_badcred); }
/* diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index fdb6b317d9747..c019d3a634c7e 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -271,6 +271,7 @@ struct svc_rqst { #define RQ_VICTIM (5) /* about to be shut down */ #define RQ_BUSY (6) /* request is busy */ #define RQ_DATA (7) /* request has data */ +#define RQ_AUTHERR (8) /* Request status is auth error */ unsigned long rq_flags; /* flags field */ ktime_t rq_qtime; /* enqueue time */
@@ -504,6 +505,7 @@ unsigned int svc_fill_write_vector(struct svc_rqst *rqstp, char *svc_fill_symlink_pathname(struct svc_rqst *rqstp, struct kvec *first, void *p, size_t total); +__be32 svc_return_autherr(struct svc_rqst *rqstp, __be32 auth_err);
#define RPC_MAX_ADDRBUFLEN (63U)
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 536bf369b9732..c95c8f6ada64b 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -1146,6 +1146,22 @@ static __printf(2,3) void svc_printk(struct svc_rqst *rqstp, const char *fmt, ..
extern void svc_tcp_prep_reply_hdr(struct svc_rqst *);
+__be32 +svc_return_autherr(struct svc_rqst *rqstp, __be32 auth_err) +{ + set_bit(RQ_AUTHERR, &rqstp->rq_flags); + return auth_err; +} +EXPORT_SYMBOL_GPL(svc_return_autherr); + +static __be32 +svc_get_autherr(struct svc_rqst *rqstp, __be32 *statp) +{ + if (test_and_clear_bit(RQ_AUTHERR, &rqstp->rq_flags)) + return *statp; + return rpc_auth_ok; +} + /* * Common routine for processing the RPC request. */ @@ -1296,11 +1312,9 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) procp->pc_release(rqstp); goto dropit; } - if (*statp == rpc_autherr_badcred) { - if (procp->pc_release) - procp->pc_release(rqstp); - goto err_bad_auth; - } + auth_stat = svc_get_autherr(rqstp, statp); + if (auth_stat != rpc_auth_ok) + goto err_release_bad_auth; if (*statp == rpc_success && procp->pc_encode && !procp->pc_encode(rqstp, resv->iov_base + resv->iov_len)) { dprintk("svc: failed to encode reply\n"); @@ -1359,6 +1373,9 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) svc_putnl(resv, 2); goto sendit;
+err_release_bad_auth: + if (procp->pc_release) + procp->pc_release(rqstp); err_bad_auth: dprintk("svc: authentication failed (%d)\n", ntohl(auth_stat)); serv->sv_stats->rpcbadauth++;
From: Trond Myklebust trondmy@gmail.com
mainline inclusion from mainline-5.1-rc1 commit 1602a7b7d33741d0490682e620bb29e96ad684d7 category: bugfix bugzilla: 51818 CVE: NA
------------------------------------------------- Use READ_ONCE() to tell the compiler to not optimse away the read of xprt->xpt_flags in svc_xprt_release_slot().
Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: J. Bruce Fields bfields@redhat.com Signed-off-by: Zhang Changzhong zhangchangzhong@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/sunrpc/svc_xprt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 0f89fc6c92e2f..0ab649e028617 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -373,9 +373,13 @@ static void svc_xprt_release_slot(struct svc_rqst *rqstp)
static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt) { - if (xprt->xpt_flags & ((1<<XPT_CONN)|(1<<XPT_CLOSE))) + unsigned long xpt_flags; + + xpt_flags = READ_ONCE(xprt->xpt_flags); + + if (xpt_flags & (BIT(XPT_CONN) | BIT(XPT_CLOSE))) return true; - if (xprt->xpt_flags & ((1<<XPT_DATA)|(1<<XPT_DEFERRED))) { + if (xpt_flags & (BIT(XPT_DATA) | BIT(XPT_DEFERRED))) { if (xprt->xpt_ops->xpo_has_wspace(xprt) && svc_xprt_slots_in_range(xprt)) return true;
From: Benjamin Coddington bcodding@redhat.com
mainline inclusion from mainline-v5.4-rc1 commit 5f1bc39979d868a0358c683864bec3fc8395440b category: bugfix bugzilla: 51816 CVE: NA
-------------------------------------------------
The GSS Message Integrity Check data for krb5i may lie partially in the XDR reply buffer's pages and tail. If so, we try to copy the entire MIC into free space in the tail. But as the estimations of the slack space required for authentication and verification have improved there may be less free space in the tail to complete this copy -- see commit 2c94b8eca1a2 ("SUNRPC: Use au_rslack when computing reply buffer size"). In fact, there may only be room in the tail for a single copy of the MIC, and not part of the MIC and then another complete copy.
The real world failure reported is that `ls` of a directory on NFS may sometimes return -EIO, which can be traced back to xdr_buf_read_netobj() failing to find available free space in the tail to copy the MIC.
Fix this by checking for the case of the MIC crossing the boundaries of head, pages, and tail. If so, shift the buffer until the MIC is contained completely within the pages or tail. This allows the remainder of the function to create a sub buffer that directly address the complete MIC.
Signed-off-by: Benjamin Coddington bcodding@redhat.com Cc: stable@vger.kernel.org # v5.1 Reviewed-by: Chuck Lever chuck.lever@oracle.com Signed-off-by: Anna Schumaker Anna.Schumaker@Netapp.com Signed-off-by: Lu Wei luwei32@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/sunrpc/xdr.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 540e340e2565c..c306f242ce342 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -1199,16 +1199,29 @@ xdr_encode_word(struct xdr_buf *buf, unsigned int base, u32 obj) EXPORT_SYMBOL_GPL(xdr_encode_word);
/* If the netobj starting offset bytes from the start of xdr_buf is contained - * entirely in the head or the tail, set object to point to it; otherwise - * try to find space for it at the end of the tail, copy it there, and - * set obj to point to it. */ + * entirely in the head, pages, or tail, set object to point to it; otherwise + * shift the buffer until it is contained entirely within the pages or tail. + */ int xdr_buf_read_netobj(struct xdr_buf *buf, struct xdr_netobj *obj, unsigned int offset) { struct xdr_buf subbuf; + unsigned int boundary;
if (xdr_decode_word(buf, offset, &obj->len)) return -EFAULT; - if (xdr_buf_subsegment(buf, &subbuf, offset + 4, obj->len)) + offset += 4; + + /* Is the obj partially in the head? */ + boundary = buf->head[0].iov_len; + if (offset < boundary && (offset + obj->len) > boundary) + xdr_shift_buf(buf, boundary - offset); + + /* Is the obj partially in the pages? */ + boundary += buf->page_len; + if (offset < boundary && (offset + obj->len) > boundary) + xdr_shrink_pagelen(buf, boundary - offset); + + if (xdr_buf_subsegment(buf, &subbuf, offset, obj->len)) return -EFAULT;
/* Is the obj contained entirely in the head? */ @@ -1220,11 +1233,7 @@ int xdr_buf_read_netobj(struct xdr_buf *buf, struct xdr_netobj *obj, unsigned in if (subbuf.tail[0].iov_len == obj->len) return 0;
- /* use end of tail as storage for obj: - * (We don't copy to the beginning because then we'd have - * to worry about doing a potentially overlapping copy. - * This assumes the object is at most half the length of the - * tail.) */ + /* Find a contiguous area in @buf to hold all of @obj */ if (obj->len > buf->buflen - buf->len) return -ENOMEM; if (buf->tail[0].iov_len != 0)
From: Trond Myklebust trond.myklebust@hammerspace.com
mainline inclusion from mainline-v5.3-rc1 commit 163f88211c147d96b46e376337190a02203ace02 category: bugfix bugzilla: 51816 CVE: NA
-------------------------------------------------
When looking for the next transport to use for an RPC call, skip those that are in the process of being destroyed and that have a zero refcount.
Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/sunrpc/xprtmultipath.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/net/sunrpc/xprtmultipath.c b/net/sunrpc/xprtmultipath.c index e2d64c7138c3a..6ebaa58b4eff4 100644 --- a/net/sunrpc/xprtmultipath.c +++ b/net/sunrpc/xprtmultipath.c @@ -192,10 +192,22 @@ void xprt_iter_default_rewind(struct rpc_xprt_iter *xpi) WRITE_ONCE(xpi->xpi_cursor, NULL); }
+static +bool xprt_is_active(const struct rpc_xprt *xprt) +{ + return kref_read(&xprt->kref) != 0; +} + static struct rpc_xprt *xprt_switch_find_first_entry(struct list_head *head) { - return list_first_or_null_rcu(head, struct rpc_xprt, xprt_switch); + struct rpc_xprt *pos; + + list_for_each_entry_rcu(pos, head, xprt_switch) { + if (xprt_is_active(pos)) + return pos; + } + return NULL; }
static @@ -213,9 +225,12 @@ struct rpc_xprt *xprt_switch_find_current_entry(struct list_head *head, const struct rpc_xprt *cur) { struct rpc_xprt *pos; + bool found = false;
list_for_each_entry_rcu(pos, head, xprt_switch) { if (cur == pos) + found = true; + if (found && xprt_is_active(pos)) return pos; } return NULL; @@ -260,9 +275,12 @@ struct rpc_xprt *xprt_switch_find_next_entry(struct list_head *head, const struct rpc_xprt *cur) { struct rpc_xprt *pos, *prev = NULL; + bool found = false;
list_for_each_entry_rcu(pos, head, xprt_switch) { if (cur == prev) + found = true; + if (found && xprt_is_active(pos)) return pos; prev = pos; }
From: Trond Myklebust trondmy@gmail.com
mainline inclusion from mainline-v5.6-rc1 commit 1d82163714c16ebe09c7a8c9cd3cef7abcc16208 category: bugfix bugzilla: 51810 CVE: NA
-------------------------------------------------
When we unhash the cache entry, we need to handle any pending upcalls by calling cache_fresh_unlocked().
Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: J. Bruce Fields bfields@redhat.com Signed-off-by: Lu Wei luwei32@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/sunrpc/cache.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index afab8fce92054..d2c089e5041fb 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1855,7 +1855,9 @@ void sunrpc_cache_unhash(struct cache_detail *cd, struct cache_head *h) if (!hlist_unhashed(&h->cache_list)){ hlist_del_init(&h->cache_list); cd->entries--; + set_bit(CACHE_CLEANED, &h->flags); write_unlock(&cd->hash_lock); + cache_fresh_unlocked(h, cd); cache_put(h, cd); } else write_unlock(&cd->hash_lock);
From: Arnd Bergmann arnd@arndb.de
mainline inclusion from mainline-v5.6-rc1 commit 294ec5b87a8aaef664efb00ba62e4ef6ca05707c category: bugfix bugzilla: 51810 CVE: NA
-------------------------------------------------
Using signed 32-bit types for UTC time leads to the y2038 overflow, which is what happens in the sunrpc code at the moment.
This changes the sunrpc code over to use time64_t where possible. The one exception is the gss_import_v{1,2}_context() function for kerberos5, which uses 32-bit timestamps in the protocol. Here, we can at least treat the numbers as 'unsigned', which extends the range from 2038 to 2106.
Signed-off-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Lu Wei luwei32@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- include/linux/sunrpc/gss_api.h | 4 ++-- include/linux/sunrpc/gss_krb5.h | 2 +- net/sunrpc/auth_gss/gss_krb5_mech.c | 12 +++++++++--- net/sunrpc/auth_gss/gss_krb5_seal.c | 8 ++++---- net/sunrpc/auth_gss/gss_krb5_unseal.c | 6 +++--- net/sunrpc/auth_gss/gss_krb5_wrap.c | 16 ++++++++-------- net/sunrpc/auth_gss/gss_mech_switch.c | 2 +- net/sunrpc/auth_gss/svcauth_gss.c | 4 ++-- 8 files changed, 30 insertions(+), 24 deletions(-)
diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h index 566d5f547567e..e260d1b4590e5 100644 --- a/include/linux/sunrpc/gss_api.h +++ b/include/linux/sunrpc/gss_api.h @@ -49,7 +49,7 @@ int gss_import_sec_context( size_t bufsize, struct gss_api_mech *mech, struct gss_ctx **ctx_id, - time_t *endtime, + time64_t *endtime, gfp_t gfp_mask); u32 gss_get_mic( struct gss_ctx *ctx_id, @@ -110,7 +110,7 @@ struct gss_api_ops { const void *input_token, size_t bufsize, struct gss_ctx *ctx_id, - time_t *endtime, + time64_t *endtime, gfp_t gfp_mask); u32 (*gss_get_mic)( struct gss_ctx *ctx_id, diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 7df625d41e358..2b2dce09f3b76 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -106,7 +106,7 @@ struct krb5_ctx { struct crypto_skcipher *initiator_enc_aux; u8 Ksess[GSS_KRB5_MAX_KEYLEN]; /* session key */ u8 cksum[GSS_KRB5_MAX_KEYLEN]; - s32 endtime; + time64_t endtime; u32 seq_send; u64 seq_send64; struct xdr_netobj mech_used; diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 14f2823ad6c20..893d8a4805921 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -249,6 +249,7 @@ static int gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) { int tmp; + u32 time32;
p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate)); if (IS_ERR(p)) @@ -286,9 +287,11 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) p = ERR_PTR(-ENOSYS); goto out_err; } - p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime)); + p = simple_get_bytes(p, end, &time32, sizeof(time32)); if (IS_ERR(p)) goto out_err; + /* unsigned 32-bit time overflows in year 2106 */ + ctx->endtime = (time64_t)time32; p = simple_get_bytes(p, end, &ctx->seq_send, sizeof(ctx->seq_send)); if (IS_ERR(p)) goto out_err; @@ -584,15 +587,18 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, gfp_t gfp_mask) { int keylen; + u32 time32;
p = simple_get_bytes(p, end, &ctx->flags, sizeof(ctx->flags)); if (IS_ERR(p)) goto out_err; ctx->initiate = ctx->flags & KRB5_CTX_FLAG_INITIATOR;
- p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime)); + p = simple_get_bytes(p, end, &time32, sizeof(time32)); if (IS_ERR(p)) goto out_err; + /* unsigned 32-bit time overflows in year 2106 */ + ctx->endtime = (time64_t)time32; p = simple_get_bytes(p, end, &ctx->seq_send64, sizeof(ctx->seq_send64)); if (IS_ERR(p)) goto out_err; @@ -655,7 +661,7 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, static int gss_import_sec_context_kerberos(const void *p, size_t len, struct gss_ctx *ctx_id, - time_t *endtime, + time64_t *endtime, gfp_t gfp_mask) { const void *end = (const void *)((const char *)p + len); diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c index e1f0571843c8c..38ccb0ab5af86 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seal.c +++ b/net/sunrpc/auth_gss/gss_krb5_seal.c @@ -133,14 +133,14 @@ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text, struct xdr_netobj md5cksum = {.len = sizeof(cksumdata), .data = cksumdata}; void *ptr; - s32 now; + time64_t now; u32 seq_send; u8 *cksumkey;
dprintk("RPC: %s\n", __func__); BUG_ON(ctx == NULL);
- now = get_seconds(); + now = ktime_get_real_seconds();
ptr = setup_token(ctx, token);
@@ -174,7 +174,7 @@ gss_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text, struct xdr_netobj cksumobj = { .len = sizeof(cksumdata), .data = cksumdata}; void *krb5_hdr; - s32 now; + time64_t now; u64 seq_send; u8 *cksumkey; unsigned int cksum_usage; @@ -207,7 +207,7 @@ gss_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text,
memcpy(krb5_hdr + GSS_KRB5_TOK_HDR_LEN, cksumobj.data, cksumobj.len);
- now = get_seconds(); + now = ktime_get_real_seconds();
return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; } diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c index ef2b25b86d2f4..aaab91cf24c8f 100644 --- a/net/sunrpc/auth_gss/gss_krb5_unseal.c +++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c @@ -124,7 +124,7 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
/* it got through unscathed. Make sure the context is unexpired */
- now = get_seconds(); + now = ktime_get_real_seconds();
if (now > ctx->endtime) return GSS_S_CONTEXT_EXPIRED; @@ -149,7 +149,7 @@ gss_verify_mic_v2(struct krb5_ctx *ctx, char cksumdata[GSS_KRB5_MAX_CKSUM_LEN]; struct xdr_netobj cksumobj = {.len = sizeof(cksumdata), .data = cksumdata}; - s32 now; + time64_t now; u8 *ptr = read_token->data; u8 *cksumkey; u8 flags; @@ -194,7 +194,7 @@ gss_verify_mic_v2(struct krb5_ctx *ctx, return GSS_S_BAD_SIG;
/* it got through unscathed. Make sure the context is unexpired */ - now = get_seconds(); + now = ktime_get_real_seconds(); if (now > ctx->endtime) return GSS_S_CONTEXT_EXPIRED;
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 39a2e672900bd..b85899bf9d796 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c @@ -163,7 +163,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, .data = cksumdata}; int blocksize = 0, plainlen; unsigned char *ptr, *msg_start; - s32 now; + time64_t now; int headlen; struct page **tmp_pages; u32 seq_send; @@ -172,7 +172,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
dprintk("RPC: %s\n", __func__);
- now = get_seconds(); + now = ktime_get_real_seconds();
blocksize = crypto_skcipher_blocksize(kctx->enc); gss_krb5_add_padding(buf, offset, blocksize); @@ -270,7 +270,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) char cksumdata[GSS_KRB5_MAX_CKSUM_LEN]; struct xdr_netobj md5cksum = {.len = sizeof(cksumdata), .data = cksumdata}; - s32 now; + time64_t now; int direction; s32 seqnum; unsigned char *ptr; @@ -361,7 +361,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
/* it got through unscathed. Make sure the context is unexpired */
- now = get_seconds(); + now = ktime_get_real_seconds();
if (now > kctx->endtime) return GSS_S_CONTEXT_EXPIRED; @@ -441,7 +441,7 @@ gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf, struct page **pages) { u8 *ptr, *plainhdr; - s32 now; + time64_t now; u8 flags = 0x00; __be16 *be16ptr; __be64 *be64ptr; @@ -485,14 +485,14 @@ gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset, if (err) return err;
- now = get_seconds(); + now = ktime_get_real_seconds(); return (kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; }
static u32 gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) { - s32 now; + time64_t now; u8 *ptr; u8 flags = 0x00; u16 ec, rrc; @@ -561,7 +561,7 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) /* do sequencing checks */
/* it got through unscathed. Make sure the context is unexpired */ - now = get_seconds(); + now = ktime_get_real_seconds(); if (now > kctx->endtime) return GSS_S_CONTEXT_EXPIRED;
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c index c7d88f979c566..94c52433f05ee 100644 --- a/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/net/sunrpc/auth_gss/gss_mech_switch.c @@ -405,7 +405,7 @@ int gss_import_sec_context(const void *input_token, size_t bufsize, struct gss_api_mech *mech, struct gss_ctx **ctx_id, - time_t *endtime, + time64_t *endtime, gfp_t gfp_mask) { if (!(*ctx_id = kzalloc(sizeof(**ctx_id), gfp_mask))) diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index a04a7d2772975..28ea194bd87a5 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -423,7 +423,7 @@ static int rsc_parse(struct cache_detail *cd, int id; int len, rv; struct rsc rsci, *rscp = NULL; - time_t expiry; + time64_t expiry; int status = -EINVAL; struct gss_api_mech *gm = NULL;
@@ -1177,7 +1177,7 @@ static int gss_proxy_save_rsc(struct cache_detail *cd, static atomic64_t ctxhctr; long long ctxh; struct gss_api_mech *gm = NULL; - time_t expiry; + time64_t expiry; int status = -EINVAL;
memset(&rsci, 0, sizeof(rsci));
From: Chuck Lever chuck.lever@oracle.com
mainline inclusion from mainline-v5.5-rc1 commit 8729aaba74626c4ebce3abf1b9e96bb62d2958ca category: bugfix bugzilla: 51810 CVE: NA
-------------------------------------------------
I noticed that for callback requests, the reported backlog latency is always zero, and the rtt value is crazy big. The problem was that rqst->rq_xtime is never set for backchannel requests.
Fixes: 78215759e20d ("SUNRPC: Make RTT measurement more ... ") Signed-off-by: Chuck Lever chuck.lever@oracle.com Signed-off-by: J. Bruce Fields bfields@redhat.com Signed-off-by: Lu Wei luwei32@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/sunrpc/xprtrdma/svc_rdma_backchannel.c | 1 + net/sunrpc/xprtsock.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c index fc6ea5b7e32c8..9d962a4cf610d 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c +++ b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c @@ -198,6 +198,7 @@ rpcrdma_bc_send_request(struct svcxprt_rdma *rdma, struct rpc_rqst *rqst) pr_info("%s: %*ph\n", __func__, 64, rqst->rq_buffer); #endif
+ rqst->rq_xtime = ktime_get(); rc = svc_rdma_bc_sendto(rdma, rqst, ctxt); if (rc) { svc_rdma_send_ctxt_put(rdma, ctxt); diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index bd5a7da70ae0f..60ebb402ba61f 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -2698,6 +2698,9 @@ static int bc_sendto(struct rpc_rqst *req)
tailoff = (unsigned long)xbufp->tail[0].iov_base & ~PAGE_MASK; headoff = (unsigned long)xbufp->head[0].iov_base & ~PAGE_MASK; + + req->rq_xtime = ktime_get(); + len = svc_send_common(sock, xbufp, virt_to_page(xbufp->head[0].iov_base), headoff, xbufp->tail[0].iov_base, tailoff); @@ -2719,7 +2722,6 @@ static int bc_send_request(struct rpc_task *task) 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 */