aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4xdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r--fs/nfs/nfs4xdr.c58
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 */
3985static 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;
4011out_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 */
4020static 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
3981static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) 4036static 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);
4011xdr_error: 4069xdr_error: