aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4proc.c28
-rw-r--r--fs/nfs/nfs4xdr.c91
-rw-r--r--include/linux/nfs4.h1
-rw-r--r--include/linux/nfs_xdr.h10
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:
6015out: 6015out:
6016 return err; 6016 return err;
6017} 6017}
6018static 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
6035static 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
6020struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { 6048struct 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
786const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + 795const 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
1975static 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 */
2863static 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
2838static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) 2878static 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
5415static 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;
5438out_overflow:
5439 print_overflow_msg(__func__, xdr);
5440out:
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,
6534out: 6603out:
6535 return status; 6604 return status;
6536} 6605}
6606
6607/*
6608 * Decode TEST_STATEID response
6609 */
6610static 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);
6624out:
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
1095struct nfs41_test_stateid_args {
1096 nfs4_stateid *stateid;
1097 struct nfs4_sequence_args seq_args;
1098};
1099
1100struct 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
1097struct nfs_page; 1107struct nfs_page;