diff options
| author | Bryan Schumaker <bjschuma@netapp.com> | 2010-10-21 16:33:17 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-10-23 15:27:37 -0400 |
| commit | ae42c70a60fe330d9c2af7c4b92ce78484308e37 (patch) | |
| tree | a70a200f3d031240e32e69d87375b021004e9817 | |
| parent | 9942438089d5c0e3adecdcb7bc360b8fe0ce7e62 (diff) | |
NFS: introduce generic decode_getattr function
Getattr should be able to decode errors and the readdir file handle.
decode_getfattr_attrs does the actual attribute decoding, while
decode_getfattr_generic will check the opcode before decoding. This will
let other functions call decode_getfattr_attrs to decode their attributes.
Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
| -rw-r--r-- | fs/nfs/nfs4xdr.c | 117 |
1 files changed, 98 insertions, 19 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 8346e977d837..b7eff205d3d8 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
| @@ -2848,6 +2848,58 @@ out_overflow: | |||
| 2848 | return -EIO; | 2848 | return -EIO; |
| 2849 | } | 2849 | } |
| 2850 | 2850 | ||
| 2851 | static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap) | ||
| 2852 | { | ||
| 2853 | __be32 *p; | ||
| 2854 | |||
| 2855 | if (unlikely(bitmap[0] & (FATTR4_WORD0_RDATTR_ERROR - 1U))) | ||
| 2856 | return -EIO; | ||
| 2857 | if (likely(bitmap[0] & FATTR4_WORD0_RDATTR_ERROR)) { | ||
| 2858 | p = xdr_inline_decode(xdr, 4); | ||
| 2859 | if (unlikely(!p)) | ||
| 2860 | goto out_overflow; | ||
| 2861 | bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; | ||
| 2862 | } | ||
| 2863 | return 0; | ||
| 2864 | out_overflow: | ||
| 2865 | print_overflow_msg(__func__, xdr); | ||
| 2866 | return -EIO; | ||
| 2867 | } | ||
| 2868 | |||
| 2869 | static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fh *fh) | ||
| 2870 | { | ||
| 2871 | __be32 *p; | ||
| 2872 | int len; | ||
| 2873 | |||
| 2874 | if (fh == NULL) { | ||
| 2875 | bitmap[0] &= ~FATTR4_WORD0_FILEHANDLE; | ||
| 2876 | return 0; | ||
| 2877 | } | ||
| 2878 | |||
| 2879 | memset(fh, 0, sizeof(*fh)); | ||
| 2880 | |||
| 2881 | if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEHANDLE - 1U))) | ||
| 2882 | return -EIO; | ||
| 2883 | if (likely(bitmap[0] & FATTR4_WORD0_FILEHANDLE)) { | ||
| 2884 | p = xdr_inline_decode(xdr, 4); | ||
| 2885 | if (unlikely(!p)) | ||
| 2886 | goto out_overflow; | ||
| 2887 | len = be32_to_cpup(p); | ||
| 2888 | if (len > NFS4_FHSIZE) | ||
| 2889 | return -EIO; | ||
| 2890 | fh->size = len; | ||
| 2891 | p = xdr_inline_decode(xdr, len); | ||
| 2892 | if (unlikely(!p)) | ||
| 2893 | goto out_overflow; | ||
| 2894 | memcpy(fh->data, p, len); | ||
| 2895 | bitmap[0] &= ~FATTR4_WORD0_FILEHANDLE; | ||
| 2896 | } | ||
| 2897 | return 0; | ||
| 2898 | out_overflow: | ||
| 2899 | print_overflow_msg(__func__, xdr); | ||
| 2900 | return -EIO; | ||
| 2901 | } | ||
| 2902 | |||
| 2851 | static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) | 2903 | static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) |
| 2852 | { | 2904 | { |
| 2853 | __be32 *p; | 2905 | __be32 *p; |
| @@ -3744,29 +3796,14 @@ xdr_error: | |||
| 3744 | return status; | 3796 | return status; |
| 3745 | } | 3797 | } |
| 3746 | 3798 | ||
| 3747 | static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, | 3799 | static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, |
| 3800 | struct nfs_fattr *fattr, struct nfs_fh *fh, | ||
| 3748 | const struct nfs_server *server, int may_sleep) | 3801 | const struct nfs_server *server, int may_sleep) |
| 3749 | { | 3802 | { |
| 3750 | __be32 *savep; | ||
| 3751 | uint32_t attrlen, | ||
| 3752 | bitmap[2] = {0}, | ||
| 3753 | type; | ||
| 3754 | int status; | 3803 | int status; |
| 3755 | umode_t fmode = 0; | 3804 | umode_t fmode = 0; |
| 3756 | uint64_t fileid; | 3805 | uint64_t fileid; |
| 3757 | 3806 | uint32_t type; | |
| 3758 | status = decode_op_hdr(xdr, OP_GETATTR); | ||
| 3759 | if (status < 0) | ||
| 3760 | goto xdr_error; | ||
| 3761 | |||
| 3762 | status = decode_attr_bitmap(xdr, bitmap); | ||
| 3763 | if (status < 0) | ||
| 3764 | goto xdr_error; | ||
| 3765 | |||
| 3766 | status = decode_attr_length(xdr, &attrlen, &savep); | ||
| 3767 | if (status < 0) | ||
| 3768 | goto xdr_error; | ||
| 3769 | |||
| 3770 | 3807 | ||
| 3771 | status = decode_attr_type(xdr, bitmap, &type); | 3808 | status = decode_attr_type(xdr, bitmap, &type); |
| 3772 | if (status < 0) | 3809 | if (status < 0) |
| @@ -3792,6 +3829,14 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, | |||
| 3792 | goto xdr_error; | 3829 | goto xdr_error; |
| 3793 | fattr->valid |= status; | 3830 | fattr->valid |= status; |
| 3794 | 3831 | ||
| 3832 | status = decode_attr_error(xdr, bitmap); | ||
| 3833 | if (status < 0) | ||
| 3834 | goto xdr_error; | ||
| 3835 | |||
| 3836 | status = decode_attr_filehandle(xdr, bitmap, fh); | ||
| 3837 | if (status < 0) | ||
| 3838 | goto xdr_error; | ||
| 3839 | |||
| 3795 | status = decode_attr_fileid(xdr, bitmap, &fattr->fileid); | 3840 | status = decode_attr_fileid(xdr, bitmap, &fattr->fileid); |
| 3796 | if (status < 0) | 3841 | if (status < 0) |
| 3797 | goto xdr_error; | 3842 | goto xdr_error; |
| @@ -3857,17 +3902,51 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, | |||
| 3857 | status = decode_attr_mounted_on_fileid(xdr, bitmap, &fileid); | 3902 | status = decode_attr_mounted_on_fileid(xdr, bitmap, &fileid); |
| 3858 | if (status < 0) | 3903 | if (status < 0) |
| 3859 | goto xdr_error; | 3904 | goto xdr_error; |
| 3860 | if (status != 0 && !(fattr->valid & status)) { | 3905 | if (status != 0) { |
| 3861 | fattr->fileid = fileid; | 3906 | fattr->fileid = fileid; |
| 3862 | fattr->valid |= status; | 3907 | fattr->valid |= status; |
| 3863 | } | 3908 | } |
| 3864 | 3909 | ||
| 3910 | xdr_error: | ||
| 3911 | dprintk("%s: xdr returned %d\n", __func__, -status); | ||
| 3912 | return status; | ||
| 3913 | } | ||
| 3914 | |||
| 3915 | static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, | ||
| 3916 | struct nfs_fh *fh, const struct nfs_server *server, int may_sleep) | ||
| 3917 | { | ||
| 3918 | __be32 *savep; | ||
| 3919 | uint32_t attrlen, | ||
| 3920 | bitmap[2] = {0}; | ||
| 3921 | int status; | ||
| 3922 | |||
| 3923 | status = decode_op_hdr(xdr, OP_GETATTR); | ||
| 3924 | if (status < 0) | ||
| 3925 | goto xdr_error; | ||
| 3926 | |||
| 3927 | status = decode_attr_bitmap(xdr, bitmap); | ||
| 3928 | if (status < 0) | ||
| 3929 | goto xdr_error; | ||
| 3930 | |||
| 3931 | status = decode_attr_length(xdr, &attrlen, &savep); | ||
| 3932 | if (status < 0) | ||
| 3933 | goto xdr_error; | ||
| 3934 | |||
| 3935 | status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server, may_sleep); | ||
| 3936 | if (status < 0) | ||
| 3937 | goto xdr_error; | ||
| 3938 | |||
| 3865 | status = verify_attr_len(xdr, savep, attrlen); | 3939 | status = verify_attr_len(xdr, savep, attrlen); |
| 3866 | xdr_error: | 3940 | xdr_error: |
| 3867 | dprintk("%s: xdr returned %d\n", __func__, -status); | 3941 | dprintk("%s: xdr returned %d\n", __func__, -status); |
| 3868 | return status; | 3942 | return status; |
| 3869 | } | 3943 | } |
| 3870 | 3944 | ||
| 3945 | static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, | ||
| 3946 | const struct nfs_server *server, int may_sleep) | ||
| 3947 | { | ||
| 3948 | return decode_getfattr_generic(xdr, fattr, NULL, server, may_sleep); | ||
| 3949 | } | ||
| 3871 | 3950 | ||
| 3872 | static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) | 3951 | static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) |
| 3873 | { | 3952 | { |
