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: |