From: Anne Marie Merritt <annemarie.merritt@xxxxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxx> Signed-off-by: Lance Shelton <lance.shelton@xxxxxxxxxxxxxxx> Signed-off-by: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx> --- 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 --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 99c7cf5944f8..4e6cc54016ba 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -211,6 +211,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 @@ -236,6 +237,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, @@ -322,7 +324,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)) @@ -5481,7 +5485,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 2131754e64f0..280df43c5bf2 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; @@ -4783,6 +4802,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 34288dcf8547..1839fed16b18 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -143,6 +143,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 308324d197f4..dedc7e0bf2b9 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) /* -- 2.33.1