aboutsummaryrefslogtreecommitdiff
path: root/fs/nfsd/nfs4xdr.c
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <[email protected]>2018-09-26 15:54:31 +0200
committerBartlomiej Zolnierkiewicz <[email protected]>2018-09-26 15:54:31 +0200
commitaaccf3c97418f169afdbb5855e9cbcbda34e90fd (patch)
tree5d4207e67958bdbc23288cf30178692f5534e1a0 /fs/nfsd/nfs4xdr.c
parentf39684524b391c5a7ed0ac44db4fec3357af1c5d (diff)
parent6bf4ca7fbc85d80446ac01c0d1d77db4d91a6d84 (diff)
Merge tag 'v4.19-rc5' of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux into fbdev-for-next
Sync with upstream (which now contains fbdev-v4.19 changes) to prepare a base for fbdev-v4.20 changes.
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r--fs/nfsd/nfs4xdr.c43
1 files changed, 37 insertions, 6 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index a96843c59fc1..418fa9c78186 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1390,10 +1390,8 @@ nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
p += XDR_QUADLEN(dummy);
}
- /* ssp_window and ssp_num_gss_handles */
+ /* ignore ssp_window and ssp_num_gss_handles: */
READ_BUF(8);
- dummy = be32_to_cpup(p++);
- dummy = be32_to_cpup(p++);
break;
default:
goto xdr_error;
@@ -2006,6 +2004,31 @@ static __be32 *encode_change(__be32 *p, struct kstat *stat, struct inode *inode,
return p;
}
+/*
+ * ctime (in NFSv4, time_metadata) is not writeable, and the client
+ * doesn't really care what resolution could theoretically be stored by
+ * the filesystem.
+ *
+ * The client cares how close together changes can be while still
+ * guaranteeing ctime changes. For most filesystems (which have
+ * timestamps with nanosecond fields) that is limited by the resolution
+ * of the time returned from current_time() (which I'm assuming to be
+ * 1/HZ).
+ */
+static __be32 *encode_time_delta(__be32 *p, struct inode *inode)
+{
+ struct timespec ts;
+ u32 ns;
+
+ ns = max_t(u32, NSEC_PER_SEC/HZ, inode->i_sb->s_time_gran);
+ ts = ns_to_timespec(ns);
+
+ p = xdr_encode_hyper(p, ts.tv_sec);
+ *p++ = cpu_to_be32(ts.tv_nsec);
+
+ return p;
+}
+
static __be32 *encode_cinfo(__be32 *p, struct nfsd4_change_info *c)
{
*p++ = cpu_to_be32(c->atomic);
@@ -2797,9 +2820,7 @@ out_acl:
p = xdr_reserve_space(xdr, 12);
if (!p)
goto out_resource;
- *p++ = cpu_to_be32(0);
- *p++ = cpu_to_be32(1);
- *p++ = cpu_to_be32(0);
+ p = encode_time_delta(p, d_inode(dentry));
}
if (bmval1 & FATTR4_WORD1_TIME_METADATA) {
p = xdr_reserve_space(xdr, 12);
@@ -2868,6 +2889,16 @@ out_acl:
goto out;
}
+ if (bmval2 & FATTR4_WORD2_CHANGE_ATTR_TYPE) {
+ p = xdr_reserve_space(xdr, 4);
+ if (!p)
+ goto out_resource;
+ if (IS_I_VERSION(d_inode(dentry)))
+ *p++ = cpu_to_be32(NFS4_CHANGE_TYPE_IS_MONOTONIC_INCR);
+ else
+ *p++ = cpu_to_be32(NFS4_CHANGE_TYPE_IS_TIME_METADATA);
+ }
+
if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
status = nfsd4_encode_security_label(xdr, rqstp, context,
contextlen);