NAME
dk_softc,
dk_init,
dk_attach,
dk_detach,
dk_open,
dk_close,
dk_size,
dk_dump,
dk_ioctl,
dk_strategy,
dk_strategy_defer,
dk_strategy_pending,
dk_start,
dk_done,
dk_drain,
dk_discard,
dk_getdefaultlabel,
dk_getdisklabel,
—
disk driver subroutines
SYNOPSIS
#include <sys/bufq.h>
#include <sys/disk.h>
#include <dev/dkvar.h>
void
dk_init(
struct
dk_softc *,
device_t,
int dtype);
void
dk_attach(
struct
dk_softc *);
void
dk_detach(
struct
dk_softc *);
int
dk_open(
struct
dk_softc *,
dev_t,
int flags,
int fmt,
struct lwp *);
int
dk_close(
struct
dk_softc *,
dev_t,
int flags,
int fmt,
struct lwp *);
int
dk_discard(
struct
dk_softc *,
dev_t,
off_t pos,
off_t len);
int
dk_size(
struct
dk_softc *,
dev_t);
int
dk_dump(
struct
dk_softc *,
dev_t,
daddr_t blkno,
void *vav,
size_t size);
int
dk_ioctl(
struct
dk_softc *,
dev_t,
u_long cmd,
void *data,
int flag,
struct lwp *);
void
dk_strategy(
struct
dk_softc *,
struct buf
*);
int
dk_strategy_defer(
struct
dk_softc *,
struct buf
*);
int
dk_strategy_pending(
struct
dk_softc *);
void
dk_start(
struct
dk_softc *,
struct buf
*);
void
dk_done(
struct
dk_softc *,
struct buf
*);
int
dk_drain(
struct
dk_softc *);
void
dk_getdefaultlabel(
struct
dk_softc *,
struct
disklabel *);
void
dk_getdisklabel(
struct
dk_softc *,
dev_t);
DESCRIPTION
The disk driver subroutines provide common functionality for all disk drivers to
reduce the amount of replicated code. For many disk drivers, their
corresponding entry points can be made mostly stubs.
The subroutines encapsulate data structures found in a driver's softc into
struct dk_softc {
device_t sc_dev;
struct disk sc_dkdev;
struct bufq_state sc_bufq;
krndsource_t sc_rnd_source;
}
The
dk_softc structure therefore replaces the
device_t member of the driver's softc struct.
The following is a brief description of each function in the framework:
-
-
- dk_init()
- Initialize the dk_softc structure.
-
-
- dk_attach()
- Attach framework after driver has attached the
disk(9) subsystem, created a
bufq(9) and is ready to handle
I/O.
-
-
- dk_detach()
- Undo dk_attach.
-
-
- dk_open()
- Handles open steps for the
disk(9) framework, acquires
the disklabel and validates open parameters. The driver may provide the
d_firstopen callback to handle initialization
steps.
-
-
- dk_close()
- Handles close steps for the
disk(9) framework. The driver
may provide the d_lastclose callback to handle
finalization steps. dk_open and
dk_close are serialized by the openlock mutex.
-
-
- dk_discard()
- Validates parameters, computes raw block numbers and passes
these to the d_discard callback.
-
-
- dk_size()
- Returns dump size information from the
disklabel(9) and opens
and closes the driver when necessary.
-
-
- dk_dump()
- Validates parameters, computes raw block numbers and
iterates over the d_dumpblocks callback in appropriate
chunks determined by the d_iosize callback.
-
-
- dk_ioctl()
- Handles the ioctls
DIOCKLABEL
,
DIOCWLABEL
, DIOCGDEFLABEL
,
DIOCGSTRATEGY
, and
DIOCSSTRATEGY
and passes other disk ioctls through
the disk(9) framework. Returns
ENOTTY when an ioctl isn't implemented. This routine is
run as a fallback to handle commands that are not specific to the
driver.
-
-
- dk_strategy()
- Validates parameters, computes raw block numbers, queues a
buffer for I/O and triggers queue processing by calling
dk_start.
-
-
- dk_strategy_defer()
- Alternative to dk_strategy that only
queues the buffer. Drivers that implement a separate I/O thread can use
dk_strategy_defer within their own strategy routine and
signal the thread through a private interface.
-
-
- dk_strategy_pending()
- This function is called by an I/O thread to determine if
work has been queued by dk_strategy_defer. The driver
must then call dk_start to trigger queue
processing.
-
-
- dk_start()
- If bp !=
NULL
put it into the queue. Run the d_diskstart callback for
every buffer until the queue is empty or the callback returns
EAGAIN. In the latter case, the buffer is saved and
issued on the next queue run. This also calls disk_busy
accordingly to handle I/O metrics.
-
-
- dk_done()
- Called by the driver when an I/O operation completed.
dk_done logs errors, calls disk_unbusy
to handle I/O metrics and collects entropy for the
cprng(9).
-
-
- dk_drain()
- Aborts all queued I/O. This function must be called instead
of bufq_drain() to cooperate with
dk_start.
-
-
- dk_getdefaultlabel()
- Compute a common default disklabel for all disk drivers.
Some drivers provide device specific information or assign specific disk
formats to partitions. Such drivers may implement the
d_label callback that is called by
dk_getdefaultlabel after initializing the label with
common values.
-
-
- dk_getdisklabel()
- Read disklabel with machine dependent low-level function
readdisklabel and do sanity checks.
DRIVER INTERFACE
The driver needs to provide a common set of entry points that are used by the
disk driver subroutines and the
disk(9) framework.
struct dkdriver {
void (*d_strategy)(struct buf *);
void (*d_minphys)(struct buf *);
int (*d_open)(dev_t, int, int, struct lwp *);
int (*d_close)(dev_t, int, int, struct lwp *);
int (*d_diskstart)(device_t, struct buf *);
void (*d_iosize)(device_t, int *);
int (*d_dumpblocks)(device_t, void *, daddr_t, int);
int (*d_lastclose)(device_t);
int (*d_discard)(device_t, off_t, off_t);
int (*d_firstopen)(device_t, dev_t, int, int);
void (*d_label)(device_t, struct disklabel *);
};
-
-
- d_strategy()
- The driver strategy routine queues a single buffer for I/O
and starts queue processing as appropriate.
-
-
- d_minphys()
- The driver minphys routine limits the buffer
b_bcount to the maximum size for an I/O transfer
supported by the driver and hardware. It also calls
minphys to apply the platform limit.
-
-
- d_open()
- The driver open routine.
-
-
- d_close()
- The driver close routine.
-
-
- d_diskstart()
- Issues a single I/O request, called by
dk_start.
-
-
- d_iosize()
- Truncate I/O size to the driver limit. This is similar to
minphys but operates on an integer value instead of a
buffer.
-
-
- d_dumpblocks()
- Issue a single I/O requests, called by
dk_dump.
-
-
- d_lastclose()
- Private cleanup after last user is finished. Often used to
flush write caches.
-
-
- d_discard()
- Issue a single I/O request to invalidate a disk
region.
-
-
- d_firstopen()
- Private initialization when first user opens the
driver.
SEE ALSO
cgd(4),
ld(4),
cprng(9),
disk(9),
driver(9)
HISTORY
The
NetBSD common disk driver subroutines appeared in
NetBSD 2.0 as a base for the cryptographic disk driver
and was extended to handle disk wedges in
NetBSD 4.0.
Most functionality provided by
ld(4)
was included and extended in
NetBSD 8.0 to support
other disk drivers. The callback interface used by the
disk(9) framework has been merged
as well.
BUGS
The framework includes a
dk_lookup helper function, that is
used by the
cgd(4) driver to open a
vnode for a block device. This looks too generic and should be put somewhere
better (and be renamed).