diff options
author | Bryan Schumaker <bjschuma@netapp.com> | 2011-06-02 14:59:09 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-07-12 13:40:28 -0400 |
commit | 9aeda35fd643eba683fdb8dba8907fa796a85dda (patch) | |
tree | df797ea6f4eca0601edcdf941ac678d11c79a07a /fs/nfs/nfs4xdr.c | |
parent | 7d9747947ae66d8f6a9a9a023a3a5e28df6a536e (diff) |
NFS: added FREE_STATEID call
FREE_STATEID is used to tell the server that we want to free a stateid
that no longer has any locks associated with it. This allows the client
to reclaim locks without encountering edge conditions documented in
section 8.4.3 of RFC 5661.
Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r-- | fs/nfs/nfs4xdr.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 7d914d9e7584..c191a9baa422 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -348,6 +348,9 @@ static int nfs4_stat_to_errno(int); | |||
348 | #define encode_test_stateid_maxsz (op_encode_hdr_maxsz + 2 + \ | 348 | #define encode_test_stateid_maxsz (op_encode_hdr_maxsz + 2 + \ |
349 | XDR_QUADLEN(NFS4_STATEID_SIZE)) | 349 | XDR_QUADLEN(NFS4_STATEID_SIZE)) |
350 | #define decode_test_stateid_maxsz (op_decode_hdr_maxsz + 2 + 1) | 350 | #define decode_test_stateid_maxsz (op_decode_hdr_maxsz + 2 + 1) |
351 | #define encode_free_stateid_maxsz (op_encode_hdr_maxsz + 1 + \ | ||
352 | XDR_QUADLEN(NFS4_STATEID_SIZE)) | ||
353 | #define decode_free_stateid_maxsz (op_decode_hdr_maxsz + 1) | ||
351 | #else /* CONFIG_NFS_V4_1 */ | 354 | #else /* CONFIG_NFS_V4_1 */ |
352 | #define encode_sequence_maxsz 0 | 355 | #define encode_sequence_maxsz 0 |
353 | #define decode_sequence_maxsz 0 | 356 | #define decode_sequence_maxsz 0 |
@@ -791,6 +794,12 @@ static int nfs4_stat_to_errno(int); | |||
791 | #define NFS4_dec_test_stateid_sz (compound_decode_hdr_maxsz + \ | 794 | #define NFS4_dec_test_stateid_sz (compound_decode_hdr_maxsz + \ |
792 | decode_sequence_maxsz + \ | 795 | decode_sequence_maxsz + \ |
793 | decode_test_stateid_maxsz) | 796 | decode_test_stateid_maxsz) |
797 | #define NFS4_enc_free_stateid_sz (compound_encode_hdr_maxsz + \ | ||
798 | encode_sequence_maxsz + \ | ||
799 | encode_free_stateid_maxsz) | ||
800 | #define NFS4_dec_free_stateid_sz (compound_decode_hdr_maxsz + \ | ||
801 | decode_sequence_maxsz + \ | ||
802 | decode_free_stateid_maxsz) | ||
794 | 803 | ||
795 | const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + | 804 | const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + |
796 | compound_encode_hdr_maxsz + | 805 | compound_encode_hdr_maxsz + |
@@ -1985,6 +1994,18 @@ static void encode_test_stateid(struct xdr_stream *xdr, | |||
1985 | hdr->nops++; | 1994 | hdr->nops++; |
1986 | hdr->replen += decode_test_stateid_maxsz; | 1995 | hdr->replen += decode_test_stateid_maxsz; |
1987 | } | 1996 | } |
1997 | |||
1998 | static void encode_free_stateid(struct xdr_stream *xdr, | ||
1999 | struct nfs41_free_stateid_args *args, | ||
2000 | struct compound_hdr *hdr) | ||
2001 | { | ||
2002 | __be32 *p; | ||
2003 | p = reserve_space(xdr, 4 + NFS4_STATEID_SIZE); | ||
2004 | *p++ = cpu_to_be32(OP_FREE_STATEID); | ||
2005 | xdr_encode_opaque_fixed(p, args->stateid->data, NFS4_STATEID_SIZE); | ||
2006 | hdr->nops++; | ||
2007 | hdr->replen += decode_free_stateid_maxsz; | ||
2008 | } | ||
1988 | #endif /* CONFIG_NFS_V4_1 */ | 2009 | #endif /* CONFIG_NFS_V4_1 */ |
1989 | 2010 | ||
1990 | /* | 2011 | /* |
@@ -2873,6 +2894,23 @@ static void nfs4_xdr_enc_test_stateid(struct rpc_rqst *req, | |||
2873 | encode_test_stateid(xdr, args, &hdr); | 2894 | encode_test_stateid(xdr, args, &hdr); |
2874 | encode_nops(&hdr); | 2895 | encode_nops(&hdr); |
2875 | } | 2896 | } |
2897 | |||
2898 | /* | ||
2899 | * Encode FREE_STATEID request | ||
2900 | */ | ||
2901 | static void nfs4_xdr_enc_free_stateid(struct rpc_rqst *req, | ||
2902 | struct xdr_stream *xdr, | ||
2903 | struct nfs41_free_stateid_args *args) | ||
2904 | { | ||
2905 | struct compound_hdr hdr = { | ||
2906 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | ||
2907 | }; | ||
2908 | |||
2909 | encode_compound_hdr(xdr, req, &hdr); | ||
2910 | encode_sequence(xdr, &args->seq_args, &hdr); | ||
2911 | encode_free_stateid(xdr, args, &hdr); | ||
2912 | encode_nops(&hdr); | ||
2913 | } | ||
2876 | #endif /* CONFIG_NFS_V4_1 */ | 2914 | #endif /* CONFIG_NFS_V4_1 */ |
2877 | 2915 | ||
2878 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | 2916 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) |
@@ -5440,6 +5478,26 @@ out_overflow: | |||
5440 | out: | 5478 | out: |
5441 | return -EIO; | 5479 | return -EIO; |
5442 | } | 5480 | } |
5481 | |||
5482 | static int decode_free_stateid(struct xdr_stream *xdr, | ||
5483 | struct nfs41_free_stateid_res *res) | ||
5484 | { | ||
5485 | __be32 *p; | ||
5486 | int status; | ||
5487 | |||
5488 | status = decode_op_hdr(xdr, OP_FREE_STATEID); | ||
5489 | if (status) | ||
5490 | return status; | ||
5491 | |||
5492 | p = xdr_inline_decode(xdr, 4); | ||
5493 | if (unlikely(!p)) | ||
5494 | goto out_overflow; | ||
5495 | res->status = be32_to_cpup(p++); | ||
5496 | return res->status; | ||
5497 | out_overflow: | ||
5498 | print_overflow_msg(__func__, xdr); | ||
5499 | return -EIO; | ||
5500 | } | ||
5443 | #endif /* CONFIG_NFS_V4_1 */ | 5501 | #endif /* CONFIG_NFS_V4_1 */ |
5444 | 5502 | ||
5445 | /* | 5503 | /* |
@@ -6624,6 +6682,27 @@ static int nfs4_xdr_dec_test_stateid(struct rpc_rqst *rqstp, | |||
6624 | out: | 6682 | out: |
6625 | return status; | 6683 | return status; |
6626 | } | 6684 | } |
6685 | |||
6686 | /* | ||
6687 | * Decode FREE_STATEID response | ||
6688 | */ | ||
6689 | static int nfs4_xdr_dec_free_stateid(struct rpc_rqst *rqstp, | ||
6690 | struct xdr_stream *xdr, | ||
6691 | struct nfs41_free_stateid_res *res) | ||
6692 | { | ||
6693 | struct compound_hdr hdr; | ||
6694 | int status; | ||
6695 | |||
6696 | status = decode_compound_hdr(xdr, &hdr); | ||
6697 | if (status) | ||
6698 | goto out; | ||
6699 | status = decode_sequence(xdr, &res->seq_res, rqstp); | ||
6700 | if (status) | ||
6701 | goto out; | ||
6702 | status = decode_free_stateid(xdr, res); | ||
6703 | out: | ||
6704 | return status; | ||
6705 | } | ||
6627 | #endif /* CONFIG_NFS_V4_1 */ | 6706 | #endif /* CONFIG_NFS_V4_1 */ |
6628 | 6707 | ||
6629 | /** | 6708 | /** |
@@ -6828,6 +6907,7 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
6828 | PROC(LAYOUTRETURN, enc_layoutreturn, dec_layoutreturn), | 6907 | PROC(LAYOUTRETURN, enc_layoutreturn, dec_layoutreturn), |
6829 | PROC(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name), | 6908 | PROC(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name), |
6830 | PROC(TEST_STATEID, enc_test_stateid, dec_test_stateid), | 6909 | PROC(TEST_STATEID, enc_test_stateid, dec_test_stateid), |
6910 | PROC(FREE_STATEID, enc_free_stateid, dec_free_stateid), | ||
6831 | #endif /* CONFIG_NFS_V4_1 */ | 6911 | #endif /* CONFIG_NFS_V4_1 */ |
6832 | }; | 6912 | }; |
6833 | 6913 | ||