+ * NFS vnode attribute structure
+ */
+#define NFSTIME_ACCESS 0 /* time of last access */
+#define NFSTIME_MODIFY 1 /* time of last modification */
+#define NFSTIME_CHANGE 2 /* time file changed */
+#define NFSTIME_CREATE 3 /* time file created */
+#define NFSTIME_BACKUP 4 /* time of last backup */
+#define NFSTIME_COUNT 5
+
+#define NFS_COMPARE_MTIME(TVP, NVAP, CMP) \
+ (((TVP)->tv_sec == (NVAP)->nva_timesec[NFSTIME_MODIFY]) ? \
+ ((TVP)->tv_nsec CMP (NVAP)->nva_timensec[NFSTIME_MODIFY]) : \
+ ((TVP)->tv_sec CMP (NVAP)->nva_timesec[NFSTIME_MODIFY]))
+#define NFS_COPY_TIME(TVP, NVAP, WHICH) \
+ do { \
+ (TVP)->tv_sec = (NVAP)->nva_timesec[NFSTIME_##WHICH]; \
+ (TVP)->tv_nsec = (NVAP)->nva_timensec[NFSTIME_##WHICH]; \
+ } while (0)
+
+struct nfs_vattr {
+ enum vtype nva_type; /* vnode type (for create) */
+ uint32_t nva_mode; /* files access mode (and type) */
+ uid_t nva_uid; /* owner user id */
+ gid_t nva_gid; /* owner group id */
+ nfs_specdata nva_rawdev; /* device the special file represents */
+ uint32_t nva_flags; /* file flags */
+ uint32_t nva_maxlink; /* maximum # of links (v4) */
+ uint64_t nva_nlink; /* number of references to file */
+ uint64_t nva_fileid; /* file id */
+ nfs_fsid nva_fsid; /* file system id */
+ uint64_t nva_size; /* file size in bytes */
+ uint64_t nva_bytes; /* bytes of disk space held by file */
+ uint64_t nva_change; /* change attribute */
+ int64_t nva_timesec[NFSTIME_COUNT];
+ int32_t nva_timensec[NFSTIME_COUNT];
+ uint32_t nva_bitmap[NFS_ATTR_BITMAP_LEN]; /* attributes that are valid */
+};
+
+#define NFS_FFLAG_ARCHIVED 0x0001
+#define NFS_FFLAG_HIDDEN 0x0002
+#define NFS_FFLAG_NAMED_ATTR 0x0004 /* file has named attributes */
+
+/*
+ * macros for detecting node changes
+ *
+ * These macros help us determine if a file has been changed on the server and
+ * thus whether or not we need to invalidate any cached data.
+ *
+ * For NFSv2/v3, the modification time is used.
+ * For NFSv4, the change attribute is used.
+ */
+#define NFS_CHANGED(VERS, NP, NVAP) \
+ (((VERS) >= NFS_VER4) ? \
+ ((NP)->n_change != (NVAP)->nva_change) : \
+ NFS_COMPARE_MTIME(&(NP)->n_mtime, (NVAP), !=))
+#define NFS_CHANGED_NC(VERS, NP, NVAP) \
+ (((VERS) >= NFS_VER4) ? \
+ ((NP)->n_ncchange != (NVAP)->nva_change) : \
+ NFS_COMPARE_MTIME(&(NP)->n_ncmtime, (NVAP), !=))
+#define NFS_CHANGED_UPDATE(VERS, NP, NVAP) \
+ do { \
+ if ((VERS) >= NFS_VER4) \
+ (NP)->n_change = (NVAP)->nva_change; \
+ else \
+ NFS_COPY_TIME(&(NP)->n_mtime, (NVAP), MODIFY); \
+ } while (0)
+#define NFS_CHANGED_UPDATE_NC(VERS, NP, NVAP) \
+ do { \
+ if ((VERS) >= NFS_VER4) \
+ (NP)->n_ncchange = (NVAP)->nva_change; \
+ else \
+ NFS_COPY_TIME(&(NP)->n_ncmtime, (NVAP), MODIFY); \
+ } while (0)
+
+/*
+ * The nfsnode is the NFS equivalent of an inode.
+ * There is a unique nfsnode for each NFS vnode.