+ * flags for buf_flushdirtyblks and buf_iterate
+ */
+#define BUF_SKIP_NONLOCKED 0x01
+#define BUF_SKIP_LOCKED 0x02
+#define BUF_SCAN_CLEAN 0x04 /* scan the clean buffers */
+#define BUF_SCAN_DIRTY 0x08 /* scan the dirty buffers */
+#define BUF_NOTIFY_BUSY 0x10 /* notify the caller about the busy pages during the scan */
+
+
+#define BUF_RETURNED 0
+#define BUF_RETURNED_DONE 1
+#define BUF_CLAIMED 2
+#define BUF_CLAIMED_DONE 3
+/*!
+ * @function buf_flushdirtyblks
+ * @abstract Write dirty file blocks to disk.
+ * @param vp The vnode whose blocks to flush.
+ * @param wait Wait for writes to complete before returning.
+ * @param flags Can pass zero, meaning "flush all dirty buffers."
+ * BUF_SKIP_NONLOCKED: Skip buffers which are not busy when we encounter them.
+ * BUF_SKIP_LOCKED: Skip buffers which are busy when we encounter them.
+ * @param msg String to pass to msleep().
+ */
+void buf_flushdirtyblks(vnode_t vp, int wait, int flags, const char *msg);
+
+/*!
+ * @function buf_iterate
+ * @abstract Perform some operation on all buffers associated with a vnode.
+ * @param vp The vnode whose buffers to scan.
+ * @param callout Function to call on each buffer. Should return one of:
+ * BUF_RETURNED: buf_iterate() should call buf_brelse() on the buffer.
+ * BUF_RETURNED_DONE: buf_iterate() should call buf_brelse() on the buffer and then stop iterating.
+ * BUF_CLAIMED: buf_iterate() should continue iterating (and not call buf_brelse()).
+ * BUF_CLAIMED_DONE: buf_iterate() should stop iterating (and not call buf_brelse()).
+ * @param flags
+ * BUF_SKIP_NONLOCKED: Skip buffers which are not busy when we encounter them. BUF_SKIP_LOCKED: Skip buffers which are busy when we encounter them.
+ * BUF_SCAN_CLEAN: Call out on clean buffers.
+ * BUF_SCAN_DIRTY: Call out on dirty buffers.
+ * BUF_NOTIFY_BUSY: If a buffer cannot be acquired, pass a NULL buffer to callout; otherwise,
+ * that buffer will be silently skipped.
+ * @param arg Argument to pass to callout in addition to buffer.
+ */
+void buf_iterate(vnode_t vp, int (*callout)(buf_t, void *), int flags, void *arg);
+
+/*!
+ * @function buf_clear
+ * @abstract Zero out the storage associated with a buffer.
+ * @discussion Calls buf_map() to get the buffer's data address; for a B_CLUSTER
+ * buffer (one which has had buf_setupl() called on it), it tries to map the buffer's
+ * UPL into memory; should only be called once during the life cycle of an iobuf (one allocated
+ * with buf_alloc()).
+ * @param bp The buffer to zero out.
+ */
+void buf_clear(buf_t bp);
+
+/*!
+ * @function buf_bawrite
+ * @abstract Start an asychronous write on a buffer.
+ * @discussion Calls VNOP_BWRITE to start the process of propagating an asynchronous write down to the device layer.
+ * Callers can wait for writes to complete at their discretion using buf_biowait(). When this function is called,
+ * data should already have been written to the buffer's data region.
+ * @param bp The buffer on which to initiate I/O.
+ * @return EWOULDBLOCK if write count is high and "throttle" is zero; otherwise, errors from VNOP_BWRITE.
+ */
+errno_t buf_bawrite(buf_t bp);
+
+/*!
+ * @function buf_bdwrite
+ * @abstract Mark a buffer for delayed write.
+ * @discussion Marks a buffer as waiting for delayed write and the current I/O as complete; data will be written to backing store
+ * before the buffer is reused, but it will not be queued for I/O immediately. Note that for buffers allocated
+ * with buf_alloc(), there are no such guarantees; you must take care of your own flushing to disk. If
+ * the number of delayed writes pending on the system is greater than an internal limit and the caller has not
+ * requested otherwise [see return_error] , buf_bdwrite() will unilaterally launch an asynchronous I/O with buf_bawrite() to keep the pile of
+ * delayed writes from getting too large.
+ * @param bp The buffer to mark for delayed write.
+ * @return EAGAIN for return_error != 0 case, 0 for succeess, errors from buf_bawrite.
+ */
+errno_t buf_bdwrite(buf_t bp);
+
+/*!
+ * @function buf_bwrite
+ * @abstract Write a buffer's data to backing store.
+ * @discussion Once the data in a buffer has been modified, buf_bwrite() starts sending it to disk by calling
+ * VNOP_STRATEGY. Unless B_ASYNC has been set on the buffer (by buf_setflags() or otherwise), data will have
+ * been written to disk when buf_bwrite() returns. See Bach (p 56).
+ * @param bp The buffer to write to disk.
+ * @return 0 for success; errors from buf_biowait().
+ */
+errno_t buf_bwrite(buf_t bp);
+
+/*!
+ * @function buf_biodone
+ * @abstract Mark an I/O as completed.
+ * @discussion buf_biodone() should be called by whosoever decides that an I/O on a buffer is complete; for example,
+ * IOStorageFamily. It clears the dirty flag on a buffer and signals on the vnode that a write has completed
+ * with vnode_writedone(). If a callout or filter has been set on the buffer, that function is called. In the case
+ * of a callout, that function is expected to take care of cleaning up and freeing the buffer.
+ * Otherwise, if the buffer is marked B_ASYNC (e.g. it was passed to buf_bawrite()), then buf_biodone()
+ * considers itself justified in calling buf_brelse() to return it to free lists--no one is waiting for it. Finally,
+ * waiters on the bp (e.g. in buf_biowait()) are woken up.
+ * @param bp The buffer to mark as done with I/O.
+ */
+void buf_biodone(buf_t bp);
+
+/*!
+ * @function buf_biowait
+ * @abstract Wait for I/O on a buffer to complete.
+ * @discussion Waits for I/O on a buffer to finish, as marked by a buf_biodone() call.
+ * @param bp The buffer to wait on.
+ * @return 0 for a successful wait; nonzero the buffer has been marked as EINTR or had an error set on it.
+ */
+errno_t buf_biowait(buf_t bp);
+
+/*!
+ * @function buf_brelse
+ * @abstract Release any claim to a buffer, sending it back to free lists.
+ * @discussion buf_brelse() cleans up buffer state and releases a buffer to the free lists. If the buffer
+ * is not marked invalid and its pages are dirty (e.g. a delayed write was made), its data will be commited
+ * to backing store. If it is marked invalid, its data will be discarded completely.
+ * A valid, cacheable buffer will be put on a list and kept in the buffer hash so it
+ * can be found again; otherwise, it will be dissociated from its vnode and treated as empty. Which list a valid
+ * buffer is placed on depends on the use of buf_markaged(), whether it is metadata, and the B_LOCKED flag. A
+ * B_LOCKED buffer will not be available for reuse by other files, though its data may be paged out.
+ * Note that buf_brelse() is intended for use with traditionally allocated buffers.
+ * @param bp The buffer to release.
+ */
+void buf_brelse(buf_t bp);
+
+/*!
+ * @function buf_bread
+ * @abstract Synchronously read a block of a file.
+ * @discussion buf_bread() is the traditional way to read a single logical block of a file through the buffer cache.
+ * It tries to find the buffer and corresponding page(s) in core, calls VNOP_STRATEGY if necessary to bring the data
+ * into memory, and waits for I/O to complete. It should not be used to read blocks of greater than 4K (one VM page)
+ * in size; use cluster routines for large reads. Indeed, the cluster layer is a more efficient choice for reading DATA
+ * unless you need some finely-tuned semantics that it cannot provide.
+ * @param vp The file from which to read.
+ * @param blkno The logical (filesystem) block number to read.
+ * @param size Size of block; do not use for sizes > 4K.
+ * @param cred Credential to store and use for reading from disk if data are not already in core.
+ * @param bpp Destination pointer for buffer.
+ * @return 0 for success, or an error from buf_biowait().
+ */
+errno_t buf_bread(vnode_t vp, daddr64_t blkno, int size, kauth_cred_t cred, buf_t *bpp);
+
+/*!
+ * @function buf_breadn
+ * @abstract Read a block from a file with read-ahead.
+ * @discussion buf_breadn() reads one block synchronously in the style of buf_bread() and fires
+ * off a specified set of asynchronous reads to improve the likelihood of future cache hits.
+ * It should not be used to read blocks of greater than 4K (one VM page) in size; use cluster
+ * routines for large reads. Indeed, the cluster layer is a more efficient choice for reading DATA
+ * unless you need some finely-tuned semantics that it cannot provide.
+ * @param vp The file from which to read.
+ * @param blkno The logical (filesystem) block number to read synchronously.
+ * @param size Size of block; do not use for sizes > 4K.
+ * @param rablks Array of logical block numbers for asynchronous read-aheads.
+ * @param rasizes Array of block sizes for asynchronous read-aheads, each index corresponding to same index in "rablks."
+ * @param nrablks Number of entries in read-ahead arrays.
+ * @param cred Credential to store and use for reading from disk if data are not already in core.
+ * @param bpp Destination pointer for buffer.
+ * @return 0 for success, or an error from buf_biowait().
+ */
+errno_t buf_breadn(vnode_t vp, daddr64_t blkno, int size, daddr64_t *rablks, int *rasizes, int nrablks, kauth_cred_t cred, buf_t *bpp);
+
+/*!
+ * @function buf_meta_bread
+ * @abstract Synchronously read a metadata block of a file.
+ * @discussion buf_meta_bread() is the traditional way to read a single logical block of a file through the buffer cache.
+ * It tries to find the buffer and corresponding page(s) in core, calls VNOP_STRATEGY if necessary to bring the data
+ * into memory, and waits for I/O to complete. It should not be used to read blocks of greater than 4K (one VM page)
+ * in size; use cluster routines for large reads. Reading meta-data through the traditional buffer cache, unlike
+ * reading data, is efficient and encouraged, especially if the blocks being read are significantly smaller than page size.
+ * @param vp The file from which to read.
+ * @param blkno The logical (filesystem) block number to read.
+ * @param size Size of block; do not use for sizes > 4K.
+ * @param cred Credential to store and use for reading from disk if data are not already in core.
+ * @param bpp Destination pointer for buffer.
+ * @return 0 for success, or an error from buf_biowait().
+ */
+errno_t buf_meta_bread(vnode_t vp, daddr64_t blkno, int size, kauth_cred_t cred, buf_t *bpp);
+
+/*!
+ * @function buf_meta_breadn
+ * @abstract Read a metadata block from a file with read-ahead.
+ * @discussion buf_meta_breadn() reads one block synchronously in the style of buf_meta_bread() and fires
+ * off a specified set of asynchronous reads to improve the likelihood of future cache hits.
+ * It should not be used to read blocks of greater than 4K (one VM page) in size; use cluster
+ * routines for large reads.
+ * @param vp The file from which to read.
+ * @param blkno The logical (filesystem) block number to read synchronously.
+ * @param size Size of block; do not use for sizes > 4K.
+ * @param rablks Array of logical block numbers for asynchronous read-aheads.
+ * @param rasizes Array of block sizes for asynchronous read-aheads, each index corresponding to same index in "rablks."
+ * @param nrablks Number of entries in read-ahead arrays.
+ * @param cred Credential to store and use for reading from disk if data are not already in core.
+ * @param bpp Destination pointer for buffer.
+ * @return 0 for success, or an error from buf_biowait().
+ */
+errno_t buf_meta_breadn(vnode_t vp, daddr64_t blkno, int size, daddr64_t *rablks, int *rasizes, int nrablks, kauth_cred_t cred, buf_t *bpp);
+
+/*!
+ * @function minphys
+ * @abstract Adjust a buffer's count to be no more than maximum physical I/O transfer size for the host architecture.
+ * @discussion physio() takes as a parameter a function to bound transfer sizes for each VNOP_STRATEGY() call. minphys()
+ * is a default implementation. It calls buf_setcount() to make the buffer's count the min() of its current count
+ * and the max I/O size for the host architecture.
+ * @param bp The buffer whose byte count to modify.
+ * @return New byte count.