summaryrefslogtreecommitdiff
path: root/static/netbsd/man9/bufferio.9
diff options
context:
space:
mode:
authorJacob McDonnell <jacob@jacobmcdonnell.com>2026-04-25 15:32:58 -0400
committerJacob McDonnell <jacob@jacobmcdonnell.com>2026-04-25 15:32:58 -0400
commit5cb84ec742fd33f78c8022863fadaa8d0d93e176 (patch)
tree1a81ca3665e6153923e40db7b0d988f8573ab59c /static/netbsd/man9/bufferio.9
parenta59214f344567c037d5776879bcfc5fcc1d4d5f6 (diff)
feat: Added NetBSD man pages
Diffstat (limited to 'static/netbsd/man9/bufferio.9')
-rw-r--r--static/netbsd/man9/bufferio.9442
1 files changed, 442 insertions, 0 deletions
diff --git a/static/netbsd/man9/bufferio.9 b/static/netbsd/man9/bufferio.9
new file mode 100644
index 00000000..67591629
--- /dev/null
+++ b/static/netbsd/man9/bufferio.9
@@ -0,0 +1,442 @@
+.\" $NetBSD: bufferio.9,v 1.18 2019/09/12 21:08:35 sevan Exp $
+.\"
+.\" Copyright (c) 2015 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Taylor R. Campbell.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd September 12, 2019
+.Dt BUFFERIO 9
+.Os
+.Sh NAME
+.Nm BUFFERIO ,
+.Nm biodone ,
+.Nm biowait ,
+.Nm getiobuf ,
+.Nm putiobuf ,
+.Nm nestiobuf_setup ,
+.Nm nestiobuf_done
+.Nd block I/O buffer transfers
+.Sh SYNOPSIS
+.In sys/buf.h
+.Ft void
+.Fn biodone "buf_t *bp"
+.Ft int
+.Fn biowait "buf_t *bp"
+.Ft buf_t *
+.Fn getiobuf "struct vnode *vp" "bool waitok"
+.Ft void
+.Fn putiobuf "buf_t *bp"
+.Ft void
+.Fn nestiobuf_setup "buf_t *mbp" "buf_t *bp" "int offset" \
+ "size_t size"
+.Ft void
+.Fn nestiobuf_done "buf_t *mbp" "int donebytes" "int error"
+.Sh DESCRIPTION
+The
+.Nm
+subsystem manages block I/O buffer transfers, described by the
+.Vt "struct buf"
+structure, which serves multiple purposes between users in
+.Nm ,
+users in
+.Xr buffercache 9 ,
+and users in block device drivers to execute transfers to physical
+disks.
+.Sh BLOCK DEVICE USERS
+Users of
+.Nm
+wishing to submit a buffer for block I/O transfer must obtain a
+.Vt "struct buf" ,
+e.g. via
+.Fn getiobuf ,
+fill its parameters, and submit it to a block device with
+.Xr bdev_strategy 9 ,
+usually via
+.Xr VOP_STRATEGY 9 .
+.Pp
+The parameters to an I/O transfer described by
+.Fa bp
+are specified by the following
+.Vt "struct buf"
+fields:
+.Bl -tag -width 6n -offset abcd
+.It Fa bp Ns Li "->b_flags"
+Flags specifying the type of transfer.
+.Bl -tag -width 6n -compact
+.It Dv B_READ
+Transfer is read from device.
+If not set, transfer is write to device.
+.It Dv B_ASYNC
+Asynchronous I/O.
+Caller must not provide
+.Fa bp Ns Li "->b_iodone"
+and must not call
+.Fn biowait bp .
+.El
+For legibility, callers should indicate writes by passing the
+pseudo-flag
+.Dv B_WRITE ,
+which is zero.
+.It Fa bp Ns Li "->b_data"
+Pointer to kernel virtual address of source/target for transfer.
+.It Fa bp Ns Li "->b_bcount"
+Nonnegative number of bytes requested for transfer.
+.It Fa bp Ns Li "->b_blkno"
+Block number at which to do transfer.
+.It Fa bp Ns Li "->b_iodone"
+I/O completion callback.
+.Dv B_ASYNC
+must not be set in
+.Fa bp Ns Li "->b_flags" .
+.El
+.Pp
+Additionally, if the I/O transfer is a write associated with a
+.Xr vnode 9
+.Fa vp ,
+then before the user submits it to a block device, the user must
+increment
+.Fa vp Ns Li "->v_numoutput" .
+The user must not acquire
+.Fa vp Ns Ap s
+vnode lock between incrementing
+.Fa vp Ns Li "->v_numoutput"
+and submitting
+.Fa bp
+to a block device \(em doing so will likely cause deadlock with the
+syncer.
+.Pp
+Block I/O transfer completion may be notified by the
+.Fa bp Ns Li "->b_iodone"
+callback, by signalling
+.Fn biowait
+waiters, or not at all in the
+.Dv B_ASYNC
+case.
+.Bl -dash
+.It
+If the user sets the
+.Fa bp Ns Li "->b_iodone"
+callback to a
+.Pf non- Dv NULL
+function pointer, it will be called in soft interrupt context when the
+I/O transfer is complete.
+The user
+.Em may not
+call
+.Fn biowait bp
+in this case.
+.It
+If
+.Dv B_ASYNC
+is set, then the I/O transfer is asynchronous and the user will not be
+notified when it is completed.
+The user
+.Em may not
+call
+.Fn biowait bp
+in this case.
+.It
+Otherwise, if
+.Fa bp Ns Li "->b_iodone"
+is
+.Dv NULL
+and
+.Dv B_ASYNC
+is not specified, the user may wait for the I/O transfer to complete
+with
+.Fn biowait bp .
+.El
+.Pp
+Once an I/O transfer has completed, its
+.Vt "struct buf"
+may be reused, but the user must first clear the
+.Dv BO_DONE
+flag of
+.Fa bp Ns Li "->b_oflags"
+before reusing it.
+.Sh NESTED I/O TRANSFERS
+Sometimes an I/O transfer from a single buffer in memory cannot go to a
+single location on a block device: it must be split up into smaller
+transfers for each segment of the memory buffer.
+.Pp
+After initializing the
+.Li b_flags ,
+.Li b_data ,
+and
+.Li b_bcount
+parameters of an I/O transfer for the buffer, called the
+.Em master
+buffer, the user can issue smaller transfers for segments of the buffer
+using
+.Fn nestiobuf_setup .
+When nested I/O transfers complete, in any order, they debit from the
+amount of work left to be done in the master buffer.
+If any segments of the buffer were skipped, the user can report this
+with
+.Fn nestiobuf_done
+to debit the skipped part of the work.
+.Pp
+The master buffer's I/O transfer is completed when all nested buffers'
+I/O transfers are completed, and if
+.Fn nestiobuf_done
+is called in the case of skipped segments.
+.Pp
+For writes associated with a vnode
+.Fa vp ,
+.Fn nestiobuf_setup
+accounts for
+.Fa vp Ns Li "->v_numoutput" ,
+so the caller is not allowed to acquire
+.Fa vp Ns Ap s
+vnode lock before submitting the nested I/O transfer to a block
+device.
+However, the caller is responsible for accounting the master buffer in
+.Fa vp Ns Li "->v_numoutput" .
+This must be done very carefully because after incrementing
+.Fa vp Ns Li "->v_numoutput" ,
+the caller is not allowed to acquire
+.Fa vp Ns Ap s
+vnode lock before either calling
+.Fn nestiobuf_done
+or submitting the last nested I/O transfer to a block device.
+.Pp
+For example:
+.Bd -literal -offset abcd
+struct buf *mbp, *bp;
+size_t skipped = 0;
+unsigned i;
+int error = 0;
+
+mbp = getiobuf(vp, true);
+mbp->b_data = data;
+mbp->b_resid = mbp->b_bcount = datalen;
+mbp->b_flags = B_WRITE;
+
+KASSERT(0 < nsegs);
+KASSERT(datalen == nsegs*segsz);
+for (i = 0; i < nsegs; i++) {
+ struct vnode *devvp;
+ daddr_t blkno;
+
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ error = VOP_BMAP(vp, i*segsz, &devvp, &blkno, NULL);
+ VOP_UNLOCK(vp);
+ if (error == 0 && blkno == -1)
+ error = EIO;
+ if (error) {
+ /* Give up early, don't try to handle holes. */
+ skipped += datalen - i*segsz;
+ break;
+ }
+
+ bp = getiobuf(vp, true);
+ nestiobuf_setup(bp, mbp, i*segsz, segsz);
+ bp->b_blkno = blkno;
+ if (i == nsegs - 1) /* Last segment. */
+ break;
+ VOP_STRATEGY(devvp, bp);
+}
+
+/*
+ * Account v_numoutput for master write.
+ * (Must not vn_lock before last VOP_STRATEGY!)
+ */
+mutex_enter(&vp->v_interlock);
+vp->v_numoutput++;
+mutex_exit(&vp->v_interlock);
+
+if (skipped)
+ nestiobuf_done(mbp, skipped, error);
+else
+ VOP_STRATEGY(devvp, bp);
+.Ed
+.Sh BLOCK DEVICE DRIVERS
+Block device drivers implement a
+.Sq strategy
+method, in the
+.Li d_strategy
+member of
+.Li struct bdevsw
+.Pq Xr driver 9 ,
+to queue a buffer for disk I/O.
+The inputs to the strategy method are:
+.Bl -tag -width 6n -offset abcd
+.It Fa bp Ns Li "->b_flags"
+Flags specifying the type of transfer.
+.Bl -tag -width 6n -compact
+.It Dv B_READ
+Transfer is read from device.
+If not set, transfer is write to device.
+.El
+.It Fa bp Ns Li "->b_data"
+Pointer to kernel virtual address of source/target for transfer.
+.It Fa bp Ns Li "->b_bcount"
+Nonnegative number of bytes requested for transfer.
+.It Fa bp Ns Li "->b_blkno"
+Block number at which to do transfer, relative to partition start.
+.El
+.Pp
+If the strategy method uses
+.Xr bufq 9 ,
+it must additionally initialize the following fields before queueing
+.Fa bp
+with
+.Xr bufq_put 9 :
+.Bl -tag -width 6n -offset abcd
+.It Fa bp Ns Li "->b_rawblkno"
+Block number relative to volume start.
+.El
+.Pp
+When the I/O transfer is complete, whether it succeeded or failed, the
+strategy method must:
+.Bl -dash
+.It
+Set
+.Fa bp Ns Li "->b_error"
+to zero on success, or to an
+.Xr errno 2
+error code on failure.
+.It
+Set
+.Fa bp Ns Li "->b_resid"
+to the number of bytes remaining to transfer, whether on success or
+on failure.
+If no bytes were transferred, this must be set to
+.Fa bp Ns Li "->b_bcount" .
+.It
+Call
+.Fn biodone bp .
+.El
+.Sh FUNCTIONS
+.Bl -tag -width abcd
+.It Fn biodone bp
+Notify that the I/O transfer described by
+.Fa bp
+has completed.
+.Pp
+To be called by a block device driver.
+Caller must first set
+.Fa bp Ns Li "->b_error"
+to an error code and
+.Fa bp Ns Li "->b_resid"
+to the number of bytes remaining to transfer.
+.It Fn biowait bp
+Wait for the synchronous I/O transfer described by
+.Fa bp
+to complete.
+Returns the value of
+.Fa bp Ns Li "->b_error" .
+.Pp
+To be called by a user requesting the I/O transfer.
+.Pp
+May not be called if
+.Fa bp
+has a callback or is asynchronous \(em that is, if
+.Fa bp Ns Li "->b_iodone"
+is set, or if
+.Dv B_ASYNC
+is set in
+.Fa bp Ns Li "->b_flags" .
+.It Fn getiobuf vp waitok
+Allocate a
+.Vt "struct buf"
+for an I/O transfer.
+If
+.Fa vp
+is
+.Pf non- Dv NULL ,
+the transfer is associated with it.
+If
+.Fa waitok
+is false,
+returns
+.Dv NULL
+if none can be allocated immediately.
+.Pp
+The resulting
+.Vt "struct buf"
+pointer must eventually be passed to
+.Fn putiobuf
+to release it.
+Do
+.Em not
+use
+.Xr brelse 9 .
+.Pp
+The buffer may not be used for an asynchronous I/O transfer, because
+there is no way to know when it is completed and may be safely passed
+to
+.Fn putiobuf .
+Asynchronous I/O transfers are allowed only for buffers in the
+.Xr buffercache 9 .
+.Pp
+May sleep if
+.Fa waitok
+is true.
+.It Fn putiobuf bp
+Free
+.Fa bp ,
+which must have been allocated by
+.Fn getiobuf .
+Either
+.Fa bp
+must never have been submitted to a block device, or the I/O transfer
+must have completed.
+.El
+.Sh CODE REFERENCES
+The
+.Nm
+subsystem is implemented in
+.Pa sys/kern/vfs_bio.c .
+.Sh SEE ALSO
+.Xr buffercache 9 ,
+.Xr bufq 9
+.Sh BUGS
+The
+.Nm
+abstraction provides no way to cancel an I/O transfer once it has been
+submitted to a block device.
+.Pp
+The
+.Nm
+abstraction provides no way to do I/O transfers with non-kernel pages,
+e.g. directly to buffers in userland without copying into the kernel
+first.
+.Pp
+The
+.Vt "struct buf"
+type is all mixed up with the
+.Xr buffercache 9 .
+.Pp
+The
+.Nm
+abstraction is a totally idiotic API design.
+.Pp
+The
+.Li v_numoutput
+accounting required of
+.Nm
+callers is asinine.