Skip to content

Commit 7a6b604

Browse files
committed
Merge tag 'nfsd-5.9' of git://git.linux-nfs.org/projects/cel/cel-2.6
Pull NFS server updates from Chuck Lever: "Highlights: - Support for user extended attributes on NFS (RFC 8276) - Further reduce unnecessary NFSv4 delegation recalls Notable fixes: - Fix recent krb5p regression - Address a few resource leaks and a rare NULL dereference Other: - De-duplicate RPC/RDMA error handling and other utility functions - Replace storage and display of kernel memory addresses by tracepoints" * tag 'nfsd-5.9' of git://git.linux-nfs.org/projects/cel/cel-2.6: (38 commits) svcrdma: CM event handler clean up svcrdma: Remove transport reference counting svcrdma: Fix another Receive buffer leak SUNRPC: Refresh the show_rqstp_flags() macro nfsd: netns.h: delete a duplicated word SUNRPC: Fix ("SUNRPC: Add "@len" parameter to gss_unwrap()") nfsd: avoid a NULL dereference in __cld_pipe_upcall() nfsd4: a client's own opens needn't prevent delegations nfsd: Use seq_putc() in two functions svcrdma: Display chunk completion ID when posting a rw_ctxt svcrdma: Record send_ctxt completion ID in trace_svcrdma_post_send() svcrdma: Introduce Send completion IDs svcrdma: Record Receive completion ID in svc_rdma_decode_rqst svcrdma: Introduce Receive completion IDs svcrdma: Introduce infrastructure to support completion IDs svcrdma: Add common XDR encoders for RDMA and Read segments svcrdma: Add common XDR decoders for RDMA and Read segments SUNRPC: Add helpers for decoding list discriminators symbolically svcrdma: Remove declarations for functions long removed svcrdma: Clean up trace_svcrdma_send_failed() tracepoint ...
2 parents 8d3e09b + b297fed commit 7a6b604

32 files changed

+1807
-466
lines changed

fs/locks.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1808,6 +1808,9 @@ check_conflicting_open(struct file *filp, const long arg, int flags)
18081808

18091809
if (flags & FL_LAYOUT)
18101810
return 0;
1811+
if (flags & FL_DELEG)
1812+
/* We leave these checks to the caller. */
1813+
return 0;
18111814

18121815
if (arg == F_RDLCK)
18131816
return inode_is_open_for_write(inode) ? -EAGAIN : 0;

fs/nfsd/netns.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ struct nfsd_net {
171171
unsigned int longest_chain_cachesize;
172172

173173
struct shrinker nfsd_reply_cache_shrinker;
174-
/* utsname taken from the the process that starts the server */
174+
/* utsname taken from the process that starts the server */
175175
char nfsd_name[UNX_MAXNODENAME+1];
176176
};
177177

fs/nfsd/nfs4idmap.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ idtoname_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
168168
ent->id);
169169
if (test_bit(CACHE_VALID, &h->flags))
170170
seq_printf(m, " %s", ent->name);
171-
seq_printf(m, "\n");
171+
seq_putc(m, '\n');
172172
return 0;
173173
}
174174

@@ -346,7 +346,7 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
346346
ent->name);
347347
if (test_bit(CACHE_VALID, &h->flags))
348348
seq_printf(m, " %u", ent->id);
349-
seq_printf(m, "\n");
349+
seq_putc(m, '\n');
350350
return 0;
351351
}
352352

fs/nfsd/nfs4proc.c

Lines changed: 127 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,8 +566,14 @@ nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
566566
union nfsd4_op_u *u)
567567
{
568568
struct nfsd4_access *access = &u->access;
569+
u32 access_full;
569570

570-
if (access->ac_req_access & ~NFS3_ACCESS_FULL)
571+
access_full = NFS3_ACCESS_FULL;
572+
if (cstate->minorversion >= 2)
573+
access_full |= NFS4_ACCESS_XALIST | NFS4_ACCESS_XAREAD |
574+
NFS4_ACCESS_XAWRITE;
575+
576+
if (access->ac_req_access & ~access_full)
571577
return nfserr_inval;
572578

573579
access->ac_resp_access = access->ac_req_access;
@@ -2091,6 +2097,68 @@ nfsd4_layoutreturn(struct svc_rqst *rqstp,
20912097
}
20922098
#endif /* CONFIG_NFSD_PNFS */
20932099

2100+
static __be32
2101+
nfsd4_getxattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2102+
union nfsd4_op_u *u)
2103+
{
2104+
struct nfsd4_getxattr *getxattr = &u->getxattr;
2105+
2106+
return nfsd_getxattr(rqstp, &cstate->current_fh,
2107+
getxattr->getxa_name, &getxattr->getxa_buf,
2108+
&getxattr->getxa_len);
2109+
}
2110+
2111+
static __be32
2112+
nfsd4_setxattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2113+
union nfsd4_op_u *u)
2114+
{
2115+
struct nfsd4_setxattr *setxattr = &u->setxattr;
2116+
__be32 ret;
2117+
2118+
if (opens_in_grace(SVC_NET(rqstp)))
2119+
return nfserr_grace;
2120+
2121+
ret = nfsd_setxattr(rqstp, &cstate->current_fh, setxattr->setxa_name,
2122+
setxattr->setxa_buf, setxattr->setxa_len,
2123+
setxattr->setxa_flags);
2124+
2125+
if (!ret)
2126+
set_change_info(&setxattr->setxa_cinfo, &cstate->current_fh);
2127+
2128+
return ret;
2129+
}
2130+
2131+
static __be32
2132+
nfsd4_listxattrs(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2133+
union nfsd4_op_u *u)
2134+
{
2135+
/*
2136+
* Get the entire list, then copy out only the user attributes
2137+
* in the encode function.
2138+
*/
2139+
return nfsd_listxattr(rqstp, &cstate->current_fh,
2140+
&u->listxattrs.lsxa_buf, &u->listxattrs.lsxa_len);
2141+
}
2142+
2143+
static __be32
2144+
nfsd4_removexattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2145+
union nfsd4_op_u *u)
2146+
{
2147+
struct nfsd4_removexattr *removexattr = &u->removexattr;
2148+
__be32 ret;
2149+
2150+
if (opens_in_grace(SVC_NET(rqstp)))
2151+
return nfserr_grace;
2152+
2153+
ret = nfsd_removexattr(rqstp, &cstate->current_fh,
2154+
removexattr->rmxa_name);
2155+
2156+
if (!ret)
2157+
set_change_info(&removexattr->rmxa_cinfo, &cstate->current_fh);
2158+
2159+
return ret;
2160+
}
2161+
20942162
/*
20952163
* NULL call.
20962164
*/
@@ -2700,6 +2768,42 @@ static inline u32 nfsd4_seek_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
27002768
return (op_encode_hdr_size + 3) * sizeof(__be32);
27012769
}
27022770

2771+
static inline u32 nfsd4_getxattr_rsize(struct svc_rqst *rqstp,
2772+
struct nfsd4_op *op)
2773+
{
2774+
u32 maxcount, rlen;
2775+
2776+
maxcount = svc_max_payload(rqstp);
2777+
rlen = min_t(u32, XATTR_SIZE_MAX, maxcount);
2778+
2779+
return (op_encode_hdr_size + 1 + XDR_QUADLEN(rlen)) * sizeof(__be32);
2780+
}
2781+
2782+
static inline u32 nfsd4_setxattr_rsize(struct svc_rqst *rqstp,
2783+
struct nfsd4_op *op)
2784+
{
2785+
return (op_encode_hdr_size + op_encode_change_info_maxsz)
2786+
* sizeof(__be32);
2787+
}
2788+
static inline u32 nfsd4_listxattrs_rsize(struct svc_rqst *rqstp,
2789+
struct nfsd4_op *op)
2790+
{
2791+
u32 maxcount, rlen;
2792+
2793+
maxcount = svc_max_payload(rqstp);
2794+
rlen = min(op->u.listxattrs.lsxa_maxcount, maxcount);
2795+
2796+
return (op_encode_hdr_size + 4 + XDR_QUADLEN(rlen)) * sizeof(__be32);
2797+
}
2798+
2799+
static inline u32 nfsd4_removexattr_rsize(struct svc_rqst *rqstp,
2800+
struct nfsd4_op *op)
2801+
{
2802+
return (op_encode_hdr_size + op_encode_change_info_maxsz)
2803+
* sizeof(__be32);
2804+
}
2805+
2806+
27032807
static const struct nfsd4_operation nfsd4_ops[] = {
27042808
[OP_ACCESS] = {
27052809
.op_func = nfsd4_access,
@@ -3081,6 +3185,28 @@ static const struct nfsd4_operation nfsd4_ops[] = {
30813185
.op_name = "OP_COPY_NOTIFY",
30823186
.op_rsize_bop = nfsd4_copy_notify_rsize,
30833187
},
3188+
[OP_GETXATTR] = {
3189+
.op_func = nfsd4_getxattr,
3190+
.op_name = "OP_GETXATTR",
3191+
.op_rsize_bop = nfsd4_getxattr_rsize,
3192+
},
3193+
[OP_SETXATTR] = {
3194+
.op_func = nfsd4_setxattr,
3195+
.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
3196+
.op_name = "OP_SETXATTR",
3197+
.op_rsize_bop = nfsd4_setxattr_rsize,
3198+
},
3199+
[OP_LISTXATTRS] = {
3200+
.op_func = nfsd4_listxattrs,
3201+
.op_name = "OP_LISTXATTRS",
3202+
.op_rsize_bop = nfsd4_listxattrs_rsize,
3203+
},
3204+
[OP_REMOVEXATTR] = {
3205+
.op_func = nfsd4_removexattr,
3206+
.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
3207+
.op_name = "OP_REMOVEXATTR",
3208+
.op_rsize_bop = nfsd4_removexattr_rsize,
3209+
},
30843210
};
30853211

30863212
/**

fs/nfsd/nfs4recover.c

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -747,13 +747,11 @@ struct cld_upcall {
747747
};
748748

749749
static int
750-
__cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg)
750+
__cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn)
751751
{
752752
int ret;
753753
struct rpc_pipe_msg msg;
754754
struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, cu_u);
755-
struct nfsd_net *nn = net_generic(pipe->dentry->d_sb->s_fs_info,
756-
nfsd_net_id);
757755

758756
memset(&msg, 0, sizeof(msg));
759757
msg.data = cmsg;
@@ -773,7 +771,7 @@ __cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg)
773771
}
774772

775773
static int
776-
cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg)
774+
cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn)
777775
{
778776
int ret;
779777

@@ -782,7 +780,7 @@ cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg)
782780
* upcalls queued.
783781
*/
784782
do {
785-
ret = __cld_pipe_upcall(pipe, cmsg);
783+
ret = __cld_pipe_upcall(pipe, cmsg, nn);
786784
} while (ret == -EAGAIN);
787785

788786
return ret;
@@ -1115,7 +1113,7 @@ nfsd4_cld_create(struct nfs4_client *clp)
11151113
memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
11161114
clp->cl_name.len);
11171115

1118-
ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
1116+
ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
11191117
if (!ret) {
11201118
ret = cup->cu_u.cu_msg.cm_status;
11211119
set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
@@ -1180,7 +1178,7 @@ nfsd4_cld_create_v2(struct nfs4_client *clp)
11801178
} else
11811179
cmsg->cm_u.cm_clntinfo.cc_princhash.cp_len = 0;
11821180

1183-
ret = cld_pipe_upcall(cn->cn_pipe, cmsg);
1181+
ret = cld_pipe_upcall(cn->cn_pipe, cmsg, nn);
11841182
if (!ret) {
11851183
ret = cmsg->cm_status;
11861184
set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
@@ -1218,7 +1216,7 @@ nfsd4_cld_remove(struct nfs4_client *clp)
12181216
memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
12191217
clp->cl_name.len);
12201218

1221-
ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
1219+
ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
12221220
if (!ret) {
12231221
ret = cup->cu_u.cu_msg.cm_status;
12241222
clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
@@ -1261,7 +1259,7 @@ nfsd4_cld_check_v0(struct nfs4_client *clp)
12611259
memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
12621260
clp->cl_name.len);
12631261

1264-
ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
1262+
ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
12651263
if (!ret) {
12661264
ret = cup->cu_u.cu_msg.cm_status;
12671265
set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
@@ -1404,7 +1402,7 @@ nfsd4_cld_grace_start(struct nfsd_net *nn)
14041402
}
14051403

14061404
cup->cu_u.cu_msg.cm_cmd = Cld_GraceStart;
1407-
ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
1405+
ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
14081406
if (!ret)
14091407
ret = cup->cu_u.cu_msg.cm_status;
14101408

@@ -1432,7 +1430,7 @@ nfsd4_cld_grace_done_v0(struct nfsd_net *nn)
14321430

14331431
cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone;
14341432
cup->cu_u.cu_msg.cm_u.cm_gracetime = nn->boot_time;
1435-
ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
1433+
ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
14361434
if (!ret)
14371435
ret = cup->cu_u.cu_msg.cm_status;
14381436

@@ -1460,7 +1458,7 @@ nfsd4_cld_grace_done(struct nfsd_net *nn)
14601458
}
14611459

14621460
cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone;
1463-
ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
1461+
ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
14641462
if (!ret)
14651463
ret = cup->cu_u.cu_msg.cm_status;
14661464

@@ -1524,7 +1522,7 @@ nfsd4_cld_get_version(struct nfsd_net *nn)
15241522
goto out_err;
15251523
}
15261524
cup->cu_u.cu_msg.cm_cmd = Cld_GetVersion;
1527-
ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
1525+
ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
15281526
if (!ret) {
15291527
ret = cup->cu_u.cu_msg.cm_status;
15301528
if (ret)

fs/nfsd/nfs4state.c

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4940,6 +4940,32 @@ static struct file_lock *nfs4_alloc_init_lease(struct nfs4_delegation *dp,
49404940
return fl;
49414941
}
49424942

4943+
static int nfsd4_check_conflicting_opens(struct nfs4_client *clp,
4944+
struct nfs4_file *fp)
4945+
{
4946+
struct nfs4_clnt_odstate *co;
4947+
struct file *f = fp->fi_deleg_file->nf_file;
4948+
struct inode *ino = locks_inode(f);
4949+
int writes = atomic_read(&ino->i_writecount);
4950+
4951+
if (fp->fi_fds[O_WRONLY])
4952+
writes--;
4953+
if (fp->fi_fds[O_RDWR])
4954+
writes--;
4955+
WARN_ON_ONCE(writes < 0);
4956+
if (writes > 0)
4957+
return -EAGAIN;
4958+
spin_lock(&fp->fi_lock);
4959+
list_for_each_entry(co, &fp->fi_clnt_odstate, co_perfile) {
4960+
if (co->co_client != clp) {
4961+
spin_unlock(&fp->fi_lock);
4962+
return -EAGAIN;
4963+
}
4964+
}
4965+
spin_unlock(&fp->fi_lock);
4966+
return 0;
4967+
}
4968+
49434969
static struct nfs4_delegation *
49444970
nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
49454971
struct nfs4_file *fp, struct nfs4_clnt_odstate *odstate)
@@ -4959,9 +4985,12 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
49594985

49604986
nf = find_readable_file(fp);
49614987
if (!nf) {
4962-
/* We should always have a readable file here */
4963-
WARN_ON_ONCE(1);
4964-
return ERR_PTR(-EBADF);
4988+
/*
4989+
* We probably could attempt another open and get a read
4990+
* delegation, but for now, don't bother until the
4991+
* client actually sends us one.
4992+
*/
4993+
return ERR_PTR(-EAGAIN);
49654994
}
49664995
spin_lock(&state_lock);
49674996
spin_lock(&fp->fi_lock);
@@ -4991,11 +5020,19 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
49915020
if (!fl)
49925021
goto out_clnt_odstate;
49935022

5023+
status = nfsd4_check_conflicting_opens(clp, fp);
5024+
if (status) {
5025+
locks_free_lock(fl);
5026+
goto out_clnt_odstate;
5027+
}
49945028
status = vfs_setlease(fp->fi_deleg_file->nf_file, fl->fl_type, &fl, NULL);
49955029
if (fl)
49965030
locks_free_lock(fl);
49975031
if (status)
49985032
goto out_clnt_odstate;
5033+
status = nfsd4_check_conflicting_opens(clp, fp);
5034+
if (status)
5035+
goto out_clnt_odstate;
49995036

50005037
spin_lock(&state_lock);
50015038
spin_lock(&fp->fi_lock);
@@ -5077,17 +5114,6 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open,
50775114
goto out_no_deleg;
50785115
if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED))
50795116
goto out_no_deleg;
5080-
/*
5081-
* Also, if the file was opened for write or
5082-
* create, there's a good chance the client's
5083-
* about to write to it, resulting in an
5084-
* immediate recall (since we don't support
5085-
* write delegations):
5086-
*/
5087-
if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
5088-
goto out_no_deleg;
5089-
if (open->op_create == NFS4_OPEN_CREATE)
5090-
goto out_no_deleg;
50915117
break;
50925118
default:
50935119
goto out_no_deleg;

0 commit comments

Comments
 (0)