diff options
Diffstat (limited to 'fs/nfsd/nfs4proc.c')
-rw-r--r-- | fs/nfsd/nfs4proc.c | 492 |
1 files changed, 286 insertions, 206 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 74a6e573e061..d27e75ad25e3 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -95,11 +95,15 @@ check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, u32 *bmval, u32 *writable) { struct dentry *dentry = cstate->current_fh.fh_dentry; + struct svc_export *exp = cstate->current_fh.fh_export; if (!nfsd_attrs_supported(cstate->minorversion, bmval)) return nfserr_attrnotsupp; if ((bmval[0] & FATTR4_WORD0_ACL) && !IS_POSIXACL(d_inode(dentry))) 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)) return nfserr_inval; if (writable && (bmval[2] & FATTR4_WORD2_MODE_UMASK) && @@ -340,8 +344,9 @@ copy_clientid(clientid_t *clid, struct nfsd4_session *session) static __be32 nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_open *open) + union nfsd4_op_u *u) { + struct nfsd4_open *open = &u->open; __be32 status; struct svc_fh *resfh = NULL; struct net *net = SVC_NET(rqstp); @@ -463,14 +468,14 @@ out: */ static __be32 nfsd4_open_omfg(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_op *op) { - struct nfsd4_open *open = (struct nfsd4_open *)&op->u; + struct nfsd4_open *open = &op->u.open; if (!seqid_mutating_err(ntohl(op->status))) return op->status; if (nfsd4_has_session(cstate)) return op->status; open->op_xdr_error = op->status; - return nfsd4_open(rqstp, cstate, open); + return nfsd4_open(rqstp, cstate, &op->u); } /* @@ -478,19 +483,21 @@ static __be32 nfsd4_open_omfg(struct svc_rqst *rqstp, struct nfsd4_compound_stat */ static __be32 nfsd4_getfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct svc_fh **getfh) + union nfsd4_op_u *u) { if (!cstate->current_fh.fh_dentry) return nfserr_nofilehandle; - *getfh = &cstate->current_fh; + u->getfh = &cstate->current_fh; return nfs_ok; } static __be32 nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_putfh *putfh) + union nfsd4_op_u *u) { + struct nfsd4_putfh *putfh = &u->putfh; + fh_put(&cstate->current_fh); cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen; memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval, @@ -500,7 +507,7 @@ nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, static __be32 nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - void *arg) + union nfsd4_op_u *u) { __be32 status; @@ -511,7 +518,7 @@ nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, static __be32 nfsd4_restorefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - void *arg) + union nfsd4_op_u *u) { if (!cstate->save_fh.fh_dentry) return nfserr_restorefh; @@ -526,7 +533,7 @@ nfsd4_restorefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, static __be32 nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - void *arg) + union nfsd4_op_u *u) { if (!cstate->current_fh.fh_dentry) return nfserr_nofilehandle; @@ -544,8 +551,10 @@ nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, */ static __be32 nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_access *access) + union nfsd4_op_u *u) { + struct nfsd4_access *access = &u->access; + if (access->ac_req_access & ~NFS3_ACCESS_FULL) return nfserr_inval; @@ -570,8 +579,10 @@ static void gen_boot_verifier(nfs4_verifier *verifier, struct net *net) static __be32 nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_commit *commit) + union nfsd4_op_u *u) { + struct nfsd4_commit *commit = &u->commit; + gen_boot_verifier(&commit->co_verf, SVC_NET(rqstp)); return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset, commit->co_count); @@ -579,8 +590,9 @@ nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, static __be32 nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_create *create) + union nfsd4_op_u *u) { + struct nfsd4_create *create = &u->create; struct svc_fh resfh; __be32 status; dev_t rdev; @@ -666,8 +678,9 @@ out: static __be32 nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_getattr *getattr) + union nfsd4_op_u *u) { + struct nfsd4_getattr *getattr = &u->getattr; __be32 status; status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP); @@ -687,8 +700,9 @@ nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, static __be32 nfsd4_link(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_link *link) + union nfsd4_op_u *u) { + struct nfsd4_link *link = &u->link; __be32 status = nfserr_nofilehandle; if (!cstate->save_fh.fh_dentry) @@ -719,24 +733,25 @@ static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh) static __be32 nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - void *arg) + union nfsd4_op_u *u) { return nfsd4_do_lookupp(rqstp, &cstate->current_fh); } static __be32 nfsd4_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_lookup *lookup) + union nfsd4_op_u *u) { return nfsd_lookup(rqstp, &cstate->current_fh, - lookup->lo_name, lookup->lo_len, + u->lookup.lo_name, u->lookup.lo_len, &cstate->current_fh); } static __be32 nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_read *read) + union nfsd4_op_u *u) { + struct nfsd4_read *read = &u->read; __be32 status; read->rd_filp = NULL; @@ -771,8 +786,9 @@ out: static __be32 nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_readdir *readdir) + union nfsd4_op_u *u) { + struct nfsd4_readdir *readdir = &u->readdir; u64 cookie = readdir->rd_cookie; static const nfs4_verifier zeroverf; @@ -796,17 +812,18 @@ nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, static __be32 nfsd4_readlink(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_readlink *readlink) + union nfsd4_op_u *u) { - readlink->rl_rqstp = rqstp; - readlink->rl_fhp = &cstate->current_fh; + u->readlink.rl_rqstp = rqstp; + u->readlink.rl_fhp = &cstate->current_fh; return nfs_ok; } static __be32 nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_remove *remove) + union nfsd4_op_u *u) { + struct nfsd4_remove *remove = &u->remove; __be32 status; if (opens_in_grace(SVC_NET(rqstp))) @@ -822,8 +839,9 @@ nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, static __be32 nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_rename *rename) + union nfsd4_op_u *u) { + struct nfsd4_rename *rename = &u->rename; __be32 status = nfserr_nofilehandle; if (!cstate->save_fh.fh_dentry) @@ -843,8 +861,9 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, static __be32 nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_secinfo *secinfo) + union nfsd4_op_u *u) { + struct nfsd4_secinfo *secinfo = &u->secinfo; struct svc_export *exp; struct dentry *dentry; __be32 err; @@ -872,11 +891,11 @@ nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, static __be32 nfsd4_secinfo_no_name(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_secinfo_no_name *sin) + union nfsd4_op_u *u) { __be32 err; - switch (sin->sin_style) { + switch (u->secinfo_no_name.sin_style) { case NFS4_SECINFO_STYLE4_CURRENT_FH: break; case NFS4_SECINFO_STYLE4_PARENT: @@ -888,15 +907,16 @@ nfsd4_secinfo_no_name(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstat return nfserr_inval; } - sin->sin_exp = exp_get(cstate->current_fh.fh_export); + u->secinfo_no_name.sin_exp = exp_get(cstate->current_fh.fh_export); fh_put(&cstate->current_fh); return nfs_ok; } static __be32 nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_setattr *setattr) + union nfsd4_op_u *u) { + struct nfsd4_setattr *setattr = &u->setattr; __be32 status = nfs_ok; int err; @@ -956,8 +976,9 @@ static int fill_in_write_vector(struct kvec *vec, struct nfsd4_write *write) static __be32 nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_write *write) + union nfsd4_op_u *u) { + struct nfsd4_write *write = &u->write; stateid_t *stateid = &write->wr_stateid; struct file *filp = NULL; __be32 status = nfs_ok; @@ -983,7 +1004,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, status = nfsd_vfs_write(rqstp, &cstate->current_fh, filp, write->wr_offset, rqstp->rq_vec, nvecs, &cnt, - &write->wr_how_written); + write->wr_how_written); fput(filp); write->wr_bytes_written = cnt; @@ -1030,8 +1051,9 @@ out_put_src: static __be32 nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_clone *clone) + union nfsd4_op_u *u) { + struct nfsd4_clone *clone = &u->clone; struct file *src, *dst; __be32 status; @@ -1051,8 +1073,9 @@ out: static __be32 nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_copy *copy) + union nfsd4_op_u *u) { + struct nfsd4_copy *copy = &u->copy; struct file *src, *dst; __be32 status; ssize_t bytes; @@ -1107,23 +1130,24 @@ nfsd4_fallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, static __be32 nfsd4_allocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_fallocate *fallocate) + union nfsd4_op_u *u) { - return nfsd4_fallocate(rqstp, cstate, fallocate, 0); + return nfsd4_fallocate(rqstp, cstate, &u->allocate, 0); } static __be32 nfsd4_deallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_fallocate *fallocate) + union nfsd4_op_u *u) { - return nfsd4_fallocate(rqstp, cstate, fallocate, + return nfsd4_fallocate(rqstp, cstate, &u->deallocate, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE); } static __be32 nfsd4_seek(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_seek *seek) + union nfsd4_op_u *u) { + struct nfsd4_seek *seek = &u->seek; int whence; __be32 status; struct file *file; @@ -1228,21 +1252,21 @@ out_kfree: static __be32 nfsd4_nverify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_verify *verify) + union nfsd4_op_u *u) { __be32 status; - status = _nfsd4_verify(rqstp, cstate, verify); + status = _nfsd4_verify(rqstp, cstate, &u->verify); return status == nfserr_not_same ? nfs_ok : status; } static __be32 nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - struct nfsd4_verify *verify) + union nfsd4_op_u *u) { __be32 status; - status = _nfsd4_verify(rqstp, cstate, verify); + status = _nfsd4_verify(rqstp, cstate, &u->nverify); return status == nfserr_same ? nfs_ok : status; } @@ -1255,7 +1279,8 @@ nfsd4_layout_verify(struct svc_export *exp, unsigned int layout_type) return NULL; } - if (!(exp->ex_layout_types & (1 << layout_type))) { + if (layout_type >= LAYOUT_TYPE_MAX || + !(exp->ex_layout_types & (1 << layout_type))) { dprintk("%s: layout type %d not supported\n", __func__, layout_type); return NULL; @@ -1266,9 +1291,9 @@ nfsd4_layout_verify(struct svc_export *exp, unsigned int layout_type) static __be32 nfsd4_getdeviceinfo(struct svc_rqst *rqstp, - struct nfsd4_compound_state *cstate, - struct nfsd4_getdeviceinfo *gdp) + struct nfsd4_compound_state *cstate, union nfsd4_op_u *u) { + struct nfsd4_getdeviceinfo *gdp = &u->getdeviceinfo; const struct nfsd4_layout_ops *ops; struct nfsd4_deviceid_map *map; struct svc_export *exp; @@ -1312,9 +1337,9 @@ out: static __be32 nfsd4_layoutget(struct svc_rqst *rqstp, - struct nfsd4_compound_state *cstate, - struct nfsd4_layoutget *lgp) + struct nfsd4_compound_state *cstate, union nfsd4_op_u *u) { + struct nfsd4_layoutget *lgp = &u->layoutget; struct svc_fh *current_fh = &cstate->current_fh; const struct nfsd4_layout_ops *ops; struct nfs4_layout_stateid *ls; @@ -1392,9 +1417,9 @@ out: static __be32 nfsd4_layoutcommit(struct svc_rqst *rqstp, - struct nfsd4_compound_state *cstate, - struct nfsd4_layoutcommit *lcp) + struct nfsd4_compound_state *cstate, union nfsd4_op_u *u) { + struct nfsd4_layoutcommit *lcp = &u->layoutcommit; const struct nfsd4_layout_seg *seg = &lcp->lc_seg; struct svc_fh *current_fh = &cstate->current_fh; const struct nfsd4_layout_ops *ops; @@ -1456,9 +1481,9 @@ out: static __be32 nfsd4_layoutreturn(struct svc_rqst *rqstp, - struct nfsd4_compound_state *cstate, - struct nfsd4_layoutreturn *lrp) + struct nfsd4_compound_state *cstate, union nfsd4_op_u *u) { + struct nfsd4_layoutreturn *lrp = &u->layoutreturn; struct svc_fh *current_fh = &cstate->current_fh; __be32 nfserr; @@ -1505,7 +1530,7 @@ out: * NULL call. */ static __be32 -nfsd4_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) +nfsd4_proc_null(struct svc_rqst *rqstp) { return nfs_ok; } @@ -1516,12 +1541,6 @@ static inline void nfsd4_increment_op_stats(u32 opnum) nfsdstats.nfs4_opcount[opnum]++; } -typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *, - void *); -typedef u32(*nfsd4op_rsize)(struct svc_rqst *, struct nfsd4_op *op); -typedef void(*stateid_setter)(struct nfsd4_compound_state *, void *); -typedef void(*stateid_getter)(struct nfsd4_compound_state *, void *); - enum nfsd4_op_flags { ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */ ALLOWED_ON_ABSENT_FS = 1 << 1, /* ops processed on absent fs */ @@ -1553,16 +1572,19 @@ enum nfsd4_op_flags { }; struct nfsd4_operation { - nfsd4op_func op_func; + __be32 (*op_func)(struct svc_rqst *, struct nfsd4_compound_state *, + union nfsd4_op_u *); u32 op_flags; char *op_name; /* Try to get response size before operation */ - nfsd4op_rsize op_rsize_bop; - stateid_getter op_get_currentstateid; - stateid_setter op_set_currentstateid; + u32 (*op_rsize_bop)(struct svc_rqst *, struct nfsd4_op *); + void (*op_get_currentstateid)(struct nfsd4_compound_state *, + union nfsd4_op_u *); + void (*op_set_currentstateid)(struct nfsd4_compound_state *, + union nfsd4_op_u *); }; -static struct nfsd4_operation nfsd4_ops[]; +static const struct nfsd4_operation nfsd4_ops[]; static const char *nfsd4_op_name(unsigned opnum); @@ -1599,7 +1621,7 @@ static __be32 nfs41_check_op_ordering(struct nfsd4_compoundargs *args) return nfs_ok; } -static inline struct nfsd4_operation *OPDESC(struct nfsd4_op *op) +static inline const struct nfsd4_operation *OPDESC(struct nfsd4_op *op) { return &nfsd4_ops[op->opnum]; } @@ -1617,10 +1639,9 @@ static bool need_wrongsec_check(struct svc_rqst *rqstp) struct nfsd4_compoundargs *argp = rqstp->rq_argp; struct nfsd4_op *this = &argp->ops[resp->opcnt - 1]; struct nfsd4_op *next = &argp->ops[resp->opcnt]; - struct nfsd4_operation *thisd; - struct nfsd4_operation *nextd; + const struct nfsd4_operation *thisd = OPDESC(this); + const struct nfsd4_operation *nextd; - thisd = OPDESC(this); /* * Most ops check wronsec on our own; only the putfh-like ops * have special rules. @@ -1668,12 +1689,12 @@ static void svcxdr_init_encode(struct svc_rqst *rqstp, * COMPOUND call. */ static __be32 -nfsd4_proc_compound(struct svc_rqst *rqstp, - struct nfsd4_compoundargs *args, - struct nfsd4_compoundres *resp) +nfsd4_proc_compound(struct svc_rqst *rqstp) { + struct nfsd4_compoundargs *args = rqstp->rq_argp; + struct nfsd4_compoundres *resp = rqstp->rq_resp; struct nfsd4_op *op; - struct nfsd4_operation *opdesc; + const struct nfsd4_operation *opdesc; struct nfsd4_compound_state *cstate = &resp->cstate; struct svc_fh *current_fh = &cstate->current_fh; struct svc_fh *save_fh = &cstate->save_fh; @@ -1764,6 +1785,12 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, opdesc->op_get_currentstateid(cstate, &op->u); op->status = opdesc->op_func(rqstp, cstate, &op->u); + /* Only from SEQUENCE */ + if (cstate->status == nfserr_replay_cache) { + dprintk("%s NFS4.1 replay from cache\n", __func__); + status = op->status; + goto out; + } if (!op->status) { if (opdesc->op_set_currentstateid) opdesc->op_set_currentstateid(cstate, &op->u); @@ -1774,14 +1801,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, if (need_wrongsec_check(rqstp)) op->status = check_nfsd_access(current_fh->fh_export, rqstp); } - encode_op: - /* Only from SEQUENCE */ - if (cstate->status == nfserr_replay_cache) { - dprintk("%s NFS4.1 replay from cache\n", __func__); - status = op->status; - goto out; - } if (op->status == nfserr_replay_me) { op->replay = &cstate->replay_owner->so_replay; nfsd4_encode_replay(&resp->xdr, op); @@ -1838,6 +1858,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); } +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) { return (op_encode_hdr_size + op_encode_verifier_maxsz) * sizeof(__be32); @@ -1892,6 +1918,11 @@ static inline u32 nfsd4_getattr_rsize(struct svc_rqst *rqstp, 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) { return (op_encode_hdr_size + op_encode_change_info_maxsz) @@ -1933,6 +1964,11 @@ static inline u32 nfsd4_readdir_rsize(struct svc_rqst *rqstp, struct nfsd4_op *o 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) { return (op_encode_hdr_size + op_encode_change_info_maxsz) @@ -1952,11 +1988,23 @@ static inline u32 nfsd4_sequence_rsize(struct svc_rqst *rqstp, + 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) { 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) { return (op_encode_hdr_size + 2 + XDR_QUADLEN(NFS4_VERIFIER_SIZE)) * @@ -2011,6 +2059,19 @@ static inline u32 nfsd4_copy_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) } #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, * so we need to define an arbitrary upper bound here. @@ -2040,347 +2101,366 @@ static inline u32 nfsd4_layoutreturn_rsize(struct svc_rqst *rqstp, struct nfsd4_ } #endif /* CONFIG_NFSD_PNFS */ -static struct nfsd4_operation nfsd4_ops[] = { + +static inline u32 nfsd4_seek_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) +{ + return (op_encode_hdr_size + 3) * sizeof(__be32); +} + +static const struct nfsd4_operation nfsd4_ops[] = { [OP_ACCESS] = { - .op_func = (nfsd4op_func)nfsd4_access, + .op_func = nfsd4_access, .op_name = "OP_ACCESS", + .op_rsize_bop = nfsd4_access_rsize, }, [OP_CLOSE] = { - .op_func = (nfsd4op_func)nfsd4_close, + .op_func = nfsd4_close, .op_flags = OP_MODIFIES_SOMETHING, .op_name = "OP_CLOSE", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize, - .op_get_currentstateid = (stateid_getter)nfsd4_get_closestateid, - .op_set_currentstateid = (stateid_setter)nfsd4_set_closestateid, + .op_rsize_bop = nfsd4_status_stateid_rsize, + .op_get_currentstateid = nfsd4_get_closestateid, + .op_set_currentstateid = nfsd4_set_closestateid, }, [OP_COMMIT] = { - .op_func = (nfsd4op_func)nfsd4_commit, + .op_func = nfsd4_commit, .op_flags = OP_MODIFIES_SOMETHING, .op_name = "OP_COMMIT", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_commit_rsize, + .op_rsize_bop = nfsd4_commit_rsize, }, [OP_CREATE] = { - .op_func = (nfsd4op_func)nfsd4_create, + .op_func = nfsd4_create, .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME | OP_CLEAR_STATEID, .op_name = "OP_CREATE", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_create_rsize, + .op_rsize_bop = nfsd4_create_rsize, }, [OP_DELEGRETURN] = { - .op_func = (nfsd4op_func)nfsd4_delegreturn, + .op_func = nfsd4_delegreturn, .op_flags = OP_MODIFIES_SOMETHING, .op_name = "OP_DELEGRETURN", .op_rsize_bop = nfsd4_only_status_rsize, - .op_get_currentstateid = (stateid_getter)nfsd4_get_delegreturnstateid, + .op_get_currentstateid = nfsd4_get_delegreturnstateid, }, [OP_GETATTR] = { - .op_func = (nfsd4op_func)nfsd4_getattr, + .op_func = nfsd4_getattr, .op_flags = ALLOWED_ON_ABSENT_FS, .op_rsize_bop = nfsd4_getattr_rsize, .op_name = "OP_GETATTR", }, [OP_GETFH] = { - .op_func = (nfsd4op_func)nfsd4_getfh, + .op_func = nfsd4_getfh, .op_name = "OP_GETFH", + .op_rsize_bop = nfsd4_getfh_rsize, }, [OP_LINK] = { - .op_func = (nfsd4op_func)nfsd4_link, + .op_func = nfsd4_link, .op_flags = ALLOWED_ON_ABSENT_FS | OP_MODIFIES_SOMETHING | OP_CACHEME, .op_name = "OP_LINK", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_link_rsize, + .op_rsize_bop = nfsd4_link_rsize, }, [OP_LOCK] = { - .op_func = (nfsd4op_func)nfsd4_lock, + .op_func = nfsd4_lock, .op_flags = OP_MODIFIES_SOMETHING, .op_name = "OP_LOCK", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_lock_rsize, - .op_set_currentstateid = (stateid_setter)nfsd4_set_lockstateid, + .op_rsize_bop = nfsd4_lock_rsize, + .op_set_currentstateid = nfsd4_set_lockstateid, }, [OP_LOCKT] = { - .op_func = (nfsd4op_func)nfsd4_lockt, + .op_func = nfsd4_lockt, .op_name = "OP_LOCKT", + .op_rsize_bop = nfsd4_lock_rsize, }, [OP_LOCKU] = { - .op_func = (nfsd4op_func)nfsd4_locku, + .op_func = nfsd4_locku, .op_flags = OP_MODIFIES_SOMETHING, .op_name = "OP_LOCKU", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize, - .op_get_currentstateid = (stateid_getter)nfsd4_get_lockustateid, + .op_rsize_bop = nfsd4_status_stateid_rsize, + .op_get_currentstateid = nfsd4_get_lockustateid, }, [OP_LOOKUP] = { - .op_func = (nfsd4op_func)nfsd4_lookup, + .op_func = nfsd4_lookup, .op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID, .op_name = "OP_LOOKUP", + .op_rsize_bop = nfsd4_only_status_rsize, }, [OP_LOOKUPP] = { - .op_func = (nfsd4op_func)nfsd4_lookupp, + .op_func = nfsd4_lookupp, .op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID, .op_name = "OP_LOOKUPP", + .op_rsize_bop = nfsd4_only_status_rsize, }, [OP_NVERIFY] = { - .op_func = (nfsd4op_func)nfsd4_nverify, + .op_func = nfsd4_nverify, .op_name = "OP_NVERIFY", + .op_rsize_bop = nfsd4_only_status_rsize, }, [OP_OPEN] = { - .op_func = (nfsd4op_func)nfsd4_open, + .op_func = nfsd4_open, .op_flags = OP_HANDLES_WRONGSEC | OP_MODIFIES_SOMETHING, .op_name = "OP_OPEN", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_open_rsize, - .op_set_currentstateid = (stateid_setter)nfsd4_set_openstateid, + .op_rsize_bop = nfsd4_open_rsize, + .op_set_currentstateid = nfsd4_set_openstateid, }, [OP_OPEN_CONFIRM] = { - .op_func = (nfsd4op_func)nfsd4_open_confirm, + .op_func = nfsd4_open_confirm, .op_flags = OP_MODIFIES_SOMETHING, .op_name = "OP_OPEN_CONFIRM", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize, + .op_rsize_bop = nfsd4_status_stateid_rsize, }, [OP_OPEN_DOWNGRADE] = { - .op_func = (nfsd4op_func)nfsd4_open_downgrade, + .op_func = nfsd4_open_downgrade, .op_flags = OP_MODIFIES_SOMETHING, .op_name = "OP_OPEN_DOWNGRADE", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize, - .op_get_currentstateid = (stateid_getter)nfsd4_get_opendowngradestateid, - .op_set_currentstateid = (stateid_setter)nfsd4_set_opendowngradestateid, + .op_rsize_bop = nfsd4_status_stateid_rsize, + .op_get_currentstateid = nfsd4_get_opendowngradestateid, + .op_set_currentstateid = nfsd4_set_opendowngradestateid, }, [OP_PUTFH] = { - .op_func = (nfsd4op_func)nfsd4_putfh, + .op_func = nfsd4_putfh, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS | OP_IS_PUTFH_LIKE | OP_CLEAR_STATEID, .op_name = "OP_PUTFH", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, + .op_rsize_bop = nfsd4_only_status_rsize, }, [OP_PUTPUBFH] = { - .op_func = (nfsd4op_func)nfsd4_putrootfh, + .op_func = nfsd4_putrootfh, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS | OP_IS_PUTFH_LIKE | OP_CLEAR_STATEID, .op_name = "OP_PUTPUBFH", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, + .op_rsize_bop = nfsd4_only_status_rsize, }, [OP_PUTROOTFH] = { - .op_func = (nfsd4op_func)nfsd4_putrootfh, + .op_func = nfsd4_putrootfh, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS | OP_IS_PUTFH_LIKE | OP_CLEAR_STATEID, .op_name = "OP_PUTROOTFH", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, + .op_rsize_bop = nfsd4_only_status_rsize, }, [OP_READ] = { - .op_func = (nfsd4op_func)nfsd4_read, + .op_func = nfsd4_read, .op_name = "OP_READ", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_read_rsize, - .op_get_currentstateid = (stateid_getter)nfsd4_get_readstateid, + .op_rsize_bop = nfsd4_read_rsize, + .op_get_currentstateid = nfsd4_get_readstateid, }, [OP_READDIR] = { - .op_func = (nfsd4op_func)nfsd4_readdir, + .op_func = nfsd4_readdir, .op_name = "OP_READDIR", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_readdir_rsize, + .op_rsize_bop = nfsd4_readdir_rsize, }, [OP_READLINK] = { - .op_func = (nfsd4op_func)nfsd4_readlink, + .op_func = nfsd4_readlink, .op_name = "OP_READLINK", + .op_rsize_bop = nfsd4_readlink_rsize, }, [OP_REMOVE] = { - .op_func = (nfsd4op_func)nfsd4_remove, + .op_func = nfsd4_remove, .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, .op_name = "OP_REMOVE", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_remove_rsize, + .op_rsize_bop = nfsd4_remove_rsize, }, [OP_RENAME] = { - .op_func = (nfsd4op_func)nfsd4_rename, + .op_func = nfsd4_rename, .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, .op_name = "OP_RENAME", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_rename_rsize, + .op_rsize_bop = nfsd4_rename_rsize, }, [OP_RENEW] = { - .op_func = (nfsd4op_func)nfsd4_renew, + .op_func = nfsd4_renew, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS | OP_MODIFIES_SOMETHING, .op_name = "OP_RENEW", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, + .op_rsize_bop = nfsd4_only_status_rsize, }, [OP_RESTOREFH] = { - .op_func = (nfsd4op_func)nfsd4_restorefh, + .op_func = nfsd4_restorefh, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING, .op_name = "OP_RESTOREFH", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, + .op_rsize_bop = nfsd4_only_status_rsize, }, [OP_SAVEFH] = { - .op_func = (nfsd4op_func)nfsd4_savefh, + .op_func = nfsd4_savefh, .op_flags = OP_HANDLES_WRONGSEC | OP_MODIFIES_SOMETHING, .op_name = "OP_SAVEFH", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, + .op_rsize_bop = nfsd4_only_status_rsize, }, [OP_SECINFO] = { - .op_func = (nfsd4op_func)nfsd4_secinfo, + .op_func = nfsd4_secinfo, .op_flags = OP_HANDLES_WRONGSEC, .op_name = "OP_SECINFO", + .op_rsize_bop = nfsd4_secinfo_rsize, }, [OP_SETATTR] = { - .op_func = (nfsd4op_func)nfsd4_setattr, + .op_func = nfsd4_setattr, .op_name = "OP_SETATTR", .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, - .op_rsize_bop = (nfsd4op_rsize)nfsd4_setattr_rsize, - .op_get_currentstateid = (stateid_getter)nfsd4_get_setattrstateid, + .op_rsize_bop = nfsd4_setattr_rsize, + .op_get_currentstateid = nfsd4_get_setattrstateid, }, [OP_SETCLIENTID] = { - .op_func = (nfsd4op_func)nfsd4_setclientid, + .op_func = nfsd4_setclientid, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS | OP_MODIFIES_SOMETHING | OP_CACHEME, .op_name = "OP_SETCLIENTID", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_setclientid_rsize, + .op_rsize_bop = nfsd4_setclientid_rsize, }, [OP_SETCLIENTID_CONFIRM] = { - .op_func = (nfsd4op_func)nfsd4_setclientid_confirm, + .op_func = nfsd4_setclientid_confirm, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS | OP_MODIFIES_SOMETHING | OP_CACHEME, .op_name = "OP_SETCLIENTID_CONFIRM", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, + .op_rsize_bop = nfsd4_only_status_rsize, }, [OP_VERIFY] = { - .op_func = (nfsd4op_func)nfsd4_verify, + .op_func = nfsd4_verify, .op_name = "OP_VERIFY", + .op_rsize_bop = nfsd4_only_status_rsize, }, [OP_WRITE] = { - .op_func = (nfsd4op_func)nfsd4_write, + .op_func = nfsd4_write, .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, .op_name = "OP_WRITE", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize, - .op_get_currentstateid = (stateid_getter)nfsd4_get_writestateid, + .op_rsize_bop = nfsd4_write_rsize, + .op_get_currentstateid = nfsd4_get_writestateid, }, [OP_RELEASE_LOCKOWNER] = { - .op_func = (nfsd4op_func)nfsd4_release_lockowner, + .op_func = nfsd4_release_lockowner, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS | OP_MODIFIES_SOMETHING, .op_name = "OP_RELEASE_LOCKOWNER", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, + .op_rsize_bop = nfsd4_only_status_rsize, }, /* NFSv4.1 operations */ [OP_EXCHANGE_ID] = { - .op_func = (nfsd4op_func)nfsd4_exchange_id, + .op_func = nfsd4_exchange_id, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP | OP_MODIFIES_SOMETHING, .op_name = "OP_EXCHANGE_ID", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_exchange_id_rsize, + .op_rsize_bop = nfsd4_exchange_id_rsize, }, [OP_BACKCHANNEL_CTL] = { - .op_func = (nfsd4op_func)nfsd4_backchannel_ctl, + .op_func = nfsd4_backchannel_ctl, .op_flags = ALLOWED_WITHOUT_FH | OP_MODIFIES_SOMETHING, .op_name = "OP_BACKCHANNEL_CTL", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, + .op_rsize_bop = nfsd4_only_status_rsize, }, [OP_BIND_CONN_TO_SESSION] = { - .op_func = (nfsd4op_func)nfsd4_bind_conn_to_session, + .op_func = nfsd4_bind_conn_to_session, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP | OP_MODIFIES_SOMETHING, .op_name = "OP_BIND_CONN_TO_SESSION", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_bind_conn_to_session_rsize, + .op_rsize_bop = nfsd4_bind_conn_to_session_rsize, }, [OP_CREATE_SESSION] = { - .op_func = (nfsd4op_func)nfsd4_create_session, + .op_func = nfsd4_create_session, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP | OP_MODIFIES_SOMETHING, .op_name = "OP_CREATE_SESSION", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_create_session_rsize, + .op_rsize_bop = nfsd4_create_session_rsize, }, [OP_DESTROY_SESSION] = { - .op_func = (nfsd4op_func)nfsd4_destroy_session, + .op_func = nfsd4_destroy_session, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP | OP_MODIFIES_SOMETHING, .op_name = "OP_DESTROY_SESSION", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, + .op_rsize_bop = nfsd4_only_status_rsize, }, [OP_SEQUENCE] = { - .op_func = (nfsd4op_func)nfsd4_sequence, + .op_func = nfsd4_sequence, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP, .op_name = "OP_SEQUENCE", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_sequence_rsize, + .op_rsize_bop = nfsd4_sequence_rsize, }, [OP_DESTROY_CLIENTID] = { - .op_func = (nfsd4op_func)nfsd4_destroy_clientid, + .op_func = nfsd4_destroy_clientid, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP | OP_MODIFIES_SOMETHING, .op_name = "OP_DESTROY_CLIENTID", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, + .op_rsize_bop = nfsd4_only_status_rsize, }, [OP_RECLAIM_COMPLETE] = { - .op_func = (nfsd4op_func)nfsd4_reclaim_complete, + .op_func = nfsd4_reclaim_complete, .op_flags = ALLOWED_WITHOUT_FH | OP_MODIFIES_SOMETHING, .op_name = "OP_RECLAIM_COMPLETE", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, + .op_rsize_bop = nfsd4_only_status_rsize, }, [OP_SECINFO_NO_NAME] = { - .op_func = (nfsd4op_func)nfsd4_secinfo_no_name, + .op_func = nfsd4_secinfo_no_name, .op_flags = OP_HANDLES_WRONGSEC, .op_name = "OP_SECINFO_NO_NAME", + .op_rsize_bop = nfsd4_secinfo_rsize, }, [OP_TEST_STATEID] = { - .op_func = (nfsd4op_func)nfsd4_test_stateid, + .op_func = nfsd4_test_stateid, .op_flags = ALLOWED_WITHOUT_FH, .op_name = "OP_TEST_STATEID", + .op_rsize_bop = nfsd4_test_stateid_rsize, }, [OP_FREE_STATEID] = { - .op_func = (nfsd4op_func)nfsd4_free_stateid, + .op_func = nfsd4_free_stateid, .op_flags = ALLOWED_WITHOUT_FH | OP_MODIFIES_SOMETHING, .op_name = "OP_FREE_STATEID", - .op_get_currentstateid = (stateid_getter)nfsd4_get_freestateid, - .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, + .op_get_currentstateid = nfsd4_get_freestateid, + .op_rsize_bop = nfsd4_only_status_rsize, }, #ifdef CONFIG_NFSD_PNFS [OP_GETDEVICEINFO] = { - .op_func = (nfsd4op_func)nfsd4_getdeviceinfo, + .op_func = nfsd4_getdeviceinfo, .op_flags = ALLOWED_WITHOUT_FH, .op_name = "OP_GETDEVICEINFO", + .op_rsize_bop = nfsd4_getdeviceinfo_rsize, }, [OP_LAYOUTGET] = { - .op_func = (nfsd4op_func)nfsd4_layoutget, + .op_func = nfsd4_layoutget, .op_flags = OP_MODIFIES_SOMETHING, .op_name = "OP_LAYOUTGET", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_layoutget_rsize, + .op_rsize_bop = nfsd4_layoutget_rsize, }, [OP_LAYOUTCOMMIT] = { - .op_func = (nfsd4op_func)nfsd4_layoutcommit, + .op_func = nfsd4_layoutcommit, .op_flags = OP_MODIFIES_SOMETHING, .op_name = "OP_LAYOUTCOMMIT", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_layoutcommit_rsize, + .op_rsize_bop = nfsd4_layoutcommit_rsize, }, [OP_LAYOUTRETURN] = { - .op_func = (nfsd4op_func)nfsd4_layoutreturn, + .op_func = nfsd4_layoutreturn, .op_flags = OP_MODIFIES_SOMETHING, .op_name = "OP_LAYOUTRETURN", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_layoutreturn_rsize, + .op_rsize_bop = nfsd4_layoutreturn_rsize, }, #endif /* CONFIG_NFSD_PNFS */ /* NFSv4.2 operations */ [OP_ALLOCATE] = { - .op_func = (nfsd4op_func)nfsd4_allocate, + .op_func = nfsd4_allocate, .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, .op_name = "OP_ALLOCATE", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, + .op_rsize_bop = nfsd4_only_status_rsize, }, [OP_DEALLOCATE] = { - .op_func = (nfsd4op_func)nfsd4_deallocate, + .op_func = nfsd4_deallocate, .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, .op_name = "OP_DEALLOCATE", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, + .op_rsize_bop = nfsd4_only_status_rsize, }, [OP_CLONE] = { - .op_func = (nfsd4op_func)nfsd4_clone, + .op_func = nfsd4_clone, .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, .op_name = "OP_CLONE", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, + .op_rsize_bop = nfsd4_only_status_rsize, }, [OP_COPY] = { - .op_func = (nfsd4op_func)nfsd4_copy, + .op_func = nfsd4_copy, .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, .op_name = "OP_COPY", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_copy_rsize, + .op_rsize_bop = nfsd4_copy_rsize, }, [OP_SEEK] = { - .op_func = (nfsd4op_func)nfsd4_seek, + .op_func = nfsd4_seek, .op_name = "OP_SEEK", + .op_rsize_bop = nfsd4_seek_rsize, }, }; @@ -2425,14 +2505,11 @@ bool nfsd4_spo_must_allow(struct svc_rqst *rqstp) 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 || op->status == nfserr_notsupp) 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) @@ -2454,19 +2531,19 @@ static const char *nfsd4_op_name(unsigned opnum) #define nfsd4_voidres nfsd4_voidargs struct nfsd4_voidargs { int dummy; }; -static struct svc_procedure nfsd_procedures4[2] = { +static const struct svc_procedure nfsd_procedures4[2] = { [NFSPROC4_NULL] = { - .pc_func = (svc_procfunc) nfsd4_proc_null, - .pc_encode = (kxdrproc_t) nfs4svc_encode_voidres, + .pc_func = nfsd4_proc_null, + .pc_encode = nfs4svc_encode_voidres, .pc_argsize = sizeof(struct nfsd4_voidargs), .pc_ressize = sizeof(struct nfsd4_voidres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = 1, }, [NFSPROC4_COMPOUND] = { - .pc_func = (svc_procfunc) nfsd4_proc_compound, - .pc_decode = (kxdrproc_t) nfs4svc_decode_compoundargs, - .pc_encode = (kxdrproc_t) nfs4svc_encode_compoundres, + .pc_func = nfsd4_proc_compound, + .pc_decode = nfs4svc_decode_compoundargs, + .pc_encode = nfs4svc_encode_compoundres, .pc_argsize = sizeof(struct nfsd4_compoundargs), .pc_ressize = sizeof(struct nfsd4_compoundres), .pc_release = nfsd4_release_compoundargs, @@ -2475,13 +2552,16 @@ static struct svc_procedure nfsd_procedures4[2] = { }, }; -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, +static unsigned int nfsd_count3[ARRAY_SIZE(nfsd_procedures4)]; +const struct svc_version nfsd_version4 = { + .vs_vers = 4, + .vs_nproc = 2, + .vs_proc = nfsd_procedures4, + .vs_count = nfsd_count3, + .vs_dispatch = nfsd_dispatch, + .vs_xdrsize = NFS4_SVC_XDRSIZE, + .vs_rpcb_optnl = true, + .vs_need_cong_ctrl = true, }; /* |