xref: /xnu-8019.80.24/bsd/nfs/nfsnode.h (revision a325d9c4a84054e40bbe985afedcb50ab80993ea)
1 /*
2  * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
29 /*
30  * Copyright (c) 1989, 1993
31  *	The Regents of the University of California.  All rights reserved.
32  *
33  * This code is derived from software contributed to Berkeley by
34  * Rick Macklem at The University of Guelph.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
39  * 1. Redistributions of source code must retain the above copyright
40  *    notice, this list of conditions and the following disclaimer.
41  * 2. Redistributions in binary form must reproduce the above copyright
42  *    notice, this list of conditions and the following disclaimer in the
43  *    documentation and/or other materials provided with the distribution.
44  * 3. All advertising materials mentioning features or use of this software
45  *    must display the following acknowledgement:
46  *	This product includes software developed by the University of
47  *	California, Berkeley and its contributors.
48  * 4. Neither the name of the University nor the names of its contributors
49  *    may be used to endorse or promote products derived from this software
50  *    without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62  * SUCH DAMAGE.
63  *
64  *	@(#)nfsnode.h	8.9 (Berkeley) 5/14/95
65  * FreeBSD-Id: nfsnode.h,v 1.24 1997/10/28 14:06:25 bde Exp $
66  */
67 
68 
69 #ifndef _NFS_NFSNODE_H_
70 #define _NFS_NFSNODE_H_
71 
72 #include <sys/appleapiopts.h>
73 
74 #ifdef __APPLE_API_PRIVATE
75 #ifndef _NFS_NFS_H_
76 #include <nfs/nfs.h>
77 #endif
78 #include <sys/kauth.h>
79 #include <os/refcnt.h>
80 
81 /*
82  * Silly rename structure that hangs off the nfsnode until the name
83  * can be removed by nfs_vnop_inactive()
84  */
85 struct nfs_sillyrename {
86 	kauth_cred_t    nsr_cred;
87 	struct nfsnode  *nsr_dnp;
88 	int             nsr_namlen;
89 	char            nsr_name[20];
90 };
91 
92 /*
93  * NFS buf pages struct
94  */
95 typedef struct {
96 	uint64_t               pages[8];
97 } nfsbufpgs;
98 
99 /*
100  * The nfsbuf is the nfs equivalent to a struct buf.
101  */
102 struct nfsbuf {
103 	LIST_ENTRY(nfsbuf)      nb_hash;        /* hash chain */
104 	LIST_ENTRY(nfsbuf)      nb_vnbufs;      /* nfsnode's nfsbuf chain */
105 	TAILQ_ENTRY(nfsbuf)     nb_free;        /* free list position if not active. */
106 	os_refcnt_t             nb_refs;        /* outstanding references. */
107 	daddr64_t               nb_lblkno;      /* logical block number. */
108 	uint64_t                nb_verf;        /* V3 write verifier */
109 	time_t                  nb_timestamp;   /* buffer timestamp */
110 	nfsbufpgs               nb_valid;       /* valid pages in buf */
111 	nfsbufpgs               nb_dirty;       /* dirty pages in buf */
112 	caddr_t                 nb_data;        /* mapped buffer */
113 	nfsnode_t               nb_np;          /* nfsnode buffer belongs to */
114 	kauth_cred_t            nb_rcred;       /* read credentials reference */
115 	kauth_cred_t            nb_wcred;       /* write credentials reference */
116 	void *                  nb_pagelist;    /* upl */
117 	volatile uint32_t       nb_flags;       /* NB_* flags. */
118 	volatile uint32_t       nb_lflags;      /* NBL_* flags. */
119 	uint32_t                nb_bufsize;     /* buffer size */
120 	int                     nb_error;       /* errno value. */
121 	int                     nb_commitlevel; /* lowest write commit level */
122 	off_t                   nb_validoff;    /* offset in buffer of valid region. */
123 	off_t                   nb_validend;    /* offset of end of valid region. */
124 	off_t                   nb_dirtyoff;    /* offset in buffer of dirty region. */
125 	off_t                   nb_dirtyend;    /* offset of end of dirty region. */
126 	off_t                   nb_offio;       /* offset in buffer of I/O region. */
127 	off_t                   nb_endio;       /* offset of end of I/O region. */
128 	uint64_t                nb_rpcs;        /* Count of RPCs remaining for this buffer. */
129 };
130 
131 #define NFS_MAXBSIZE    (8 * 64 * PAGE_SIZE)    /* valid/dirty page masks limit buffer size */
132 
133 #define NFS_A_LOT_OF_NEEDCOMMITS        256                     /* max# uncommitted buffers for a node */
134 #define NFS_A_LOT_OF_DELAYED_WRITES     MAX(nfsbufcnt/8,512)    /* max# "delwri" buffers in system */
135 
136 /*
137  * These flags are kept in b_lflags...
138  * nfs_buf_mutex must be held before examining/updating
139  */
140 #define NBL_BUSY        0x00000001      /* I/O in progress. */
141 #define NBL_WANTED      0x00000002      /* Process wants this buffer. */
142 
143 /*
144  * These flags are kept in nb_flags and they're (purposefully)
145  * very similar to the B_* flags for struct buf.
146  * nfs_buf_mutex is not needed to examine/update these.
147  */
148 #define NB_STALEWVERF   0x00000001      /* write verifier changed on us */
149 #define NB_NEEDCOMMIT   0x00000002      /* buffer needs to be committed */
150 #define NB_ASYNC        0x00000004      /* Start I/O, do not wait. */
151 #define NB_CACHE        0x00000020      /* buffer data found in the cache */
152 #define NB_STABLE       0x00000040      /* write FILESYNC not UNSTABLE */
153 #define NB_DELWRI       0x00000080      /* delayed write: dirty range needs to be written */
154 #define NB_DONE         0x00000200      /* I/O completed. */
155 #define NB_EINTR        0x00000400      /* I/O was interrupted */
156 #define NB_ERROR        0x00000800      /* I/O error occurred. */
157 #define NB_INVAL        0x00002000      /* Does not contain valid info. */
158 #define NB_NCRDAHEAD    0x00004000      /* "nocache readahead" data */
159 #define NB_NOCACHE      0x00008000      /* Do not cache block after use. */
160 #define NB_WRITE        0x00000000      /* Write buffer (pseudo flag). */
161 #define NB_READ         0x00100000      /* Read buffer. */
162 #define NB_MULTASYNCRPC 0x00200000      /* multiple async RPCs issued for buffer */
163 #define NB_PAGELIST     0x00400000      /* Buffer describes pagelist I/O. */
164 #define NB_WRITEINPROG  0x01000000      /* Write in progress. */
165 #define NB_META         0x40000000      /* buffer contains meta-data. */
166 
167 /* Flags for operation type in nfs_buf_get() */
168 #define NBLK_READ       0x00000001      /* buffer for read */
169 #define NBLK_WRITE      0x00000002      /* buffer for write */
170 #define NBLK_META       0x00000004      /* buffer for metadata */
171 #define NBLK_OPMASK     0x00000007      /* operation mask */
172 /* modifiers for above flags... */
173 #define NBLK_NOWAIT     0x40000000      /* don't wait on busy buffer */
174 #define NBLK_ONLYVALID  0x80000000      /* only return cached buffer */
175 
176 /* These flags are used for nfsbuf iterating */
177 #define NBI_ITER                0x01    /* iteration in progress */
178 #define NBI_ITERWANT            0x02    /* waiting to iterate */
179 #define NBI_CLEAN               0x04    /* requesting clean buffers */
180 #define NBI_DIRTY               0x08    /* requesting dirty buffers */
181 #define NBI_NOWAIT              0x10    /* don't block on NBI_ITER */
182 
183 /* Flags for nfs_buf_acquire */
184 #define NBAC_NOWAIT             0x01    /* Don't wait if buffer is busy */
185 #define NBAC_REMOVE             0x02    /* Remove from free list once buffer is acquired */
186 
187 /* macros for nfsbufpgs */
188 #define NBPGS_STRUCT_SIZE               sizeof(nfsbufpgs)
189 #define NBPGS_ELEMENT_SIZE              sizeof(((nfsbufpgs *)0)->pages[0])
190 #define NBPGS_ELEMENT_PAGES             (8 * NBPGS_ELEMENT_SIZE)
191 #define NBPGS_ELEMENTS                  (NBPGS_STRUCT_SIZE / NBPGS_ELEMENT_SIZE)
192 #define NBPGS_ERASE(NFSBP)              bzero((NFSBP), NBPGS_STRUCT_SIZE)
193 #define NBPGS_COPY(NFSBPDST, NFSBPSRC)  memcpy((NFSBPDST), (NFSBPSRC), NBPGS_STRUCT_SIZE)
194 #define NBPGS_IS_EQUAL(NFSBP1, NFSBP2)  (memcmp((NFSBP1), (NFSBP2), NBPGS_STRUCT_SIZE) == 0)
195 #define NBPGS_GET(NFSBP, P)             ((NFSBP)->pages[((P)/NBPGS_ELEMENT_PAGES)] & (1LLU << ((P) % NBPGS_ELEMENT_PAGES)))
196 #define NBPGS_SET(NFSBP, P)             ((NFSBP)->pages[((P)/NBPGS_ELEMENT_PAGES)] |= (1LLU << ((P) % NBPGS_ELEMENT_PAGES)))
197 #define NBPGS_UNSET(NFSBP, P)           ((NFSBP)->pages[((P)/NBPGS_ELEMENT_PAGES)] &= ~(1LLU << ((P) % NBPGS_ELEMENT_PAGES)))
198 
199 /* some convenience macros...  */
200 #define NBOFF(BP)                       ((off_t)(BP)->nb_lblkno * (off_t)(BP)->nb_bufsize)
201 #define NBPGVALID(BP, P)                NBPGS_GET(&((BP)->nb_valid), (P))
202 #define NBPGDIRTY(BP, P)                NBPGS_GET(&((BP)->nb_dirty), (P))
203 #define NBPGVALID_SET(BP, P)            NBPGS_SET(&((BP)->nb_valid), (P))
204 #define NBPGDIRTY_SET(BP, P)            NBPGS_SET(&((BP)->nb_dirty), (P))
205 
206 #define NBUFSTAMPVALID(BP)              ((BP)->nb_timestamp != ~0)
207 #define NBUFSTAMPINVALIDATE(BP)         ((BP)->nb_timestamp = ~0)
208 
209 #define NFS_BUF_MAP(BP) \
210 	do { \
211 	        if (!(BP)->nb_data && nfs_buf_map(BP)) \
212 	                panic("nfs_buf_map failed"); \
213 	} while (0)
214 
215 LIST_HEAD(nfsbuflists, nfsbuf);
216 TAILQ_HEAD(nfsbuffreehead, nfsbuf);
217 
218 extern lck_mtx_t nfs_buf_mutex;
219 extern int nfsbufcnt, nfsbufmin, nfsbufmax, nfsbufmetacnt, nfsbufmetamax;
220 extern int nfsbuffreecnt, nfsbuffreemetacnt, nfsbufdelwricnt, nfsneedbuffer;
221 extern int nfs_nbdwrite;
222 extern struct nfsbuffreehead nfsbuffree, nfsbufdelwri;
223 
224 #ifdef NFSBUFDEBUG
225 #define NFSBUFCNTCHK() \
226 	do { \
227 	if (	(nfsbufcnt < 0) || \
228 	        (nfsbufcnt > nfsbufmax) || \
229 	        (nfsbufmetacnt < 0) || \
230 	        (nfsbufmetacnt > nfsbufmetamax) || \
231 	        (nfsbufmetacnt > nfsbufcnt) || \
232 	        (nfsbuffreecnt < 0) || \
233 	        (nfsbuffreecnt > nfsbufmax) || \
234 	        (nfsbuffreecnt > nfsbufcnt) || \
235 	        (nfsbuffreemetacnt < 0) || \
236 	        (nfsbuffreemetacnt > nfsbufmax) || \
237 	        (nfsbuffreemetacnt > nfsbufcnt) || \
238 	        (nfsbuffreemetacnt > nfsbufmetamax) || \
239 	        (nfsbuffreemetacnt > nfsbufmetacnt) || \
240 	        (nfsbufdelwricnt < 0) || \
241 	        (nfsbufdelwricnt > nfsbufmax) || \
242 	        (nfsbufdelwricnt > nfsbufcnt) || \
243 	        (nfs_nbdwrite < 0) || \
244 	        (nfs_nbdwrite > nfsbufcnt) || \
245 	        0) \
246 	        panic("nfsbuf count error: max %d meta %d cnt %d meta %d free %d meta %d delwr %d bdw %d\n", \
247 	                nfsbufmax, nfsbufmetamax, nfsbufcnt, nfsbufmetacnt, nfsbuffreecnt, nfsbuffreemetacnt, \
248 	                nfsbufdelwricnt, nfs_nbdwrite); \
249 	} while (0)
250 #else
251 #define NFSBUFCNTCHK()
252 #endif
253 
254 /*
255  * NFS directory buffer
256  *
257  * Each buffer for a directory consists of:
258  *
259  * - a small header
260  * - a packed list of direntry structures
261  *   (if RDIRPLUS is enabled, a file handle and attrstamp are
262  *   packed after the direntry name.)
263  * - free/unused space
264  * - if RDIRPLUS is enabled, an array of attributes
265  *   that is indexed backwards from the end of the buffer.
266  */
267 struct nfs_dir_buf_header {
268 	uint16_t        ndbh_flags;     /* flags (see below) */
269 	uint16_t        ndbh_count;     /* # of entries */
270 	off_t           ndbh_entry_end; /* end offset of direntry data */
271 	uint32_t        ndbh_ncgen;     /* name cache generation# */
272 	uint32_t        ndbh_pad;       /* reserved */
273 };
274 /* ndbh_flags */
275 #define NDB_FULL        0x0001  /* buffer has been filled */
276 #define NDB_EOF         0x0002  /* buffer contains EOF */
277 #define NDB_PLUS        0x0004  /* buffer contains RDIRPLUS data */
278 
279 #define NFS_DIR_BUF_FIRST_DIRENTRY(BP) \
280 	((struct direntry*)((char*)((BP)->nb_data) + sizeof(*ndbhp)))
281 #define NFS_DIR_BUF_NVATTR(BP, IDX) \
282 	(&((struct nfs_vattr*)((char*)((BP)->nb_data) + (BP)->nb_bufsize))[-((IDX)+1)])
283 #define NFS_DIRENTRY_LEN(namlen) \
284 	((sizeof(struct direntry) + (namlen) - (MAXPATHLEN-1) + 7) & ~7)
285 #define NFS_DIRENTRY_LEN_16(namlen) \
286 	        (uint16_t)(NFS_DIRENTRY_LEN(namlen)); assert((namlen) <= UINT16_MAX);
287 #define NFS_DIRENT_LEN(namlen) \
288 	((sizeof(struct dirent) - (NAME_MAX+1)) + (((namlen) + 1 + 3) &~ 3))
289 #define NFS_DIRENTRY_NEXT(DP) \
290 	((struct direntry*)((char*)(DP) + (DP)->d_reclen))
291 #define NFS_DIR_COOKIE_POTENTIALLY_TRUNCATED(C) \
292 	((C) && ((((C) >> 32) == 0) || (((C) & 0x80000000ULL) && (((C) >> 32) == 0xffffffff))))
293 #define NFS_DIR_COOKIE_SAME32(C1, C2) \
294 	(((C1) & 0xffffffffULL) == ((C2) & 0xffffffffULL))
295 
296 /*
297  * NFS directory cookie cache
298  *
299  * This structure is used to cache cookie-to-buffer mappings for
300  * cookies recently returned from READDIR.  The entries are kept in an
301  * array.  The most-recently-used (MRU) list is headed by the entry at
302  * index "mru".  The index of the next entry in the list is kept in the
303  * "next" array.  (An index value of -1 marks an invalid entry.)
304  */
305 #define NFSNUMCOOKIES           14
306 struct nfsdmap {
307 	int8_t          free;                   /* next unused slot */
308 	int8_t          mru;                    /* head of MRU list */
309 	int8_t          next[NFSNUMCOOKIES];    /* MRU list links */
310 	struct {
311 		uint64_t    key;                /* cookie */
312 		uint64_t    lbn;                /* lbn of buffer */
313 	} cookies[NFSNUMCOOKIES];               /* MRU list entries */
314 };
315 
316 /*
317  * NFS vnode attribute structure
318  */
319 #define NFSTIME_ACCESS  0       /* time of last access */
320 #define NFSTIME_MODIFY  1       /* time of last modification */
321 #define NFSTIME_CHANGE  2       /* time file changed */
322 #define NFSTIME_CREATE  3       /* time file created */
323 #define NFSTIME_BACKUP  4       /* time of last backup */
324 #define NFSTIME_ADDED   5       /* time added (FPnfs only) */
325 #define NFSTIME_COUNT   6
326 
327 #define NFS_COMPARE_MTIME(TVP, NVAP, CMP) \
328 	(((TVP)->tv_sec == (NVAP)->nva_timesec[NFSTIME_MODIFY]) ?       \
329 	 ((TVP)->tv_nsec CMP (NVAP)->nva_timensec[NFSTIME_MODIFY]) :    \
330 	 ((TVP)->tv_sec CMP (NVAP)->nva_timesec[NFSTIME_MODIFY]))
331 #define NFS_COPY_TIME(TVP, NVAP, WHICH) \
332 	do { \
333 	(TVP)->tv_sec = (NVAP)->nva_timesec[NFSTIME_##WHICH]; \
334 	(TVP)->tv_nsec = (NVAP)->nva_timensec[NFSTIME_##WHICH]; \
335 	} while (0)
336 
337 struct nfs_vattr {
338 	enum vtype      nva_type;       /* vnode type (for create) */
339 	mode_t          nva_mode;       /* file's access mode (and type) */
340 	uid_t           nva_uid;        /* owner user id */
341 	gid_t           nva_gid;        /* owner group id */
342 	guid_t          nva_uuuid;      /* owner user UUID */
343 	guid_t          nva_guuid;      /* owner group UUID */
344 	kauth_acl_t     nva_acl;        /* access control list */
345 	nfs_specdata    nva_rawdev;     /* device the special file represents */
346 	uint32_t        nva_flags;      /* file flags (see below) */
347 	uint32_t        nva_maxlink;    /* maximum # of links (v4) */
348 	uint64_t        nva_nlink;      /* number of references to file */
349 	uint64_t        nva_fileid;     /* file id */
350 	nfs_fsid        nva_fsid;       /* file system id */
351 	uint64_t        nva_size;       /* file size in bytes */
352 	uint64_t        nva_bytes;      /* bytes of disk space held by file */
353 	uint64_t        nva_change;     /* change attribute */
354 	time_t          nva_timesec[NFSTIME_COUNT];
355 	long            nva_timensec[NFSTIME_COUNT];
356 	uint32_t        nva_bitmap[NFS_ATTR_BITMAP_LEN]; /* attributes that are valid */
357 
358 	/* FPnfs only. */
359 	uint32_t        nva_bsd_flags;  /* BSD flags */
360 	uint64_t        nva_parentid;   /* parent file id */
361 	uint64_t        nva_allocsize;  /* size allocated on disk */
362 };
363 
364 /* nva_flags */
365 #define NFS_FFLAG_ARCHIVED              0x0001
366 #define NFS_FFLAG_HIDDEN                0x0002
367 #define NFS_FFLAG_HAS_NAMED_ATTRS       0x0004  /* file has named attributes */
368 #define NFS_FFLAG_TRIGGER               0x0008  /* node is a trigger/mirror mount point */
369 #define NFS_FFLAG_TRIGGER_REFERRAL      0x0010  /* trigger is a referral */
370 #define NFS_FFLAG_PARTIAL_WRITE         0x0020  /* partial attribute for NFSv4 writes */
371 #define NFS_FFLAG_FILEID_CONTAINS_XID   0x0040  /* xid might be stashed in nva_fileid is rdirplus is enabled */
372 #define NFS_FFLAG_IS_ATTR               0x8000  /* file is a named attribute file/directory */
373 /* FPnfs only */
374 #define NFS_FFLAG_FPNFS_BSD_FLAGS   0x01000000
375 #define NFS_FFLAG_FPNFS_PARENTID    0x02000000
376 #define NFS_FFLAG_FPNFS_ADDEDTIME   0x04000000
377 
378 /* flags for nfs_getattr() */
379 #define NGA_CACHED      0x0001  /* use cached attributes (if still valid) */
380 #define NGA_UNCACHED    0x0002  /* fetch new attributes */
381 #define NGA_ACL         0x0004  /* fetch ACL */
382 #define NGA_MONITOR     0x0008  /* vnode monitor attr update poll */
383 #define NGA_SOFT        0x0010  /* use cached attributes if ETIMEOUT */
384 
385 /* macros for initting/cleaning up nfs_vattr structures */
386 #define NVATTR_INIT(NVAP) \
387 	do { \
388 	        NFS_CLEAR_ATTRIBUTES((NVAP)->nva_bitmap); \
389 	        (NVAP)->nva_flags = 0; \
390 	        (NVAP)->nva_acl = NULL; \
391 	} while (0)
392 #define NVATTR_CLEANUP(NVAP) \
393 	do { \
394 	        NFS_CLEAR_ATTRIBUTES((NVAP)->nva_bitmap); \
395 	        if ((NVAP)->nva_acl) { \
396 	                kauth_acl_free((NVAP)->nva_acl); \
397 	                (NVAP)->nva_acl = NULL; \
398 	        } \
399 	} while (0)
400 
401 /*
402  * macros for detecting node changes
403  *
404  * These macros help us determine if a file has been changed on the server and
405  * thus whether or not we need to invalidate any cached data.
406  *
407  * For NFSv2/v3, the modification time is used.
408  * For NFSv4, the change attribute is used.
409  */
410 #define NFS_CHANGED(VERS, NP, NVAP) \
411 	        (((VERS) >= NFS_VER4) ? \
412 	                ((NP)->n_change != (NVAP)->nva_change) : \
413 	                NFS_COMPARE_MTIME(&(NP)->n_mtime, (NVAP), !=))
414 #define NFS_CHANGED_NC(VERS, NP, NVAP) \
415 	        (((VERS) >= NFS_VER4) ? \
416 	                ((NP)->n_ncchange != (NVAP)->nva_change) : \
417 	                NFS_COMPARE_MTIME(&(NP)->n_ncmtime, (NVAP), !=))
418 #define NFS_CHANGED_UPDATE(VERS, NP, NVAP) \
419 	do { \
420 	        if ((VERS) >= NFS_VER4) \
421 	                (NP)->n_change = (NVAP)->nva_change; \
422 	        else \
423 	                NFS_COPY_TIME(&(NP)->n_mtime, (NVAP), MODIFY); \
424 	} while (0)
425 #define NFS_CHANGED_UPDATE_NC(VERS, NP, NVAP) \
426 	do { \
427 	        if ((VERS) >= NFS_VER4) \
428 	                (NP)->n_ncchange = (NVAP)->nva_change; \
429 	        else \
430 	                NFS_COPY_TIME(&(NP)->n_ncmtime, (NVAP), MODIFY); \
431 	} while (0)
432 
433 
434 extern lck_grp_t nfs_open_grp;
435 extern uint32_t nfs_open_owner_seqnum, nfs_lock_owner_seqnum;
436 
437 /*
438  * NFSv4 open owner structure - one per cred per mount
439  */
440 struct nfs_open_owner {
441 	TAILQ_ENTRY(nfs_open_owner)     noo_link;       /* List of open owners (on mount) */
442 	lck_mtx_t                       noo_lock;       /* owner mutex */
443 	struct nfsmount *               noo_mount;      /* NFS mount */
444 	os_refcnt_t                     noo_refcnt;     /* # outstanding references */
445 	uint32_t                        noo_flags;      /* see below */
446 	kauth_cred_t                    noo_cred;       /* credentials of open owner */
447 	pid_t                           noo_pid;        /* process pid of this owner */
448 	uint32_t                        noo_name;       /* unique name used otw */
449 	uint32_t                        noo_seqid;      /* client-side sequence ID */
450 	TAILQ_HEAD(, nfs_open_file)     noo_opens;      /* list of open files */
451 };
452 /* noo_flags */
453 #define NFS_OPEN_OWNER_LINK     0x1     /* linked into mount's open owner list */
454 #define NFS_OPEN_OWNER_BUSY     0x2     /* open state-modifying operation in progress */
455 #define NFS_OPEN_OWNER_WANT     0x4     /* someone else wants to mark busy */
456 
457 /*
458  * NFS open file structure - one per open owner per nfsnode
459  */
460 struct nfs_open_file {
461 	lck_mtx_t                       nof_lock;               /* open file mutex */
462 	TAILQ_ENTRY(nfs_open_file)      nof_link;               /* list of open files */
463 	TAILQ_ENTRY(nfs_open_file)      nof_oolink;             /* list of open owner's open files */
464 	struct nfs_open_owner *         nof_owner;              /* open owner */
465 	nfsnode_t                       nof_np;                 /* nfsnode this open is for */
466 	nfs_stateid                     nof_stateid;            /* open stateid */
467 	thread_t                        nof_creator;            /* thread that created file */
468 	uint32_t                        nof_opencnt;            /* open file count */
469 	uint16_t                        nof_flags;              /* see below */
470 	uint8_t                         nof_access:4;           /* access mode for this open */
471 	uint8_t                         nof_deny:4;             /* deny mode for this open */
472 	uint8_t                         nof_mmap_access:4;      /* mmap open access mode */
473 	uint8_t                         nof_mmap_deny:4;        /* mmap open deny mode */
474 	/* counts of access/deny mode open combinations */
475 	uint32_t                        nof_r;                  /* read opens (deny none) */
476 	uint32_t                        nof_w;                  /* write opens (deny none) */
477 	uint32_t                        nof_rw;                 /* read/write opens (deny none) */
478 	uint32_t                        nof_r_dw;               /* read deny-write opens */
479 	/* the rest of the counts have a max of 2 (1 for open + 1 for mmap) */
480 	uint32_t                        nof_w_dw:2;             /* write deny-write opens (max 2) */
481 	uint32_t                        nof_rw_dw:2;            /* read/write deny-write opens (max 2) */
482 	uint32_t                        nof_r_drw:2;            /* read deny-read/write opens (max 2) */
483 	uint32_t                        nof_w_drw:2;            /* write deny-read/write opens (max 2) */
484 	uint32_t                        nof_rw_drw:2;           /* read/write deny-read/write opens (max 2) */
485 	/* counts of DELEGATED access/deny mode open combinations */
486 	uint32_t                        nof_d_w_dw:2;           /* write deny-write opens (max 2) */
487 	uint32_t                        nof_d_rw_dw:2;          /* read/write deny-write opens (max 2) */
488 	uint32_t                        nof_d_r_drw:2;          /* read deny-read/write opens (max 2) */
489 	uint32_t                        nof_d_w_drw:2;          /* write deny-read/write opens (max 2) */
490 	uint32_t                        nof_d_rw_drw:2;         /* read/write deny-read/write opens (max 2) */
491 	uint32_t                        nof_d_r;                /* read opens (deny none) */
492 	uint32_t                        nof_d_w;                /* write opens (deny none) */
493 	uint32_t                        nof_d_rw;               /* read/write opens (deny none) */
494 	uint32_t                        nof_d_r_dw;             /* read deny-write opens */
495 };
496 /* nof_flags */
497 #define NFS_OPEN_FILE_BUSY      0x0001  /* open state-modifying operation in progress */
498 #define NFS_OPEN_FILE_WANT      0x0002  /* someone else wants to mark busy */
499 #define NFS_OPEN_FILE_CREATE    0x0004  /* has an open(RW) from a "CREATE" call */
500 #define NFS_OPEN_FILE_NEEDCLOSE 0x0008  /* has an open(R) from an (unopen) VNOP_READ or VNOP_MMAP call */
501 #define NFS_OPEN_FILE_SETATTR   0x0020  /* has an open(W) to perform a SETATTR(size) */
502 #define NFS_OPEN_FILE_POSIXLOCK 0x0040  /* server supports POSIX locking semantics */
503 #define NFS_OPEN_FILE_LOST      0x0080  /* open state has been lost */
504 #define NFS_OPEN_FILE_REOPEN    0x0100  /* file needs to be reopened */
505 #define NFS_OPEN_FILE_REOPENING 0x0200  /* file is being reopened */
506 
507 struct nfs_lock_owner;
508 /*
509  * NFS file lock
510  *
511  * Each lock request (pending or granted) has an
512  * nfs_file_lock structure representing its state.
513  */
514 struct nfs_file_lock {
515 	TAILQ_ENTRY(nfs_file_lock)      nfl_link;       /* List of locks on nfsnode */
516 	TAILQ_ENTRY(nfs_file_lock)      nfl_lolink;     /* List of locks held by locker */
517 	struct nfs_lock_owner *         nfl_owner;      /* lock owner that holds this lock */
518 	uint64_t                        nfl_start;      /* starting offset */
519 	uint64_t                        nfl_end;        /* ending offset (inclusive) */
520 	uint32_t                        nfl_blockcnt;   /* # locks blocked on this lock */
521 	uint16_t                        nfl_flags;      /* see below */
522 	uint16_t                        nfl_type;       /* lock type: read/write */
523 };
524 /* nfl_flags */
525 #define NFS_FILE_LOCK_ALLOC             0x01    /* lock was allocated */
526 #define NFS_FILE_LOCK_STYLE_POSIX       0x02    /* POSIX-style fcntl() lock */
527 #define NFS_FILE_LOCK_STYLE_FLOCK       0x04    /* flock(2)-style lock */
528 #define NFS_FILE_LOCK_STYLE_MASK        0x06    /* lock style mask */
529 #define NFS_FILE_LOCK_WAIT              0x08    /* may block on conflicting locks */
530 #define NFS_FILE_LOCK_BLOCKED           0x10    /* request is blocked */
531 #define NFS_FILE_LOCK_DEAD              0x20    /* lock (request) no longer exists */
532 #define NFS_FILE_LOCK_DELEGATED         0x40    /* lock acquired via delegation */
533 
534 TAILQ_HEAD(nfs_file_lock_queue, nfs_file_lock);
535 
536 /*
537  * Calculate length of lock range given the endpoints.
538  * Note that struct flock has "to EOF" reported as 0 but
539  * the NFSv4 protocol has "to EOF" reported as UINT64_MAX.
540  */
541 #define NFS_FLOCK_LENGTH(S, E)  (((E) == UINT64_MAX) ? 0 : ((E) - (S) + 1))
542 #define NFS_LOCK_LENGTH(S, E)   (((E) == UINT64_MAX) ? UINT64_MAX : ((E) - (S) + 1))
543 
544 /* nfs_lock_owner_find flags */
545 #define NFS_LOCK_OWNER_FIND_ALLOC               0x01
546 #define NFS_LOCK_OWNER_FIND_DEQUEUE             0x02
547 
548 /*
549  * NFSv4 lock owner structure - per open owner per process per nfsnode
550  *
551  * A lock owner is a process + an nfsnode.
552  *
553  * Note that flock(2) locks technically should have the lock owner be
554  * an fglob pointer instead of a process.  However, implementing that
555  * correctly would not be trivial.  So, for now, flock(2) locks are
556  * essentially treated like whole-file POSIX locks.
557  */
558 struct nfs_lock_owner {
559 	lck_mtx_t                       nlo_lock;       /* owner mutex */
560 	TAILQ_ENTRY(nfs_lock_owner)     nlo_link;       /* List of lock owners (on nfsnode) */
561 	struct nfs_open_owner *         nlo_open_owner; /* corresponding open owner */
562 	struct nfs_file_lock_queue      nlo_locks;      /* list of locks held */
563 	struct nfs_file_lock            nlo_alock;      /* most lockers will only ever have one */
564 	struct timeval                  nlo_pid_start;  /* Start time of process id */
565 	caddr_t                         nlo_lockid;     /* lock identifier received by VNOP_ADVLOCK */
566 	pid_t                           nlo_pid;        /* lock-owning process ID */
567 	os_refcnt_t                     nlo_refcnt;     /* # outstanding references */
568 	uint32_t                        nlo_flags;      /* see below */
569 	uint32_t                        nlo_name;       /* unique name used otw */
570 	uint32_t                        nlo_seqid;      /* client-side sequence ID */
571 	uint32_t                        nlo_stategenid; /* mount state generation ID */
572 	nfs_stateid                     nlo_stateid;    /* lock stateid */
573 };
574 /* nlo_flags */
575 #define NFS_LOCK_OWNER_LINK     0x1     /* linked into mount's lock owner list */
576 #define NFS_LOCK_OWNER_BUSY     0x2     /* lock state-modifying operation in progress */
577 #define NFS_LOCK_OWNER_WANT     0x4     /* someone else wants to mark busy */
578 
579 /*
580  * The nfsnode is the NFS equivalent of an inode.
581  * There is a unique nfsnode for each NFS vnode.
582  * An nfsnode is 'named' by its file handle. (nget/nfs_node.c)
583  * NB: Hopefully the current order of the fields is such that everything will
584  *     be well aligned and, therefore, tightly packed.
585  */
586 
587 #define NFS_ACCESS_CACHE_SIZE   3
588 
589 struct nfsnode {
590 	lck_mtx_t               n_lock;         /* nfs node lock */
591 	lck_rw_t                n_datalock;     /* nfs node data lock */
592 	void                    *n_datalockowner;/* nfs node data lock owner (exclusive) */
593 	LIST_ENTRY(nfsnode)     n_hash;         /* Hash chain */
594 	LIST_ENTRY(nfsnode)     n_monlink;      /* list of monitored nodes */
595 	u_quad_t                n_size;         /* Current size of file */
596 	u_quad_t                n_newsize;      /* new size of file (pending update) */
597 	u_int64_t               n_xid;          /* last xid to loadattr */
598 	struct nfs_vattr        n_vattr;        /* Vnode attribute cache */
599 	time_t                  n_attrstamp;    /* Attr. cache timestamp */
600 	time_t                  n_aclstamp;     /* ACL cache timestamp */
601 	time_t                  n_evtstamp;     /* last vnode event timestamp */
602 	uint32_t                n_events;       /* pending vnode events */
603 	uint32_t                n_access[NFS_ACCESS_CACHE_SIZE + 1];      /* ACCESS cache */
604 	uid_t                   n_accessuid[NFS_ACCESS_CACHE_SIZE];     /* credentials having access */
605 	time_t                  n_accessstamp[NFS_ACCESS_CACHE_SIZE];   /* access cache timestamp */
606 	time_t                  n_rdirplusstamp_sof; /* Readdirplus sof timestamp */
607 	time_t                  n_rdirplusstamp_eof; /* Readdirplus eof timestamp */
608 	union {
609 		struct {
610 			struct timespec n3_mtime; /* Prev modify time. */
611 			struct timespec n3_ncmtime; /* namecache modify time. */
612 		} v3;
613 		struct {
614 			uint64_t        n4_change;/* prev change attribute */
615 			uint64_t        n4_ncchange;/* namecache change attribute */
616 			u_char          *n4_attrdirfh;/* associated attr directory fh */
617 			struct timeval  n4_lastio;/* time of most recent I/O on attr */
618 		} v4;
619 	} n_un4;
620 	vnode_t                 n_parent;       /* this node's parent */
621 	u_char                  *n_fhp;         /* NFS File Handle */
622 	vnode_t                 n_vnode;        /* associated vnode */
623 	mount_t                 n_mount;        /* associated mount (NHINIT) */
624 	int                     n_error;        /* Save write error value */
625 	union {
626 		struct timespec ns_atim;        /* Special file times */
627 		struct timespec nl_rltim;       /* Time of last readlink */
628 		daddr64_t       nf_lastread;    /* last block# read from (for readahead) */
629 		uint64_t        nd_cookieverf;  /* Cookie verifier (dir only) */
630 	} n_un1;
631 	union {
632 		struct timespec ns_mtim;        /* Special file times */
633 		daddr64_t       nf_lastrahead;  /* last block# read ahead */
634 		uint64_t        nd_eofcookie;   /* Dir. EOF cookie cache */
635 	} n_un2;
636 	union {
637 		struct nfs_sillyrename *nf_silly;/* Ptr to silly rename struct */
638 		struct nfsdmap *nd_cookiecache; /* dir cookie cache */
639 	} n_un3;
640 	uint32_t                n_flag;         /* node flags */
641 	uint32_t                n_fhsize;       /* size in bytes, of fh */
642 	u_short                 n_hflag;        /* node hash flags */
643 	u_short                 n_bflag;        /* node buffer flags */
644 	u_short                 n_mflag;        /* node mount flags */
645 	u_char                  n_fh[NFS_SMALLFH];/* Small File Handle */
646 	uint32_t                n_auth;         /* security flavor used for this node */
647 	struct nfsbuflists      n_cleanblkhd;   /* clean blocklist head */
648 	struct nfsbuflists      n_dirtyblkhd;   /* dirty blocklist head */
649 	union {
650 		int             nf_wrbusy;      /* # threads in write/fsync */
651 		uint32_t        nd_ncgen;       /* dir name cache generation# */
652 	} n_un5;
653 	union {
654 		int             nf_needcommitcnt;/* # bufs that need committing */
655 		daddr64_t       nd_lastdbl;     /* last dir buf lookup block# */
656 	} n_un6;
657 	int                     n_bufiterflags; /* buf iterator flags */
658 	union {
659 		int             nf_numoutput;   /* write I/Os in progress */
660 		int             nd_trigseq;     /* vnode trigger seq# */
661 	} n_un7;
662 	/* open state */
663 	lck_mtx_t               n_openlock;     /* nfs node open lock */
664 	uint32_t                n_openflags;    /* open state flags */
665 	uint32_t                n_openrefcnt;   /* # non-file opens */
666 	TAILQ_HEAD(, nfs_open_file) n_opens;     /* list of open files */
667 	/* lock state */
668 	TAILQ_HEAD(, nfs_lock_owner) n_lock_owners; /* list of lock owners */
669 	struct nfs_file_lock_queue n_locks;     /* list of locks */
670 	/* delegation state */
671 	nfs_stateid             n_dstateid;     /* delegation stateid */
672 	TAILQ_ENTRY(nfsnode)    n_dlink;        /* delegation list link */
673 	TAILQ_ENTRY(nfsnode)    n_dreturn;      /* delegation return list link */
674 	struct kauth_ace        n_dace;         /* delegation ACE */
675 };
676 
677 #define NFS_DATA_LOCK_SHARED    1
678 #define NFS_DATA_LOCK_EXCLUSIVE 2
679 
680 #define nfstimespeccmp(tvp, uvp, cmp)           \
681 	(((tvp)->tv_sec == (uvp)->tv_sec) ?     \
682 	 ((tvp)->tv_nsec cmp (uvp)->tv_nsec) :  \
683 	 ((tvp)->tv_sec cmp (uvp)->tv_sec))
684 
685 #define CHECK_NEEDCOMMITCNT(np) \
686 	do { \
687 	        if ((np)->n_needcommitcnt < 0) { \
688 	                printf("nfs: n_needcommitcnt negative\n"); \
689 	                (np)->n_needcommitcnt = 0; \
690 	        } \
691 	} while (0)
692 
693 #define n_atim                  n_un1.ns_atim
694 #define n_mtim                  n_un2.ns_mtim
695 #define n_rltim                 n_un1.nl_rltim
696 #define n_lastread              n_un1.nf_lastread
697 #define n_lastrahead            n_un2.nf_lastrahead
698 #define n_sillyrename           n_un3.nf_silly
699 #define n_wrbusy                n_un5.nf_wrbusy
700 #define n_needcommitcnt         n_un6.nf_needcommitcnt
701 #define n_numoutput             n_un7.nf_numoutput
702 #define n_cookieverf            n_un1.nd_cookieverf
703 #define n_eofcookie             n_un2.nd_eofcookie
704 #define n_cookiecache           n_un3.nd_cookiecache
705 #define n_ncgen                 n_un5.nd_ncgen
706 #define n_lastdbl               n_un6.nd_lastdbl
707 #define n_trigseq               n_un7.nd_trigseq
708 #define n_mtime                 n_un4.v3.n3_mtime
709 #define n_ncmtime               n_un4.v3.n3_ncmtime
710 #define n_change                n_un4.v4.n4_change
711 #define n_ncchange              n_un4.v4.n4_ncchange
712 #define n_attrdirfh             n_un4.v4.n4_attrdirfh
713 #define n_lastio                n_un4.v4.n4_lastio
714 
715 /*
716  * Flags for n_flag
717  */
718 #define NUPDATESIZE     0x00001 /* size of file needs updating */
719 #define NREVOKE         0x00002 /* node revoked */
720 #define NMODIFIED       0x00004 /* Might have a modified buffer in bio */
721 #define NWRITEERR       0x00008 /* Flag write errors so close will know */
722 #define NNEEDINVALIDATE 0x00010 /* need to call vinvalbuf() */
723 #define NGETATTRINPROG  0x00020 /* GETATTR RPC in progress */
724 #define NGETATTRWANT    0x00040 /* waiting for GETATTR RPC */
725 #define NACC            0x00100 /* Special file accessed */
726 #define NUPD            0x00200 /* Special file updated */
727 #define NCHG            0x00400 /* Special file times changed */
728 #define NNEGNCENTRIES   0x00800 /* directory has negative name cache entries */
729 #define NBUSY           0x01000 /* node is busy */
730 #define NBUSYWANT       0x02000 /* waiting on busy node */
731 #define NISDOTZFS       0x04000 /* a ".zfs" directory */
732 #define NISDOTZFSCHILD  0x08000 /* a child of a ".zfs" directory */
733 #define NISMAPPED       0x10000 /* node is mmapped   */
734 #define NREFRESH        0x20000 /* node's fh needs to be refreshed */
735 #define NREFRESHWANT    0x40000 /* Waiting for fh to be refreshed */
736 #define NDISARMTRIGGER  0x80000 /* Ignore node's mirror mount trigger */
737 
738 /*
739  * Flags for n_hflag
740  * Note: protected by nfs_node_hash_mutex
741  */
742 #define NHHASHED        0x0001  /* node is in hash table */
743 #define NHINIT          0x0002  /* node is being initialized */
744 #define NHLOCKED        0x0004  /* node is locked (initting or deleting) */
745 #define NHLOCKWANT      0x0008  /* someone wants to lock */
746 
747 /*
748  * Flags for n_bflag
749  * Note: protected by nfs_buf_mutex
750  */
751 #define NBFLUSHINPROG   0x0001  /* Avoid multiple calls to nfs_flush() */
752 #define NBFLUSHWANT     0x0002  /* waiting for nfs_flush() to complete */
753 #define NBINVALINPROG   0x0004  /* Avoid multiple calls to nfs_vinvalbuf() */
754 #define NBINVALWANT     0x0008  /* waiting for nfs_vinvalbuf() to complete */
755 
756 /*
757  * Flags for n_mflag
758  * Note: protected by nfsmount's nm_lock
759  */
760 #define NMMONSCANINPROG 0x0001  /* monitored node is currently updating attributes */
761 #define NMMONSCANWANT   0x0002  /* waiting for attribute update to complete */
762 
763 /*
764  * n_openflags
765  * Note: protected by n_openlock
766  */
767 #define N_OPENBUSY              0x0001  /* open state is busy - being updated */
768 #define N_OPENWANT              0x0002  /* someone wants to mark busy */
769 #define N_DELEG_READ            0x0004  /* we have a read delegation */
770 #define N_DELEG_WRITE           0x0008  /* we have a write delegation */
771 #define N_DELEG_MASK            0x000c  /* delegation mask */
772 #define N_DELEG_RETURN          0x0010  /* delegation queued for return */
773 #define N_DELEG_RETURNING       0x0020  /* delegation being returned */
774 
775 /* attr/access/ACL cache timestamp macros */
776 #define NATTRVALID(np)          ((np)->n_attrstamp != ~0)
777 #define NATTRINVALIDATE(np)     ((np)->n_attrstamp = ~0)
778 #define NACCESSVALID(np, slot)  (((slot) >= 0) && ((slot) < NFS_ACCESS_CACHE_SIZE) && ((np)->n_accessstamp[(slot)] != ~0))
779 #define NACCESSINVALIDATE(np) \
780 	do { \
781 	        int __i; \
782 	        for (__i=0; __i < NFS_ACCESS_CACHE_SIZE; __i++) \
783 	                (np)->n_accessstamp[__i] = ~0; \
784 	        (np)->n_access[NFS_ACCESS_CACHE_SIZE] = 0; \
785 	} while (0)
786 #define NACLVALID(np)           ((np)->n_aclstamp != ~0)
787 #define NACLINVALIDATE(np)      ((np)->n_aclstamp = ~0)
788 
789 /*
790  * NFS-specific flags for nfs_vinvalbuf/nfs_flush
791  */
792 #define V_IGNORE_WRITEERR       0x8000
793 
794 /*
795  * Flags for nfs_nget()
796  */
797 #define NG_MARKROOT     0x0001  /* mark vnode as root of FS */
798 #define NG_MAKEENTRY    0x0002  /* add name cache entry for vnode */
799 #define NG_NOCREATE     0x0004  /* don't create a new node, return existing one */
800 
801 /*
802  * Convert between nfsnode pointers and vnode pointers
803  */
804 #define VTONFS(vp)      ((nfsnode_t)vnode_fsnode(vp))
805 #define NFSTOV(np)      ((np)->n_vnode)
806 
807 /* nfsnode hash table mutex */
808 extern lck_mtx_t nfs_node_hash_mutex;
809 
810 /*
811  * printf-like helper macro that also outputs node name.
812  */
813 #define NP(NP, FMT, ...) \
814 	do { \
815 	        const char *__vname = (NP) ? vnode_getname(NFSTOV(NP)) : NULL; \
816 	        printf(FMT " %s\n", ##__VA_ARGS__, __vname ? __vname : "???"); \
817 	        if (__vname) vnode_putname(__vname); \
818 	} while (0)
819 
820 /*
821  * nfsiod structures
822  */
823 struct nfsiod {
824 	TAILQ_ENTRY(nfsiod)     niod_link;      /* List of nfsiods */
825 	struct nfsmount *       niod_nmp;       /* mount point for this nfsiod */
826 };
827 TAILQ_HEAD(nfsiodlist, nfsiod);
828 TAILQ_HEAD(nfsiodmountlist, nfsmount);
829 extern struct nfsiodlist nfsiodfree, nfsiodwork;
830 extern struct nfsiodmountlist nfsiodmounts;
831 extern lck_mtx_t nfsiod_mutex;
832 
833 #if defined(KERNEL)
834 
835 typedef int     vnop_t(void *);
836 extern  vnop_t  **fifo_nfsv2nodeop_p;
837 extern  vnop_t  **nfsv2_vnodeop_p;
838 extern  vnop_t  **fpnfs_vnodeop_p;
839 extern  vnop_t  **spec_nfsv2nodeop_p;
840 #if CONFIG_NFS4
841 extern  vnop_t  **fifo_nfsv4nodeop_p;
842 extern  vnop_t  **nfsv4_vnodeop_p;
843 extern  vnop_t  **spec_nfsv4nodeop_p;
844 #endif
845 /*
846  * Prototypes for NFS vnode operations
847  */
848 #define nfs_vnop_revoke nop_revoke
849 int     nfs_vnop_inactive(struct vnop_inactive_args *);
850 int     nfs_vnop_reclaim(struct vnop_reclaim_args *);
851 
852 int nfs_node_lock(nfsnode_t);
853 int nfs_node_lock_internal(nfsnode_t, int);
854 void nfs_node_lock_force(nfsnode_t);
855 void nfs_node_unlock(nfsnode_t);
856 int nfs_node_lock2(nfsnode_t, nfsnode_t);
857 void nfs_node_unlock2(nfsnode_t, nfsnode_t);
858 int nfs_node_set_busy(nfsnode_t, thread_t);
859 int nfs_node_set_busy2(nfsnode_t, nfsnode_t, thread_t);
860 int nfs_node_set_busy4(nfsnode_t, nfsnode_t, nfsnode_t, nfsnode_t, thread_t);
861 void nfs_node_clear_busy(nfsnode_t);
862 void nfs_node_clear_busy2(nfsnode_t, nfsnode_t);
863 void nfs_node_clear_busy4(nfsnode_t, nfsnode_t, nfsnode_t, nfsnode_t);
864 void nfs_data_lock(nfsnode_t, int);
865 void nfs_data_lock_noupdate(nfsnode_t, int);
866 void nfs_data_lock_internal(nfsnode_t, int, int);
867 void nfs_data_unlock(nfsnode_t);
868 void nfs_data_unlock_noupdate(nfsnode_t);
869 void nfs_data_unlock_internal(nfsnode_t, int);
870 void nfs_data_update_size(nfsnode_t, int);
871 
872 /* other stuff */
873 int nfs_removeit(struct nfs_sillyrename *);
874 int nfs_nget(mount_t, nfsnode_t, struct componentname *, u_char *, uint32_t, struct nfs_vattr *, u_int64_t *, uint32_t, int, nfsnode_t*);
875 int nfs_mount_is_dirty(mount_t);
876 void nfs_dir_cookie_cache(nfsnode_t, uint64_t, uint64_t);
877 int nfs_dir_cookie_to_lbn(nfsnode_t, uint64_t, int *, uint64_t *);
878 void nfs_invaldir(nfsnode_t);
879 uint64_t nfs_dir_buf_freespace(struct nfsbuf *, int);
880 
881 /* nfsbuf functions */
882 void nfs_nbinit(void);
883 void nfs_buf_timer(void *, void *);
884 void nfs_buf_remfree(struct nfsbuf *);
885 boolean_t nfs_buf_is_incore(nfsnode_t, daddr64_t);
886 struct nfsbuf * nfs_buf_incore(nfsnode_t, daddr64_t);
887 int nfs_buf_get(nfsnode_t, daddr64_t, uint32_t, thread_t, int, struct nfsbuf **);
888 int nfs_buf_upl_setup(struct nfsbuf *bp);
889 void nfs_buf_upl_check(struct nfsbuf *bp);
890 void nfs_buf_normalize_valid_range(nfsnode_t, struct nfsbuf *);
891 int nfs_buf_map(struct nfsbuf *);
892 void nfs_buf_release(struct nfsbuf *, int);
893 int nfs_buf_iowait(struct nfsbuf *);
894 void nfs_buf_iodone(struct nfsbuf *);
895 void nfs_buf_write_delayed(struct nfsbuf *);
896 void nfs_buf_check_write_verifier(nfsnode_t, struct nfsbuf *);
897 void nfs_buf_freeup(int);
898 void nfs_buf_refget(struct nfsbuf *bp);
899 void nfs_buf_refrele(struct nfsbuf *bp);
900 void nfs_buf_drop(struct nfsbuf *);
901 errno_t nfs_buf_acquire(struct nfsbuf *, int, int, int);
902 int nfs_buf_iterprepare(nfsnode_t, struct nfsbuflists *, int);
903 void nfs_buf_itercomplete(nfsnode_t, struct nfsbuflists *, int);
904 
905 void nfs_buf_pgs_get_page_mask(nfsbufpgs *, off_t);
906 void nfs_buf_pgs_bit_not(nfsbufpgs *);
907 void nfs_buf_pgs_bit_and(nfsbufpgs *, nfsbufpgs *, nfsbufpgs *);
908 void nfs_buf_pgs_set_pages_between(nfsbufpgs *, off_t, off_t);
909 int nfs_buf_pgs_is_set(nfsbufpgs *);
910 
911 int nfs_bioread(nfsnode_t, uio_t, int, vfs_context_t);
912 int nfs_buf_readahead(nfsnode_t, int, daddr64_t *, daddr64_t, thread_t, kauth_cred_t);
913 int nfs_buf_readdir(struct nfsbuf *, vfs_context_t);
914 int nfs_buf_read(struct nfsbuf *);
915 void nfs_buf_read_finish(struct nfsbuf *);
916 int nfs_buf_read_rpc(struct nfsbuf *, thread_t, kauth_cred_t);
917 void nfs_buf_read_rpc_finish(struct nfsreq *);
918 int nfs_buf_write(struct nfsbuf *);
919 void nfs_buf_write_finish(struct nfsbuf *, thread_t, kauth_cred_t);
920 int nfs_buf_write_rpc(struct nfsbuf *, int, thread_t, kauth_cred_t);
921 void nfs_buf_write_rpc_finish(struct nfsreq *);
922 int nfs_buf_write_dirty_pages(struct nfsbuf *, thread_t, kauth_cred_t);
923 
924 int nfs_flushcommits(nfsnode_t, int);
925 int nfs_flush(nfsnode_t, int, thread_t, int);
926 void nfs_buf_delwri_push(int);
927 void nfs_buf_delwri_service(void);
928 void nfs_buf_delwri_thread(void *, wait_result_t);
929 
930 int nfsiod_start(void);
931 void nfsiod_terminate(struct nfsiod *);
932 void nfsiod_thread(void);
933 int nfsiod_continue(int);
934 void nfs_asyncio_finish(struct nfsreq *);
935 void nfs_asyncio_resend(struct nfsreq *);
936 int nfs_async_write_start(struct nfsmount *);
937 void nfs_async_write_done(struct nfsmount *);
938 
939 #endif /* KERNEL */
940 
941 #endif /* __APPLE_API_PRIVATE */
942 #endif /* _NFS_NFSNODE_H_ */
943