+/*!
+ * @function vnode_create
+ * @abstract Create and initialize a vnode.
+ * @discussion Returns wth an iocount held on the vnode which must eventually be dropped with vnode_put().
+ * @param flavor Should be VNCREATE_FLAVOR.
+ * @param size Size of the struct vnode_fsparam in "data".
+ * @param data Pointer to a struct vnode_fsparam containing initialization information.
+ * @param vpp Pointer to a vnode pointer, to be filled in with newly created vnode.
+ * @return 0 for success, error code otherwise.
+ */
+errno_t vnode_create(uint32_t flavor, uint32_t size, void *data, vnode_t *vpp);
+
+#ifdef KERNEL_PRIVATE
+/*!
+ * @function vnode_create_empty
+ * @abstract Create an empty, uninitialized vnode.
+ * @discussion Returns with an iocount held on the vnode which must eventually be
+ * dropped with vnode_put(). The next operation performed on the vnode must be
+ * vnode_initialize (or vnode_put if the vnode is not needed anymore).
+ * This interface is provided as a mechanism to pre-flight obtaining a vnode for
+ * certain filesystem operations which may need to get a vnode without filesystem
+ * locks held. It is imperative that nothing be done with the vnode till the
+ * succeeding vnode_initialize (or vnode_put as the case may be) call.
+ * @param vpp Pointer to a vnode pointer, to be filled in with newly created vnode.
+ * @return 0 for success, error code otherwise.
+ */
+errno_t vnode_create_empty(vnode_t *vpp);
+
+/*!
+ * @function vnode_initialize
+ * @abstract Initialize a vnode obtained by vnode_create_empty
+ * @discussion Does not drop iocount held on the vnode which must eventually be
+ * dropped with vnode_put(). In case of an error however, the vnode's iocount is
+ * dropped and the vnode must not be referenced again by the caller.
+ * @param flavor Should be VNCREATE_FLAVOR.
+ * @param size Size of the struct vnode_fsparam in "data".
+ * @param data Pointer to a struct vnode_fsparam containing initialization information.
+ * @param vpp Pointer to a vnode pointer, to be filled in with newly created vnode.
+ * @return 0 for success, error code otherwise.
+ */
+errno_t vnode_initialize(uint32_t flavor, uint32_t size, void *data, vnode_t *vpp);
+#endif /* KERNEL_PRIVATE */
+
+/*!
+ * @function vnode_addfsref
+ * @abstract Mark a vnode as being stored in a filesystem hash.
+ * @discussion Should only be called once on a vnode, and never if that vnode was created with VNFS_ADDFSREF.
+ * There should be a corresponding call to vnode_removefsref() when the vnode is reclaimed; VFS assumes that a
+ * n unused vnode will not be marked as referenced by a filesystem.
+ * @param vp The vnode to mark.
+ * @return Always 0.
+ */
+int vnode_addfsref(vnode_t vp);
+
+/*!
+ * @function vnode_removefsref
+ * @abstract Mark a vnode as no longer being stored in a filesystem hash.
+ * @discussion Should only be called once on a vnode (during a reclaim), and only after the vnode has either been created with VNFS_ADDFSREF or marked by vnode_addfsref().
+ * @param vp The vnode to unmark.
+ * @return Always 0.
+ */
+int vnode_removefsref(vnode_t vp);
+
+/*!
+ * @function vnode_hasdirtyblks
+ * @abstract Check if a vnode has dirty data waiting to be written to disk.
+ * @discussion Note that this routine is unsynchronized; it is only a snapshot and its result may cease to be true at the moment it is returned..
+ * @param vp The vnode to test.
+ * @return Nonzero if there are dirty blocks, 0 otherwise
+ */
+int vnode_hasdirtyblks(vnode_t vp);
+
+/*!
+ * @function vnode_hascleanblks
+ * @abstract Check if a vnode has clean buffers associated with it.
+ * @discussion Note that this routine is unsynchronized; it is only a snapshot and its result may cease to be true at the moment it is returned..
+ * @param vp The vnode to test.
+ * @return Nonzero if there are clean blocks, 0 otherwise.
+ */
+int vnode_hascleanblks(vnode_t vp);
+
+#define VNODE_ASYNC_THROTTLE 15
+/*!
+ * @function vnode_waitforwrites
+ * @abstract Wait for the number of pending writes on a vnode to drop below a target.
+ * @param vp The vnode to monitor.
+ * @param output_target Max pending write count with which to return.
+ * @param slpflag Flags for msleep().
+ * @param slptimeout Frequency with which to force a check for completion; increments of 10 ms.
+ * @param msg String to pass msleep() .
+ * @return 0 for success, or an error value from msleep().
+ */
+int vnode_waitforwrites(vnode_t vp, int output_target, int slpflag, int slptimeout, const char *msg);
+
+/*!
+ * @function vnode_startwrite
+ * @abstract Increment the count of pending writes on a vnode.
+ * @param vp The vnode whose count to increment.
+ */
+void vnode_startwrite(vnode_t vp);
+
+/*!
+ * @function vnode_startwrite
+ * @abstract Decrement the count of pending writes on a vnode .
+ * @discussion Also wakes up threads waiting for the write count to drop, as in vnode_waitforwrites.
+ * @param vp The vnode whose count to decrement.
+ */
+void vnode_writedone(vnode_t vp);
+
+/*!
+ * @function vnode_vtype
+ * @abstract Return a vnode's type.
+ * @param vp The vnode whose type to grab.
+ * @return The vnode's type.
+ */
+enum vtype vnode_vtype(vnode_t vp);
+
+/*!
+ * @function vnode_vid
+ * @abstract Return a vnode's vid (generation number), which is constant from creation until reclaim.
+ * @param vp The vnode whose vid to grab.
+ * @return The vnode's vid.
+ */
+uint32_t vnode_vid(vnode_t vp);
+
+/*!
+ * @function vnode_isonexternalstorage
+ * @abstract Return whether or not the storage device backing a vnode is external or not.
+ * @param vp The vnode whose physical location is to be determined.
+ * @return TRUE if storage device is external, FALSE if otherwise.
+ */
+boolean_t vnode_isonexternalstorage(vnode_t vp);
+
+/*!
+ * @function vnode_mountedhere
+ * @abstract Returns a pointer to a mount placed on top of a vnode, should it exist.
+ * @param vp The vnode from whom to take the covering mount.
+ * @return Pointer to mount covering a vnode, or NULL if none exists.
+ */
+mount_t vnode_mountedhere(vnode_t vp);
+
+/*!
+ * @function vnode_mount
+ * @abstract Get the mount structure for the filesystem that a vnode belongs to.
+ * @param vp The vnode whose mount to grab.
+ * @return The mount, directly.
+ */
+mount_t vnode_mount(vnode_t vp);
+
+/*!
+ * @function vnode_specrdev
+ * @abstract Return the device id of the device associated with a special file.
+ * @param vp The vnode whose device id to extract--vnode must be a special file.
+ * @return The device id.
+ */
+dev_t vnode_specrdev(vnode_t vp);
+
+/*!
+ * @function vnode_fsnode
+ * @abstract Gets the filesystem-specific data associated with a vnode.
+ * @param vp The vnode whose data to grab.
+ * @return The filesystem-specific data, directly.
+ */
+void * vnode_fsnode(vnode_t vp);
+
+/*!
+ * @function vnode_clearfsnode
+ * @abstract Sets a vnode's filesystem-specific data to be NULL.
+ * @discussion This routine should only be called when a vnode is no longer in use, i.e. during a VNOP_RECLAIM.
+ * @param vp The vnode whose data to clear out.
+ */
+void vnode_clearfsnode(vnode_t vp);
+
+/*!
+ * @function vnode_isvroot
+ * @abstract Determine if a vnode is the root of its filesystem.
+ * @param vp The vnode to test.
+ * @return Nonzero if the vnode is the root, 0 if it is not.
+ */
+int vnode_isvroot(vnode_t vp);
+
+/*!
+ * @function vnode_issystem
+ * @abstract Determine if a vnode is marked as a System vnode.
+ * @param vp The vnode to test.
+ * @return Nonzero if the vnode is a system vnode, 0 if it is not.
+ */
+int vnode_issystem(vnode_t vp);
+
+/*!
+ * @function vnode_ismount
+ * @abstract Determine if there is currently a mount occurring which will cover this vnode.
+ * @discussion Note that this is only a snapshot; a mount may begin or end at any time.
+ * @param vp The vnode to test.
+ * @return Nonzero if there is a mount in progress, 0 otherwise.
+ */
+int vnode_ismount(vnode_t vp);
+
+/*!
+ * @function vnode_isreg
+ * @abstract Determine if a vnode is a regular file.
+ * @param vp The vnode to test.
+ * @return Nonzero if the vnode is of type VREG, 0 otherwise.
+ */
+int vnode_isreg(vnode_t vp);
+
+/*!
+ * @function vnode_isdir
+ * @abstract Determine if a vnode is a directory.
+ * @param vp The vnode to test.
+ * @return Nonzero if the vnode is of type VDIR, 0 otherwise.
+ */
+int vnode_isdir(vnode_t vp);
+
+/*!
+ * @function vnode_islnk
+ * @abstract Determine if a vnode is a symbolic link.
+ * @param vp The vnode to test.
+ * @return Nonzero if the vnode is of type VLNK, 0 otherwise.
+ */
+int vnode_islnk(vnode_t vp);
+
+/*!
+ * @function vnode_isfifo
+ * @abstract Determine if a vnode is a named pipe.
+ * @param vp The vnode to test.
+ * @return Nonzero if the vnode is of type VFIFO, 0 otherwise.
+ */
+int vnode_isfifo(vnode_t vp);
+
+/*!
+ * @function vnode_isblk
+ * @abstract Determine if a vnode is a block device special file.
+ * @param vp The vnode to test.
+ * @return Nonzero if the vnode is of type VBLK, 0 otherwise.
+ */
+int vnode_isblk(vnode_t vp);
+
+/*!
+ * @function vnode_ischr
+ * @abstract Determine if a vnode is a character device special file.
+ * @param vp The vnode to test.
+ * @return Nonzero if the vnode is of type VCHR, 0 otherwise.
+ */
+int vnode_ischr(vnode_t vp);
+
+/*!
+ * @function vnode_isswap
+ * @abstract Determine if a vnode is being used as a swap file.
+ * @param vp The vnode to test.
+ * @return Nonzero if the vnode is being used as swap, 0 otherwise.
+ */
+int vnode_isswap(vnode_t vp);
+
+/*!
+ * @function vnode_isnamedstream
+ * @abstract Determine if a vnode is a named stream.
+ * @param vp The vnode to test.
+ * @return Nonzero if the vnode is a named stream, 0 otherwise.
+ */
+int vnode_isnamedstream(vnode_t vp);
+
+#ifdef KERNEL_PRIVATE
+/*!
+ * @function vnode_setasnamedstream
+ * @abstract Set svp as a named stream of vp and take appropriate references.
+ * @param vp The vnode whose namedstream has to be set.
+ * @param svp The namedstream vnode.
+ * @return 0 if the operation is successful, an error otherwise.
+ */
+errno_t vnode_setasnamedstream(vnode_t vp, vnode_t svp);
+
+/*!
+ * @function vnode_setasfirmlink
+ * @abstract Set a vnode to act as a firmlink i.e. point to a target vnode.
+ * @param vp The vnode which is to be acted on as a firmlink.
+ * @param target_vp The vnode which will be the target of the firmlink.
+ * @return 0 if the operation is successful, an error otherwise.
+ */
+errno_t vnode_setasfirmlink(vnode_t vp, vnode_t target_vp);
+
+/*!
+ * @function vnode_getfirmlink
+ * @abstract If a vnode is a firmlink, get its target vnode.
+ * @param vp The firmlink vnode.
+ * @param target_vp The firmlink traget vnode. This vnode is returned with an iocount.
+ * @return 0 if the operation is successful, an error otherwise.
+ */
+errno_t vnode_getfirmlink(vnode_t vp, vnode_t *target_vp);
+
+#endif /* KERNEL_PRIVATE */
+
+/*!
+ * @function vnode_ismountedon
+ * @abstract Determine if a vnode is a block device on which a filesystem has been mounted.
+ * @discussion A block device marked as being mounted on cannot be opened.
+ * @param vp The vnode to test.
+ * @return Nonzero if the vnode is a block device on which an filesystem is mounted, 0 otherwise.
+ */
+int vnode_ismountedon(vnode_t vp);
+
+/*!
+ * @function vnode_setmountedon
+ * @abstract Set flags indicating that a block device vnode has been mounted as a filesystem.
+ * @discussion A block device marked as being mounted on cannot be opened.
+ * @param vp The vnode to set flags on, a block device.
+ */
+void vnode_setmountedon(vnode_t vp);
+
+/*!
+ * @function vnode_clearmountedon
+ * @abstract Clear flags indicating that a block device vnode has been mounted as a filesystem.
+ * @param vp The vnode to clear flags on, a block device.
+ */
+void vnode_clearmountedon(vnode_t vp);
+
+/*!
+ * @function vnode_isrecycled
+ * @abstract Check if a vnode is dead or in the process of being killed (recycled).
+ * @discussion This is only a snapshot: a vnode may start to be recycled, or go from dead to in use, at any time.
+ * @param vp The vnode to test.
+ * @return Nonzero if vnode is dead or being recycled, 0 otherwise.
+ */
+int vnode_isrecycled(vnode_t vp);
+
+/*!
+ * @function vnode_isnocache
+ * @abstract Check if a vnode is set to not have its data cached in memory (i.e. we write-through to disk and always read from disk).
+ * @param vp The vnode to test.
+ * @return Nonzero if vnode is set to not have data chached, 0 otherwise.
+ */
+int vnode_isnocache(vnode_t vp);
+
+/*!
+ * @function vnode_israge
+ * @abstract Check if a vnode is marked for rapid aging
+ * @param vp The vnode to test.
+ * @return Nonzero if vnode is marked for rapid aging, 0 otherwise
+ */
+int vnode_israge(vnode_t vp);
+
+/*!
+ * @function vnode_needssnapshots
+ * @abstract Check if a vnode needs snapshots events (regardless of its ctime status)
+ * @param vp The vnode to test.
+ * @return Nonzero if vnode needs snapshot events, 0 otherwise
+ */
+int vnode_needssnapshots(vnode_t vp);
+
+/*!
+ * @function vnode_setnocache
+ * @abstract Set a vnode to not have its data cached in memory (i.e. we write-through to disk and always read from disk).
+ * @param vp The vnode whose flags to set.
+ */
+void vnode_setnocache(vnode_t vp);
+
+/*!
+ * @function vnode_clearnocache
+ * @abstract Clear the flag on a vnode indicating that data should not be cached in memory (i.e. we write-through to disk and always read from disk).
+ * @param vp The vnode whose flags to clear.
+ */
+void vnode_clearnocache(vnode_t vp);
+
+/*!
+ * @function vnode_isnoreadahead
+ * @abstract Check if a vnode is set to not have data speculatively read in in hopes of future cache hits.
+ * @param vp The vnode to test.
+ * @return Nonzero if readahead is disabled, 0 otherwise.
+ */
+int vnode_isnoreadahead(vnode_t vp);
+
+/*!
+ * @function vnode_setnoreadahead
+ * @abstract Set a vnode to not have data speculatively read in in hopes of hitting in cache.
+ * @param vp The vnode on which to prevent readahead.
+ */
+void vnode_setnoreadahead(vnode_t vp);
+
+/*!
+ * @function vnode_clearnoreadahead
+ * @abstract Clear the flag indicating that a vnode should not have data speculatively read in.
+ * @param vp The vnode whose flag to clear.
+ */
+void vnode_clearnoreadahead(vnode_t vp);
+
+/*!
+ * @function vnode_isfastdevicecandidate
+ * @abstract Check if a vnode is a candidate to store on the fast device of a composite disk system
+ * @param vp The vnode which you want to test.
+ * @return Nonzero if the vnode is marked as a fast-device candidate
+ */
+int vnode_isfastdevicecandidate(vnode_t vp);
+
+/*!
+ * @function vnode_setfastdevicecandidate
+ * @abstract Mark a vnode as a candidate to store on the fast device of a composite disk system
+ * @discussion If the vnode is a directory, all its children will inherit this bit.
+ * @param vp The vnode which you want marked.
+ */
+void vnode_setfastdevicecandidate(vnode_t vp);
+
+/*!
+ * @function vnode_clearfastdevicecandidate
+ * @abstract Clear the status of a vnode being a candidate to store on the fast device of a composite disk system.
+ * @param vp The vnode whose flag to clear.
+ */
+void vnode_clearfastdevicecandidate(vnode_t vp);
+
+/*!
+ * @function vnode_isautocandidate
+ * @abstract Check if a vnode was automatically selected to be fast-dev candidate (see vnode_setfastdevicecandidate)
+ * @param vp The vnode which you want to test.
+ * @return Nonzero if the vnode was automatically marked as a fast-device candidate
+ */
+int vnode_isautocandidate(vnode_t vp);
+
+/*!
+ * @function vnode_setfastdevicecandidate
+ * @abstract Mark a vnode as an automatically selected candidate for storing on the fast device of a composite disk system
+ * @discussion If the vnode is a directory, all its children will inherit this bit.
+ * @param vp The vnode which you want marked.
+ */
+void vnode_setautocandidate(vnode_t vp);
+
+/*!
+ * @function vnode_clearautocandidate
+ * @abstract Clear the status of a vnode being an automatic candidate (see above)
+ * @param vp The vnode whose flag to clear.
+ */
+void vnode_clearautocandidate(vnode_t vp);
+