Commit 8313064c authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'nfsd-4.11' of git://linux-nfs.org/~bfields/linux

Pull nfsd updates from Bruce Fields:
 "The nfsd update this round is mainly a lot of miscellaneous cleanups
  and bugfixes.

  A couple changes could theoretically break working setups on upgrade.
  I don't expect complaints in practice, but they seem worth calling out
  just in case:

   - NFS security labels are now off by default; a new security_label
     export flag reenables it per export. But, having them on by default
     is a disaster, as it generally only makes sense if all your clients
     and servers have similar enough selinux policies. Thanks to Jason
     Tibbitts for pointing this out.

   - NFSv4/UDP support is off. It was never really supported, and the
     spec explicitly forbids it. We only ever left it on out of
     laziness; thanks to Jeff Layton for finally fixing that"

* tag 'nfsd-4.11' of git://linux-nfs.org/~bfields/linux: (34 commits)
  nfsd: Fix display of the version string
  nfsd: fix configuration of supported minor versions
  sunrpc: don't register UDP port with rpcbind when version needs congestion control
  nfs/nfsd/sunrpc: enforce transport requirements for NFSv4
  sunrpc: flag transports as having congestion control
  sunrpc: turn bitfield flags in svc_version into bools
  nfsd: remove superfluous KERN_INFO
  nfsd: special case truncates some more
  nfsd: minor nfsd_setattr cleanup
  NFSD: Reserve adequate space for LOCKT operation
  NFSD: Get response size before operation for all RPCs
  nfsd/callback: Drop a useless data copy when comparing sessionid
  nfsd/callback: skip the callback tag
  nfsd/callback: Cleanup callback cred on shutdown
  nfsd/idmap: return nfserr_inval for 0-length names
  SUNRPC/Cache: Always treat the invalid cache as unexpired
  SUNRPC: Drop all entries from cache_detail when cache_purge()
  svcrdma: Poll CQs in "workqueue" mode
  svcrdma: Combine list fields in struct svc_rdma_op_ctxt
  svcrdma: Remove unused sc_dto_q field
  ...
parents b2deee2d ff7d1179
...@@ -322,6 +322,8 @@ static int lockd_inet6addr_event(struct notifier_block *this, ...@@ -322,6 +322,8 @@ static int lockd_inet6addr_event(struct notifier_block *this,
dprintk("lockd_inet6addr_event: removed %pI6\n", &ifa->addr); dprintk("lockd_inet6addr_event: removed %pI6\n", &ifa->addr);
sin6.sin6_family = AF_INET6; sin6.sin6_family = AF_INET6;
sin6.sin6_addr = ifa->addr; sin6.sin6_addr = ifa->addr;
if (ipv6_addr_type(&sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
sin6.sin6_scope_id = ifa->idev->dev->ifindex;
svc_age_temp_xprts_now(nlmsvc_rqst->rq_server, svc_age_temp_xprts_now(nlmsvc_rqst->rq_server,
(struct sockaddr *)&sin6); (struct sockaddr *)&sin6);
} }
......
...@@ -1083,7 +1083,8 @@ struct svc_version nfs4_callback_version1 = { ...@@ -1083,7 +1083,8 @@ struct svc_version nfs4_callback_version1 = {
.vs_proc = nfs4_callback_procedures1, .vs_proc = nfs4_callback_procedures1,
.vs_xdrsize = NFS4_CALLBACK_XDRSIZE, .vs_xdrsize = NFS4_CALLBACK_XDRSIZE,
.vs_dispatch = NULL, .vs_dispatch = NULL,
.vs_hidden = 1, .vs_hidden = true,
.vs_need_cong_ctrl = true,
}; };
struct svc_version nfs4_callback_version4 = { struct svc_version nfs4_callback_version4 = {
...@@ -1092,5 +1093,6 @@ struct svc_version nfs4_callback_version4 = { ...@@ -1092,5 +1093,6 @@ struct svc_version nfs4_callback_version4 = {
.vs_proc = nfs4_callback_procedures1, .vs_proc = nfs4_callback_procedures1,
.vs_xdrsize = NFS4_CALLBACK_XDRSIZE, .vs_xdrsize = NFS4_CALLBACK_XDRSIZE,
.vs_dispatch = NULL, .vs_dispatch = NULL,
.vs_hidden = 1, .vs_hidden = true,
.vs_need_cong_ctrl = true,
}; };
...@@ -1102,6 +1102,7 @@ static struct flags { ...@@ -1102,6 +1102,7 @@ static struct flags {
{ NFSEXP_NOAUTHNLM, {"insecure_locks", ""}}, { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
{ NFSEXP_V4ROOT, {"v4root", ""}}, { NFSEXP_V4ROOT, {"v4root", ""}},
{ NFSEXP_PNFS, {"pnfs", ""}}, { NFSEXP_PNFS, {"pnfs", ""}},
{ NFSEXP_SECURITY_LABEL, {"security_label", ""}},
{ 0, {"", ""}} { 0, {"", ""}}
}; };
......
...@@ -376,5 +376,4 @@ struct svc_version nfsd_acl_version2 = { ...@@ -376,5 +376,4 @@ struct svc_version nfsd_acl_version2 = {
.vs_proc = nfsd_acl_procedures2, .vs_proc = nfsd_acl_procedures2,
.vs_dispatch = nfsd_dispatch, .vs_dispatch = nfsd_dispatch,
.vs_xdrsize = NFS3_SVC_XDRSIZE, .vs_xdrsize = NFS3_SVC_XDRSIZE,
.vs_hidden = 0,
}; };
...@@ -266,6 +266,5 @@ struct svc_version nfsd_acl_version3 = { ...@@ -266,6 +266,5 @@ struct svc_version nfsd_acl_version3 = {
.vs_proc = nfsd_acl_procedures3, .vs_proc = nfsd_acl_procedures3,
.vs_dispatch = nfsd_dispatch, .vs_dispatch = nfsd_dispatch,
.vs_xdrsize = NFS3_SVC_XDRSIZE, .vs_xdrsize = NFS3_SVC_XDRSIZE,
.vs_hidden = 0,
}; };
...@@ -193,11 +193,9 @@ nfsd3_proc_write(struct svc_rqst *rqstp, struct nfsd3_writeargs *argp, ...@@ -193,11 +193,9 @@ nfsd3_proc_write(struct svc_rqst *rqstp, struct nfsd3_writeargs *argp,
fh_copy(&resp->fh, &argp->fh); fh_copy(&resp->fh, &argp->fh);
resp->committed = argp->stable; resp->committed = argp->stable;
nfserr = nfsd_write(rqstp, &resp->fh, NULL, nfserr = nfsd_write(rqstp, &resp->fh, argp->offset,
argp->offset, rqstp->rq_vec, argp->vlen,
rqstp->rq_vec, argp->vlen, &cnt, resp->committed);
&cnt,
&resp->committed);
resp->count = cnt; resp->count = cnt;
RETURN_STATUS(nfserr); RETURN_STATUS(nfserr);
} }
......
...@@ -303,6 +303,7 @@ static int decode_cb_compound4res(struct xdr_stream *xdr, ...@@ -303,6 +303,7 @@ static int decode_cb_compound4res(struct xdr_stream *xdr,
p = xdr_inline_decode(xdr, length + 4); p = xdr_inline_decode(xdr, length + 4);
if (unlikely(p == NULL)) if (unlikely(p == NULL))
goto out_overflow; goto out_overflow;
p += XDR_QUADLEN(length);
hdr->nops = be32_to_cpup(p); hdr->nops = be32_to_cpup(p);
return 0; return 0;
out_overflow: out_overflow:
...@@ -396,13 +397,10 @@ static int decode_cb_sequence4resok(struct xdr_stream *xdr, ...@@ -396,13 +397,10 @@ static int decode_cb_sequence4resok(struct xdr_stream *xdr,
struct nfsd4_callback *cb) struct nfsd4_callback *cb)
{ {
struct nfsd4_session *session = cb->cb_clp->cl_cb_session; struct nfsd4_session *session = cb->cb_clp->cl_cb_session;
struct nfs4_sessionid id; int status = -ESERVERFAULT;
int status;
__be32 *p; __be32 *p;
u32 dummy; u32 dummy;
status = -ESERVERFAULT;
/* /*
* If the server returns different values for sessionID, slotID or * If the server returns different values for sessionID, slotID or
* sequence number, the server is looney tunes. * sequence number, the server is looney tunes.
...@@ -410,9 +408,8 @@ static int decode_cb_sequence4resok(struct xdr_stream *xdr, ...@@ -410,9 +408,8 @@ static int decode_cb_sequence4resok(struct xdr_stream *xdr,
p = xdr_inline_decode(xdr, NFS4_MAX_SESSIONID_LEN + 4 + 4 + 4 + 4); p = xdr_inline_decode(xdr, NFS4_MAX_SESSIONID_LEN + 4 + 4 + 4 + 4);
if (unlikely(p == NULL)) if (unlikely(p == NULL))
goto out_overflow; goto out_overflow;
memcpy(id.data, p, NFS4_MAX_SESSIONID_LEN);
if (memcmp(id.data, session->se_sessionid.data, if (memcmp(p, session->se_sessionid.data, NFS4_MAX_SESSIONID_LEN)) {
NFS4_MAX_SESSIONID_LEN) != 0) {
dprintk("NFS: %s Invalid session id\n", __func__); dprintk("NFS: %s Invalid session id\n", __func__);
goto out; goto out;
} }
...@@ -753,6 +750,14 @@ int set_callback_cred(void) ...@@ -753,6 +750,14 @@ int set_callback_cred(void)
return 0; return 0;
} }
void cleanup_callback_cred(void)
{
if (callback_cred) {
put_rpccred(callback_cred);
callback_cred = NULL;
}
}
static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc_clnt *client, struct nfsd4_session *ses) static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc_clnt *client, struct nfsd4_session *ses)
{ {
if (clp->cl_minorversion == 0) { if (clp->cl_minorversion == 0) {
......
...@@ -628,6 +628,10 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen, ...@@ -628,6 +628,10 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
{ {
__be32 status; __be32 status;
u32 id = -1; u32 id = -1;
if (name == NULL || namelen == 0)
return nfserr_inval;
status = do_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, &id); status = do_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, &id);
*uid = make_kuid(&init_user_ns, id); *uid = make_kuid(&init_user_ns, id);
if (!uid_valid(*uid)) if (!uid_valid(*uid))
...@@ -641,6 +645,10 @@ nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen, ...@@ -641,6 +645,10 @@ nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
{ {
__be32 status; __be32 status;
u32 id = -1; u32 id = -1;
if (name == NULL || namelen == 0)
return nfserr_inval;
status = do_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, &id); status = do_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, &id);
*gid = make_kgid(&init_user_ns, id); *gid = make_kgid(&init_user_ns, id);
if (!gid_valid(*gid)) if (!gid_valid(*gid))
......
...@@ -95,11 +95,15 @@ check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -95,11 +95,15 @@ check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
u32 *bmval, u32 *writable) u32 *bmval, u32 *writable)
{ {
struct dentry *dentry = cstate->current_fh.fh_dentry; struct dentry *dentry = cstate->current_fh.fh_dentry;
struct svc_export *exp = cstate->current_fh.fh_export;
if (!nfsd_attrs_supported(cstate->minorversion, bmval)) if (!nfsd_attrs_supported(cstate->minorversion, bmval))
return nfserr_attrnotsupp; return nfserr_attrnotsupp;
if ((bmval[0] & FATTR4_WORD0_ACL) && !IS_POSIXACL(d_inode(dentry))) if ((bmval[0] & FATTR4_WORD0_ACL) && !IS_POSIXACL(d_inode(dentry)))
return nfserr_attrnotsupp; return nfserr_attrnotsupp;
if ((bmval[2] & FATTR4_WORD2_SECURITY_LABEL) &&
!(exp->ex_flags & NFSEXP_SECURITY_LABEL))
return nfserr_attrnotsupp;
if (writable && !bmval_is_subset(bmval, writable)) if (writable && !bmval_is_subset(bmval, writable))
return nfserr_inval; return nfserr_inval;
if (writable && (bmval[2] & FATTR4_WORD2_MODE_UMASK) && if (writable && (bmval[2] & FATTR4_WORD2_MODE_UMASK) &&
...@@ -983,7 +987,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -983,7 +987,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
status = nfsd_vfs_write(rqstp, &cstate->current_fh, filp, status = nfsd_vfs_write(rqstp, &cstate->current_fh, filp,
write->wr_offset, rqstp->rq_vec, nvecs, &cnt, write->wr_offset, rqstp->rq_vec, nvecs, &cnt,
&write->wr_how_written); write->wr_how_written);
fput(filp); fput(filp);
write->wr_bytes_written = cnt; write->wr_bytes_written = cnt;
...@@ -1838,6 +1842,12 @@ static inline u32 nfsd4_status_stateid_rsize(struct svc_rqst *rqstp, struct nfsd ...@@ -1838,6 +1842,12 @@ static inline u32 nfsd4_status_stateid_rsize(struct svc_rqst *rqstp, struct nfsd
return (op_encode_hdr_size + op_encode_stateid_maxsz)* sizeof(__be32); return (op_encode_hdr_size + op_encode_stateid_maxsz)* sizeof(__be32);
} }
static inline u32 nfsd4_access_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
{
/* ac_supported, ac_resp_access */
return (op_encode_hdr_size + 2)* sizeof(__be32);
}
static inline u32 nfsd4_commit_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) static inline u32 nfsd4_commit_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
{ {
return (op_encode_hdr_size + op_encode_verifier_maxsz) * sizeof(__be32); return (op_encode_hdr_size + op_encode_verifier_maxsz) * sizeof(__be32);
...@@ -1892,6 +1902,11 @@ static inline u32 nfsd4_getattr_rsize(struct svc_rqst *rqstp, ...@@ -1892,6 +1902,11 @@ static inline u32 nfsd4_getattr_rsize(struct svc_rqst *rqstp,
return ret; return ret;
} }
static inline u32 nfsd4_getfh_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
{
return (op_encode_hdr_size + 1) * sizeof(__be32) + NFS4_FHSIZE;
}
static inline u32 nfsd4_link_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) static inline u32 nfsd4_link_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
{ {
return (op_encode_hdr_size + op_encode_change_info_maxsz) return (op_encode_hdr_size + op_encode_change_info_maxsz)
...@@ -1933,6 +1948,11 @@ static inline u32 nfsd4_readdir_rsize(struct svc_rqst *rqstp, struct nfsd4_op *o ...@@ -1933,6 +1948,11 @@ static inline u32 nfsd4_readdir_rsize(struct svc_rqst *rqstp, struct nfsd4_op *o
XDR_QUADLEN(rlen)) * sizeof(__be32); XDR_QUADLEN(rlen)) * sizeof(__be32);
} }
static inline u32 nfsd4_readlink_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
{
return (op_encode_hdr_size + 1) * sizeof(__be32) + PAGE_SIZE;
}
static inline u32 nfsd4_remove_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) static inline u32 nfsd4_remove_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
{ {
return (op_encode_hdr_size + op_encode_change_info_maxsz) return (op_encode_hdr_size + op_encode_change_info_maxsz)
...@@ -1952,11 +1972,23 @@ static inline u32 nfsd4_sequence_rsize(struct svc_rqst *rqstp, ...@@ -1952,11 +1972,23 @@ static inline u32 nfsd4_sequence_rsize(struct svc_rqst *rqstp,
+ XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) * sizeof(__be32); + XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) * sizeof(__be32);
} }
static inline u32 nfsd4_test_stateid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
{
return (op_encode_hdr_size + 1 + op->u.test_stateid.ts_num_ids)
* sizeof(__be32);
}
static inline u32 nfsd4_setattr_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) static inline u32 nfsd4_setattr_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
{ {
return (op_encode_hdr_size + nfs4_fattr_bitmap_maxsz) * sizeof(__be32); return (op_encode_hdr_size + nfs4_fattr_bitmap_maxsz) * sizeof(__be32);
} }
static inline u32 nfsd4_secinfo_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
{
return (op_encode_hdr_size + RPC_AUTH_MAXFLAVOR *
(4 + XDR_QUADLEN(GSS_OID_MAX_LEN))) * sizeof(__be32);
}
static inline u32 nfsd4_setclientid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) static inline u32 nfsd4_setclientid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
{ {
return (op_encode_hdr_size + 2 + XDR_QUADLEN(NFS4_VERIFIER_SIZE)) * return (op_encode_hdr_size + 2 + XDR_QUADLEN(NFS4_VERIFIER_SIZE)) *
...@@ -2011,6 +2043,19 @@ static inline u32 nfsd4_copy_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) ...@@ -2011,6 +2043,19 @@ static inline u32 nfsd4_copy_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
} }
#ifdef CONFIG_NFSD_PNFS #ifdef CONFIG_NFSD_PNFS
static inline u32 nfsd4_getdeviceinfo_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
{
u32 maxcount = 0, rlen = 0;
maxcount = svc_max_payload(rqstp);
rlen = min(op->u.getdeviceinfo.gd_maxcount, maxcount);
return (op_encode_hdr_size +
1 /* gd_layout_type*/ +
XDR_QUADLEN(rlen) +
2 /* gd_notify_types */) * sizeof(__be32);
}
/* /*
* At this stage we don't really know what layout driver will handle the request, * At this stage we don't really know what layout driver will handle the request,
* so we need to define an arbitrary upper bound here. * so we need to define an arbitrary upper bound here.
...@@ -2040,10 +2085,17 @@ static inline u32 nfsd4_layoutreturn_rsize(struct svc_rqst *rqstp, struct nfsd4_ ...@@ -2040,10 +2085,17 @@ static inline u32 nfsd4_layoutreturn_rsize(struct svc_rqst *rqstp, struct nfsd4_
} }
#endif /* CONFIG_NFSD_PNFS */ #endif /* CONFIG_NFSD_PNFS */
static inline u32 nfsd4_seek_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
{
return (op_encode_hdr_size + 3) * sizeof(__be32);
}
static struct nfsd4_operation nfsd4_ops[] = { static struct nfsd4_operation nfsd4_ops[] = {
[OP_ACCESS] = { [OP_ACCESS] = {
.op_func = (nfsd4op_func)nfsd4_access, .op_func = (nfsd4op_func)nfsd4_access,
.op_name = "OP_ACCESS", .op_name = "OP_ACCESS",
.op_rsize_bop = (nfsd4op_rsize)nfsd4_access_rsize,
}, },
[OP_CLOSE] = { [OP_CLOSE] = {
.op_func = (nfsd4op_func)nfsd4_close, .op_func = (nfsd4op_func)nfsd4_close,
...@@ -2081,6 +2133,7 @@ static struct nfsd4_operation nfsd4_ops[] = { ...@@ -2081,6 +2133,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
[OP_GETFH] = { [OP_GETFH] = {
.op_func = (nfsd4op_func)nfsd4_getfh, .op_func = (nfsd4op_func)nfsd4_getfh,
.op_name = "OP_GETFH", .op_name = "OP_GETFH",
.op_rsize_bop = (nfsd4op_rsize)nfsd4_getfh_rsize,
}, },
[OP_LINK] = { [OP_LINK] = {
.op_func = (nfsd4op_func)nfsd4_link, .op_func = (nfsd4op_func)nfsd4_link,
...@@ -2099,6 +2152,7 @@ static struct nfsd4_operation nfsd4_ops[] = { ...@@ -2099,6 +2152,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
[OP_LOCKT] = { [OP_LOCKT] = {
.op_func = (nfsd4op_func)nfsd4_lockt, .op_func = (nfsd4op_func)nfsd4_lockt,
.op_name = "OP_LOCKT", .op_name = "OP_LOCKT",
.op_rsize_bop = (nfsd4op_rsize)nfsd4_lock_rsize,
}, },
[OP_LOCKU] = { [OP_LOCKU] = {
.op_func = (nfsd4op_func)nfsd4_locku, .op_func = (nfsd4op_func)nfsd4_locku,
...@@ -2111,15 +2165,18 @@ static struct nfsd4_operation nfsd4_ops[] = { ...@@ -2111,15 +2165,18 @@ static struct nfsd4_operation nfsd4_ops[] = {
.op_func = (nfsd4op_func)nfsd4_lookup, .op_func = (nfsd4op_func)nfsd4_lookup,
.op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID, .op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID,
.op_name = "OP_LOOKUP", .op_name = "OP_LOOKUP",
.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
}, },
[OP_LOOKUPP] = { [OP_LOOKUPP] = {
.op_func = (nfsd4op_func)nfsd4_lookupp, .op_func = (nfsd4op_func)nfsd4_lookupp,
.op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID, .op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID,
.op_name = "OP_LOOKUPP", .op_name = "OP_LOOKUPP",
.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
}, },
[OP_NVERIFY] = { [OP_NVERIFY] = {
.op_func = (nfsd4op_func)nfsd4_nverify, .op_func = (nfsd4op_func)nfsd4_nverify,
.op_name = "OP_NVERIFY", .op_name = "OP_NVERIFY",
.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
}, },
[OP_OPEN] = { [OP_OPEN] = {
.op_func = (nfsd4op_func)nfsd4_open, .op_func = (nfsd4op_func)nfsd4_open,
...@@ -2177,6 +2234,7 @@ static struct nfsd4_operation nfsd4_ops[] = { ...@@ -2177,6 +2234,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
[OP_READLINK] = { [OP_READLINK] = {
.op_func = (nfsd4op_func)nfsd4_readlink, .op_func = (nfsd4op_func)nfsd4_readlink,
.op_name = "OP_READLINK", .op_name = "OP_READLINK",
.op_rsize_bop = (nfsd4op_rsize)nfsd4_readlink_rsize,
}, },
[OP_REMOVE] = { [OP_REMOVE] = {
.op_func = (nfsd4op_func)nfsd4_remove, .op_func = (nfsd4op_func)nfsd4_remove,
...@@ -2215,6 +2273,7 @@ static struct nfsd4_operation nfsd4_ops[] = { ...@@ -2215,6 +2273,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
.op_func = (nfsd4op_func)nfsd4_secinfo, .op_func = (nfsd4op_func)nfsd4_secinfo,
.op_flags = OP_HANDLES_WRONGSEC, .op_flags = OP_HANDLES_WRONGSEC,
.op_name = "OP_SECINFO", .op_name = "OP_SECINFO",
.op_rsize_bop = (nfsd4op_rsize)nfsd4_secinfo_rsize,
}, },
[OP_SETATTR] = { [OP_SETATTR] = {
.op_func = (nfsd4op_func)nfsd4_setattr, .op_func = (nfsd4op_func)nfsd4_setattr,
...@@ -2240,6 +2299,7 @@ static struct nfsd4_operation nfsd4_ops[] = { ...@@ -2240,6 +2299,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
[OP_VERIFY] = { [OP_VERIFY] = {
.op_func = (nfsd4op_func)nfsd4_verify, .op_func = (nfsd4op_func)nfsd4_verify,
.op_name = "OP_VERIFY", .op_name = "OP_VERIFY",
.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
}, },
[OP_WRITE] = { [OP_WRITE] = {
.op_func = (nfsd4op_func)nfsd4_write, .op_func = (nfsd4op_func)nfsd4_write,
...@@ -2314,11 +2374,13 @@ static struct nfsd4_operation nfsd4_ops[] = { ...@@ -2314,11 +2374,13 @@ static struct nfsd4_operation nfsd4_ops[] = {
.op_func = (nfsd4op_func)nfsd4_secinfo_no_name, .op_func = (nfsd4op_func)nfsd4_secinfo_no_name,
.op_flags = OP_HANDLES_WRONGSEC, .op_flags = OP_HANDLES_WRONGSEC,
.op_name = "OP_SECINFO_NO_NAME", .op_name = "OP_SECINFO_NO_NAME",
.op_rsize_bop = (nfsd4op_rsize)nfsd4_secinfo_rsize,
}, },
[OP_TEST_STATEID] = { [OP_TEST_STATEID] = {
.op_func = (nfsd4op_func)nfsd4_test_stateid, .op_func = (nfsd4op_func)nfsd4_test_stateid,
.op_flags = ALLOWED_WITHOUT_FH, .op_flags = ALLOWED_WITHOUT_FH,
.op_name = "OP_TEST_STATEID", .op_name = "OP_TEST_STATEID",
.op_rsize_bop = (nfsd4op_rsize)nfsd4_test_stateid_rsize,
}, },
[OP_FREE_STATEID] = { [OP_FREE_STATEID] = {
.op_func = (nfsd4op_func)nfsd4_free_stateid, .op_func = (nfsd4op_func)nfsd4_free_stateid,
...@@ -2332,6 +2394,7 @@ static struct nfsd4_operation nfsd4_ops[] = { ...@@ -2332,6 +2394,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
.op_func = (nfsd4op_func)nfsd4_getdeviceinfo, .op_func = (nfsd4op_func)nfsd4_getdeviceinfo,
.op_flags = ALLOWED_WITHOUT_FH, .op_flags = ALLOWED_WITHOUT_FH,
.op_name = "OP_GETDEVICEINFO", .op_name = "OP_GETDEVICEINFO",
.op_rsize_bop = (nfsd4op_rsize)nfsd4_getdeviceinfo_rsize,
}, },
[OP_LAYOUTGET] = { [OP_LAYOUTGET] = {
.op_func = (nfsd4op_func)nfsd4_layoutget, .op_func = (nfsd4op_func)nfsd4_layoutget,
...@@ -2381,6 +2444,7 @@ static struct nfsd4_operation nfsd4_ops[] = { ...@@ -2381,6 +2444,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
[OP_SEEK] = { [OP_SEEK] = {
.op_func = (nfsd4op_func)nfsd4_seek, .op_func = (nfsd4op_func)nfsd4_seek,
.op_name = "OP_SEEK", .op_name = "OP_SEEK",
.op_rsize_bop = (nfsd4op_rsize)nfsd4_seek_rsize,
}, },
}; };
...@@ -2425,14 +2489,11 @@ bool nfsd4_spo_must_allow(struct svc_rqst *rqstp) ...@@ -2425,14 +2489,11 @@ bool nfsd4_spo_must_allow(struct svc_rqst *rqstp)
int nfsd4_max_reply(struct svc_rqst *rqstp, struct nfsd4_op *op) int nfsd4_max_reply(struct svc_rqst *rqstp, struct nfsd4_op *op)
{ {
struct nfsd4_operation *opdesc;
nfsd4op_rsize estimator;
if (op->opnum == OP_ILLEGAL) if (op->opnum == OP_ILLEGAL)
return op_encode_hdr_size * sizeof(__be32); return op_encode_hdr_size * sizeof(__be32);
opdesc = OPDESC(op);
estimator = opdesc->op_rsize_bop; BUG_ON(OPDESC(op)->op_rsize_bop == NULL);
return estimator ? estimator(rqstp, op) : PAGE_SIZE; return OPDESC(op)->op_rsize_bop(rqstp, op);
} }
void warn_on_nonidempotent_op(struct nfsd4_op *op) void warn_on_nonidempotent_op(struct nfsd4_op *op)
...@@ -2476,12 +2537,13 @@ static struct svc_procedure nfsd_procedures4[2] = { ...@@ -2476,12 +2537,13 @@ static struct svc_procedure nfsd_procedures4[2] = {
}; };
struct svc_version nfsd_version4 = { struct svc_version nfsd_version4 = {
.vs_vers = 4, .vs_vers = 4,
.vs_nproc = 2, .vs_nproc = 2,
.vs_proc = nfsd_procedures4, .vs_proc = nfsd_procedures4,
.vs_dispatch = nfsd_dispatch, .vs_dispatch = nfsd_dispatch,
.vs_xdrsize = NFS4_SVC_XDRSIZE, .vs_xdrsize = NFS4_SVC_XDRSIZE,
.vs_rpcb_optnl = 1, .vs_rpcb_optnl = true,
.vs_need_cong_ctrl = true,
}; };
/* /*
......
...@@ -2281,7 +2281,7 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, struct svc_r ...@@ -2281,7 +2281,7 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, struct svc_r
out_err: out_err:
conn->cb_addr.ss_family = AF_UNSPEC; conn->cb_addr.ss_family = AF_UNSPEC;
conn->cb_addrlen = 0; conn->cb_addrlen = 0;
dprintk(KERN_INFO "NFSD: this client (clientid %08x/%08x) " dprintk("NFSD: this client (clientid %08x/%08x) "
"will not receive delegations\n", "will not receive delegations\n",
clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
...@@ -7012,23 +7012,24 @@ nfs4_state_start(void) ...@@ -7012,23 +7012,24 @@ nfs4_state_start(void)
ret = set_callback_cred(); ret = set_callback_cred();
if (ret) if (ret)
return -ENOMEM; return ret;
laundry_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, "nfsd4"); laundry_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, "nfsd4");
if (laundry_wq == NULL) { if (laundry_wq == NULL) {
ret = -ENOMEM; ret = -ENOMEM;
goto out_recovery; goto out_cleanup_cred;
} }
ret = nfsd4_create_callback_queue(); ret = nfsd4_create_callback_queue();
if (ret) if (ret)
goto out_free_laundry; goto out_free_laundry;
set_max_delegations(); set_max_delegations();
return 0; return 0;
out_free_laundry: