Loading fs/nfs/callback.c +1 −12 Original line number Diff line number Diff line Loading @@ -78,11 +78,6 @@ nfs4_callback_svc(void *vrqstp) set_freezable(); /* * FIXME: do we really need to run this under the BKL? If so, please * add a comment about what it's intended to protect. */ lock_kernel(); while (!kthread_should_stop()) { /* * Listen for a request on the socket Loading @@ -104,7 +99,6 @@ nfs4_callback_svc(void *vrqstp) preverr = err; svc_process(rqstp); } unlock_kernel(); return 0; } Loading Loading @@ -160,11 +154,6 @@ nfs41_callback_svc(void *vrqstp) set_freezable(); /* * FIXME: do we really need to run this under the BKL? If so, please * add a comment about what it's intended to protect. */ lock_kernel(); while (!kthread_should_stop()) { prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE); spin_lock_bh(&serv->sv_cb_lock); Loading @@ -183,7 +172,6 @@ nfs41_callback_svc(void *vrqstp) } finish_wait(&serv->sv_cb_waitq, &wq); } unlock_kernel(); return 0; } Loading Loading @@ -397,6 +385,7 @@ static int nfs_callback_authenticate(struct svc_rqst *rqstp) */ static struct svc_version *nfs4_callback_version[] = { [1] = &nfs4_callback_version1, [4] = &nfs4_callback_version4, }; static struct svc_stat nfs4_callback_stats; Loading fs/nfs/callback.h +15 −1 Original line number Diff line number Diff line Loading @@ -106,6 +106,19 @@ struct cb_sequenceres { extern unsigned nfs4_callback_sequence(struct cb_sequenceargs *args, struct cb_sequenceres *res); extern int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid); #define RCA4_TYPE_MASK_RDATA_DLG 0 #define RCA4_TYPE_MASK_WDATA_DLG 1 struct cb_recallanyargs { struct sockaddr *craa_addr; uint32_t craa_objs_to_keep; uint32_t craa_type_mask; }; extern unsigned nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy); #endif /* CONFIG_NFS_V4_1 */ extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res); Loading @@ -114,8 +127,9 @@ extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy); #ifdef CONFIG_NFS_V4 extern int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt); extern void nfs_callback_down(int minorversion); extern int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid); #endif /* CONFIG_NFS_V4 */ /* * nfs41: Callbacks are expected to not cause substantial latency, * so we limit their concurrency to 1 by setting up the maximum number Loading fs/nfs/callback_proc.c +63 −1 Original line number Diff line number Diff line Loading @@ -61,6 +61,16 @@ __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres * return res->status; } static int (*nfs_validate_delegation_stateid(struct nfs_client *clp))(struct nfs_delegation *, const nfs4_stateid *) { #if defined(CONFIG_NFS_V4_1) if (clp->cl_minorversion > 0) return nfs41_validate_delegation_stateid; #endif return nfs4_validate_delegation_stateid; } __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) { struct nfs_client *clp; Loading @@ -81,7 +91,8 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) inode = nfs_delegation_find_inode(clp, &args->fh); if (inode != NULL) { /* Set up a helper thread to actually return the delegation */ switch(nfs_async_inode_return_delegation(inode, &args->stateid)) { switch (nfs_async_inode_return_delegation(inode, &args->stateid, nfs_validate_delegation_stateid(clp))) { case 0: res = 0; break; Loading @@ -102,8 +113,31 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) return res; } int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid) { if (delegation == NULL || memcmp(delegation->stateid.data, stateid->data, sizeof(delegation->stateid.data)) != 0) return 0; return 1; } #if defined(CONFIG_NFS_V4_1) int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid) { if (delegation == NULL) return 0; /* seqid is 4-bytes long */ if (((u32 *) &stateid->data)[0] != 0) return 0; if (memcmp(&delegation->stateid.data[4], &stateid->data[4], sizeof(stateid->data)-4)) return 0; return 1; } /* * Validate the sequenceID sent by the server. * Return success if the sequenceID is one more than what we last saw on Loading Loading @@ -227,4 +261,32 @@ unsigned nfs4_callback_sequence(struct cb_sequenceargs *args, return res->csr_status; } unsigned nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy) { struct nfs_client *clp; int status; fmode_t flags = 0; status = htonl(NFS4ERR_OP_NOT_IN_SESSION); clp = nfs_find_client(args->craa_addr, 4); if (clp == NULL) goto out; dprintk("NFS: RECALL_ANY callback request from %s\n", rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); if (test_bit(RCA4_TYPE_MASK_RDATA_DLG, (const unsigned long *) &args->craa_type_mask)) flags = FMODE_READ; if (test_bit(RCA4_TYPE_MASK_WDATA_DLG, (const unsigned long *) &args->craa_type_mask)) flags |= FMODE_WRITE; if (flags) nfs_expire_all_delegation_types(clp, flags); status = htonl(NFS4_OK); out: dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); return status; } #endif /* CONFIG_NFS_V4_1 */ fs/nfs/callback_xdr.c +33 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #if defined(CONFIG_NFS_V4_1) #define CB_OP_SEQUENCE_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \ 4 + 1 + 3) #define CB_OP_RECALLANY_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ) #endif /* CONFIG_NFS_V4_1 */ #define NFSDBG_FACILITY NFSDBG_CALLBACK Loading Loading @@ -326,6 +327,25 @@ static unsigned decode_cb_sequence_args(struct svc_rqst *rqstp, goto out; } static unsigned decode_recallany_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct cb_recallanyargs *args) { uint32_t *p; args->craa_addr = svc_addr(rqstp); p = read_buf(xdr, 4); if (unlikely(p == NULL)) return htonl(NFS4ERR_BADXDR); args->craa_objs_to_keep = ntohl(*p++); p = read_buf(xdr, 4); if (unlikely(p == NULL)) return htonl(NFS4ERR_BADXDR); args->craa_type_mask = ntohl(*p); return 0; } #endif /* CONFIG_NFS_V4_1 */ static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) Loading Loading @@ -533,6 +553,7 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op) case OP_CB_GETATTR: case OP_CB_RECALL: case OP_CB_SEQUENCE: case OP_CB_RECALL_ANY: *op = &callback_ops[op_nr]; break; Loading @@ -540,7 +561,6 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op) case OP_CB_NOTIFY_DEVICEID: case OP_CB_NOTIFY: case OP_CB_PUSH_DELEG: case OP_CB_RECALL_ANY: case OP_CB_RECALLABLE_OBJ_AVAIL: case OP_CB_RECALL_SLOT: case OP_CB_WANTS_CANCELLED: Loading Loading @@ -688,6 +708,11 @@ static struct callback_op callback_ops[] = { .encode_res = (callback_encode_res_t)encode_cb_sequence_res, .res_maxsize = CB_OP_SEQUENCE_RES_MAXSZ, }, [OP_CB_RECALL_ANY] = { .process_op = (callback_process_op_t)nfs4_callback_recallany, .decode_args = (callback_decode_arg_t)decode_recallany_args, .res_maxsize = CB_OP_RECALLANY_RES_MAXSZ, }, #endif /* CONFIG_NFS_V4_1 */ }; Loading Loading @@ -718,3 +743,10 @@ struct svc_version nfs4_callback_version1 = { .vs_dispatch = NULL, }; struct svc_version nfs4_callback_version4 = { .vs_vers = 4, .vs_nproc = ARRAY_SIZE(nfs4_callback_procedures1), .vs_proc = nfs4_callback_procedures1, .vs_xdrsize = NFS4_CALLBACK_XDRSIZE, .vs_dispatch = NULL, }; fs/nfs/client.c +12 −2 Original line number Diff line number Diff line Loading @@ -1260,10 +1260,20 @@ static int nfs4_set_client(struct nfs_server *server, static void nfs4_session_set_rwsize(struct nfs_server *server) { #ifdef CONFIG_NFS_V4_1 struct nfs4_session *sess; u32 server_resp_sz; u32 server_rqst_sz; if (!nfs4_has_session(server->nfs_client)) return; server->rsize = server->nfs_client->cl_session->fc_attrs.max_resp_sz; server->wsize = server->nfs_client->cl_session->fc_attrs.max_rqst_sz; sess = server->nfs_client->cl_session; server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead; server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead; if (server->rsize > server_resp_sz) server->rsize = server_resp_sz; if (server->wsize > server_rqst_sz) server->wsize = server_rqst_sz; #endif /* CONFIG_NFS_V4_1 */ } Loading Loading
fs/nfs/callback.c +1 −12 Original line number Diff line number Diff line Loading @@ -78,11 +78,6 @@ nfs4_callback_svc(void *vrqstp) set_freezable(); /* * FIXME: do we really need to run this under the BKL? If so, please * add a comment about what it's intended to protect. */ lock_kernel(); while (!kthread_should_stop()) { /* * Listen for a request on the socket Loading @@ -104,7 +99,6 @@ nfs4_callback_svc(void *vrqstp) preverr = err; svc_process(rqstp); } unlock_kernel(); return 0; } Loading Loading @@ -160,11 +154,6 @@ nfs41_callback_svc(void *vrqstp) set_freezable(); /* * FIXME: do we really need to run this under the BKL? If so, please * add a comment about what it's intended to protect. */ lock_kernel(); while (!kthread_should_stop()) { prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE); spin_lock_bh(&serv->sv_cb_lock); Loading @@ -183,7 +172,6 @@ nfs41_callback_svc(void *vrqstp) } finish_wait(&serv->sv_cb_waitq, &wq); } unlock_kernel(); return 0; } Loading Loading @@ -397,6 +385,7 @@ static int nfs_callback_authenticate(struct svc_rqst *rqstp) */ static struct svc_version *nfs4_callback_version[] = { [1] = &nfs4_callback_version1, [4] = &nfs4_callback_version4, }; static struct svc_stat nfs4_callback_stats; Loading
fs/nfs/callback.h +15 −1 Original line number Diff line number Diff line Loading @@ -106,6 +106,19 @@ struct cb_sequenceres { extern unsigned nfs4_callback_sequence(struct cb_sequenceargs *args, struct cb_sequenceres *res); extern int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid); #define RCA4_TYPE_MASK_RDATA_DLG 0 #define RCA4_TYPE_MASK_WDATA_DLG 1 struct cb_recallanyargs { struct sockaddr *craa_addr; uint32_t craa_objs_to_keep; uint32_t craa_type_mask; }; extern unsigned nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy); #endif /* CONFIG_NFS_V4_1 */ extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res); Loading @@ -114,8 +127,9 @@ extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy); #ifdef CONFIG_NFS_V4 extern int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt); extern void nfs_callback_down(int minorversion); extern int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid); #endif /* CONFIG_NFS_V4 */ /* * nfs41: Callbacks are expected to not cause substantial latency, * so we limit their concurrency to 1 by setting up the maximum number Loading
fs/nfs/callback_proc.c +63 −1 Original line number Diff line number Diff line Loading @@ -61,6 +61,16 @@ __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres * return res->status; } static int (*nfs_validate_delegation_stateid(struct nfs_client *clp))(struct nfs_delegation *, const nfs4_stateid *) { #if defined(CONFIG_NFS_V4_1) if (clp->cl_minorversion > 0) return nfs41_validate_delegation_stateid; #endif return nfs4_validate_delegation_stateid; } __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) { struct nfs_client *clp; Loading @@ -81,7 +91,8 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) inode = nfs_delegation_find_inode(clp, &args->fh); if (inode != NULL) { /* Set up a helper thread to actually return the delegation */ switch(nfs_async_inode_return_delegation(inode, &args->stateid)) { switch (nfs_async_inode_return_delegation(inode, &args->stateid, nfs_validate_delegation_stateid(clp))) { case 0: res = 0; break; Loading @@ -102,8 +113,31 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) return res; } int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid) { if (delegation == NULL || memcmp(delegation->stateid.data, stateid->data, sizeof(delegation->stateid.data)) != 0) return 0; return 1; } #if defined(CONFIG_NFS_V4_1) int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid) { if (delegation == NULL) return 0; /* seqid is 4-bytes long */ if (((u32 *) &stateid->data)[0] != 0) return 0; if (memcmp(&delegation->stateid.data[4], &stateid->data[4], sizeof(stateid->data)-4)) return 0; return 1; } /* * Validate the sequenceID sent by the server. * Return success if the sequenceID is one more than what we last saw on Loading Loading @@ -227,4 +261,32 @@ unsigned nfs4_callback_sequence(struct cb_sequenceargs *args, return res->csr_status; } unsigned nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy) { struct nfs_client *clp; int status; fmode_t flags = 0; status = htonl(NFS4ERR_OP_NOT_IN_SESSION); clp = nfs_find_client(args->craa_addr, 4); if (clp == NULL) goto out; dprintk("NFS: RECALL_ANY callback request from %s\n", rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); if (test_bit(RCA4_TYPE_MASK_RDATA_DLG, (const unsigned long *) &args->craa_type_mask)) flags = FMODE_READ; if (test_bit(RCA4_TYPE_MASK_WDATA_DLG, (const unsigned long *) &args->craa_type_mask)) flags |= FMODE_WRITE; if (flags) nfs_expire_all_delegation_types(clp, flags); status = htonl(NFS4_OK); out: dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); return status; } #endif /* CONFIG_NFS_V4_1 */
fs/nfs/callback_xdr.c +33 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #if defined(CONFIG_NFS_V4_1) #define CB_OP_SEQUENCE_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \ 4 + 1 + 3) #define CB_OP_RECALLANY_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ) #endif /* CONFIG_NFS_V4_1 */ #define NFSDBG_FACILITY NFSDBG_CALLBACK Loading Loading @@ -326,6 +327,25 @@ static unsigned decode_cb_sequence_args(struct svc_rqst *rqstp, goto out; } static unsigned decode_recallany_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct cb_recallanyargs *args) { uint32_t *p; args->craa_addr = svc_addr(rqstp); p = read_buf(xdr, 4); if (unlikely(p == NULL)) return htonl(NFS4ERR_BADXDR); args->craa_objs_to_keep = ntohl(*p++); p = read_buf(xdr, 4); if (unlikely(p == NULL)) return htonl(NFS4ERR_BADXDR); args->craa_type_mask = ntohl(*p); return 0; } #endif /* CONFIG_NFS_V4_1 */ static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) Loading Loading @@ -533,6 +553,7 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op) case OP_CB_GETATTR: case OP_CB_RECALL: case OP_CB_SEQUENCE: case OP_CB_RECALL_ANY: *op = &callback_ops[op_nr]; break; Loading @@ -540,7 +561,6 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op) case OP_CB_NOTIFY_DEVICEID: case OP_CB_NOTIFY: case OP_CB_PUSH_DELEG: case OP_CB_RECALL_ANY: case OP_CB_RECALLABLE_OBJ_AVAIL: case OP_CB_RECALL_SLOT: case OP_CB_WANTS_CANCELLED: Loading Loading @@ -688,6 +708,11 @@ static struct callback_op callback_ops[] = { .encode_res = (callback_encode_res_t)encode_cb_sequence_res, .res_maxsize = CB_OP_SEQUENCE_RES_MAXSZ, }, [OP_CB_RECALL_ANY] = { .process_op = (callback_process_op_t)nfs4_callback_recallany, .decode_args = (callback_decode_arg_t)decode_recallany_args, .res_maxsize = CB_OP_RECALLANY_RES_MAXSZ, }, #endif /* CONFIG_NFS_V4_1 */ }; Loading Loading @@ -718,3 +743,10 @@ struct svc_version nfs4_callback_version1 = { .vs_dispatch = NULL, }; struct svc_version nfs4_callback_version4 = { .vs_vers = 4, .vs_nproc = ARRAY_SIZE(nfs4_callback_procedures1), .vs_proc = nfs4_callback_procedures1, .vs_xdrsize = NFS4_CALLBACK_XDRSIZE, .vs_dispatch = NULL, };
fs/nfs/client.c +12 −2 Original line number Diff line number Diff line Loading @@ -1260,10 +1260,20 @@ static int nfs4_set_client(struct nfs_server *server, static void nfs4_session_set_rwsize(struct nfs_server *server) { #ifdef CONFIG_NFS_V4_1 struct nfs4_session *sess; u32 server_resp_sz; u32 server_rqst_sz; if (!nfs4_has_session(server->nfs_client)) return; server->rsize = server->nfs_client->cl_session->fc_attrs.max_resp_sz; server->wsize = server->nfs_client->cl_session->fc_attrs.max_rqst_sz; sess = server->nfs_client->cl_session; server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead; server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead; if (server->rsize > server_resp_sz) server->rsize = server_resp_sz; if (server->wsize > server_rqst_sz) server->wsize = server_rqst_sz; #endif /* CONFIG_NFS_V4_1 */ } Loading