Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 36b3743f authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker
Browse files

NFSv4: Add a helper to encode/decode struct timespec

parent 40a3426c
Loading
Loading
Loading
Loading
+30 −15
Original line number Diff line number Diff line
@@ -99,6 +99,7 @@ static int nfs4_stat_to_errno(int);
				((3+NFS4_FHSIZE) >> 2))
#define nfs4_fattr_bitmap_maxsz 4
#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_path_maxsz		(1 + ((3 + NFS4_MAXPATHLEN) >> 2))
#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)
/* 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 + \
				3 + 3 + 3 + nfs4_owner_maxsz + \
				3*nfstime4_maxsz + \
				nfs4_owner_maxsz + \
				nfs4_group_maxsz + nfs4_label_maxsz + \
				 decode_mdsthreshold_maxsz))
#define nfs4_fattr_maxsz	(nfs4_fattr_bitmap_maxsz + \
@@ -124,7 +126,8 @@ static int nfs4_stat_to_errno(int);
				nfs4_owner_maxsz + \
				nfs4_group_maxsz + \
				nfs4_label_maxsz + \
				4 + 4)
				1 + nfstime4_maxsz + \
				1 + nfstime4_maxsz)
#define encode_savefh_maxsz     (op_encode_hdr_maxsz)
#define decode_savefh_maxsz     (op_decode_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);
}

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,
				const struct nfs4_label *label,
				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 (iap->ia_valid & ATTR_ATIME_SET) {
			bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
			len += 16;
			len += 4 + (nfstime4_maxsz << 2);
		} else if (iap->ia_valid & ATTR_ATIME) {
			bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
			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 (iap->ia_valid & ATTR_MTIME_SET) {
			bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
			len += 16;
			len += 4 + (nfstime4_maxsz << 2);
		} else if (iap->ia_valid & ATTR_MTIME) {
			bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
			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 (iap->ia_valid & ATTR_ATIME_SET) {
			*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
			p = xdr_encode_hyper(p, (s64)iap->ia_atime.tv_sec);
			*p++ = cpu_to_be32(iap->ia_atime.tv_nsec);
			p = xdr_encode_nfstime4(p, &iap->ia_atime);
		} else
			*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
	}
	if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
		if (iap->ia_valid & ATTR_MTIME_SET) {
			*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
			p = xdr_encode_hyper(p, (s64)iap->ia_mtime.tv_sec);
			*p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
			p = xdr_encode_nfstime4(p, &iap->ia_mtime);
		} else
			*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
	}
@@ -4129,19 +4138,25 @@ static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint
	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)
{
	__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))
		goto out_overflow;
	p = xdr_decode_hyper(p, &sec);
	nsec = be32_to_cpup(p);
	time->tv_sec = (time_t)sec;
	time->tv_nsec = (long)nsec;
	xdr_decode_nfstime4(p, time);
	return 0;
out_overflow:
	print_overflow_msg(__func__, xdr);