For checking the size of reply before calling a operation, we need try to get maxsize of the operation's reply. Make a struct named nfsd4_enc_op, and add enc_size for a operation, we can set the a operation's fixed size at enc_size, but except dynamic data as payload for some especial operation such as READ, READDIR, READLINK. Signed-off-by: Mi Jinlong <mijinlong@xxxxxxxxxxxxxx> --- fs/nfsd/nfs4xdr.c | 241 +++++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 180 insertions(+), 61 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 9901811..1273661 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -3146,70 +3146,189 @@ nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p) typedef __be32(* nfsd4_enc)(struct nfsd4_compoundres *, __be32, void *); +struct nfsd4_enc_op { + nfsd4_enc enc_func; + + /* size except dynamic data as payload for READ, READDIR, READLINK */ + u32 enc_size; +}; + /* * Note: nfsd4_enc_ops vector is shared for v4.0 and v4.1 * since we don't need to filter out obsolete ops as this is * done in the decoding phase. */ -static nfsd4_enc nfsd4_enc_ops[] = { - [OP_ACCESS] = (nfsd4_enc)nfsd4_encode_access, - [OP_CLOSE] = (nfsd4_enc)nfsd4_encode_close, - [OP_COMMIT] = (nfsd4_enc)nfsd4_encode_commit, - [OP_CREATE] = (nfsd4_enc)nfsd4_encode_create, - [OP_DELEGPURGE] = (nfsd4_enc)nfsd4_encode_noop, - [OP_DELEGRETURN] = (nfsd4_enc)nfsd4_encode_noop, - [OP_GETATTR] = (nfsd4_enc)nfsd4_encode_getattr, - [OP_GETFH] = (nfsd4_enc)nfsd4_encode_getfh, - [OP_LINK] = (nfsd4_enc)nfsd4_encode_link, - [OP_LOCK] = (nfsd4_enc)nfsd4_encode_lock, - [OP_LOCKT] = (nfsd4_enc)nfsd4_encode_lockt, - [OP_LOCKU] = (nfsd4_enc)nfsd4_encode_locku, - [OP_LOOKUP] = (nfsd4_enc)nfsd4_encode_noop, - [OP_LOOKUPP] = (nfsd4_enc)nfsd4_encode_noop, - [OP_NVERIFY] = (nfsd4_enc)nfsd4_encode_noop, - [OP_OPEN] = (nfsd4_enc)nfsd4_encode_open, - [OP_OPENATTR] = (nfsd4_enc)nfsd4_encode_noop, - [OP_OPEN_CONFIRM] = (nfsd4_enc)nfsd4_encode_open_confirm, - [OP_OPEN_DOWNGRADE] = (nfsd4_enc)nfsd4_encode_open_downgrade, - [OP_PUTFH] = (nfsd4_enc)nfsd4_encode_noop, - [OP_PUTPUBFH] = (nfsd4_enc)nfsd4_encode_noop, - [OP_PUTROOTFH] = (nfsd4_enc)nfsd4_encode_noop, - [OP_READ] = (nfsd4_enc)nfsd4_encode_read, - [OP_READDIR] = (nfsd4_enc)nfsd4_encode_readdir, - [OP_READLINK] = (nfsd4_enc)nfsd4_encode_readlink, - [OP_REMOVE] = (nfsd4_enc)nfsd4_encode_remove, - [OP_RENAME] = (nfsd4_enc)nfsd4_encode_rename, - [OP_RENEW] = (nfsd4_enc)nfsd4_encode_noop, - [OP_RESTOREFH] = (nfsd4_enc)nfsd4_encode_noop, - [OP_SAVEFH] = (nfsd4_enc)nfsd4_encode_noop, - [OP_SECINFO] = (nfsd4_enc)nfsd4_encode_secinfo, - [OP_SETATTR] = (nfsd4_enc)nfsd4_encode_setattr, - [OP_SETCLIENTID] = (nfsd4_enc)nfsd4_encode_setclientid, - [OP_SETCLIENTID_CONFIRM] = (nfsd4_enc)nfsd4_encode_noop, - [OP_VERIFY] = (nfsd4_enc)nfsd4_encode_noop, - [OP_WRITE] = (nfsd4_enc)nfsd4_encode_write, - [OP_RELEASE_LOCKOWNER] = (nfsd4_enc)nfsd4_encode_noop, - - /* NFSv4.1 operations */ - [OP_BACKCHANNEL_CTL] = (nfsd4_enc)nfsd4_encode_noop, - [OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_bind_conn_to_session, - [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id, - [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session, - [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_destroy_session, - [OP_FREE_STATEID] = (nfsd4_enc)nfsd4_encode_noop, - [OP_GET_DIR_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop, - [OP_GETDEVICEINFO] = (nfsd4_enc)nfsd4_encode_noop, - [OP_GETDEVICELIST] = (nfsd4_enc)nfsd4_encode_noop, - [OP_LAYOUTCOMMIT] = (nfsd4_enc)nfsd4_encode_noop, - [OP_LAYOUTGET] = (nfsd4_enc)nfsd4_encode_noop, - [OP_LAYOUTRETURN] = (nfsd4_enc)nfsd4_encode_noop, - [OP_SECINFO_NO_NAME] = (nfsd4_enc)nfsd4_encode_secinfo_no_name, - [OP_SEQUENCE] = (nfsd4_enc)nfsd4_encode_sequence, - [OP_SET_SSV] = (nfsd4_enc)nfsd4_encode_noop, - [OP_TEST_STATEID] = (nfsd4_enc)nfsd4_encode_noop, - [OP_WANT_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop, - [OP_DESTROY_CLIENTID] = (nfsd4_enc)nfsd4_encode_noop, - [OP_RECLAIM_COMPLETE] = (nfsd4_enc)nfsd4_encode_noop, +static struct nfsd4_enc_op nfsd4_enc_ops[] = { + [OP_ACCESS] = { + .enc_func = (nfsd4_enc)nfsd4_encode_access, + }, + [OP_CLOSE] = { + .enc_func = (nfsd4_enc)nfsd4_encode_close, + }, + [OP_COMMIT] = { + .enc_func = (nfsd4_enc)nfsd4_encode_commit, + }, + [OP_CREATE] = { + .enc_func = (nfsd4_enc)nfsd4_encode_create, + }, + [OP_DELEGPURGE] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_DELEGRETURN] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_GETATTR] = { + .enc_func = (nfsd4_enc)nfsd4_encode_getattr, + }, + [OP_GETFH] = { + .enc_func = (nfsd4_enc)nfsd4_encode_getfh, + }, + [OP_LINK] = { + .enc_func = (nfsd4_enc)nfsd4_encode_link, + }, + [OP_LOCK] = { + .enc_func = (nfsd4_enc)nfsd4_encode_lock, + }, + [OP_LOCKT] = { + .enc_func = (nfsd4_enc)nfsd4_encode_lockt, + }, + [OP_LOCKU] = { + .enc_func = (nfsd4_enc)nfsd4_encode_locku, + }, + [OP_LOOKUP] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_LOOKUPP] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_NVERIFY] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_OPEN] = { + .enc_func = (nfsd4_enc)nfsd4_encode_open, + }, + [OP_OPENATTR] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_OPEN_CONFIRM] = { + .enc_func = (nfsd4_enc)nfsd4_encode_open_confirm, + }, + [OP_OPEN_DOWNGRADE] = { + .enc_func = (nfsd4_enc)nfsd4_encode_open_downgrade, + }, + [OP_PUTFH] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_PUTPUBFH] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_PUTROOTFH] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_READ] = { + .enc_func = (nfsd4_enc)nfsd4_encode_read, + }, + [OP_READDIR] = { + .enc_func = (nfsd4_enc)nfsd4_encode_readdir, + }, + [OP_READLINK] = { + .enc_func = (nfsd4_enc)nfsd4_encode_readlink, + }, + [OP_REMOVE] = { + .enc_func = (nfsd4_enc)nfsd4_encode_remove, + }, + [OP_RENAME] = { + .enc_func = (nfsd4_enc)nfsd4_encode_rename, + }, + [OP_RENEW] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_RESTOREFH] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_SAVEFH] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_SECINFO] = { + .enc_func = (nfsd4_enc)nfsd4_encode_secinfo, + }, + [OP_SETATTR] = { + .enc_func = (nfsd4_enc)nfsd4_encode_setattr, + }, + [OP_SETCLIENTID] = { + .enc_func = (nfsd4_enc)nfsd4_encode_setclientid, + }, + [OP_SETCLIENTID_CONFIRM] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_VERIFY] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_WRITE] = { + .enc_func = (nfsd4_enc)nfsd4_encode_write, + }, + [OP_RELEASE_LOCKOWNER] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + + /* NFSv4.1 operations */ + [OP_BACKCHANNEL_CTL] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_BIND_CONN_TO_SESSION] = { + .enc_func = (nfsd4_enc)nfsd4_encode_bind_conn_to_session, + }, + [OP_EXCHANGE_ID] = { + .enc_func = (nfsd4_enc)nfsd4_encode_exchange_id, + }, + [OP_CREATE_SESSION] = { + .enc_func = (nfsd4_enc)nfsd4_encode_create_session, + }, + [OP_DESTROY_SESSION] = { + .enc_func = (nfsd4_enc)nfsd4_encode_destroy_session, + }, + [OP_FREE_STATEID] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_GET_DIR_DELEGATION] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_GETDEVICEINFO] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_GETDEVICELIST] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_LAYOUTCOMMIT] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_LAYOUTGET] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_LAYOUTRETURN] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_SECINFO_NO_NAME] = { + .enc_func = (nfsd4_enc)nfsd4_encode_secinfo_no_name, + }, + [OP_SEQUENCE] = { + .enc_func = (nfsd4_enc)nfsd4_encode_sequence, + }, + [OP_SET_SSV] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_TEST_STATEID] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_WANT_DELEGATION] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_DESTROY_CLIENTID] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, + [OP_RECLAIM_COMPLETE] = { + .enc_func = (nfsd4_enc)nfsd4_encode_noop, + }, }; /* @@ -3274,8 +3393,8 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) if (op->opnum == OP_ILLEGAL) goto status; BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) || - !nfsd4_enc_ops[op->opnum]); - op->status = nfsd4_enc_ops[op->opnum](resp, op->status, &op->u); + !nfsd4_enc_ops[op->opnum].enc_func); + op->status = nfsd4_enc_ops[op->opnum].enc_func(resp, op->status, &op->u); /* nfsd4_check_drc_limit guarantees enough room for error status */ if (!op->status && nfsd4_check_drc_limit(resp)) op->status = nfserr_rep_too_big_to_cache; -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html