diff options
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r-- | fs/nfs/nfs4xdr.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 07cdf925c524..207d399c8dee 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -324,6 +324,18 @@ static int nfs4_stat_to_errno(int); | |||
324 | #define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \ | 324 | #define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \ |
325 | decode_stateid_maxsz + \ | 325 | decode_stateid_maxsz + \ |
326 | XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE)) | 326 | XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE)) |
327 | #define encode_layoutcommit_maxsz (op_encode_hdr_maxsz + \ | ||
328 | 2 /* offset */ + \ | ||
329 | 2 /* length */ + \ | ||
330 | 1 /* reclaim */ + \ | ||
331 | encode_stateid_maxsz + \ | ||
332 | 1 /* new offset (true) */ + \ | ||
333 | 2 /* last byte written */ + \ | ||
334 | 1 /* nt_timechanged (false) */ + \ | ||
335 | 1 /* layoutupdate4 layout type */ + \ | ||
336 | 1 /* NULL filelayout layoutupdate4 payload */) | ||
337 | #define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3) | ||
338 | |||
327 | #else /* CONFIG_NFS_V4_1 */ | 339 | #else /* CONFIG_NFS_V4_1 */ |
328 | #define encode_sequence_maxsz 0 | 340 | #define encode_sequence_maxsz 0 |
329 | #define decode_sequence_maxsz 0 | 341 | #define decode_sequence_maxsz 0 |
@@ -727,6 +739,17 @@ static int nfs4_stat_to_errno(int); | |||
727 | decode_sequence_maxsz + \ | 739 | decode_sequence_maxsz + \ |
728 | decode_putfh_maxsz + \ | 740 | decode_putfh_maxsz + \ |
729 | decode_layoutget_maxsz) | 741 | decode_layoutget_maxsz) |
742 | #define NFS4_enc_layoutcommit_sz (compound_encode_hdr_maxsz + \ | ||
743 | encode_sequence_maxsz +\ | ||
744 | encode_putfh_maxsz + \ | ||
745 | encode_layoutcommit_maxsz + \ | ||
746 | encode_getattr_maxsz) | ||
747 | #define NFS4_dec_layoutcommit_sz (compound_decode_hdr_maxsz + \ | ||
748 | decode_sequence_maxsz + \ | ||
749 | decode_putfh_maxsz + \ | ||
750 | decode_layoutcommit_maxsz + \ | ||
751 | decode_getattr_maxsz) | ||
752 | |||
730 | 753 | ||
731 | const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + | 754 | const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + |
732 | compound_encode_hdr_maxsz + | 755 | compound_encode_hdr_maxsz + |
@@ -1816,6 +1839,34 @@ encode_layoutget(struct xdr_stream *xdr, | |||
1816 | hdr->nops++; | 1839 | hdr->nops++; |
1817 | hdr->replen += decode_layoutget_maxsz; | 1840 | hdr->replen += decode_layoutget_maxsz; |
1818 | } | 1841 | } |
1842 | |||
1843 | static int | ||
1844 | encode_layoutcommit(struct xdr_stream *xdr, | ||
1845 | const struct nfs4_layoutcommit_args *args, | ||
1846 | struct compound_hdr *hdr) | ||
1847 | { | ||
1848 | __be32 *p; | ||
1849 | |||
1850 | dprintk("%s: lbw: %llu type: %d\n", __func__, args->lastbytewritten, | ||
1851 | NFS_SERVER(args->inode)->pnfs_curr_ld->id); | ||
1852 | |||
1853 | p = reserve_space(xdr, 48 + NFS4_STATEID_SIZE); | ||
1854 | *p++ = cpu_to_be32(OP_LAYOUTCOMMIT); | ||
1855 | /* Only whole file layouts */ | ||
1856 | p = xdr_encode_hyper(p, 0); /* offset */ | ||
1857 | p = xdr_encode_hyper(p, NFS4_MAX_UINT64); /* length */ | ||
1858 | *p++ = cpu_to_be32(0); /* reclaim */ | ||
1859 | p = xdr_encode_opaque_fixed(p, args->stateid.data, NFS4_STATEID_SIZE); | ||
1860 | *p++ = cpu_to_be32(1); /* newoffset = TRUE */ | ||
1861 | p = xdr_encode_hyper(p, args->lastbytewritten); | ||
1862 | *p++ = cpu_to_be32(0); /* Never send time_modify_changed */ | ||
1863 | *p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */ | ||
1864 | *p++ = cpu_to_be32(0); /* no file layout payload */ | ||
1865 | |||
1866 | hdr->nops++; | ||
1867 | hdr->replen += decode_layoutcommit_maxsz; | ||
1868 | return 0; | ||
1869 | } | ||
1819 | #endif /* CONFIG_NFS_V4_1 */ | 1870 | #endif /* CONFIG_NFS_V4_1 */ |
1820 | 1871 | ||
1821 | /* | 1872 | /* |
@@ -2607,6 +2658,26 @@ static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req, | |||
2607 | encode_layoutget(xdr, args, &hdr); | 2658 | encode_layoutget(xdr, args, &hdr); |
2608 | encode_nops(&hdr); | 2659 | encode_nops(&hdr); |
2609 | } | 2660 | } |
2661 | |||
2662 | /* | ||
2663 | * Encode LAYOUTCOMMIT request | ||
2664 | */ | ||
2665 | static int nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req, | ||
2666 | struct xdr_stream *xdr, | ||
2667 | struct nfs4_layoutcommit_args *args) | ||
2668 | { | ||
2669 | struct compound_hdr hdr = { | ||
2670 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | ||
2671 | }; | ||
2672 | |||
2673 | encode_compound_hdr(xdr, req, &hdr); | ||
2674 | encode_sequence(xdr, &args->seq_args, &hdr); | ||
2675 | encode_putfh(xdr, NFS_FH(args->inode), &hdr); | ||
2676 | encode_layoutcommit(xdr, args, &hdr); | ||
2677 | encode_getfattr(xdr, args->bitmask, &hdr); | ||
2678 | encode_nops(&hdr); | ||
2679 | return 0; | ||
2680 | } | ||
2610 | #endif /* CONFIG_NFS_V4_1 */ | 2681 | #endif /* CONFIG_NFS_V4_1 */ |
2611 | 2682 | ||
2612 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | 2683 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) |
@@ -5007,6 +5078,35 @@ out_overflow: | |||
5007 | print_overflow_msg(__func__, xdr); | 5078 | print_overflow_msg(__func__, xdr); |
5008 | return -EIO; | 5079 | return -EIO; |
5009 | } | 5080 | } |
5081 | |||
5082 | static int decode_layoutcommit(struct xdr_stream *xdr, | ||
5083 | struct rpc_rqst *req, | ||
5084 | struct nfs4_layoutcommit_res *res) | ||
5085 | { | ||
5086 | __be32 *p; | ||
5087 | __u32 sizechanged; | ||
5088 | int status; | ||
5089 | |||
5090 | status = decode_op_hdr(xdr, OP_LAYOUTCOMMIT); | ||
5091 | if (status) | ||
5092 | return status; | ||
5093 | |||
5094 | p = xdr_inline_decode(xdr, 4); | ||
5095 | if (unlikely(!p)) | ||
5096 | goto out_overflow; | ||
5097 | sizechanged = be32_to_cpup(p); | ||
5098 | |||
5099 | if (sizechanged) { | ||
5100 | /* throw away new size */ | ||
5101 | p = xdr_inline_decode(xdr, 8); | ||
5102 | if (unlikely(!p)) | ||
5103 | goto out_overflow; | ||
5104 | } | ||
5105 | return 0; | ||
5106 | out_overflow: | ||
5107 | print_overflow_msg(__func__, xdr); | ||
5108 | return -EIO; | ||
5109 | } | ||
5010 | #endif /* CONFIG_NFS_V4_1 */ | 5110 | #endif /* CONFIG_NFS_V4_1 */ |
5011 | 5111 | ||
5012 | /* | 5112 | /* |
@@ -6068,6 +6168,34 @@ static int nfs4_xdr_dec_layoutget(struct rpc_rqst *rqstp, | |||
6068 | out: | 6168 | out: |
6069 | return status; | 6169 | return status; |
6070 | } | 6170 | } |
6171 | |||
6172 | /* | ||
6173 | * Decode LAYOUTCOMMIT response | ||
6174 | */ | ||
6175 | static int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp, | ||
6176 | struct xdr_stream *xdr, | ||
6177 | struct nfs4_layoutcommit_res *res) | ||
6178 | { | ||
6179 | struct compound_hdr hdr; | ||
6180 | int status; | ||
6181 | |||
6182 | status = decode_compound_hdr(xdr, &hdr); | ||
6183 | if (status) | ||
6184 | goto out; | ||
6185 | status = decode_sequence(xdr, &res->seq_res, rqstp); | ||
6186 | if (status) | ||
6187 | goto out; | ||
6188 | status = decode_putfh(xdr); | ||
6189 | if (status) | ||
6190 | goto out; | ||
6191 | status = decode_layoutcommit(xdr, rqstp, res); | ||
6192 | if (status) | ||
6193 | goto out; | ||
6194 | decode_getfattr(xdr, res->fattr, res->server, | ||
6195 | !RPC_IS_ASYNC(rqstp->rq_task)); | ||
6196 | out: | ||
6197 | return status; | ||
6198 | } | ||
6071 | #endif /* CONFIG_NFS_V4_1 */ | 6199 | #endif /* CONFIG_NFS_V4_1 */ |
6072 | 6200 | ||
6073 | /** | 6201 | /** |
@@ -6269,6 +6397,7 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
6269 | PROC(RECLAIM_COMPLETE, enc_reclaim_complete, dec_reclaim_complete), | 6397 | PROC(RECLAIM_COMPLETE, enc_reclaim_complete, dec_reclaim_complete), |
6270 | PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo), | 6398 | PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo), |
6271 | PROC(LAYOUTGET, enc_layoutget, dec_layoutget), | 6399 | PROC(LAYOUTGET, enc_layoutget, dec_layoutget), |
6400 | PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit), | ||
6272 | #endif /* CONFIG_NFS_V4_1 */ | 6401 | #endif /* CONFIG_NFS_V4_1 */ |
6273 | }; | 6402 | }; |
6274 | 6403 | ||