diff options
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
| -rw-r--r-- | fs/nfs/nfs4xdr.c | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index bd2101d918c8..f313c4cce7e4 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
| @@ -52,6 +52,7 @@ | |||
| 52 | #include <linux/nfs_idmap.h> | 52 | #include <linux/nfs_idmap.h> |
| 53 | #include "nfs4_fs.h" | 53 | #include "nfs4_fs.h" |
| 54 | #include "internal.h" | 54 | #include "internal.h" |
| 55 | #include "pnfs.h" | ||
| 55 | 56 | ||
| 56 | #define NFSDBG_FACILITY NFSDBG_XDR | 57 | #define NFSDBG_FACILITY NFSDBG_XDR |
| 57 | 58 | ||
| @@ -310,6 +311,19 @@ static int nfs4_stat_to_errno(int); | |||
| 310 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) | 311 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) |
| 311 | #define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4) | 312 | #define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4) |
| 312 | #define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4) | 313 | #define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4) |
| 314 | #define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + 4 + \ | ||
| 315 | XDR_QUADLEN(NFS4_DEVICEID4_SIZE)) | ||
| 316 | #define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \ | ||
| 317 | 1 /* layout type */ + \ | ||
| 318 | 1 /* opaque devaddr4 length */ + \ | ||
| 319 | /* devaddr4 payload is read into page */ \ | ||
| 320 | 1 /* notification bitmap length */ + \ | ||
| 321 | 1 /* notification bitmap */) | ||
| 322 | #define encode_layoutget_maxsz (op_encode_hdr_maxsz + 10 + \ | ||
| 323 | encode_stateid_maxsz) | ||
| 324 | #define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \ | ||
| 325 | decode_stateid_maxsz + \ | ||
| 326 | XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE)) | ||
| 313 | #else /* CONFIG_NFS_V4_1 */ | 327 | #else /* CONFIG_NFS_V4_1 */ |
| 314 | #define encode_sequence_maxsz 0 | 328 | #define encode_sequence_maxsz 0 |
| 315 | #define decode_sequence_maxsz 0 | 329 | #define decode_sequence_maxsz 0 |
| @@ -699,6 +713,20 @@ static int nfs4_stat_to_errno(int); | |||
| 699 | #define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \ | 713 | #define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \ |
| 700 | decode_sequence_maxsz + \ | 714 | decode_sequence_maxsz + \ |
| 701 | decode_reclaim_complete_maxsz) | 715 | decode_reclaim_complete_maxsz) |
| 716 | #define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz + \ | ||
| 717 | encode_sequence_maxsz +\ | ||
| 718 | encode_getdeviceinfo_maxsz) | ||
| 719 | #define NFS4_dec_getdeviceinfo_sz (compound_decode_hdr_maxsz + \ | ||
| 720 | decode_sequence_maxsz + \ | ||
| 721 | decode_getdeviceinfo_maxsz) | ||
| 722 | #define NFS4_enc_layoutget_sz (compound_encode_hdr_maxsz + \ | ||
| 723 | encode_sequence_maxsz + \ | ||
| 724 | encode_putfh_maxsz + \ | ||
| 725 | encode_layoutget_maxsz) | ||
| 726 | #define NFS4_dec_layoutget_sz (compound_decode_hdr_maxsz + \ | ||
| 727 | decode_sequence_maxsz + \ | ||
| 728 | decode_putfh_maxsz + \ | ||
| 729 | decode_layoutget_maxsz) | ||
| 702 | 730 | ||
| 703 | const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + | 731 | const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + |
| 704 | compound_encode_hdr_maxsz + | 732 | compound_encode_hdr_maxsz + |
| @@ -1737,6 +1765,58 @@ static void encode_sequence(struct xdr_stream *xdr, | |||
| 1737 | #endif /* CONFIG_NFS_V4_1 */ | 1765 | #endif /* CONFIG_NFS_V4_1 */ |
| 1738 | } | 1766 | } |
| 1739 | 1767 | ||
| 1768 | #ifdef CONFIG_NFS_V4_1 | ||
| 1769 | static void | ||
| 1770 | encode_getdeviceinfo(struct xdr_stream *xdr, | ||
| 1771 | const struct nfs4_getdeviceinfo_args *args, | ||
| 1772 | struct compound_hdr *hdr) | ||
| 1773 | { | ||
| 1774 | __be32 *p; | ||
| 1775 | |||
| 1776 | p = reserve_space(xdr, 16 + NFS4_DEVICEID4_SIZE); | ||
| 1777 | *p++ = cpu_to_be32(OP_GETDEVICEINFO); | ||
| 1778 | p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data, | ||
| 1779 | NFS4_DEVICEID4_SIZE); | ||
| 1780 | *p++ = cpu_to_be32(args->pdev->layout_type); | ||
| 1781 | *p++ = cpu_to_be32(args->pdev->pglen); /* gdia_maxcount */ | ||
| 1782 | *p++ = cpu_to_be32(0); /* bitmap length 0 */ | ||
| 1783 | hdr->nops++; | ||
| 1784 | hdr->replen += decode_getdeviceinfo_maxsz; | ||
| 1785 | } | ||
| 1786 | |||
| 1787 | static void | ||
| 1788 | encode_layoutget(struct xdr_stream *xdr, | ||
| 1789 | const struct nfs4_layoutget_args *args, | ||
| 1790 | struct compound_hdr *hdr) | ||
| 1791 | { | ||
| 1792 | nfs4_stateid stateid; | ||
| 1793 | __be32 *p; | ||
| 1794 | |||
| 1795 | p = reserve_space(xdr, 44 + NFS4_STATEID_SIZE); | ||
| 1796 | *p++ = cpu_to_be32(OP_LAYOUTGET); | ||
| 1797 | *p++ = cpu_to_be32(0); /* Signal layout available */ | ||
| 1798 | *p++ = cpu_to_be32(args->type); | ||
| 1799 | *p++ = cpu_to_be32(args->range.iomode); | ||
| 1800 | p = xdr_encode_hyper(p, args->range.offset); | ||
| 1801 | p = xdr_encode_hyper(p, args->range.length); | ||
| 1802 | p = xdr_encode_hyper(p, args->minlength); | ||
| 1803 | pnfs_get_layout_stateid(&stateid, NFS_I(args->inode)->layout, | ||
| 1804 | args->ctx->state); | ||
| 1805 | p = xdr_encode_opaque_fixed(p, &stateid.data, NFS4_STATEID_SIZE); | ||
| 1806 | *p = cpu_to_be32(args->maxcount); | ||
| 1807 | |||
| 1808 | dprintk("%s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d\n", | ||
| 1809 | __func__, | ||
| 1810 | args->type, | ||
| 1811 | args->range.iomode, | ||
| 1812 | (unsigned long)args->range.offset, | ||
| 1813 | (unsigned long)args->range.length, | ||
| 1814 | args->maxcount); | ||
| 1815 | hdr->nops++; | ||
| 1816 | hdr->replen += decode_layoutget_maxsz; | ||
| 1817 | } | ||
| 1818 | #endif /* CONFIG_NFS_V4_1 */ | ||
| 1819 | |||
| 1740 | /* | 1820 | /* |
| 1741 | * END OF "GENERIC" ENCODE ROUTINES. | 1821 | * END OF "GENERIC" ENCODE ROUTINES. |
| 1742 | */ | 1822 | */ |
| @@ -2554,6 +2634,51 @@ static int nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req, uint32_t *p, | |||
| 2554 | return 0; | 2634 | return 0; |
| 2555 | } | 2635 | } |
| 2556 | 2636 | ||
| 2637 | /* | ||
| 2638 | * Encode GETDEVICEINFO request | ||
| 2639 | */ | ||
| 2640 | static int nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req, uint32_t *p, | ||
| 2641 | struct nfs4_getdeviceinfo_args *args) | ||
| 2642 | { | ||
| 2643 | struct xdr_stream xdr; | ||
| 2644 | struct compound_hdr hdr = { | ||
| 2645 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | ||
| 2646 | }; | ||
| 2647 | |||
| 2648 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
| 2649 | encode_compound_hdr(&xdr, req, &hdr); | ||
| 2650 | encode_sequence(&xdr, &args->seq_args, &hdr); | ||
| 2651 | encode_getdeviceinfo(&xdr, args, &hdr); | ||
| 2652 | |||
| 2653 | /* set up reply kvec. Subtract notification bitmap max size (2) | ||
| 2654 | * so that notification bitmap is put in xdr_buf tail */ | ||
| 2655 | xdr_inline_pages(&req->rq_rcv_buf, (hdr.replen - 2) << 2, | ||
| 2656 | args->pdev->pages, args->pdev->pgbase, | ||
| 2657 | args->pdev->pglen); | ||
| 2658 | |||
| 2659 | encode_nops(&hdr); | ||
| 2660 | return 0; | ||
| 2661 | } | ||
| 2662 | |||
| 2663 | /* | ||
| 2664 | * Encode LAYOUTGET request | ||
| 2665 | */ | ||
| 2666 | static int nfs4_xdr_enc_layoutget(struct rpc_rqst *req, uint32_t *p, | ||
| 2667 | struct nfs4_layoutget_args *args) | ||
| 2668 | { | ||
| 2669 | struct xdr_stream xdr; | ||
| 2670 | struct compound_hdr hdr = { | ||
| 2671 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | ||
| 2672 | }; | ||
| 2673 | |||
| 2674 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
| 2675 | encode_compound_hdr(&xdr, req, &hdr); | ||
| 2676 | encode_sequence(&xdr, &args->seq_args, &hdr); | ||
| 2677 | encode_putfh(&xdr, NFS_FH(args->inode), &hdr); | ||
| 2678 | encode_layoutget(&xdr, args, &hdr); | ||
| 2679 | encode_nops(&hdr); | ||
| 2680 | return 0; | ||
| 2681 | } | ||
| 2557 | #endif /* CONFIG_NFS_V4_1 */ | 2682 | #endif /* CONFIG_NFS_V4_1 */ |
| 2558 | 2683 | ||
| 2559 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | 2684 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) |
| @@ -3978,6 +4103,61 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, | |||
| 3978 | return decode_getfattr_generic(xdr, fattr, NULL, server, may_sleep); | 4103 | return decode_getfattr_generic(xdr, fattr, NULL, server, may_sleep); |
| 3979 | } | 4104 | } |
| 3980 | 4105 | ||
| 4106 | /* | ||
| 4107 | * Decode potentially multiple layout types. Currently we only support | ||
| 4108 | * one layout driver per file system. | ||
| 4109 | */ | ||
| 4110 | static int decode_first_pnfs_layout_type(struct xdr_stream *xdr, | ||
| 4111 | uint32_t *layouttype) | ||
| 4112 | { | ||
| 4113 | uint32_t *p; | ||
| 4114 | int num; | ||
| 4115 | |||
| 4116 | p = xdr_inline_decode(xdr, 4); | ||
| 4117 | if (unlikely(!p)) | ||
| 4118 | goto out_overflow; | ||
| 4119 | num = be32_to_cpup(p); | ||
| 4120 | |||
| 4121 | /* pNFS is not supported by the underlying file system */ | ||
| 4122 | if (num == 0) { | ||
| 4123 | *layouttype = 0; | ||
| 4124 | return 0; | ||
| 4125 | } | ||
| 4126 | if (num > 1) | ||
| 4127 | printk(KERN_INFO "%s: Warning: Multiple pNFS layout drivers " | ||
| 4128 | "per filesystem not supported\n", __func__); | ||
| 4129 | |||
| 4130 | /* Decode and set first layout type, move xdr->p past unused types */ | ||
| 4131 | p = xdr_inline_decode(xdr, num * 4); | ||
| 4132 | if (unlikely(!p)) | ||
| 4133 | goto out_overflow; | ||
| 4134 | *layouttype = be32_to_cpup(p); | ||
| 4135 | return 0; | ||
| 4136 | out_overflow: | ||
| 4137 | print_overflow_msg(__func__, xdr); | ||
| 4138 | return -EIO; | ||
| 4139 | } | ||
| 4140 | |||
| 4141 | /* | ||
| 4142 | * The type of file system exported. | ||
| 4143 | * Note we must ensure that layouttype is set in any non-error case. | ||
| 4144 | */ | ||
| 4145 | static int decode_attr_pnfstype(struct xdr_stream *xdr, uint32_t *bitmap, | ||
| 4146 | uint32_t *layouttype) | ||
| 4147 | { | ||
| 4148 | int status = 0; | ||
| 4149 | |||
| 4150 | dprintk("%s: bitmap is %x\n", __func__, bitmap[1]); | ||
| 4151 | if (unlikely(bitmap[1] & (FATTR4_WORD1_FS_LAYOUT_TYPES - 1U))) | ||
| 4152 | return -EIO; | ||
| 4153 | if (bitmap[1] & FATTR4_WORD1_FS_LAYOUT_TYPES) { | ||
| 4154 | status = decode_first_pnfs_layout_type(xdr, layouttype); | ||
| 4155 | bitmap[1] &= ~FATTR4_WORD1_FS_LAYOUT_TYPES; | ||
| 4156 | } else | ||
| 4157 | *layouttype = 0; | ||
| 4158 | return status; | ||
| 4159 | } | ||
| 4160 | |||
| 3981 | static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) | 4161 | static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) |
| 3982 | { | 4162 | { |
| 3983 | __be32 *savep; | 4163 | __be32 *savep; |
| @@ -4006,6 +4186,9 @@ static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) | |||
| 4006 | status = decode_attr_time_delta(xdr, bitmap, &fsinfo->time_delta); | 4186 | status = decode_attr_time_delta(xdr, bitmap, &fsinfo->time_delta); |
| 4007 | if (status != 0) | 4187 | if (status != 0) |
| 4008 | goto xdr_error; | 4188 | goto xdr_error; |
| 4189 | status = decode_attr_pnfstype(xdr, bitmap, &fsinfo->layouttype); | ||
| 4190 | if (status != 0) | ||
| 4191 | goto xdr_error; | ||
| 4009 | 4192 | ||
| 4010 | status = verify_attr_len(xdr, savep, attrlen); | 4193 | status = verify_attr_len(xdr, savep, attrlen); |
| 4011 | xdr_error: | 4194 | xdr_error: |
| @@ -4772,6 +4955,134 @@ out_overflow: | |||
| 4772 | #endif /* CONFIG_NFS_V4_1 */ | 4955 | #endif /* CONFIG_NFS_V4_1 */ |
| 4773 | } | 4956 | } |
| 4774 | 4957 | ||
| 4958 | #if defined(CONFIG_NFS_V4_1) | ||
| 4959 | |||
| 4960 | static int decode_getdeviceinfo(struct xdr_stream *xdr, | ||
| 4961 | struct pnfs_device *pdev) | ||
| 4962 | { | ||
| 4963 | __be32 *p; | ||
| 4964 | uint32_t len, type; | ||
| 4965 | int status; | ||
| 4966 | |||
| 4967 | status = decode_op_hdr(xdr, OP_GETDEVICEINFO); | ||
| 4968 | if (status) { | ||
| 4969 | if (status == -ETOOSMALL) { | ||
| 4970 | p = xdr_inline_decode(xdr, 4); | ||
| 4971 | if (unlikely(!p)) | ||
| 4972 | goto out_overflow; | ||
| 4973 | pdev->mincount = be32_to_cpup(p); | ||
| 4974 | dprintk("%s: Min count too small. mincnt = %u\n", | ||
| 4975 | __func__, pdev->mincount); | ||
| 4976 | } | ||
| 4977 | return status; | ||
| 4978 | } | ||
| 4979 | |||
| 4980 | p = xdr_inline_decode(xdr, 8); | ||
| 4981 | if (unlikely(!p)) | ||
| 4982 | goto out_overflow; | ||
| 4983 | type = be32_to_cpup(p++); | ||
| 4984 | if (type != pdev->layout_type) { | ||
| 4985 | dprintk("%s: layout mismatch req: %u pdev: %u\n", | ||
| 4986 | __func__, pdev->layout_type, type); | ||
| 4987 | return -EINVAL; | ||
| 4988 | } | ||
| 4989 | /* | ||
| 4990 | * Get the length of the opaque device_addr4. xdr_read_pages places | ||
| 4991 | * the opaque device_addr4 in the xdr_buf->pages (pnfs_device->pages) | ||
| 4992 | * and places the remaining xdr data in xdr_buf->tail | ||
| 4993 | */ | ||
| 4994 | pdev->mincount = be32_to_cpup(p); | ||
| 4995 | xdr_read_pages(xdr, pdev->mincount); /* include space for the length */ | ||
| 4996 | |||
| 4997 | /* Parse notification bitmap, verifying that it is zero. */ | ||
| 4998 | p = xdr_inline_decode(xdr, 4); | ||
| 4999 | if (unlikely(!p)) | ||
| 5000 | goto out_overflow; | ||
| 5001 | len = be32_to_cpup(p); | ||
| 5002 | if (len) { | ||
| 5003 | int i; | ||
| 5004 | |||
| 5005 | p = xdr_inline_decode(xdr, 4 * len); | ||
| 5006 | if (unlikely(!p)) | ||
| 5007 | goto out_overflow; | ||
| 5008 | for (i = 0; i < len; i++, p++) { | ||
| 5009 | if (be32_to_cpup(p)) { | ||
| 5010 | dprintk("%s: notifications not supported\n", | ||
| 5011 | __func__); | ||
| 5012 | return -EIO; | ||
| 5013 | } | ||
| 5014 | } | ||
| 5015 | } | ||
| 5016 | return 0; | ||
| 5017 | out_overflow: | ||
| 5018 | print_overflow_msg(__func__, xdr); | ||
| 5019 | return -EIO; | ||
| 5020 | } | ||
| 5021 | |||
| 5022 | static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, | ||
| 5023 | struct nfs4_layoutget_res *res) | ||
| 5024 | { | ||
| 5025 | __be32 *p; | ||
| 5026 | int status; | ||
| 5027 | u32 layout_count; | ||
| 5028 | |||
| 5029 | status = decode_op_hdr(xdr, OP_LAYOUTGET); | ||
| 5030 | if (status) | ||
| 5031 | return status; | ||
| 5032 | p = xdr_inline_decode(xdr, 8 + NFS4_STATEID_SIZE); | ||
| 5033 | if (unlikely(!p)) | ||
| 5034 | goto out_overflow; | ||
| 5035 | res->return_on_close = be32_to_cpup(p++); | ||
| 5036 | p = xdr_decode_opaque_fixed(p, res->stateid.data, NFS4_STATEID_SIZE); | ||
| 5037 | layout_count = be32_to_cpup(p); | ||
| 5038 | if (!layout_count) { | ||
| 5039 | dprintk("%s: server responded with empty layout array\n", | ||
| 5040 | __func__); | ||
| 5041 | return -EINVAL; | ||
| 5042 | } | ||
| 5043 | |||
| 5044 | p = xdr_inline_decode(xdr, 24); | ||
| 5045 | if (unlikely(!p)) | ||
| 5046 | goto out_overflow; | ||
| 5047 | p = xdr_decode_hyper(p, &res->range.offset); | ||
| 5048 | p = xdr_decode_hyper(p, &res->range.length); | ||
| 5049 | res->range.iomode = be32_to_cpup(p++); | ||
| 5050 | res->type = be32_to_cpup(p++); | ||
| 5051 | |||
| 5052 | status = decode_opaque_inline(xdr, &res->layout.len, (char **)&p); | ||
| 5053 | if (unlikely(status)) | ||
| 5054 | return status; | ||
| 5055 | |||
| 5056 | dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n", | ||
| 5057 | __func__, | ||
| 5058 | (unsigned long)res->range.offset, | ||
| 5059 | (unsigned long)res->range.length, | ||
| 5060 | res->range.iomode, | ||
| 5061 | res->type, | ||
| 5062 | res->layout.len); | ||
| 5063 | |||
| 5064 | /* nfs4_proc_layoutget allocated a single page */ | ||
| 5065 | if (res->layout.len > PAGE_SIZE) | ||
| 5066 | return -ENOMEM; | ||
| 5067 | memcpy(res->layout.buf, p, res->layout.len); | ||
| 5068 | |||
| 5069 | if (layout_count > 1) { | ||
| 5070 | /* We only handle a length one array at the moment. Any | ||
| 5071 | * further entries are just ignored. Note that this means | ||
| 5072 | * the client may see a response that is less than the | ||
| 5073 | * minimum it requested. | ||
| 5074 | */ | ||
| 5075 | dprintk("%s: server responded with %d layouts, dropping tail\n", | ||
| 5076 | __func__, layout_count); | ||
| 5077 | } | ||
| 5078 | |||
| 5079 | return 0; | ||
| 5080 | out_overflow: | ||
| 5081 | print_overflow_msg(__func__, xdr); | ||
| 5082 | return -EIO; | ||
| 5083 | } | ||
| 5084 | #endif /* CONFIG_NFS_V4_1 */ | ||
| 5085 | |||
| 4775 | /* | 5086 | /* |
| 4776 | * END OF "GENERIC" DECODE ROUTINES. | 5087 | * END OF "GENERIC" DECODE ROUTINES. |
| 4777 | */ | 5088 | */ |
| @@ -5799,6 +6110,53 @@ static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp, uint32_t *p, | |||
| 5799 | status = decode_reclaim_complete(&xdr, (void *)NULL); | 6110 | status = decode_reclaim_complete(&xdr, (void *)NULL); |
| 5800 | return status; | 6111 | return status; |
| 5801 | } | 6112 | } |
| 6113 | |||
| 6114 | /* | ||
| 6115 | * Decode GETDEVINFO response | ||
| 6116 | */ | ||
| 6117 | static int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp, uint32_t *p, | ||
| 6118 | struct nfs4_getdeviceinfo_res *res) | ||
| 6119 | { | ||
| 6120 | struct xdr_stream xdr; | ||
| 6121 | struct compound_hdr hdr; | ||
| 6122 | int status; | ||
| 6123 | |||
| 6124 | xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); | ||
| 6125 | status = decode_compound_hdr(&xdr, &hdr); | ||
| 6126 | if (status != 0) | ||
| 6127 | goto out; | ||
| 6128 | status = decode_sequence(&xdr, &res->seq_res, rqstp); | ||
| 6129 | if (status != 0) | ||
| 6130 | goto out; | ||
| 6131 | status = decode_getdeviceinfo(&xdr, res->pdev); | ||
| 6132 | out: | ||
| 6133 | return status; | ||
| 6134 | } | ||
| 6135 | |||
| 6136 | /* | ||
| 6137 | * Decode LAYOUTGET response | ||
| 6138 | */ | ||
| 6139 | static int nfs4_xdr_dec_layoutget(struct rpc_rqst *rqstp, uint32_t *p, | ||
| 6140 | struct nfs4_layoutget_res *res) | ||
| 6141 | { | ||
| 6142 | struct xdr_stream xdr; | ||
| 6143 | struct compound_hdr hdr; | ||
| 6144 | int status; | ||
| 6145 | |||
| 6146 | xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); | ||
| 6147 | status = decode_compound_hdr(&xdr, &hdr); | ||
| 6148 | if (status) | ||
| 6149 | goto out; | ||
| 6150 | status = decode_sequence(&xdr, &res->seq_res, rqstp); | ||
| 6151 | if (status) | ||
| 6152 | goto out; | ||
| 6153 | status = decode_putfh(&xdr); | ||
| 6154 | if (status) | ||
| 6155 | goto out; | ||
| 6156 | status = decode_layoutget(&xdr, rqstp, res); | ||
| 6157 | out: | ||
| 6158 | return status; | ||
| 6159 | } | ||
| 5802 | #endif /* CONFIG_NFS_V4_1 */ | 6160 | #endif /* CONFIG_NFS_V4_1 */ |
| 5803 | 6161 | ||
| 5804 | __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | 6162 | __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, |
| @@ -5990,6 +6348,8 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
| 5990 | PROC(SEQUENCE, enc_sequence, dec_sequence), | 6348 | PROC(SEQUENCE, enc_sequence, dec_sequence), |
| 5991 | PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time), | 6349 | PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time), |
| 5992 | PROC(RECLAIM_COMPLETE, enc_reclaim_complete, dec_reclaim_complete), | 6350 | PROC(RECLAIM_COMPLETE, enc_reclaim_complete, dec_reclaim_complete), |
| 6351 | PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo), | ||
| 6352 | PROC(LAYOUTGET, enc_layoutget, dec_layoutget), | ||
| 5993 | #endif /* CONFIG_NFS_V4_1 */ | 6353 | #endif /* CONFIG_NFS_V4_1 */ |
| 5994 | }; | 6354 | }; |
| 5995 | 6355 | ||
