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>
This commit is contained in:
Trond Myklebust 2018-03-20 17:03:10 -04:00 committed by Anna Schumaker
parent 40a3426c75
commit 36b3743fef
1 changed files with 30 additions and 15 deletions

View File

@ -99,6 +99,7 @@ static int nfs4_stat_to_errno(int);
((3+NFS4_FHSIZE) >> 2)) ((3+NFS4_FHSIZE) >> 2))
#define nfs4_fattr_bitmap_maxsz 4 #define nfs4_fattr_bitmap_maxsz 4
#define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz) #define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
#define nfstime4_maxsz (3)
#define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2)) #define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2))
#define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2))
#define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
@ -113,7 +114,8 @@ static int nfs4_stat_to_errno(int);
#define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8) #define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8)
/* This is based on getfattr, which uses the most attributes: */ /* This is based on getfattr, which uses the most attributes: */
#define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \
3 + 3 + 3 + nfs4_owner_maxsz + \ 3*nfstime4_maxsz + \
nfs4_owner_maxsz + \
nfs4_group_maxsz + nfs4_label_maxsz + \ nfs4_group_maxsz + nfs4_label_maxsz + \
decode_mdsthreshold_maxsz)) decode_mdsthreshold_maxsz))
#define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \
@ -124,7 +126,8 @@ static int nfs4_stat_to_errno(int);
nfs4_owner_maxsz + \ nfs4_owner_maxsz + \
nfs4_group_maxsz + \ nfs4_group_maxsz + \
nfs4_label_maxsz + \ nfs4_label_maxsz + \
4 + 4) 1 + nfstime4_maxsz + \
1 + nfstime4_maxsz)
#define encode_savefh_maxsz (op_encode_hdr_maxsz) #define encode_savefh_maxsz (op_encode_hdr_maxsz)
#define decode_savefh_maxsz (op_decode_hdr_maxsz) #define decode_savefh_maxsz (op_decode_hdr_maxsz)
#define encode_restorefh_maxsz (op_encode_hdr_maxsz) #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
encode_opaque_fixed(xdr, verf->data, NFS4_VERIFIER_SIZE); encode_opaque_fixed(xdr, verf->data, NFS4_VERIFIER_SIZE);
} }
static __be32 *
xdr_encode_nfstime4(__be32 *p, const struct timespec *t)
{
p = xdr_encode_hyper(p, (__s64)t->tv_sec);
*p++ = cpu_to_be32(t->tv_nsec);
return p;
}
static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
const struct nfs4_label *label, const struct nfs4_label *label,
const umode_t *umask, const umode_t *umask,
@ -1100,7 +1111,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
if (attrmask[1] & FATTR4_WORD1_TIME_ACCESS_SET) { if (attrmask[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
if (iap->ia_valid & ATTR_ATIME_SET) { if (iap->ia_valid & ATTR_ATIME_SET) {
bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET; bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
len += 16; len += 4 + (nfstime4_maxsz << 2);
} else if (iap->ia_valid & ATTR_ATIME) { } else if (iap->ia_valid & ATTR_ATIME) {
bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET; bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
len += 4; len += 4;
@ -1109,7 +1120,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
if (attrmask[1] & FATTR4_WORD1_TIME_MODIFY_SET) { if (attrmask[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
if (iap->ia_valid & ATTR_MTIME_SET) { if (iap->ia_valid & ATTR_MTIME_SET) {
bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET; bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
len += 16; len += 4 + (nfstime4_maxsz << 2);
} else if (iap->ia_valid & ATTR_MTIME) { } else if (iap->ia_valid & ATTR_MTIME) {
bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET; bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
len += 4; len += 4;
@ -1135,16 +1146,14 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) { if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
if (iap->ia_valid & ATTR_ATIME_SET) { if (iap->ia_valid & ATTR_ATIME_SET) {
*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
p = xdr_encode_hyper(p, (s64)iap->ia_atime.tv_sec); p = xdr_encode_nfstime4(p, &iap->ia_atime);
*p++ = cpu_to_be32(iap->ia_atime.tv_nsec);
} else } else
*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
} }
if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) { if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
if (iap->ia_valid & ATTR_MTIME_SET) { if (iap->ia_valid & ATTR_MTIME_SET) {
*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
p = xdr_encode_hyper(p, (s64)iap->ia_mtime.tv_sec); p = xdr_encode_nfstime4(p, &iap->ia_mtime);
*p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
} else } else
*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
} }
@ -4129,19 +4138,25 @@ out_overflow:
return -EIO; return -EIO;
} }
static __be32 *
xdr_decode_nfstime4(__be32 *p, struct timespec *t)
{
__u64 sec;
p = xdr_decode_hyper(p, &sec);
t-> tv_sec = (time_t)sec;
t->tv_nsec = be32_to_cpup(p++);
return p;
}
static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time) static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time)
{ {
__be32 *p; __be32 *p;
uint64_t sec;
uint32_t nsec;
p = xdr_inline_decode(xdr, 12); p = xdr_inline_decode(xdr, nfstime4_maxsz << 2);
if (unlikely(!p)) if (unlikely(!p))
goto out_overflow; goto out_overflow;
p = xdr_decode_hyper(p, &sec); xdr_decode_nfstime4(p, time);
nsec = be32_to_cpup(p);
time->tv_sec = (time_t)sec;
time->tv_nsec = (long)nsec;
return 0; return 0;
out_overflow: out_overflow:
print_overflow_msg(__func__, xdr); print_overflow_msg(__func__, xdr);