diff options
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
| -rw-r--r-- | fs/nfs/nfs4xdr.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index bd2101d918c8..8b4dfa393f0f 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
| @@ -3978,6 +3978,61 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, | |||
| 3978 | return decode_getfattr_generic(xdr, fattr, NULL, server, may_sleep); | 3978 | return decode_getfattr_generic(xdr, fattr, NULL, server, may_sleep); |
| 3979 | } | 3979 | } |
| 3980 | 3980 | ||
| 3981 | /* | ||
| 3982 | * Decode potentially multiple layout types. Currently we only support | ||
| 3983 | * one layout driver per file system. | ||
| 3984 | */ | ||
| 3985 | static int decode_first_pnfs_layout_type(struct xdr_stream *xdr, | ||
| 3986 | uint32_t *layouttype) | ||
| 3987 | { | ||
| 3988 | uint32_t *p; | ||
| 3989 | int num; | ||
| 3990 | |||
| 3991 | p = xdr_inline_decode(xdr, 4); | ||
| 3992 | if (unlikely(!p)) | ||
| 3993 | goto out_overflow; | ||
| 3994 | num = be32_to_cpup(p); | ||
| 3995 | |||
| 3996 | /* pNFS is not supported by the underlying file system */ | ||
| 3997 | if (num == 0) { | ||
| 3998 | *layouttype = 0; | ||
| 3999 | return 0; | ||
| 4000 | } | ||
| 4001 | if (num > 1) | ||
| 4002 | printk(KERN_INFO "%s: Warning: Multiple pNFS layout drivers " | ||
| 4003 | "per filesystem not supported\n", __func__); | ||
| 4004 | |||
| 4005 | /* Decode and set first layout type, move xdr->p past unused types */ | ||
| 4006 | p = xdr_inline_decode(xdr, num * 4); | ||
| 4007 | if (unlikely(!p)) | ||
| 4008 | goto out_overflow; | ||
| 4009 | *layouttype = be32_to_cpup(p); | ||
| 4010 | return 0; | ||
| 4011 | out_overflow: | ||
| 4012 | print_overflow_msg(__func__, xdr); | ||
| 4013 | return -EIO; | ||
| 4014 | } | ||
| 4015 | |||
| 4016 | /* | ||
| 4017 | * The type of file system exported. | ||
| 4018 | * Note we must ensure that layouttype is set in any non-error case. | ||
| 4019 | */ | ||
| 4020 | static int decode_attr_pnfstype(struct xdr_stream *xdr, uint32_t *bitmap, | ||
| 4021 | uint32_t *layouttype) | ||
| 4022 | { | ||
| 4023 | int status = 0; | ||
| 4024 | |||
| 4025 | dprintk("%s: bitmap is %x\n", __func__, bitmap[1]); | ||
| 4026 | if (unlikely(bitmap[1] & (FATTR4_WORD1_FS_LAYOUT_TYPES - 1U))) | ||
| 4027 | return -EIO; | ||
| 4028 | if (bitmap[1] & FATTR4_WORD1_FS_LAYOUT_TYPES) { | ||
| 4029 | status = decode_first_pnfs_layout_type(xdr, layouttype); | ||
| 4030 | bitmap[1] &= ~FATTR4_WORD1_FS_LAYOUT_TYPES; | ||
| 4031 | } else | ||
| 4032 | *layouttype = 0; | ||
| 4033 | return status; | ||
| 4034 | } | ||
| 4035 | |||
| 3981 | static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) | 4036 | static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) |
| 3982 | { | 4037 | { |
| 3983 | __be32 *savep; | 4038 | __be32 *savep; |
| @@ -4006,6 +4061,9 @@ static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) | |||
| 4006 | status = decode_attr_time_delta(xdr, bitmap, &fsinfo->time_delta); | 4061 | status = decode_attr_time_delta(xdr, bitmap, &fsinfo->time_delta); |
| 4007 | if (status != 0) | 4062 | if (status != 0) |
| 4008 | goto xdr_error; | 4063 | goto xdr_error; |
| 4064 | status = decode_attr_pnfstype(xdr, bitmap, &fsinfo->layouttype); | ||
| 4065 | if (status != 0) | ||
| 4066 | goto xdr_error; | ||
| 4009 | 4067 | ||
| 4010 | status = verify_attr_len(xdr, savep, attrlen); | 4068 | status = verify_attr_len(xdr, savep, attrlen); |
| 4011 | xdr_error: | 4069 | xdr_error: |
