|
@@ -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,
|
|
|
|
|
|
|
|
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
|
|
|
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,
|
|
|
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
|
|
|
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,
|
|
|
+ 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)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#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_
|
|
|
}
|
|
}
|
|
|
#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[] = {
|
|
|
[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[] = {
|
|
|
[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[] = {
|
|
|
.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[] = {
|
|
|
[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[] = {
|
|
|
.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[] = {
|
|
|
[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[] = {
|
|
|
.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[] = {
|
|
|
.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[] = {
|
|
|
[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)
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
- return estimator ? estimator(rqstp, op) : PAGE_SIZE;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ BUG_ON(OPDESC(op)->op_rsize_bop == NULL);
|
|
|
|
|
+ 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] = {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
struct svc_version nfsd_version4 = {
|
|
struct svc_version nfsd_version4 = {
|
|
|
- .vs_vers = 4,
|
|
|
|
|
- .vs_nproc = 2,
|
|
|
|
|
- .vs_proc = nfsd_procedures4,
|
|
|
|
|
- .vs_dispatch = nfsd_dispatch,
|
|
|
|
|
- .vs_xdrsize = NFS4_SVC_XDRSIZE,
|
|
|
|
|
- .vs_rpcb_optnl = 1,
|
|
|
|
|
|
|
+ .vs_vers = 4,
|
|
|
|
|
+ .vs_nproc = 2,
|
|
|
|
|
+ .vs_proc = nfsd_procedures4,
|
|
|
|
|
+ .vs_dispatch = nfsd_dispatch,
|
|
|
|
|
+ .vs_xdrsize = NFS4_SVC_XDRSIZE,
|
|
|
|
|
+ .vs_rpcb_optnl = true,
|
|
|
|
|
+ .vs_need_cong_ctrl = true,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
/*
|