diff options
| -rw-r--r-- | fs/nfs/nfs4proc.c | 1 | ||||
| -rw-r--r-- | fs/nfs/nfs4xdr.c | 58 | ||||
| -rw-r--r-- | include/linux/nfs_xdr.h | 1 |
3 files changed, 60 insertions, 0 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index e87fe612ca18..a5f1edb45b47 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -130,6 +130,7 @@ const u32 nfs4_fsinfo_bitmap[2] = { FATTR4_WORD0_MAXFILESIZE | |||
| 130 | | FATTR4_WORD0_MAXWRITE | 130 | | FATTR4_WORD0_MAXWRITE |
| 131 | | FATTR4_WORD0_LEASE_TIME, | 131 | | FATTR4_WORD0_LEASE_TIME, |
| 132 | FATTR4_WORD1_TIME_DELTA | 132 | FATTR4_WORD1_TIME_DELTA |
| 133 | | FATTR4_WORD1_FS_LAYOUT_TYPES | ||
| 133 | }; | 134 | }; |
| 134 | 135 | ||
| 135 | const u32 nfs4_fs_locations_bitmap[2] = { | 136 | const u32 nfs4_fs_locations_bitmap[2] = { |
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: |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index da7a1300dc60..065f9d105d05 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
| @@ -114,6 +114,7 @@ struct nfs_fsinfo { | |||
| 114 | __u64 maxfilesize; | 114 | __u64 maxfilesize; |
| 115 | struct timespec time_delta; /* server time granularity */ | 115 | struct timespec time_delta; /* server time granularity */ |
| 116 | __u32 lease_time; /* in seconds */ | 116 | __u32 lease_time; /* in seconds */ |
| 117 | __u32 layouttype; /* supported pnfs layout driver */ | ||
| 117 | }; | 118 | }; |
| 118 | 119 | ||
| 119 | struct nfs_fsstat { | 120 | struct nfs_fsstat { |
