-#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().
- @return void.
- */
-void buf_flushdirtyblks(vnode_t, int, int, const char *);
-
-/*!
- @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 flag
- 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.
- @return void.
- */
-void buf_iterate(vnode_t, int (*)(buf_t, void *), int, void *);
-
-/*!
- @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.
- @return void.
- */
-void buf_clear(buf_t);
-
-/*!
- @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.
- @param throttle If "throttle" is nonzero and more than VNODE_ASYNC_THROTTLE writes are in progress on this file,
- buf_bawrite() will block until the write count drops below VNODE_ASYNC_THROTTLE. If "throttle" is zero and the write
- count is high, it will fail with EWOULDBLOCK; the caller can decide whether to make a blocking call or pursue
- other opportunities.
- @return EWOULDBLOCK if write count is high and "throttle" is zero; otherwise, errors from VNOP_BWRITE.
- */
-errno_t buf_bawrite(buf_t);
-
-/*!
- @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.
- @param return_error If the number of pending delayed writes systemwide is larger than an internal limit,
- return EAGAIN rather than doing an asynchronous write.
- @return EAGAIN for return_error != 0 case, 0 for succeess, errors from buf_bawrite.
- */
-errno_t buf_bdwrite(buf_t);
-
-/*!
- @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);
-
-/*!
- @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.
- @return void.
- */
-void buf_biodone(buf_t);
-
-/*!
- @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);
-
-/*!
- @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.
- @retrn void.
- */
-void buf_brelse(buf_t);
-
-/*!
- @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, daddr64_t, int, kauth_cred_t, buf_t *);
-
-/*!
- @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, daddr64_t, int, daddr64_t *, int *, int, kauth_cred_t, buf_t *);
-
-/*!
- @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, daddr64_t, int, kauth_cred_t, buf_t *);
-
-/*!
- @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, daddr64_t, int, daddr64_t *, int *, int, kauth_cred_t, buf_t *);
-
-/*!
- @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.
- */
-u_int minphys(buf_t bp);
-
-/*!
- @function physio
- @abstract Perform I/O on a device to/from target memory described by a uio.
- @discussion physio() allows I/O directly from a device to user-space memory. It waits
- for all I/O to complete before returning.
- @param f_strategy Strategy routine to call to initiate I/O.
- @param bp Buffer to configure and pass to strategy routine; can be NULL.
- @param dev Device on which to perform I/O.
- @param flags B_READ or B_WRITE.
- @param f_minphys Function which calls buf_setcount() to set a byte count which is suitably
- small for the device in question. Returns byte count that has been set (or unchanged) on the buffer.
- @param uio UIO describing the I/O operation.
- @param blocksize Logical block size for this vnode.
- @return 0 for success; EFAULT for an invalid uio; errors from buf_biowait().
- */
-int physio(void (*)(buf_t), buf_t, dev_t, int , u_int (*)(buf_t), struct uio *, int );
+#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.
+ */
+u_int minphys(buf_t bp);
+
+/*!
+ * @function physio
+ * @abstract Perform I/O on a device to/from target memory described by a uio.
+ * @discussion physio() allows I/O directly from a device to user-space memory. It waits
+ * for all I/O to complete before returning.
+ * @param f_strategy Strategy routine to call to initiate I/O.
+ * @param bp Buffer to configure and pass to strategy routine; can be NULL.
+ * @param dev Device on which to perform I/O.
+ * @param flags B_READ or B_WRITE.
+ * @param f_minphys Function which calls buf_setcount() to set a byte count which is suitably
+ * small for the device in question. Returns byte count that has been set (or unchanged) on the buffer.
+ * @param uio UIO describing the I/O operation.
+ * @param blocksize Logical block size for this vnode.
+ * @return 0 for success; EFAULT for an invalid uio; errors from buf_biowait().
+ */
+int physio(void (*f_strategy)(buf_t), buf_t bp, dev_t dev, int flags, u_int (*f_minphys)(buf_t), struct uio *uio, int blocksize);