summaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4xdr.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2018-03-20 17:03:10 -0400
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2018-04-10 16:06:22 -0400
commit36b3743fef88616f92b49949fe1022f345970258 (patch)
tree48763cb5e2b2d51926b5813187da7a819bed64a2 /fs/nfs/nfs4xdr.c
parent40a3426c75e1621ee6d88be2352f5dd85f557aed (diff)
NFSv4: Add a helper to encode/decode struct timespec
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r--fs/nfs/nfs4xdr.c45
1 files changed, 30 insertions, 15 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 3d088230c975..79f1774b9d68 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -99,6 +99,7 @@ static int nfs4_stat_to_errno(int);
99 ((3+NFS4_FHSIZE) >> 2)) 99 ((3+NFS4_FHSIZE) >> 2))
100#define nfs4_fattr_bitmap_maxsz 4 100#define nfs4_fattr_bitmap_maxsz 4
101#define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz) 101#define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
102#define nfstime4_maxsz (3)
102#define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2)) 103#define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2))
103#define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) 104#define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2))
104#define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) 105#define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
@@ -113,7 +114,8 @@ static int nfs4_stat_to_errno(int);
113#define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8) 114#define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8)
114/* This is based on getfattr, which uses the most attributes: */ 115/* This is based on getfattr, which uses the most attributes: */
115#define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ 116#define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \
116 3 + 3 + 3 + nfs4_owner_maxsz + \ 117 3*nfstime4_maxsz + \
118 nfs4_owner_maxsz + \
117 nfs4_group_maxsz + nfs4_label_maxsz + \ 119 nfs4_group_maxsz + nfs4_label_maxsz + \
118 decode_mdsthreshold_maxsz)) 120 decode_mdsthreshold_maxsz))
119#define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ 121#define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \
@@ -124,7 +126,8 @@ static int nfs4_stat_to_errno(int);
124 nfs4_owner_maxsz + \ 126 nfs4_owner_maxsz + \
125 nfs4_group_maxsz + \ 127 nfs4_group_maxsz + \
126 nfs4_label_maxsz + \ 128 nfs4_label_maxsz + \
127 4 + 4) 129 1 + nfstime4_maxsz + \
130 1 + nfstime4_maxsz)
128#define encode_savefh_maxsz (op_encode_hdr_maxsz) 131#define encode_savefh_maxsz (op_encode_hdr_maxsz)
129#define decode_savefh_maxsz (op_decode_hdr_maxsz) 132#define decode_savefh_maxsz (op_decode_hdr_maxsz)
130#define encode_restorefh_maxsz (op_encode_hdr_maxsz) 133#define encode_restorefh_maxsz (op_encode_hdr_maxsz)
@@ -1041,6 +1044,14 @@ static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *ve
1041 encode_opaque_fixed(xdr, verf->data, NFS4_VERIFIER_SIZE); 1044 encode_opaque_fixed(xdr, verf->data, NFS4_VERIFIER_SIZE);
1042} 1045}
1043 1046
1047static __be32 *
1048xdr_encode_nfstime4(__be32 *p, const struct timespec *t)
1049{
1050 p = xdr_encode_hyper(p, (__s64)t->tv_sec);
1051 *p++ = cpu_to_be32(t->tv_nsec);
1052 return p;
1053}
1054
1044static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, 1055static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
1045 const struct nfs4_label *label, 1056 const struct nfs4_label *label,
1046 const umode_t *umask, 1057 const umode_t *umask,
@@ -1100,7 +1111,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
1100 if (attrmask[1] & FATTR4_WORD1_TIME_ACCESS_SET) { 1111 if (attrmask[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
1101 if (iap->ia_valid & ATTR_ATIME_SET) { 1112 if (iap->ia_valid & ATTR_ATIME_SET) {
1102 bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET; 1113 bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
1103 len += 16; 1114 len += 4 + (nfstime4_maxsz << 2);
1104 } else if (iap->ia_valid & ATTR_ATIME) { 1115 } else if (iap->ia_valid & ATTR_ATIME) {
1105 bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET; 1116 bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
1106 len += 4; 1117 len += 4;
@@ -1109,7 +1120,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
1109 if (attrmask[1] & FATTR4_WORD1_TIME_MODIFY_SET) { 1120 if (attrmask[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
1110 if (iap->ia_valid & ATTR_MTIME_SET) { 1121 if (iap->ia_valid & ATTR_MTIME_SET) {
1111 bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET; 1122 bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
1112 len += 16; 1123 len += 4 + (nfstime4_maxsz << 2);
1113 } else if (iap->ia_valid & ATTR_MTIME) { 1124 } else if (iap->ia_valid & ATTR_MTIME) {
1114 bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET; 1125 bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
1115 len += 4; 1126 len += 4;
@@ -1135,16 +1146,14 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
1135 if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) { 1146 if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
1136 if (iap->ia_valid & ATTR_ATIME_SET) { 1147 if (iap->ia_valid & ATTR_ATIME_SET) {
1137 *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); 1148 *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
1138 p = xdr_encode_hyper(p, (s64)iap->ia_atime.tv_sec); 1149 p = xdr_encode_nfstime4(p, &iap->ia_atime);
1139 *p++ = cpu_to_be32(iap->ia_atime.tv_nsec);
1140 } else 1150 } else
1141 *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); 1151 *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
1142 } 1152 }
1143 if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) { 1153 if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
1144 if (iap->ia_valid & ATTR_MTIME_SET) { 1154 if (iap->ia_valid & ATTR_MTIME_SET) {
1145 *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); 1155 *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
1146 p = xdr_encode_hyper(p, (s64)iap->ia_mtime.tv_sec); 1156 p = xdr_encode_nfstime4(p, &iap->ia_mtime);
1147 *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
1148 } else 1157 } else
1149 *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); 1158 *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
1150 } 1159 }
@@ -4129,19 +4138,25 @@ out_overflow:
4129 return -EIO; 4138 return -EIO;
4130} 4139}
4131 4140
4141static __be32 *
4142xdr_decode_nfstime4(__be32 *p, struct timespec *t)
4143{
4144 __u64 sec;
4145
4146 p = xdr_decode_hyper(p, &sec);
4147 t-> tv_sec = (time_t)sec;
4148 t->tv_nsec = be32_to_cpup(p++);
4149 return p;
4150}
4151
4132static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time) 4152static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time)
4133{ 4153{
4134 __be32 *p; 4154 __be32 *p;
4135 uint64_t sec;
4136 uint32_t nsec;
4137 4155
4138 p = xdr_inline_decode(xdr, 12); 4156 p = xdr_inline_decode(xdr, nfstime4_maxsz << 2);
4139 if (unlikely(!p)) 4157 if (unlikely(!p))
4140 goto out_overflow; 4158 goto out_overflow;
4141 p = xdr_decode_hyper(p, &sec); 4159 xdr_decode_nfstime4(p, time);
4142 nsec = be32_to_cpup(p);
4143 time->tv_sec = (time_t)sec;
4144 time->tv_nsec = (long)nsec;
4145 return 0; 4160 return 0;
4146out_overflow: 4161out_overflow:
4147 print_overflow_msg(__func__, xdr); 4162 print_overflow_msg(__func__, xdr);