diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-03-24 17:03:14 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-03-24 17:03:14 -0400 |
commit | 0acd2201920d0968919f4f5797d63f7b6f2b19d4 (patch) | |
tree | 9b241d264f42eff3ff4eeffb67616fca0490e460 /fs/nfs/nfs4xdr.c | |
parent | 8f70e95f9f4159184f557a1db60c909d7c1bd2e3 (diff) | |
parent | 35124a0994fc02545b14b9fa3aad000b3331f1c0 (diff) |
Merge branch 'nfs-for-2.6.39' into nfs-for-next
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r-- | fs/nfs/nfs4xdr.c | 167 |
1 files changed, 154 insertions, 13 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 21c3004b72d5..dddfb5795d7b 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -327,6 +327,18 @@ static int nfs4_stat_to_errno(int); | |||
327 | #define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \ | 327 | #define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \ |
328 | decode_stateid_maxsz + \ | 328 | decode_stateid_maxsz + \ |
329 | XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE)) | 329 | XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE)) |
330 | #define encode_layoutcommit_maxsz (op_encode_hdr_maxsz + \ | ||
331 | 2 /* offset */ + \ | ||
332 | 2 /* length */ + \ | ||
333 | 1 /* reclaim */ + \ | ||
334 | encode_stateid_maxsz + \ | ||
335 | 1 /* new offset (true) */ + \ | ||
336 | 2 /* last byte written */ + \ | ||
337 | 1 /* nt_timechanged (false) */ + \ | ||
338 | 1 /* layoutupdate4 layout type */ + \ | ||
339 | 1 /* NULL filelayout layoutupdate4 payload */) | ||
340 | #define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3) | ||
341 | |||
330 | #else /* CONFIG_NFS_V4_1 */ | 342 | #else /* CONFIG_NFS_V4_1 */ |
331 | #define encode_sequence_maxsz 0 | 343 | #define encode_sequence_maxsz 0 |
332 | #define decode_sequence_maxsz 0 | 344 | #define decode_sequence_maxsz 0 |
@@ -738,6 +750,17 @@ static int nfs4_stat_to_errno(int); | |||
738 | decode_sequence_maxsz + \ | 750 | decode_sequence_maxsz + \ |
739 | decode_putfh_maxsz + \ | 751 | decode_putfh_maxsz + \ |
740 | decode_layoutget_maxsz) | 752 | decode_layoutget_maxsz) |
753 | #define NFS4_enc_layoutcommit_sz (compound_encode_hdr_maxsz + \ | ||
754 | encode_sequence_maxsz +\ | ||
755 | encode_putfh_maxsz + \ | ||
756 | encode_layoutcommit_maxsz + \ | ||
757 | encode_getattr_maxsz) | ||
758 | #define NFS4_dec_layoutcommit_sz (compound_decode_hdr_maxsz + \ | ||
759 | decode_sequence_maxsz + \ | ||
760 | decode_putfh_maxsz + \ | ||
761 | decode_layoutcommit_maxsz + \ | ||
762 | decode_getattr_maxsz) | ||
763 | |||
741 | 764 | ||
742 | const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + | 765 | const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + |
743 | compound_encode_hdr_maxsz + | 766 | compound_encode_hdr_maxsz + |
@@ -1839,6 +1862,34 @@ encode_layoutget(struct xdr_stream *xdr, | |||
1839 | hdr->nops++; | 1862 | hdr->nops++; |
1840 | hdr->replen += decode_layoutget_maxsz; | 1863 | hdr->replen += decode_layoutget_maxsz; |
1841 | } | 1864 | } |
1865 | |||
1866 | static int | ||
1867 | encode_layoutcommit(struct xdr_stream *xdr, | ||
1868 | const struct nfs4_layoutcommit_args *args, | ||
1869 | struct compound_hdr *hdr) | ||
1870 | { | ||
1871 | __be32 *p; | ||
1872 | |||
1873 | dprintk("%s: lbw: %llu type: %d\n", __func__, args->lastbytewritten, | ||
1874 | NFS_SERVER(args->inode)->pnfs_curr_ld->id); | ||
1875 | |||
1876 | p = reserve_space(xdr, 48 + NFS4_STATEID_SIZE); | ||
1877 | *p++ = cpu_to_be32(OP_LAYOUTCOMMIT); | ||
1878 | /* Only whole file layouts */ | ||
1879 | p = xdr_encode_hyper(p, 0); /* offset */ | ||
1880 | p = xdr_encode_hyper(p, NFS4_MAX_UINT64); /* length */ | ||
1881 | *p++ = cpu_to_be32(0); /* reclaim */ | ||
1882 | p = xdr_encode_opaque_fixed(p, args->stateid.data, NFS4_STATEID_SIZE); | ||
1883 | *p++ = cpu_to_be32(1); /* newoffset = TRUE */ | ||
1884 | p = xdr_encode_hyper(p, args->lastbytewritten); | ||
1885 | *p++ = cpu_to_be32(0); /* Never send time_modify_changed */ | ||
1886 | *p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */ | ||
1887 | *p++ = cpu_to_be32(0); /* no file layout payload */ | ||
1888 | |||
1889 | hdr->nops++; | ||
1890 | hdr->replen += decode_layoutcommit_maxsz; | ||
1891 | return 0; | ||
1892 | } | ||
1842 | #endif /* CONFIG_NFS_V4_1 */ | 1893 | #endif /* CONFIG_NFS_V4_1 */ |
1843 | 1894 | ||
1844 | /* | 1895 | /* |
@@ -2317,7 +2368,8 @@ static void nfs4_xdr_enc_commit(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
2317 | encode_sequence(xdr, &args->seq_args, &hdr); | 2368 | encode_sequence(xdr, &args->seq_args, &hdr); |
2318 | encode_putfh(xdr, args->fh, &hdr); | 2369 | encode_putfh(xdr, args->fh, &hdr); |
2319 | encode_commit(xdr, args, &hdr); | 2370 | encode_commit(xdr, args, &hdr); |
2320 | encode_getfattr(xdr, args->bitmask, &hdr); | 2371 | if (args->bitmask) |
2372 | encode_getfattr(xdr, args->bitmask, &hdr); | ||
2321 | encode_nops(&hdr); | 2373 | encode_nops(&hdr); |
2322 | } | 2374 | } |
2323 | 2375 | ||
@@ -2645,7 +2697,31 @@ static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req, | |||
2645 | encode_sequence(xdr, &args->seq_args, &hdr); | 2697 | encode_sequence(xdr, &args->seq_args, &hdr); |
2646 | encode_putfh(xdr, NFS_FH(args->inode), &hdr); | 2698 | encode_putfh(xdr, NFS_FH(args->inode), &hdr); |
2647 | encode_layoutget(xdr, args, &hdr); | 2699 | encode_layoutget(xdr, args, &hdr); |
2700 | |||
2701 | xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, | ||
2702 | args->layout.pages, 0, args->layout.pglen); | ||
2703 | |||
2704 | encode_nops(&hdr); | ||
2705 | } | ||
2706 | |||
2707 | /* | ||
2708 | * Encode LAYOUTCOMMIT request | ||
2709 | */ | ||
2710 | static int nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req, | ||
2711 | struct xdr_stream *xdr, | ||
2712 | struct nfs4_layoutcommit_args *args) | ||
2713 | { | ||
2714 | struct compound_hdr hdr = { | ||
2715 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | ||
2716 | }; | ||
2717 | |||
2718 | encode_compound_hdr(xdr, req, &hdr); | ||
2719 | encode_sequence(xdr, &args->seq_args, &hdr); | ||
2720 | encode_putfh(xdr, NFS_FH(args->inode), &hdr); | ||
2721 | encode_layoutcommit(xdr, args, &hdr); | ||
2722 | encode_getfattr(xdr, args->bitmask, &hdr); | ||
2648 | encode_nops(&hdr); | 2723 | encode_nops(&hdr); |
2724 | return 0; | ||
2649 | } | 2725 | } |
2650 | #endif /* CONFIG_NFS_V4_1 */ | 2726 | #endif /* CONFIG_NFS_V4_1 */ |
2651 | 2727 | ||
@@ -5063,6 +5139,9 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
5063 | __be32 *p; | 5139 | __be32 *p; |
5064 | int status; | 5140 | int status; |
5065 | u32 layout_count; | 5141 | u32 layout_count; |
5142 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; | ||
5143 | struct kvec *iov = rcvbuf->head; | ||
5144 | u32 hdrlen, recvd; | ||
5066 | 5145 | ||
5067 | status = decode_op_hdr(xdr, OP_LAYOUTGET); | 5146 | status = decode_op_hdr(xdr, OP_LAYOUTGET); |
5068 | if (status) | 5147 | if (status) |
@@ -5079,17 +5158,14 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
5079 | return -EINVAL; | 5158 | return -EINVAL; |
5080 | } | 5159 | } |
5081 | 5160 | ||
5082 | p = xdr_inline_decode(xdr, 24); | 5161 | p = xdr_inline_decode(xdr, 28); |
5083 | if (unlikely(!p)) | 5162 | if (unlikely(!p)) |
5084 | goto out_overflow; | 5163 | goto out_overflow; |
5085 | p = xdr_decode_hyper(p, &res->range.offset); | 5164 | p = xdr_decode_hyper(p, &res->range.offset); |
5086 | p = xdr_decode_hyper(p, &res->range.length); | 5165 | p = xdr_decode_hyper(p, &res->range.length); |
5087 | res->range.iomode = be32_to_cpup(p++); | 5166 | res->range.iomode = be32_to_cpup(p++); |
5088 | res->type = be32_to_cpup(p++); | 5167 | res->type = be32_to_cpup(p++); |
5089 | 5168 | res->layoutp->len = be32_to_cpup(p); | |
5090 | status = decode_opaque_inline(xdr, &res->layout.len, (char **)&p); | ||
5091 | if (unlikely(status)) | ||
5092 | return status; | ||
5093 | 5169 | ||
5094 | dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n", | 5170 | dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n", |
5095 | __func__, | 5171 | __func__, |
@@ -5097,12 +5173,18 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
5097 | (unsigned long)res->range.length, | 5173 | (unsigned long)res->range.length, |
5098 | res->range.iomode, | 5174 | res->range.iomode, |
5099 | res->type, | 5175 | res->type, |
5100 | res->layout.len); | 5176 | res->layoutp->len); |
5177 | |||
5178 | hdrlen = (u8 *) xdr->p - (u8 *) iov->iov_base; | ||
5179 | recvd = req->rq_rcv_buf.len - hdrlen; | ||
5180 | if (res->layoutp->len > recvd) { | ||
5181 | dprintk("NFS: server cheating in layoutget reply: " | ||
5182 | "layout len %u > recvd %u\n", | ||
5183 | res->layoutp->len, recvd); | ||
5184 | return -EINVAL; | ||
5185 | } | ||
5101 | 5186 | ||
5102 | /* nfs4_proc_layoutget allocated a single page */ | 5187 | xdr_read_pages(xdr, res->layoutp->len); |
5103 | if (res->layout.len > PAGE_SIZE) | ||
5104 | return -ENOMEM; | ||
5105 | memcpy(res->layout.buf, p, res->layout.len); | ||
5106 | 5188 | ||
5107 | if (layout_count > 1) { | 5189 | if (layout_count > 1) { |
5108 | /* We only handle a length one array at the moment. Any | 5190 | /* We only handle a length one array at the moment. Any |
@@ -5119,6 +5201,35 @@ out_overflow: | |||
5119 | print_overflow_msg(__func__, xdr); | 5201 | print_overflow_msg(__func__, xdr); |
5120 | return -EIO; | 5202 | return -EIO; |
5121 | } | 5203 | } |
5204 | |||
5205 | static int decode_layoutcommit(struct xdr_stream *xdr, | ||
5206 | struct rpc_rqst *req, | ||
5207 | struct nfs4_layoutcommit_res *res) | ||
5208 | { | ||
5209 | __be32 *p; | ||
5210 | __u32 sizechanged; | ||
5211 | int status; | ||
5212 | |||
5213 | status = decode_op_hdr(xdr, OP_LAYOUTCOMMIT); | ||
5214 | if (status) | ||
5215 | return status; | ||
5216 | |||
5217 | p = xdr_inline_decode(xdr, 4); | ||
5218 | if (unlikely(!p)) | ||
5219 | goto out_overflow; | ||
5220 | sizechanged = be32_to_cpup(p); | ||
5221 | |||
5222 | if (sizechanged) { | ||
5223 | /* throw away new size */ | ||
5224 | p = xdr_inline_decode(xdr, 8); | ||
5225 | if (unlikely(!p)) | ||
5226 | goto out_overflow; | ||
5227 | } | ||
5228 | return 0; | ||
5229 | out_overflow: | ||
5230 | print_overflow_msg(__func__, xdr); | ||
5231 | return -EIO; | ||
5232 | } | ||
5122 | #endif /* CONFIG_NFS_V4_1 */ | 5233 | #endif /* CONFIG_NFS_V4_1 */ |
5123 | 5234 | ||
5124 | /* | 5235 | /* |
@@ -5836,8 +5947,9 @@ static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
5836 | status = decode_commit(xdr, res); | 5947 | status = decode_commit(xdr, res); |
5837 | if (status) | 5948 | if (status) |
5838 | goto out; | 5949 | goto out; |
5839 | decode_getfattr(xdr, res->fattr, res->server, | 5950 | if (res->fattr) |
5840 | !RPC_IS_ASYNC(rqstp->rq_task)); | 5951 | decode_getfattr(xdr, res->fattr, res->server, |
5952 | !RPC_IS_ASYNC(rqstp->rq_task)); | ||
5841 | out: | 5953 | out: |
5842 | return status; | 5954 | return status; |
5843 | } | 5955 | } |
@@ -6205,6 +6317,34 @@ static int nfs4_xdr_dec_layoutget(struct rpc_rqst *rqstp, | |||
6205 | out: | 6317 | out: |
6206 | return status; | 6318 | return status; |
6207 | } | 6319 | } |
6320 | |||
6321 | /* | ||
6322 | * Decode LAYOUTCOMMIT response | ||
6323 | */ | ||
6324 | static int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp, | ||
6325 | struct xdr_stream *xdr, | ||
6326 | struct nfs4_layoutcommit_res *res) | ||
6327 | { | ||
6328 | struct compound_hdr hdr; | ||
6329 | int status; | ||
6330 | |||
6331 | status = decode_compound_hdr(xdr, &hdr); | ||
6332 | if (status) | ||
6333 | goto out; | ||
6334 | status = decode_sequence(xdr, &res->seq_res, rqstp); | ||
6335 | if (status) | ||
6336 | goto out; | ||
6337 | status = decode_putfh(xdr); | ||
6338 | if (status) | ||
6339 | goto out; | ||
6340 | status = decode_layoutcommit(xdr, rqstp, res); | ||
6341 | if (status) | ||
6342 | goto out; | ||
6343 | decode_getfattr(xdr, res->fattr, res->server, | ||
6344 | !RPC_IS_ASYNC(rqstp->rq_task)); | ||
6345 | out: | ||
6346 | return status; | ||
6347 | } | ||
6208 | #endif /* CONFIG_NFS_V4_1 */ | 6348 | #endif /* CONFIG_NFS_V4_1 */ |
6209 | 6349 | ||
6210 | /** | 6350 | /** |
@@ -6403,6 +6543,7 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
6403 | PROC(RECLAIM_COMPLETE, enc_reclaim_complete, dec_reclaim_complete), | 6543 | PROC(RECLAIM_COMPLETE, enc_reclaim_complete, dec_reclaim_complete), |
6404 | PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo), | 6544 | PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo), |
6405 | PROC(LAYOUTGET, enc_layoutget, dec_layoutget), | 6545 | PROC(LAYOUTGET, enc_layoutget, dec_layoutget), |
6546 | PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit), | ||
6406 | #endif /* CONFIG_NFS_V4_1 */ | 6547 | #endif /* CONFIG_NFS_V4_1 */ |
6407 | }; | 6548 | }; |
6408 | 6549 | ||