diff mbox series

[5/8] nfs: Add 'time backup' to nfs inode

Message ID 20211217204854.439578-6-trondmy@kernel.org (mailing list archive)
State New, archived
Headers show
Series Support btime and other NFSv4 specific attributes | expand

Commit Message

Trond Myklebust Dec. 17, 2021, 8:48 p.m. UTC
From: Anne Marie Merritt <annemarie.merritt@primarydata.com>

Add tracking of the NFSv4 'time backup' attribute, along with
corresponding bitfields, request, and decode xdr routines.

Signed-off-by: Anne Marie Merritt <annemarie.merritt@primarydata.com>
Signed-off-by: Lance Shelton <lance.shelton@hammerspace.com>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
---
 fs/nfs/inode.c          | 11 +++++++++++
 fs/nfs/nfs4proc.c       |  8 ++++++--
 fs/nfs/nfs4trace.h      |  3 ++-
 fs/nfs/nfs4xdr.c        | 24 ++++++++++++++++++++++++
 include/linux/nfs_fs.h  |  1 +
 include/linux/nfs_xdr.h |  3 +++
 6 files changed, 47 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 9f138dc1880d..4673b091ea31 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -524,6 +524,7 @@  nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
 		memset(&inode->i_mtime, 0, sizeof(inode->i_mtime));
 		memset(&inode->i_ctime, 0, sizeof(inode->i_ctime));
 		memset(&nfsi->btime, 0, sizeof(nfsi->btime));
+		memset(&nfsi->timebackup, 0, sizeof(nfsi->timebackup));
 		nfsi->archive = 0;
 		nfsi->hidden = 0;
 		nfsi->system = 0;
@@ -554,6 +555,10 @@  nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
 			nfsi->btime = fattr->btime;
 		else if (fattr_supported & NFS_ATTR_FATTR_BTIME)
 			nfs_set_cache_invalid(inode, NFS_INO_INVALID_BTIME);
+		if (fattr->valid & NFS_ATTR_FATTR_TIME_BACKUP)
+			nfsi->timebackup = fattr->time_backup;
+		else if (fattr_supported & NFS_ATTR_FATTR_TIME_BACKUP)
+			nfs_set_cache_invalid(inode, NFS_INO_INVALID_WINATTR);
 		if (fattr->valid & NFS_ATTR_FATTR_ARCHIVE)
 			nfsi->archive = (fattr->hsa_flags & NFS_HSA_ARCHIVE) ? 1 : 0;
 		else if (fattr_supported & NFS_ATTR_FATTR_ARCHIVE)
@@ -2161,6 +2166,12 @@  static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 		nfsi->cache_validity |=
 			save_cache_validity & NFS_INO_INVALID_BTIME;
 
+	if (fattr->valid & NFS_ATTR_FATTR_TIME_BACKUP)
+		nfsi->timebackup = fattr->time_backup;
+	else if (fattr_supported & NFS_ATTR_FATTR_TIME_BACKUP)
+		nfsi->cache_validity |=
+			save_cache_validity & NFS_INO_INVALID_WINATTR;
+
 	if (fattr->valid & NFS_ATTR_FATTR_ARCHIVE)
 		nfsi->archive = (fattr->hsa_flags & NFS_HSA_ARCHIVE) ? 1 : 0;
 	else if (fattr_supported & NFS_ATTR_FATTR_ARCHIVE)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 06df71f6371b..d3a528a4c9b7 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -210,6 +210,7 @@  const u32 nfs4_fattr_bitmap[3] = {
 	| FATTR4_WORD1_SPACE_USED
 	| FATTR4_WORD1_SYSTEM
 	| FATTR4_WORD1_TIME_ACCESS
+	| FATTR4_WORD1_TIME_BACKUP
 	| FATTR4_WORD1_TIME_CREATE
 	| FATTR4_WORD1_TIME_METADATA
 	| FATTR4_WORD1_TIME_MODIFY
@@ -235,6 +236,7 @@  static const u32 nfs4_pnfs_open_bitmap[3] = {
 	| FATTR4_WORD1_SPACE_USED
 	| FATTR4_WORD1_SYSTEM
 	| FATTR4_WORD1_TIME_ACCESS
+	| FATTR4_WORD1_TIME_BACKUP
 	| FATTR4_WORD1_TIME_CREATE
 	| FATTR4_WORD1_TIME_METADATA
 	| FATTR4_WORD1_TIME_MODIFY,
@@ -321,7 +323,7 @@  static void nfs4_bitmap_copy_adjust(__u32 *dst, const __u32 *src,
 
 	if (!(cache_validity & NFS_INO_INVALID_WINATTR)) {
 		dst[0] &= ~(FATTR4_WORD0_ARCHIVE | FATTR4_WORD0_HIDDEN);
-		dst[1] &= ~FATTR4_WORD1_SYSTEM;
+		dst[1] &= ~(FATTR4_WORD1_SYSTEM | FATTR4_WORD1_TIME_BACKUP);
 	}
 }
 
@@ -3916,6 +3918,8 @@  static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
 			server->fattr_valid &= ~NFS_ATTR_FATTR_MTIME;
 		if (!(res.attr_bitmask[1] & FATTR4_WORD1_TIME_MODIFY))
 			server->fattr_valid &= ~NFS_ATTR_FATTR_MTIME;
+		if (!(res.attr_bitmask[1] & FATTR4_WORD1_TIME_BACKUP))
+			server->fattr_valid &= ~NFS_ATTR_FATTR_TIME_BACKUP;
 		if (!(res.attr_bitmask[1] & FATTR4_WORD1_TIME_CREATE))
 			server->fattr_valid &= ~NFS_ATTR_FATTR_BTIME;
 		if (!(res.attr_bitmask[1] & FATTR4_WORD1_SYSTEM))
@@ -5479,7 +5483,7 @@  static void nfs4_bitmask_set(__u32 bitmask[NFS4_BITMASK_SZ], const __u32 *src,
 		bitmask[1] |= FATTR4_WORD1_TIME_CREATE;
 	if (cache_validity & NFS_INO_INVALID_WINATTR) {
 		bitmask[0] |= FATTR4_WORD0_ARCHIVE | FATTR4_WORD0_HIDDEN;
-		bitmask[1] |= FATTR4_WORD1_SYSTEM;
+		bitmask[1] |= FATTR4_WORD1_SYSTEM | FATTR4_WORD1_TIME_BACKUP;
 	}
 
 	if (cache_validity & NFS_INO_INVALID_SIZE)
diff --git a/fs/nfs/nfs4trace.h b/fs/nfs/nfs4trace.h
index babcd3207e8f..5e72639b469e 100644
--- a/fs/nfs/nfs4trace.h
+++ b/fs/nfs/nfs4trace.h
@@ -34,7 +34,8 @@ 
 		{ NFS_ATTR_FATTR_BTIME, "BTIME" }, \
 		{ NFS_ATTR_FATTR_HIDDEN, "HIDDEN" }, \
 		{ NFS_ATTR_FATTR_SYSTEM, "SYSTEM" }, \
-		{ NFS_ATTR_FATTR_ARCHIVE, "ARCHIVE" })
+		{ NFS_ATTR_FATTR_ARCHIVE, "ARCHIVE" }, \
+		{ NFS_ATTR_FATTR_TIME_BACKUP, "TIME_BACKUP" })
 
 DECLARE_EVENT_CLASS(nfs4_clientid_event,
 		TP_PROTO(
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index ca3f1bcd321c..68885ba5fc58 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1619,6 +1619,7 @@  static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
 			    FATTR4_WORD1_OWNER| FATTR4_WORD1_OWNER_GROUP |
 			    FATTR4_WORD1_RAWDEV | FATTR4_WORD1_SPACE_USED |
 			    FATTR4_WORD1_SYSTEM | FATTR4_WORD1_TIME_ACCESS |
+			    FATTR4_WORD1_TIME_BACKUP |
 			    FATTR4_WORD1_TIME_CREATE |
 			    FATTR4_WORD1_TIME_METADATA |
 			    FATTR4_WORD1_TIME_MODIFY;
@@ -4192,6 +4193,24 @@  static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, str
 	return status;
 }
 
+static int decode_attr_time_backup(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec64 *time)
+{
+	int status = 0;
+
+	time->tv_sec = 0;
+	time->tv_nsec = 0;
+	if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_BACKUP - 1U)))
+		return -EIO;
+	if (likely(bitmap[1] & FATTR4_WORD1_TIME_BACKUP)) {
+		status = decode_attr_time(xdr, time);
+		if (status == 0)
+			status = NFS_ATTR_FATTR_TIME_BACKUP;
+		bitmap[1] &= ~FATTR4_WORD1_TIME_BACKUP;
+	}
+	dprintk("%s: time_backup=%ld\n", __func__, (long)time->tv_sec);
+	return status;
+}
+
 static int decode_attr_time_create(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec64 *time)
 {
 	int status = 0;
@@ -4782,6 +4801,11 @@  static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
 		goto xdr_error;
 	fattr->valid |= status;
 
+	status = decode_attr_time_backup(xdr, bitmap, &fattr->time_backup);
+	if (status < 0)
+		goto xdr_error;
+	fattr->valid |= status;
+
 	status = decode_attr_time_create(xdr, bitmap, &fattr->btime);
 	if (status < 0)
 		goto xdr_error;
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 337a3a17dbaf..5f1dbd7a7b69 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -141,6 +141,7 @@  struct nfs_inode {
 	 */
 
 	struct timespec64	btime;
+	struct timespec64	timebackup;
 
 	unsigned char		archive : 1;
 	unsigned char		hidden : 1;
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 8563162fd7e1..69c19f465571 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -73,6 +73,7 @@  struct nfs_fattr {
 	struct timespec64	mtime;
 	struct timespec64	ctime;
 	struct timespec64	btime;
+	struct timespec64	time_backup;
 	__u32			hsa_flags;	/* hidden, system, archive flags bitfield */
 	__u64			change_attr;	/* NFSv4 change attribute */
 	__u64			pre_change_attr;/* pre-op NFSv4 change attribute */
@@ -117,6 +118,7 @@  struct nfs_fattr {
 #define NFS_ATTR_FATTR_HIDDEN           BIT_ULL(27)
 #define NFS_ATTR_FATTR_SYSTEM           BIT_ULL(28)
 #define NFS_ATTR_FATTR_ARCHIVE          BIT_ULL(29)
+#define NFS_ATTR_FATTR_TIME_BACKUP      BIT_ULL(30)
 
 #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \
 		| NFS_ATTR_FATTR_MODE \
@@ -141,6 +143,7 @@  struct nfs_fattr {
 		| NFS_ATTR_FATTR_HIDDEN \
 		| NFS_ATTR_FATTR_SYSTEM \
 		| NFS_ATTR_FATTR_ARCHIVE \
+		| NFS_ATTR_FATTR_TIME_BACKUP \
 		| NFS_ATTR_FATTR_V4_SECURITY_LABEL)
 
 /*