+extern int VFS_IOCTL(mount_t mp, u_long command, caddr_t data,
+ int flags, vfs_context_t context);
+extern int VFS_VGET_SNAPDIR(mount_t, vnode_t *, vfs_context_t);
+#endif /* BSD_KERNEL_PRIVATE */
+/*
+ * prototypes for exported VFS operations
+ */
+
+/*!
+ * @function vfs_fsadd
+ * @abstract Register a filesystem with VFS.
+ * @discussion Typically called by a filesystem Kernel Extension when it is loaded.
+ * @param vfe Filesystem information: table of vfs operations, list of vnode operation tables,
+ * filesystem type number (can be omitted with VFS_TBLNOTYPENUM flag), name, flags.
+ * @param handle Opaque handle which will be passed to vfs_fsremove.
+ * @return 0 for success, else an error code.
+ */
+int vfs_fsadd(struct vfs_fsentry *vfe, vfstable_t *handle);
+
+/*!
+ * @function vfs_fsremove
+ * @abstract Unregister a filesystem with VFS.
+ * @discussion Typically called by a filesystem Kernel Extension when it is unloaded.
+ * @param handle Handle which was returned by vfs_fsadd.
+ * @return 0 for success, else an error code.
+ */
+int vfs_fsremove(vfstable_t handle);
+
+/*!
+ * @function vfs_iterate
+ * @abstract Iterate over all mountpoints with a callback. Used, for example, by sync().
+ * @param flags Unused.
+ * @param callout Function which takes a mount and arbitrary passed-in "arg," and returns one of VFS_RETURNED_DONE or VFS_CLAIMED_DONE: end
+ * iteration and return success. VFS_RETURNED or VFS_CLAIMED: continue iterating. Anything else: continue iterating.
+ * @param arg Arbitrary data to pass to callback.
+ * @return 0 for success, else an error code.
+ */
+int vfs_iterate(int flags, int (*callout)(struct mount *, void *), void *arg);
+
+/*!
+ * @function vfs_init_io_attributes
+ * @abstract Set I/O attributes on a mountpoint based on device properties.
+ * @param devvp Block device vnode from which a filesystem is being mounted.
+ * @param mp Mountpoint whose I/O parameters to initialize.
+ * @return 0 for success, else an error code.
+ */
+int vfs_init_io_attributes(vnode_t devvp, mount_t mp);
+
+/*!
+ * @function vfs_flags
+ * @abstract Retrieve mount flags.
+ * @discussion Results will be in the bitwise "OR" of MNT_VISFLAGMASK and MNT_CMDFLAGS.
+ * @param mp Mount whose flags to grab.
+ * @return Flags.
+ */
+uint64_t vfs_flags(mount_t mp);
+
+/*!
+ * @function vfs_setflags
+ * @abstract Set flags on a mount.
+ * @discussion Sets mount flags to the bitwise "OR" of their current value and the specified bits. Often
+ * used by a filesystem as part of the mount process.
+ * @param mp Mount whose flags to set.
+ * @param flags Flags to activate. Must be in the bitwise "OR" of MNT_VISFLAGMASK and MNT_CMDFLAGS.
+ */
+void vfs_setflags(mount_t mp, uint64_t flags);
+
+/*!
+ * @function vfs_clearflags
+ * @abstract Clear flags on a mount.
+ * @discussion Sets mount flags to the bitwise "AND" of their current value and the complement of the specified bits.
+ * @param mp Mount whose flags to set.
+ * @param flags Flags to deactivate. Must be in the bitwise "OR" of MNT_VISFLAGMASK and MNT_CMDFLAGS.
+ */
+void vfs_clearflags(mount_t mp, uint64_t flags);
+
+/*!
+ * @function vfs_issynchronous
+ * @abstract Determine if writes to a filesystem occur synchronously.
+ * @param mp Mount to test.
+ * @return Nonzero if writes occur synchronously, else 0.
+ */
+int vfs_issynchronous(mount_t mp);
+
+/*!
+ * @function vfs_iswriteupgrade
+ * @abstract Determine if a filesystem is mounted read-only but a request has been made to upgrade
+ * to read-write.
+ * @param mp Mount to test.
+ * @return Nonzero if a request has been made to update from read-only to read-write, else 0.
+ */
+int vfs_iswriteupgrade(mount_t mp);
+
+/*!
+ * @function vfs_isupdate
+ * @abstract Determine if a mount update is in progress.
+ * @param mp Mount to test.
+ * @return Nonzero if a mount update is in progress, 0 otherwise.
+ */
+int vfs_isupdate(mount_t mp);
+
+/*!
+ * @function vfs_isreload
+ * @abstract Determine if a reload of filesystem data is in progress. This can only be the case
+ * for a read-only filesystem; all data is brought in from secondary storage.
+ * @param mp Mount to test.
+ * @return Nonzero if a request has been made to reload data, else 0.
+ */
+int vfs_isreload(mount_t mp);
+
+/*!
+ * @function vfs_isforce
+ * @abstract Determine if a forced unmount is in progress.
+ * @discussion A forced unmount invalidates open files.
+ * @param mp Mount to test.
+ * @return Nonzero if a request has been made to forcibly unmount, else 0.
+ */
+int vfs_isforce(mount_t mp);
+
+/*!
+ * @function vfs_isunmount
+ * @abstract Determine if an unmount is in progress.
+ * @discussion This is an unsynchronized snapshot of the mount state. It should only be called
+ * if the mount is known to be valid, e.g. there are known to be live files on that volume.
+ * @param mp Mount to test.
+ * @return Nonzero if an unmount is in progress, else zero.
+ */
+int vfs_isunmount(mount_t mp);
+
+/*!
+ * @function vfs_isrdonly
+ * @abstract Determine if a filesystem is mounted read-only.
+ * @param mp Mount to test.
+ * @return Nonzero if filesystem is mounted read-only, else 0.
+ */
+int vfs_isrdonly(mount_t mp);
+
+/*!
+ * @function vfs_isrdwr
+ * @abstract Determine if a filesystem is mounted with writes enabled.
+ * @param mp Mount to test.
+ * @return Nonzero if filesystem is mounted read-write, else 0.
+ */
+int vfs_isrdwr(mount_t mp);
+
+/*!
+ * @function vfs_authopaque
+ * @abstract Determine if a filesystem's authorization decisions occur remotely.
+ * @param mp Mount to test.
+ * @return Nonzero if filesystem authorization is controlled remotely, else 0.
+ */
+int vfs_authopaque(mount_t mp);
+
+/*!
+ * @function vfs_authopaqueaccess
+ * @abstract Check if a filesystem is marked as having reliable remote VNOP_ACCESS support.
+ * @param mp Mount to test.
+ * @return Nonzero if VNOP_ACCESS is supported remotely, else 0.
+ */
+int vfs_authopaqueaccess(mount_t mp);
+
+/*!
+ * @function vfs_setauthopaque
+ * @abstract Mark a filesystem as having authorization decisions controlled remotely.
+ * @param mp Mount to mark.
+ */
+void vfs_setauthopaque(mount_t mp);
+
+/*!
+ * @function vfs_setauthopaqueaccess
+ * @abstract Mark a filesystem as having remote VNOP_ACCESS support.
+ * @param mp Mount to mark.
+ */
+void vfs_setauthopaqueaccess(mount_t mp);
+
+/*!
+ * @function vfs_clearauthopaque
+ * @abstract Mark a filesystem as not having remote authorization decisions.
+ * @param mp Mount to mark.
+ */
+void vfs_clearauthopaque(mount_t mp);
+
+/*!
+ * @function vfs_clearauthopaque
+ * @abstract Mark a filesystem as not having remote VNOP_ACCESS support.
+ * @param mp Mount to mark.
+ */
+void vfs_clearauthopaqueaccess(mount_t mp);
+
+/*!
+ * @function vfs_setextendedsecurity
+ * @abstract Mark a filesystem as supporting security controls beyond POSIX permissions.
+ * @discussion Specific controls include ACLs, file owner UUIDs, and group UUIDs.
+ * @param mp Mount to test.
+ */
+void vfs_setextendedsecurity(mount_t mp);
+
+/*!
+ * @function vfs_clearextendedsecurity
+ * @abstract Mark a filesystem as NOT supporting security controls beyond POSIX permissions.
+ * @discussion Specific controls include ACLs, file owner UUIDs, and group UUIDs.
+ * @param mp Mount to test.
+ */
+void vfs_clearextendedsecurity(mount_t mp);
+
+/*!
+ * @function vfs_setnoswap
+ * @abstract Mark a filesystem as unable to use swap files.
+ * @param mp Mount to mark.
+ */
+void vfs_setnoswap(mount_t mp);
+
+/*!
+ * @function vfs_clearnoswap
+ * @abstract Mark a filesystem as capable of using swap files.
+ * @param mp Mount to mark.
+ */
+void vfs_clearnoswap(mount_t mp);
+
+/*!
+ * @function vfs_setlocklocal
+ * @abstract Mark a filesystem as using VFS-level advisory locking support.
+ * @discussion Advisory locking operations will not call down to the filesystem if this flag is set.
+ * @param mp Mount to mark.
+ */
+void vfs_setlocklocal(mount_t mp);
+
+/*!
+ * @function vfs_authcache_ttl
+ * @abstract Determine the time-to-live of cached authorized credentials for files in this filesystem.
+ * @discussion If a filesystem is set to allow caching credentials, the VFS layer can authorize
+ * previously-authorized actions from the same vfs_context_t without calling down to the filesystem (though
+ * it will not deny based on the cache).
+ * @param mp Mount for which to check cache lifetime.
+ * @return Cache lifetime in seconds. CACHED_RIGHT_INFINITE_TTL indicates that credentials never expire.
+ */
+int vfs_authcache_ttl(mount_t mp);
+
+/*!
+ * @function vfs_setauthcache_ttl
+ * @abstract Enable credential caching and set time-to-live of cached authorized credentials for files in this filesystem.
+ * @discussion If a filesystem is set to allow caching credentials, the VFS layer can authorize
+ * previously-authorized actions from the same vfs_context_t without calling down to the filesystem (though
+ * it will not deny based on the cache).
+ * @param mp Mount for which to set cache lifetime.
+ */
+void vfs_setauthcache_ttl(mount_t mp, int ttl);
+
+/*!
+ * @function vfs_clearauthcache_ttl
+ * @abstract Remove time-to-live controls for cached credentials on a filesytem. Filesystems with remote authorization
+ * decisions (opaque) will still have KAUTH_VNODE_SEARCH rights cached for a default of CACHED_LOOKUP_RIGHT_TTL seconds.
+ * @param mp Mount for which to clear cache lifetime.
+ */
+void vfs_clearauthcache_ttl(mount_t mp);
+
+/*
+ * return value from vfs_cachedrights_ttl if
+ * neither MNTK_AUTH_OPAQUE | MNTK_AUTH_CACHE_TTL
+ * is set in mnt_kern_flag.. it indicates
+ * that no TTL is being applied to the vnode rights cache
+ */
+#define CACHED_RIGHT_INFINITE_TTL ~0
+
+/*!
+ * @function vfs_maxsymlen
+ * @abstract Get the maximum length of a symbolic link on a filesystem.
+ * @param mp Mount from which to get symlink length cap.
+ * @return Max symlink length.
+ */
+uint32_t vfs_maxsymlen(mount_t mp);
+
+/*!
+ * @function vfs_setmaxsymlen
+ * @abstract Set the maximum length of a symbolic link on a filesystem.
+ * @param mp Mount on which to set symlink length cap.
+ * @param symlen Length to set.
+ */
+void vfs_setmaxsymlen(mount_t mp, uint32_t symlen);
+
+/*!
+ * @function vfs_fsprivate
+ * @abstract Get filesystem-private mount data.
+ * @discussion A filesystem generally has an internal mount structure which it attaches to the VFS-level mount structure
+ * as part of the mounting process.
+ * @param mp Mount for which to get private data.
+ * @return Private data.
+ */
+void * vfs_fsprivate(mount_t mp);
+
+/*!
+ * @function vfs_setfsprivate
+ * @abstract Set filesystem-private mount data.
+ * @discussion A filesystem generally has an internal mount structure which it attaches to the VFS-level mount structure
+ * as part of the mounting process.
+ * @param mp Mount for which to set private data.
+ */
+void vfs_setfsprivate(mount_t mp, void *mntdata);
+
+/*!
+ * @function vfs_statfs
+ * @abstract Get information about filesystem status.
+ * @discussion Each filesystem has a struct vfsstatfs associated with it which is updated as events occur; this function
+ * returns a pointer to it. Note that the data in the structure will continue to change over time and also that it may
+ * be quite stale if vfs_update_vfsstat has not been called recently.
+ * @param mp Mount for which to get vfsstatfs pointer.
+ * @return Pointer to vfsstatfs.
+ */
+struct vfsstatfs * vfs_statfs(mount_t mp);
+#define VFS_USER_EVENT 0
+#define VFS_KERNEL_EVENT 1
+
+/*!
+ * @function vfs_update_vfsstat
+ * @abstract Update cached filesystem status information in the VFS mount structure.
+ * @discussion Each filesystem has a struct vfsstatfs associated with it which is updated as events occur; this function
+ * updates it so that the structure pointer returned by vfs_statfs() returns a pointer to fairly recent data.
+ * @param mp Mount for which to update cached status information.
+ * @param ctx Context to authenticate against for call down to filesystem.
+ * @param eventtype VFS_USER_EVENT: need for update is driven by user-level request; perform additional authentication.
+ * VFS_KERNEL_EVENT: need for update is driven by in-kernel events. Skip extra authentication.
+ * @return 0 for success, or an error code for authentication failure or problem with call to filesystem to
+ * request information.
+ */
+int vfs_update_vfsstat(mount_t mp, vfs_context_t ctx, int eventtype);
+
+/*!
+ * @function vfs_typenum
+ * @abstract Get (archaic) filesystem type number.
+ * @discussion Filesystem type numbers are an old construct; most filesystems just get a number assigned based on
+ * the order in which they are registered with the system.
+ * @param mp Mount for which to get type number.
+ * @return Type number.
+ */
+int vfs_typenum(mount_t mp);
+
+/*!
+ * @function vfs_name
+ * @abstract Copy filesystem name into a buffer.
+ * @discussion Get filesystem name; this refers to the filesystem type of which a mount is an instantiation,
+ * rather than a name specific to the mountpoint.
+ * @param mp Mount for which to get name.
+ * @param buffer Destination for name; length should be at least MFSNAMELEN.
+ */
+void vfs_name(mount_t mp, char *buffer);
+
+/*!
+ * @function vfs_devblocksize
+ * @abstract Get the block size of the device underlying a mount.
+ * @param mp Mount for which to get block size.
+ * @return Block size.
+ */
+int vfs_devblocksize(mount_t mp);
+
+/*!
+ * @function vfs_ioattr
+ * @abstract Get I/O attributes associated with a mounpoint.
+ * @param mp Mount for which to get attributes. If NULL, system defaults are filled into ioattrp.
+ * @param ioattrp Destination for results.
+ */
+void vfs_ioattr(mount_t mp, struct vfsioattr *ioattrp);
+
+/*!
+ * @function vfs_setioattr
+ * @abstract Set I/O attributes associated with a mounpoint.
+ * @param mp Mount for which to set attributes.
+ * @param ioattrp Structure containing I/O parameters; all fields must be filled in.
+ */
+void vfs_setioattr(mount_t mp, struct vfsioattr *ioattrp);
+
+/*!
+ * @function vfs_64bitready
+ * @abstract Check if the filesystem associated with a mountpoint is marked ready for interaction with 64-bit user processes.
+ * @param mp Mount to test.
+ * @return Nonzero if filesystem is ready for 64-bit; 0 otherwise.
+ */
+int vfs_64bitready(mount_t mp);
+
+
+#define LK_NOWAIT 1
+/*!
+ * @function vfs_busy
+ * @abstract "Busy" a mountpoint.
+ * @discussion vfs_busy() will "busy" a mountpoint, preventing unmounts from taking off, by taking its reader-writer lock
+ * in a shared manner. If a mount is dead,
+ * it will fail; if an unmount is in progress, depending on flags, it will either fail immediately or block
+ * until the unmount completes (then failing if the unmount has succeeded, or potentially succeeding if unmounting failed).
+ * A successful vfs_busy() must be followed by a vfs_unbusy() to release the lock on the mount.
+ * @param mp Mount to busy.
+ * @param flags LK_NOWAIT: fail with ENOENT if an unmount is in progress.
+ * @return 0 for success, with a lock held; an error code otherwise, with no lock held.
+ */
+int vfs_busy(mount_t mp, int flags);
+
+/*!
+ * @function vfs_unbusy
+ * @abstract "Unbusy" a mountpoint by releasing its read-write lock.
+ * @discussion A successful vfs_busy() must be followed by a vfs_unbusy() to release the lock on the mount.
+ * @param mp Mount to unbusy.
+ */
+void vfs_unbusy(mount_t mp);
+
+/*!
+ * @function vfs_getnewfsid
+ * @abstract Generate a unique filesystem ID for a mount and store it in the mount structure.
+ * @discussion Filesystem IDs are returned as part of "struct statfs." This function is typically
+ * called as part of file-system specific mount code (i.e. through VFS_MOUNT).
+ * @param mp Mount to set an ID for.
+ */
+void vfs_getnewfsid(struct mount *mp);
+
+/*!
+ * @function vfs_getvfs
+ * @abstract Given a filesystem ID, look up a mount structure.
+ * @param fsid Filesystem ID to look up.
+ * @return Mountpoint if found, else NULL. Note unmounting mountpoints can be returned.
+ */
+mount_t vfs_getvfs(fsid_t *fsid);
+
+/*!
+ * @function vfs_mountedon
+ * @abstract Check whether a given block device has a filesystem mounted on it.
+ * @discussion Note that this is NOT a check for a covered vnode (the directory upon which
+ * a filesystem is mounted)--it is a test for whether a block device is being used as the source
+ * of a filesystem. Note that a block device marked as being mounted on cannot be opened.
+ * @param vp The vnode to test.
+ * @return EBUSY if vnode is indeed the source of a filesystem; 0 if it is not.
+ */
+int vfs_mountedon(struct vnode *vp);
+
+/*!
+ * @function vfs_unmountbyfsid
+ * @abstract Find a filesystem by ID and unmount it.
+ * @param fsid ID of filesystem to unmount, as found through (for example) statfs.
+ * @param flags MNT_FORCE: forcibly invalidate files open on the mount (though in-flight I/O operations
+ * will be allowed to complete).
+ * @param ctx Context against which to authenticate unmount operation.
+ * @return 0 for succcess, nonero for failure.
+ */
+int vfs_unmountbyfsid(fsid_t *fsid, int flags, vfs_context_t ctx);
+
+/*!
+ * @function vfs_event_signal
+ * @abstract Post a kqueue-style event on a filesystem (EVFILT_FS).
+ * @param fsid Unused.
+ * @param event Events to post.
+ * @param data Unused.
+ */
+void vfs_event_signal(fsid_t *fsid, u_int32_t event, intptr_t data);
+
+/*!
+ * @function vfs_event_init
+ * @abstract This function should not be called by kexts.
+ */
+void vfs_event_init(void); /* XXX We should not export this */
+
+/*!
+ * @function vfs_set_root_unmount_cleanly
+ * @abstract This function should be called by the root file system
+ * when it is being mounted if the file system state is consistent.
+ */
+void vfs_set_root_unmounted_cleanly(void);
+
+#ifdef KERNEL_PRIVATE
+int vfs_getbyid(fsid_t *fsid, ino64_t ino, vnode_t *vpp, vfs_context_t ctx);
+int vfs_getattr(mount_t mp, struct vfs_attr *vfa, vfs_context_t ctx);
+int vfs_setattr(mount_t mp, struct vfs_attr *vfa, vfs_context_t ctx);
+int vfs_extendedsecurity(mount_t);
+mount_t vfs_getvfs_by_mntonname(char *);
+vnode_t vfs_vnodecovered(mount_t mp); /* Returns vnode with an iocount that must be released with vnode_put() */
+vnode_t vfs_devvp(mount_t mp); /* Please see block comment with implementation */
+int vfs_nativexattrs(mount_t mp); /* whether or not the FS supports EAs natively */
+void * vfs_mntlabel(mount_t mp); /* Safe to cast to "struct label*"; returns "void*" to limit dependence of mount.h on security headers. */
+void vfs_setcompoundopen(mount_t mp);
+uint64_t vfs_throttle_mask(mount_t mp);
+int vfs_isswapmount(mount_t mp);
+
+struct vnode_trigger_info;
+
+/*!
+ * @function vfs_addtrigger
+ * @abstract Create an "external" trigger vnode: look up a vnode and mark it as
+ * a trigger. Can only safely be called in the context of a callback set by
+ * vfs_settriggercallback(). May only be used on a file which is not already
+ * marked as a trigger.
+ * @param relpath Path relative to root of mountpoint at which to mark trigger.
+ * @param vtip Information about trigger; analogous to "vnode_trigger_param"
+ * argument to vnode_create.
+ * @param ctx Authorization context.
+ */
+int vfs_addtrigger(mount_t mp, const char *relpath, struct vnode_trigger_info *vtip, vfs_context_t ctx);
+
+
+/*!
+ * @enum vfs_trigger_callback_op_t
+ * @abstract Operation to perform after an attempted unmount (successful or otherwise).
+ * @constant VTC_REPLACE Unmount failed: attempt to replace triggers. Only valid
+ * VFS operation to perform in this context is vfs_addtrigger().
+ * @constant VTC_RELEASE Unmount succeeded: release external triggering context.
+ */
+typedef enum {
+ VTC_REPLACE,
+ VTC_RELEASE
+} vfs_trigger_callback_op_t;
+
+/*!
+ * @typedef vfs_trigger_callback_t
+ * @abstract Callback to be passed to vfs_settriggercallback() and invoked from
+ * unmount context.
+ * @param mp Mountpoint on which unmount is occurring.
+ * @param op Operation (see vfs_trigger_callback_op_t)
+ * @param data Context passed to vfs_settriggercallback()
+ * @param ctx Authorization context in which unmount is occurring.
+ */
+typedef void vfs_trigger_callback_t(mount_t mp, vfs_trigger_callback_op_t op, void *data, vfs_context_t ctx);
+
+/*!
+ * @function vfs_settriggercallback
+ * @abstract Install a callback to be called after unmount attempts on a volume,
+ * to restore triggers for failed unmounts and release state for successful ones.
+ * @discussion Installs a callback which will be called in two situations: a
+ * failed unmount where vnodes may have been reclaimed and a successful unmount.
+ * Gives an external trigger-marking entity an opportunity to replace triggers
+ * which may have been reclaimed. The callback can only be installed (not
+ * cleared), and only one callback can be installed. The callback will be called
+ * with a read-write lock held on the mount point; in the VTC_REPLACE case, the
+ * <em>only</em> valid VFS operation to perform in the context of the callback is
+ * vfs_addtrigger() on the mountpoint in question. This rwlock is held in order
+ * to attempt to provide some modicum of coverage from lookups which might find
+ * missing trigger vnodes and receive spurious ENOENTs. Note that this
+ * protection is incomplete--current working directories, or traversals up into a
+ * volume via ".." may still find missing triggers. As of this writing, no
+ * serialization mechanism exists to do better than this.
+ * When the "op" is VTC_RELEASE, the mountpoint is going away, and the only valid
+ * VFS operation is to free the private data pointer if needed. The callback
+ * will be called immediately, with VTC_REPLACE, from vfs_settriggercallback(),
+ * if installation is successful.
+ * @param fsid FSID for filesystem in question.
+ * @param vtc Callback pointer.
+ * @param data Context pointer to be passed to callback.
+ * @param flags Currently unused.
+ * @param ctx Authorization context.
+ * @return 0 for success. EBUSY if a trigger has already been installed.
+ */
+int vfs_settriggercallback(fsid_t *fsid, vfs_trigger_callback_t vtc, void *data, uint32_t flags, vfs_context_t ctx);
+
+/* tags a volume as not supporting extended readdir for NFS exports */
+void mount_set_noreaddirext(mount_t);