]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/nfs/nfsnode.h
xnu-1228.15.4.tar.gz
[apple/xnu.git] / bsd / nfs / nfsnode.h
index cd3a8d080f6eeb4ec7edbaf0fb7eb7fc7e42d828..794841e72b8bb1a71963cf25798e0b46e5b855a1 100644 (file)
@@ -1,16 +1,19 @@
 /*
- * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ * 
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
  * 
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
@@ -20,7 +23,7 @@
  * Please see the License for the specific language governing rights and
  * limitations under the License.
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
 /*
 #ifndef _NFS_NFS_H_
 #include <nfs/nfs.h>
 #endif
-#include <sys/lock.h>
-
 
 /*
  * Silly rename structure that hangs off the nfsnode until the name
- * can be removed by nfs_inactive()
+ * can be removed by nfs_vnop_inactive()
  */
-struct sillyrename {
-       struct  ucred *s_cred;
-       struct  vnode *s_dvp;
-       long    s_namlen;
-       char    s_name[20];
+struct nfs_sillyrename {
+       kauth_cred_t    nsr_cred;
+       struct nfsnode  *nsr_dnp;
+       int             nsr_namlen;
+       char            nsr_name[20];
 };
 
 /*
@@ -103,124 +104,471 @@ struct nfsdmap {
 };
 
 /*
- * The nfsnode is the nfs equivalent to ufs's inode. Any similarity
- * is purely coincidental.
- * There is a unique nfsnode allocated for each active file,
- * each current directory, each mounted-on file, text file, and the root.
+ * The nfsbuf is the nfs equivalent to a struct buf.
+ */
+struct nfsbuf {
+       LIST_ENTRY(nfsbuf)      nb_hash;        /* hash chain */
+       LIST_ENTRY(nfsbuf)      nb_vnbufs;      /* nfsnode's nfsbuf chain */
+       TAILQ_ENTRY(nfsbuf)     nb_free;        /* free list position if not active. */
+       volatile long           nb_flags;       /* NB_* flags. */
+       volatile long           nb_lflags;      /* NBL_* flags. */
+       volatile long           nb_refs;        /* outstanding references. */
+       long                    nb_bufsize;     /* buffer size */
+       daddr64_t               nb_lblkno;      /* logical block number. */
+       uint64_t                nb_verf;        /* V3 write verifier */
+       int                     nb_commitlevel; /* lowest write commit level */
+       time_t                  nb_timestamp;   /* buffer timestamp */
+       int                     nb_error;       /* errno value. */
+       u_int32_t               nb_valid;       /* valid pages in buf */
+       u_int32_t               nb_dirty;       /* dirty pages in buf */
+       int                     nb_validoff;    /* offset in buffer of valid region. */
+       int                     nb_validend;    /* offset of end of valid region. */
+       int                     nb_dirtyoff;    /* offset in buffer of dirty region. */
+       int                     nb_dirtyend;    /* offset of end of dirty region. */
+       int                     nb_offio;       /* offset in buffer of I/O region. */
+       int                     nb_endio;       /* offset of end of I/O region. */
+       int                     nb_rpcs;        /* Count of RPCs remaining for this buffer. */
+       caddr_t                 nb_data;        /* mapped buffer */
+       nfsnode_t               nb_np;          /* nfsnode buffer belongs to */
+       kauth_cred_t            nb_rcred;       /* read credentials reference */
+       kauth_cred_t            nb_wcred;       /* write credentials reference */
+       void *                  nb_pagelist;    /* upl */
+};
+
+#define NFS_MAXBSIZE   (32 * PAGE_SIZE)        /* valid/dirty page masks limit buffer size */
+
+#define NFS_A_LOT_OF_NEEDCOMMITS       256                     /* max# uncommitted buffers for a node */
+#define NFS_A_LOT_OF_DELAYED_WRITES    MAX(nfsbufcnt/8,512)    /* max# "delwri" buffers in system */
+
+/*
+ * These flags are kept in b_lflags...
+ * nfs_buf_mutex must be held before examining/updating
+ */
+#define        NBL_BUSY        0x00000001      /* I/O in progress. */
+#define        NBL_WANTED      0x00000002      /* Process wants this buffer. */
+
+/*
+ * These flags are kept in nb_flags and they're (purposefully)
+ * very similar to the B_* flags for struct buf.
+ * nfs_buf_mutex is not needed to examine/update these.
+ */
+#define        NB_STALEWVERF   0x00000001      /* write verifier changed on us */
+#define        NB_NEEDCOMMIT   0x00000002      /* buffer needs to be committed */
+#define        NB_ASYNC        0x00000004      /* Start I/O, do not wait. */
+#define        NB_CACHE        0x00000020      /* buffer data found in the cache */
+#define        NB_STABLE       0x00000040      /* write FILESYNC not UNSTABLE */
+#define        NB_DELWRI       0x00000080      /* delayed write: dirty range needs to be written */
+#define        NB_DONE         0x00000200      /* I/O completed. */
+#define        NB_EINTR        0x00000400      /* I/O was interrupted */
+#define        NB_ERROR        0x00000800      /* I/O error occurred. */
+#define        NB_INVAL        0x00002000      /* Does not contain valid info. */
+#define        NB_NCRDAHEAD    0x00004000      /* "nocache readahead" data */
+#define        NB_NOCACHE      0x00008000      /* Do not cache block after use. */
+#define        NB_WRITE        0x00000000      /* Write buffer (pseudo flag). */
+#define        NB_READ         0x00100000      /* Read buffer. */
+#define        NB_MULTASYNCRPC 0x00200000      /* multiple async RPCs issued for buffer */
+#define        NB_PAGELIST     0x00400000      /* Buffer describes pagelist I/O. */
+#define        NB_WRITEINPROG  0x01000000      /* Write in progress. */
+#define        NB_META         0x40000000      /* buffer contains meta-data. */
+
+/* Flags for operation type in nfs_buf_get() */
+#define        NBLK_READ       0x00000001      /* buffer for read */
+#define        NBLK_WRITE      0x00000002      /* buffer for write */
+#define        NBLK_META       0x00000004      /* buffer for metadata */
+#define        NBLK_OPMASK     0x00000007      /* operation mask */
+/* modifiers for above flags... */
+#define NBLK_NOWAIT    0x40000000      /* don't wait on busy buffer */
+#define NBLK_ONLYVALID 0x80000000      /* only return cached buffer */
+
+/* These flags are used for nfsbuf iterating */
+#define NBI_ITER               0x01    /* iteration in progress */
+#define NBI_ITERWANT           0x02    /* waiting to iterate */
+#define NBI_CLEAN              0x04    /* requesting clean buffers */
+#define NBI_DIRTY              0x08    /* requesting dirty buffers */
+#define NBI_NOWAIT             0x10    /* don't block on NBI_ITER */
+
+/* Flags for nfs_buf_acquire */
+#define NBAC_NOWAIT            0x01    /* Don't wait if buffer is busy */
+#define NBAC_REMOVE            0x02    /* Remove from free list once buffer is acquired */
+
+/* some convenience macros...  */
+#define NBOFF(BP)                      ((off_t)(BP)->nb_lblkno * (off_t)(BP)->nb_bufsize)
+#define NBPGVALID(BP,P)                        (((BP)->nb_valid >> (P)) & 0x1)
+#define NBPGDIRTY(BP,P)                        (((BP)->nb_dirty >> (P)) & 0x1)
+#define NBPGVALID_SET(BP,P)            ((BP)->nb_valid |= (1 << (P)))
+#define NBPGDIRTY_SET(BP,P)            ((BP)->nb_dirty |= (1 << (P)))
+
+#define NBUFSTAMPVALID(BP)             ((BP)->nb_timestamp != ~0)
+#define NBUFSTAMPINVALIDATE(BP)                ((BP)->nb_timestamp = ~0)
+
+#define NFS_BUF_MAP(BP) \
+       do { \
+               if (!(BP)->nb_data && nfs_buf_map(BP)) \
+                       panic("nfs_buf_map failed"); \
+       } while (0)
+
+LIST_HEAD(nfsbuflists, nfsbuf);
+TAILQ_HEAD(nfsbuffreehead, nfsbuf);
+
+#define NFSNOLIST ((struct nfsbuf *)0xdeadbeef)
+
+__private_extern__ lck_mtx_t *nfs_buf_mutex;
+__private_extern__ int nfsbufcnt, nfsbufmin, nfsbufmax, nfsbufmetacnt, nfsbufmetamax;
+__private_extern__ int nfsbuffreecnt, nfsbuffreemetacnt, nfsbufdelwricnt, nfsneedbuffer;
+__private_extern__ int nfs_nbdwrite;
+__private_extern__ struct nfsbuffreehead nfsbuffree, nfsbufdelwri;
+
+#ifdef NFSBUFDEBUG
+#define NFSBUFCNTCHK() \
+       do { \
+       if (    (nfsbufcnt < 0) || \
+               (nfsbufcnt > nfsbufmax) || \
+               (nfsbufmetacnt < 0) || \
+               (nfsbufmetacnt > nfsbufmetamax) || \
+               (nfsbufmetacnt > nfsbufcnt) || \
+               (nfsbuffreecnt < 0) || \
+               (nfsbuffreecnt > nfsbufmax) || \
+               (nfsbuffreecnt > nfsbufcnt) || \
+               (nfsbuffreemetacnt < 0) || \
+               (nfsbuffreemetacnt > nfsbufmax) || \
+               (nfsbuffreemetacnt > nfsbufcnt) || \
+               (nfsbuffreemetacnt > nfsbufmetamax) || \
+               (nfsbuffreemetacnt > nfsbufmetacnt) || \
+               (nfsbufdelwricnt < 0) || \
+               (nfsbufdelwricnt > nfsbufmax) || \
+               (nfsbufdelwricnt > nfsbufcnt) || \
+               (nfs_nbdwrite < 0) || \
+               (nfs_nbdwrite > nfsbufcnt) || \
+               0) \
+               panic("nfsbuf count error: max %d meta %d cnt %d meta %d free %d meta %d delwr %d bdw %d\n", \
+                       nfsbufmax, nfsbufmetamax, nfsbufcnt, nfsbufmetacnt, nfsbuffreecnt, nfsbuffreemetacnt, \
+                       nfsbufdelwricnt, nfs_nbdwrite); \
+       } while (0)
+#else
+#define NFSBUFCNTCHK()
+#endif
+
+/*
+ * 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.
  * An nfsnode is 'named' by its file handle. (nget/nfs_node.c)
- * If this structure exceeds 256 bytes (it is currently 256 using 4.4BSD-Lite
- * type definitions), file handles of > 32 bytes should probably be split out
- * into a separate MALLOC()'d data structure. (Reduce the size of nfsfh_t by
- * changing the definition in sys/mount.h of NFS_SMALLFH.)
  * NB: Hopefully the current order of the fields is such that everything will
  *     be well aligned and, therefore, tightly packed.
  */
+
+#define NFS_ACCESS_CACHE_SIZE  3
+
 struct nfsnode {
-       struct lock__bsd__      n_lock; /* the vnode lock */
+       lck_rw_t                n_lock;         /* nfs node lock */
+       void                    *n_lockowner;   /* nfs node lock owner (exclusive) */
+       lck_rw_t                n_datalock;     /* nfs node data lock */
+       void                    *n_datalockowner;/* nfs node data lock owner (exclusive) */
        LIST_ENTRY(nfsnode)     n_hash;         /* Hash chain */
-       CIRCLEQ_ENTRY(nfsnode)  n_timer;        /* Nqnfs timer chain */
        u_quad_t                n_size;         /* Current size of file */
-       u_quad_t                n_brev;         /* Modify rev when cached */
-       u_quad_t                n_lrev;         /* Modify rev for lease */
-       struct vattr            n_vattr;        /* Vnode attribute cache */
+       u_quad_t                n_newsize;      /* new size of file (pending update) */
+       u_int64_t               n_xid;          /* last xid to loadattr */
+       struct nfs_vattr        n_vattr;        /* Vnode attribute cache */
        time_t                  n_attrstamp;    /* Attr. cache timestamp */
-        u_int32_t               n_mode;         /* ACCESS mode cache */
-        uid_t                   n_modeuid;      /* credentials having mode */
-        time_t                  n_modestamp;    /* mode cache timestamp */
-       time_t                  n_mtime;        /* Prev modify time. */
-       time_t                  n_ctime;        /* Prev create time. */
-       time_t                  n_expiry;       /* Lease expiry time */
-       nfsfh_t                 *n_fhp;         /* NFS File Handle */
-       struct vnode            *n_vnode;       /* associated vnode */
-       struct lockf            *n_lockf;       /* Locking record of file */
+       u_int8_t                n_mode[NFS_ACCESS_CACHE_SIZE+1];        /* ACCESS mode cache */
+       uid_t                   n_modeuid[NFS_ACCESS_CACHE_SIZE];       /* credentials having mode */
+       time_t                  n_modestamp[NFS_ACCESS_CACHE_SIZE];     /* mode cache timestamp */
+       union {
+           struct {
+               struct timespec n3_mtime;       /* Prev modify time. */
+               struct timespec n3_ncmtime;     /* namecache modify time. */
+           } v3;
+           struct {
+               uint64_t        n4_change;      /* prev change attribute */
+               uint64_t        n4_ncchange;    /* namecache change attribute */
+           } v4;
+       } n_un4;
+       vnode_t                 n_parent;       /* this node's parent */
+       u_char                  *n_fhp;         /* NFS File Handle */
+       vnode_t                 n_vnode;        /* associated vnode */
+       mount_t                 n_mount;        /* associated mount (NHINIT) */
        int                     n_error;        /* Save write error value */
        union {
                struct timespec nf_atim;        /* Special file times */
                nfsuint64       nd_cookieverf;  /* Cookie verifier (dir only) */
        } n_un1;
        union {
-               struct timespec nf_mtim;
+               struct timespec nf_mtim;        /* Special file times */
+               daddr64_t       nf_lastread;    /* last block# read from (for readahead) */
                off_t           nd_direof;      /* Dir. EOF offset cache */
        } n_un2;
        union {
-               struct sillyrename *nf_silly;   /* Ptr to silly rename struct */
+               struct nfs_sillyrename *nf_silly;/* Ptr to silly rename struct */
                LIST_HEAD(, nfsdmap) nd_cook;   /* cookies */
        } n_un3;
-       short                   n_fhsize;       /* size in bytes, of fh */
-       short                   n_flag;         /* Flag for locking.. */
-       nfsfh_t                 n_fh;           /* Small File Handle */
-       u_int64_t               n_xid;          /* last xid to loadattr */
+       u_short                 n_fhsize;       /* size in bytes, of fh */
+       u_short                 n_flag;         /* node flags */
+       u_short                 n_hflag;        /* node hash flags */
+       u_short                 n_bflag;        /* node buffer flags */
+       u_char                  n_fh[NFS_SMALLFH];/* Small File Handle */
+       struct nfsbuflists      n_cleanblkhd;   /* clean blocklist head */
+       struct nfsbuflists      n_dirtyblkhd;   /* dirty blocklist head */
+       int                     n_wrbusy;       /* # threads in write/fsync */
+       int                     n_needcommitcnt;/* # bufs that need committing */
+       int                     n_bufiterflags; /* buf iterator flags */
 };
 
-#define n_atim         n_un1.nf_atim
-#define n_mtim         n_un2.nf_mtim
-#define n_sillyrename  n_un3.nf_silly
-#define n_cookieverf   n_un1.nd_cookieverf
-#define n_direofoffset n_un2.nd_direof
-#define n_cookies      n_un3.nd_cook
+#define NFS_NODE_LOCK_SHARED   1
+#define NFS_NODE_LOCK_EXCLUSIVE        2
+#define NFS_NODE_LOCK_FORCE    3
+
+#define nfstimespeccmp(tvp, uvp, cmp)          \
+       (((tvp)->tv_sec == (uvp)->tv_sec) ?     \
+        ((tvp)->tv_nsec cmp (uvp)->tv_nsec) :  \
+        ((tvp)->tv_sec cmp (uvp)->tv_sec))
+
+#define CHECK_NEEDCOMMITCNT(np) \
+       do { \
+               if ((np)->n_needcommitcnt < 0) { \
+                       printf("nfs: n_needcommitcnt negative\n"); \
+                       (np)->n_needcommitcnt = 0; \
+               } \
+       } while (0)
+
+#define n_atim                 n_un1.nf_atim
+#define n_mtim                 n_un2.nf_mtim
+#define n_lastread             n_un2.nf_lastread
+#define n_sillyrename          n_un3.nf_silly
+#define n_cookieverf           n_un1.nd_cookieverf
+#define n_direofoffset         n_un2.nd_direof
+#define n_cookies              n_un3.nd_cook
+#define n_mtime                        n_un4.v3.n3_mtime
+#define n_ncmtime              n_un4.v3.n3_ncmtime
+#define n_change               n_un4.v4.n4_change
+#define n_ncchange             n_un4.v4.n4_ncchange
 
 /*
  * Flags for n_flag
  */
-#define        NFLUSHWANT      0x0001  /* Want wakeup from a flush in prog. */
-#define        NFLUSHINPROG    0x0002  /* Avoid multiple calls to vinvalbuf() */
+#define        NUPDATESIZE     0x0001  /* size of file needs updating */
 #define        NMODIFIED       0x0004  /* Might have a modified buffer in bio */
 #define        NWRITEERR       0x0008  /* Flag write errors so close will know */
-#define        NQNFSNONCACHE   0x0020  /* Non-cachable lease */
-#define        NQNFSWRITE      0x0040  /* Write lease */
-#define        NQNFSEVICTED    0x0080  /* Has been evicted */
+#define        NNEEDINVALIDATE 0x0010  /* need to call vinvalbuf() */
 #define        NACC            0x0100  /* Special file accessed */
 #define        NUPD            0x0200  /* Special file updated */
 #define        NCHG            0x0400  /* Special file times changed */
-#define NLOCKED                0x0800  /* node is locked */
-#define NWANTED                0x0100  /* someone wants to lock */
+#define        NNEGNCENTRIES   0x0800  /* directory has negative name cache entries */
+
+/*
+ * Flags for n_hflag
+ * Note: protected by nfs_node_hash_mutex
+ */
+#define NHHASHED       0x0001  /* node is in hash table */
+#define NHINIT         0x0002  /* node is being initialized */
+#define NHLOCKED       0x0004  /* node is locked (initting or deleting) */
+#define NHLOCKWANT     0x0008  /* someone wants to lock */
+
+/*
+ * Flags for n_bflag
+ * Note: protected by nfs_buf_mutex
+ */
+#define        NBFLUSHINPROG   0x0001  /* Avoid multiple calls to nfs_flush() */
+#define        NBFLUSHWANT     0x0002  /* waiting for nfs_flush() to complete */
+#define        NBINVALINPROG   0x0004  /* Avoid multiple calls to nfs_vinvalbuf() */
+#define        NBINVALWANT     0x0008  /* waiting for nfs_vinvalbuf() to complete */
+
+/* attr/mode timestamp macros */
+#define NATTRVALID(np)         ((np)->n_attrstamp != ~0)
+#define NATTRINVALIDATE(np)    ((np)->n_attrstamp = ~0)
+#define NMODEVALID(np, slot)   (((slot) >= 0) && ((slot) < 3) && ((np)->n_modestamp[(slot)] != ~0))
+#define NMODEINVALIDATE(np) \
+       do { \
+               (np)->n_modestamp[0] = ~0; \
+               (np)->n_modestamp[1] = ~0; \
+               (np)->n_modestamp[2] = ~0; \
+               (np)->n_mode[3] = 0; \
+       } while (0)
+
+/*
+ * NFS-specific flags for nfs_vinvalbuf/nfs_flush
+ */
+#define V_IGNORE_WRITEERR      0x8000
+
+/*
+ * Flags for nfs_nget()
+ */
+#define        NG_MARKROOT     0x0001  /* mark vnode as root of FS */
+#define        NG_MAKEENTRY    0x0002  /* add name cache entry for vnode */
 
 /*
  * Convert between nfsnode pointers and vnode pointers
  */
-#define VTONFS(vp)     ((struct nfsnode *)(vp)->v_data)
-#define NFSTOV(np)     ((struct vnode *)(np)->n_vnode)
+#define VTONFS(vp)     ((nfsnode_t)vnode_fsnode(vp))
+#define NFSTOV(np)     ((np)->n_vnode)
+
+/* nfsnode hash table mutex */
+__private_extern__ lck_mtx_t *nfs_node_hash_mutex;
 
 /*
- * Queue head for nfsiod's
+ * nfsiod structures
  */
-extern TAILQ_HEAD(nfs_bufq, buf) nfs_bufq;
-extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
-extern struct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON];
+struct nfsiod {
+       TAILQ_ENTRY(nfsiod)     niod_link;      /* List of nfsiods */
+       struct nfsmount *       niod_nmp;       /* mount point for this nfsiod */
+};
+TAILQ_HEAD(nfsiodlist, nfsiod);
+TAILQ_HEAD(nfsiodmountlist, nfsmount);
+__private_extern__ struct nfsiodlist nfsiodfree, nfsiodwork;
+__private_extern__ struct nfsiodmountlist nfsiodmounts;
+__private_extern__ lck_mtx_t *nfsiod_mutex;
 
 #if defined(KERNEL)
 
-typedef int     vop_t __P((void *));
-extern vop_t   **fifo_nfsv2nodeop_p;
-extern vop_t   **nfsv2_vnodeop_p;
-extern vop_t   **spec_nfsv2nodeop_p;
+typedef int     vnop_t(void *);
+extern vnop_t  **fifo_nfsv2nodeop_p;
+extern vnop_t  **nfsv2_vnodeop_p;
+extern vnop_t  **spec_nfsv2nodeop_p;
+extern vnop_t  **fifo_nfsv4nodeop_p;
+extern vnop_t  **nfsv4_vnodeop_p;
+extern vnop_t  **spec_nfsv4nodeop_p;
 
 /*
  * Prototypes for NFS vnode operations
  */
-int    nfs_write __P((struct vop_write_args *));
-#define        nfs_lease_check ((int (*) __P((struct  vop_lease_args *)))nullop)
-#define nqnfs_vop_lease_check  lease_check
-int    nqnfs_vop_lease_check __P((struct vop_lease_args *));
-#define nfs_revoke vop_revoke
-#define nfs_seek ((int (*) __P((struct  vop_seek_args *)))nullop)
-int    nfs_abortop __P((struct vop_abortop_args *));
-int    nfs_inactive __P((struct vop_inactive_args *));
-int    nfs_reclaim __P((struct vop_reclaim_args *));
-int nfs_lock __P((struct vop_lock_args *));
-int nfs_unlock __P((struct vop_unlock_args *));
-int nfs_islocked __P((struct vop_islocked_args *));
-
-#define nfs_reallocblks \
-       ((int (*) __P((struct  vop_reallocblks_args *)))eopnotsupp)
+int    nfs_vnop_write(struct vnop_write_args *);
+#define nfs_vnop_revoke nop_revoke
+int    nfs_vnop_inactive(struct vnop_inactive_args *);
+int    nfs_vnop_reclaim(struct vnop_reclaim_args *);
+
+int nfs_lock(nfsnode_t, int);
+void nfs_unlock(nfsnode_t);
+int nfs_lock2(nfsnode_t, nfsnode_t, int);
+void nfs_unlock2(nfsnode_t, nfsnode_t);
+int nfs_lock4(nfsnode_t, nfsnode_t, nfsnode_t, nfsnode_t, int);
+void nfs_unlock4(nfsnode_t, nfsnode_t, nfsnode_t, nfsnode_t);
+void nfs_data_lock(nfsnode_t, int);
+void nfs_data_lock2(nfsnode_t, int, int);
+void nfs_data_unlock(nfsnode_t);
+void nfs_data_unlock2(nfsnode_t, int);
+void nfs_data_update_size(nfsnode_t, int);
 
 /* other stuff */
-int    nfs_removeit __P((struct sillyrename *));
-int    nfs_nget __P((struct mount *,nfsfh_t *,int,struct nfsnode **));
-nfsuint64 *nfs_getcookie __P((struct nfsnode *, off_t, int));
-void nfs_invaldir __P((struct vnode *));
+int nfs_removeit(struct nfs_sillyrename *);
+int nfs_nget(mount_t,nfsnode_t,struct componentname *,u_char *,int,struct nfs_vattr *,u_int64_t *,int,nfsnode_t*);
+nfsuint64 *nfs_getcookie(nfsnode_t, off_t, int);
+void nfs_invaldir(nfsnode_t);
+
+/* nfsbuf functions */
+void nfs_nbinit(void);
+void nfs_buf_timer(void *, void *);
+void nfs_buf_remfree(struct nfsbuf *);
+boolean_t nfs_buf_is_incore(nfsnode_t, daddr64_t);
+struct nfsbuf * nfs_buf_incore(nfsnode_t, daddr64_t);
+int nfs_buf_get(nfsnode_t, daddr64_t, int, thread_t, int, struct nfsbuf **);
+int nfs_buf_upl_setup(struct nfsbuf *bp);
+void nfs_buf_upl_check(struct nfsbuf *bp);
+void nfs_buf_normalize_valid_range(nfsnode_t, struct nfsbuf *);
+int nfs_buf_map(struct nfsbuf *);
+void nfs_buf_release(struct nfsbuf *, int);
+int nfs_buf_iowait(struct nfsbuf *);
+void nfs_buf_iodone(struct nfsbuf *);
+void nfs_buf_write_delayed(struct nfsbuf *);
+void nfs_buf_check_write_verifier(nfsnode_t, struct nfsbuf *);
+void nfs_buf_freeup(int);
+void nfs_buf_refget(struct nfsbuf *bp);
+void nfs_buf_refrele(struct nfsbuf *bp);
+void nfs_buf_drop(struct nfsbuf *);
+errno_t nfs_buf_acquire(struct nfsbuf *, int, int, int);
+int nfs_buf_iterprepare(nfsnode_t, struct nfsbuflists *, int);
+void nfs_buf_itercomplete(nfsnode_t, struct nfsbuflists *, int);
+
+int nfs_bioread(nfsnode_t, struct uio *, int, int *, vfs_context_t);
+int nfs_buf_readdir(struct nfsbuf *, vfs_context_t);
+int nfs_buf_read(struct nfsbuf *);
+void nfs_buf_read_finish(struct nfsbuf *);
+int nfs_buf_read_rpc(struct nfsbuf *, thread_t, kauth_cred_t);
+void nfs_buf_read_rpc_finish(struct nfsreq *);
+int nfs_buf_write(struct nfsbuf *);
+void nfs_buf_write_finish(struct nfsbuf *, thread_t, kauth_cred_t);
+int nfs_buf_write_rpc(struct nfsbuf *, int, thread_t, kauth_cred_t);
+void nfs_buf_write_rpc_finish(struct nfsreq *);
+int nfs_buf_write_dirty_pages(struct nfsbuf *, thread_t, kauth_cred_t);
+
+int nfs_flushcommits(nfsnode_t, int);
+int nfs_flush(nfsnode_t, int, thread_t, int);
 
-#define nqnfs_lease_updatetime lease_updatetime
+int nfsiod_start(void);
+void nfs_asyncio_finish(struct nfsreq *);
+void nfs_asyncio_resend(struct nfsreq *);
 
 #endif /* KERNEL */