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 /fs/nfs | |
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>
Diffstat (limited to 'fs/nfs')
-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 | { |