diff options
-rw-r--r-- | fs/nfs/nfs4proc.c | 28 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 91 | ||||
-rw-r--r-- | include/linux/nfs4.h | 1 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 10 |
4 files changed, 130 insertions, 0 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 892bff53f61d..5612ba997db7 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -6015,6 +6015,34 @@ out_freepage: | |||
6015 | out: | 6015 | out: |
6016 | return err; | 6016 | return err; |
6017 | } | 6017 | } |
6018 | static int _nfs41_test_stateid(struct nfs_server *server, struct nfs4_state *state) | ||
6019 | { | ||
6020 | int status; | ||
6021 | struct nfs41_test_stateid_args args = { | ||
6022 | .stateid = &state->stateid, | ||
6023 | }; | ||
6024 | struct nfs41_test_stateid_res res; | ||
6025 | struct rpc_message msg = { | ||
6026 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_TEST_STATEID], | ||
6027 | .rpc_argp = &args, | ||
6028 | .rpc_resp = &res, | ||
6029 | }; | ||
6030 | args.seq_args.sa_session = res.seq_res.sr_session = NULL; | ||
6031 | status = nfs4_call_sync_sequence(server->client, server, &msg, &args.seq_args, &res.seq_res, 0, 1); | ||
6032 | return status; | ||
6033 | } | ||
6034 | |||
6035 | static int nfs41_test_stateid(struct nfs_server *server, struct nfs4_state *state) | ||
6036 | { | ||
6037 | struct nfs4_exception exception = { }; | ||
6038 | int err; | ||
6039 | do { | ||
6040 | err = nfs4_handle_exception(server, | ||
6041 | _nfs41_test_stateid(server, state), | ||
6042 | &exception); | ||
6043 | } while (exception.retry); | ||
6044 | return err; | ||
6045 | } | ||
6018 | #endif /* CONFIG_NFS_V4_1 */ | 6046 | #endif /* CONFIG_NFS_V4_1 */ |
6019 | 6047 | ||
6020 | struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { | 6048 | struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index c8c069a6319b..7d914d9e7584 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -345,6 +345,9 @@ static int nfs4_stat_to_errno(int); | |||
345 | 1 + decode_stateid_maxsz) | 345 | 1 + decode_stateid_maxsz) |
346 | #define encode_secinfo_no_name_maxsz (op_encode_hdr_maxsz + 1) | 346 | #define encode_secinfo_no_name_maxsz (op_encode_hdr_maxsz + 1) |
347 | #define decode_secinfo_no_name_maxsz decode_secinfo_maxsz | 347 | #define decode_secinfo_no_name_maxsz decode_secinfo_maxsz |
348 | #define encode_test_stateid_maxsz (op_encode_hdr_maxsz + 2 + \ | ||
349 | XDR_QUADLEN(NFS4_STATEID_SIZE)) | ||
350 | #define decode_test_stateid_maxsz (op_decode_hdr_maxsz + 2 + 1) | ||
348 | #else /* CONFIG_NFS_V4_1 */ | 351 | #else /* CONFIG_NFS_V4_1 */ |
349 | #define encode_sequence_maxsz 0 | 352 | #define encode_sequence_maxsz 0 |
350 | #define decode_sequence_maxsz 0 | 353 | #define decode_sequence_maxsz 0 |
@@ -782,6 +785,12 @@ static int nfs4_stat_to_errno(int); | |||
782 | decode_sequence_maxsz + \ | 785 | decode_sequence_maxsz + \ |
783 | decode_putrootfh_maxsz + \ | 786 | decode_putrootfh_maxsz + \ |
784 | decode_secinfo_no_name_maxsz) | 787 | decode_secinfo_no_name_maxsz) |
788 | #define NFS4_enc_test_stateid_sz (compound_encode_hdr_maxsz + \ | ||
789 | encode_sequence_maxsz + \ | ||
790 | encode_test_stateid_maxsz) | ||
791 | #define NFS4_dec_test_stateid_sz (compound_decode_hdr_maxsz + \ | ||
792 | decode_sequence_maxsz + \ | ||
793 | decode_test_stateid_maxsz) | ||
785 | 794 | ||
786 | const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + | 795 | const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + |
787 | compound_encode_hdr_maxsz + | 796 | compound_encode_hdr_maxsz + |
@@ -1962,6 +1971,20 @@ encode_secinfo_no_name(struct xdr_stream *xdr, | |||
1962 | hdr->replen += decode_secinfo_no_name_maxsz; | 1971 | hdr->replen += decode_secinfo_no_name_maxsz; |
1963 | return 0; | 1972 | return 0; |
1964 | } | 1973 | } |
1974 | |||
1975 | static void encode_test_stateid(struct xdr_stream *xdr, | ||
1976 | struct nfs41_test_stateid_args *args, | ||
1977 | struct compound_hdr *hdr) | ||
1978 | { | ||
1979 | __be32 *p; | ||
1980 | |||
1981 | p = reserve_space(xdr, 8 + NFS4_STATEID_SIZE); | ||
1982 | *p++ = cpu_to_be32(OP_TEST_STATEID); | ||
1983 | *p++ = cpu_to_be32(1); | ||
1984 | xdr_encode_opaque_fixed(p, args->stateid->data, NFS4_STATEID_SIZE); | ||
1985 | hdr->nops++; | ||
1986 | hdr->replen += decode_test_stateid_maxsz; | ||
1987 | } | ||
1965 | #endif /* CONFIG_NFS_V4_1 */ | 1988 | #endif /* CONFIG_NFS_V4_1 */ |
1966 | 1989 | ||
1967 | /* | 1990 | /* |
@@ -2833,6 +2856,23 @@ static int nfs4_xdr_enc_secinfo_no_name(struct rpc_rqst *req, | |||
2833 | encode_nops(&hdr); | 2856 | encode_nops(&hdr); |
2834 | return 0; | 2857 | return 0; |
2835 | } | 2858 | } |
2859 | |||
2860 | /* | ||
2861 | * Encode TEST_STATEID request | ||
2862 | */ | ||
2863 | static void nfs4_xdr_enc_test_stateid(struct rpc_rqst *req, | ||
2864 | struct xdr_stream *xdr, | ||
2865 | struct nfs41_test_stateid_args *args) | ||
2866 | { | ||
2867 | struct compound_hdr hdr = { | ||
2868 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | ||
2869 | }; | ||
2870 | |||
2871 | encode_compound_hdr(xdr, req, &hdr); | ||
2872 | encode_sequence(xdr, &args->seq_args, &hdr); | ||
2873 | encode_test_stateid(xdr, args, &hdr); | ||
2874 | encode_nops(&hdr); | ||
2875 | } | ||
2836 | #endif /* CONFIG_NFS_V4_1 */ | 2876 | #endif /* CONFIG_NFS_V4_1 */ |
2837 | 2877 | ||
2838 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | 2878 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) |
@@ -5371,6 +5411,35 @@ out_overflow: | |||
5371 | print_overflow_msg(__func__, xdr); | 5411 | print_overflow_msg(__func__, xdr); |
5372 | return -EIO; | 5412 | return -EIO; |
5373 | } | 5413 | } |
5414 | |||
5415 | static int decode_test_stateid(struct xdr_stream *xdr, | ||
5416 | struct nfs41_test_stateid_res *res) | ||
5417 | { | ||
5418 | __be32 *p; | ||
5419 | int status; | ||
5420 | int num_res; | ||
5421 | |||
5422 | status = decode_op_hdr(xdr, OP_TEST_STATEID); | ||
5423 | if (status) | ||
5424 | return status; | ||
5425 | |||
5426 | p = xdr_inline_decode(xdr, 4); | ||
5427 | if (unlikely(!p)) | ||
5428 | goto out_overflow; | ||
5429 | num_res = be32_to_cpup(p++); | ||
5430 | if (num_res != 1) | ||
5431 | goto out; | ||
5432 | |||
5433 | p = xdr_inline_decode(xdr, 4); | ||
5434 | if (unlikely(!p)) | ||
5435 | goto out_overflow; | ||
5436 | res->status = be32_to_cpup(p++); | ||
5437 | return res->status; | ||
5438 | out_overflow: | ||
5439 | print_overflow_msg(__func__, xdr); | ||
5440 | out: | ||
5441 | return -EIO; | ||
5442 | } | ||
5374 | #endif /* CONFIG_NFS_V4_1 */ | 5443 | #endif /* CONFIG_NFS_V4_1 */ |
5375 | 5444 | ||
5376 | /* | 5445 | /* |
@@ -6534,6 +6603,27 @@ static int nfs4_xdr_dec_secinfo_no_name(struct rpc_rqst *rqstp, | |||
6534 | out: | 6603 | out: |
6535 | return status; | 6604 | return status; |
6536 | } | 6605 | } |
6606 | |||
6607 | /* | ||
6608 | * Decode TEST_STATEID response | ||
6609 | */ | ||
6610 | static int nfs4_xdr_dec_test_stateid(struct rpc_rqst *rqstp, | ||
6611 | struct xdr_stream *xdr, | ||
6612 | struct nfs41_test_stateid_res *res) | ||
6613 | { | ||
6614 | struct compound_hdr hdr; | ||
6615 | int status; | ||
6616 | |||
6617 | status = decode_compound_hdr(xdr, &hdr); | ||
6618 | if (status) | ||
6619 | goto out; | ||
6620 | status = decode_sequence(xdr, &res->seq_res, rqstp); | ||
6621 | if (status) | ||
6622 | goto out; | ||
6623 | status = decode_test_stateid(xdr, res); | ||
6624 | out: | ||
6625 | return status; | ||
6626 | } | ||
6537 | #endif /* CONFIG_NFS_V4_1 */ | 6627 | #endif /* CONFIG_NFS_V4_1 */ |
6538 | 6628 | ||
6539 | /** | 6629 | /** |
@@ -6737,6 +6827,7 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
6737 | PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit), | 6827 | PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit), |
6738 | PROC(LAYOUTRETURN, enc_layoutreturn, dec_layoutreturn), | 6828 | PROC(LAYOUTRETURN, enc_layoutreturn, dec_layoutreturn), |
6739 | PROC(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name), | 6829 | PROC(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name), |
6830 | PROC(TEST_STATEID, enc_test_stateid, dec_test_stateid), | ||
6740 | #endif /* CONFIG_NFS_V4_1 */ | 6831 | #endif /* CONFIG_NFS_V4_1 */ |
6741 | }; | 6832 | }; |
6742 | 6833 | ||
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index 7cc7d5745be5..efe07f7a8765 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h | |||
@@ -564,6 +564,7 @@ enum { | |||
564 | NFSPROC4_CLNT_LAYOUTCOMMIT, | 564 | NFSPROC4_CLNT_LAYOUTCOMMIT, |
565 | NFSPROC4_CLNT_LAYOUTRETURN, | 565 | NFSPROC4_CLNT_LAYOUTRETURN, |
566 | NFSPROC4_CLNT_SECINFO_NO_NAME, | 566 | NFSPROC4_CLNT_SECINFO_NO_NAME, |
567 | NFSPROC4_CLNT_TEST_STATEID, | ||
567 | }; | 568 | }; |
568 | 569 | ||
569 | /* nfs41 types */ | 570 | /* nfs41 types */ |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 7159e1da63b6..e696c1fb139a 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -1092,6 +1092,16 @@ struct nfs41_secinfo_no_name_args { | |||
1092 | struct nfs4_sequence_args seq_args; | 1092 | struct nfs4_sequence_args seq_args; |
1093 | }; | 1093 | }; |
1094 | 1094 | ||
1095 | struct nfs41_test_stateid_args { | ||
1096 | nfs4_stateid *stateid; | ||
1097 | struct nfs4_sequence_args seq_args; | ||
1098 | }; | ||
1099 | |||
1100 | struct nfs41_test_stateid_res { | ||
1101 | unsigned int status; | ||
1102 | struct nfs4_sequence_res seq_res; | ||
1103 | }; | ||
1104 | |||
1095 | #endif /* CONFIG_NFS_V4_1 */ | 1105 | #endif /* CONFIG_NFS_V4_1 */ |
1096 | 1106 | ||
1097 | struct nfs_page; | 1107 | struct nfs_page; |