Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'nfs-for-5.4-3' of git://git.linux-nfs.org/projects/anna/linux-nfs

Pull NFS client bugfixes from Anna Schumaker:
"This contains two delegation fixes (with the RCU lock leak fix marked
for stable), and three patches to fix destroying the the sunrpc back
channel.

Stable bugfixes:

- Fix an RCU lock leak in nfs4_refresh_delegation_stateid()

Other fixes:

- The TCP back channel mustn't disappear while requests are
outstanding

- The RDMA back channel mustn't disappear while requests are
outstanding

- Destroy the back channel when we destroy the host transport

- Don't allow a cached open with a revoked delegation"

* tag 'nfs-for-5.4-3' of git://git.linux-nfs.org/projects/anna/linux-nfs:
NFS: Fix an RCU lock leak in nfs4_refresh_delegation_stateid()
NFSv4: Don't allow a cached open with a revoked delegation
SUNRPC: Destroy the back channel when we destroy the host transport
SUNRPC: The RDMA back channel mustn't disappear while requests are outstanding
SUNRPC: The TCP back channel mustn't disappear while requests are outstanding

+30 -9
+11 -1
fs/nfs/delegation.c
··· 53 53 return false; 54 54 } 55 55 56 + struct nfs_delegation *nfs4_get_valid_delegation(const struct inode *inode) 57 + { 58 + struct nfs_delegation *delegation; 59 + 60 + delegation = rcu_dereference(NFS_I(inode)->delegation); 61 + if (nfs4_is_valid_delegation(delegation, 0)) 62 + return delegation; 63 + return NULL; 64 + } 65 + 56 66 static int 57 67 nfs4_do_check_delegation(struct inode *inode, fmode_t flags, bool mark) 58 68 { ··· 1191 1181 if (delegation != NULL && 1192 1182 nfs4_stateid_match_other(dst, &delegation->stateid)) { 1193 1183 dst->seqid = delegation->stateid.seqid; 1194 - return ret; 1184 + ret = true; 1195 1185 } 1196 1186 rcu_read_unlock(); 1197 1187 out:
+1
fs/nfs/delegation.h
··· 68 68 bool nfs4_copy_delegation_stateid(struct inode *inode, fmode_t flags, nfs4_stateid *dst, const struct cred **cred); 69 69 bool nfs4_refresh_delegation_stateid(nfs4_stateid *dst, struct inode *inode); 70 70 71 + struct nfs_delegation *nfs4_get_valid_delegation(const struct inode *inode); 71 72 void nfs_mark_delegation_referenced(struct nfs_delegation *delegation); 72 73 int nfs4_have_delegation(struct inode *inode, fmode_t flags); 73 74 int nfs4_check_delegation(struct inode *inode, fmode_t flags);
+2 -5
fs/nfs/nfs4proc.c
··· 1440 1440 return 0; 1441 1441 if ((delegation->type & fmode) != fmode) 1442 1442 return 0; 1443 - if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) 1444 - return 0; 1445 1443 switch (claim) { 1446 1444 case NFS4_OPEN_CLAIM_NULL: 1447 1445 case NFS4_OPEN_CLAIM_FH: ··· 1808 1810 static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) 1809 1811 { 1810 1812 struct nfs4_state *state = opendata->state; 1811 - struct nfs_inode *nfsi = NFS_I(state->inode); 1812 1813 struct nfs_delegation *delegation; 1813 1814 int open_mode = opendata->o_arg.open_flags; 1814 1815 fmode_t fmode = opendata->o_arg.fmode; ··· 1824 1827 } 1825 1828 spin_unlock(&state->owner->so_lock); 1826 1829 rcu_read_lock(); 1827 - delegation = rcu_dereference(nfsi->delegation); 1830 + delegation = nfs4_get_valid_delegation(state->inode); 1828 1831 if (!can_open_delegated(delegation, fmode, claim)) { 1829 1832 rcu_read_unlock(); 1830 1833 break; ··· 2368 2371 data->o_arg.open_flags, claim)) 2369 2372 goto out_no_action; 2370 2373 rcu_read_lock(); 2371 - delegation = rcu_dereference(NFS_I(data->state->inode)->delegation); 2374 + delegation = nfs4_get_valid_delegation(data->state->inode); 2372 2375 if (can_open_delegated(delegation, data->o_arg.fmode, claim)) 2373 2376 goto unlock_no_action; 2374 2377 rcu_read_unlock();
+5
include/linux/sunrpc/bc_xprt.h
··· 64 64 return 0; 65 65 } 66 66 67 + static inline void xprt_destroy_backchannel(struct rpc_xprt *xprt, 68 + unsigned int max_reqs) 69 + { 70 + } 71 + 67 72 static inline bool svc_is_backchannel(const struct svc_rqst *rqstp) 68 73 { 69 74 return false;
+4 -3
net/sunrpc/backchannel_rqst.c
··· 220 220 goto out; 221 221 222 222 spin_lock_bh(&xprt->bc_pa_lock); 223 - xprt->bc_alloc_max -= max_reqs; 223 + xprt->bc_alloc_max -= min(max_reqs, xprt->bc_alloc_max); 224 224 list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) { 225 225 dprintk("RPC: req=%p\n", req); 226 226 list_del(&req->rq_bc_pa_list); ··· 307 307 */ 308 308 dprintk("RPC: Last session removed req=%p\n", req); 309 309 xprt_free_allocation(req); 310 - return; 311 310 } 311 + xprt_put(xprt); 312 312 } 313 313 314 314 /* ··· 339 339 spin_unlock(&xprt->bc_pa_lock); 340 340 if (new) { 341 341 if (req != new) 342 - xprt_free_bc_rqst(new); 342 + xprt_free_allocation(new); 343 343 break; 344 344 } else if (req) 345 345 break; ··· 368 368 set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); 369 369 370 370 dprintk("RPC: add callback request to list\n"); 371 + xprt_get(xprt); 371 372 spin_lock(&bc_serv->sv_cb_lock); 372 373 list_add(&req->rq_bc_list, &bc_serv->sv_cb_list); 373 374 wake_up(&bc_serv->sv_cb_waitq);
+5
net/sunrpc/xprt.c
··· 1943 1943 rpc_destroy_wait_queue(&xprt->backlog); 1944 1944 kfree(xprt->servername); 1945 1945 /* 1946 + * Destroy any existing back channel 1947 + */ 1948 + xprt_destroy_backchannel(xprt, UINT_MAX); 1949 + 1950 + /* 1946 1951 * Tear down transport state and free the rpc_xprt 1947 1952 */ 1948 1953 xprt->ops->destroy(xprt);
+2
net/sunrpc/xprtrdma/backchannel.c
··· 163 163 spin_lock(&xprt->bc_pa_lock); 164 164 list_add_tail(&rqst->rq_bc_pa_list, &xprt->bc_pa_list); 165 165 spin_unlock(&xprt->bc_pa_lock); 166 + xprt_put(xprt); 166 167 } 167 168 168 169 static struct rpc_rqst *rpcrdma_bc_rqst_get(struct rpcrdma_xprt *r_xprt) ··· 260 259 261 260 /* Queue rqst for ULP's callback service */ 262 261 bc_serv = xprt->bc_serv; 262 + xprt_get(xprt); 263 263 spin_lock(&bc_serv->sv_cb_lock); 264 264 list_add(&rqst->rq_bc_list, &bc_serv->sv_cb_list); 265 265 spin_unlock(&bc_serv->sv_cb_lock);