xref: /netbsd-src/share/man/man9/disk.9 (revision 01869ca4d24a86379a68731bf9706a9f0820fe4e)
1*01869ca4Swiz.\"	$NetBSD: disk.9,v 1.46 2017/07/03 21:28:48 wiz Exp $
26defd3c8Sthorpej.\"
36defd3c8Sthorpej.\" Copyright (c) 1995, 1996 Jason R. Thorpe.
46defd3c8Sthorpej.\" All rights reserved.
56defd3c8Sthorpej.\"
66defd3c8Sthorpej.\" Redistribution and use in source and binary forms, with or without
76defd3c8Sthorpej.\" modification, are permitted provided that the following conditions
86defd3c8Sthorpej.\" are met:
96defd3c8Sthorpej.\" 1. Redistributions of source code must retain the above copyright
106defd3c8Sthorpej.\"    notice, this list of conditions and the following disclaimer.
116defd3c8Sthorpej.\" 2. Redistributions in binary form must reproduce the above copyright
126defd3c8Sthorpej.\"    notice, this list of conditions and the following disclaimer in the
136defd3c8Sthorpej.\"    documentation and/or other materials provided with the distribution.
146defd3c8Sthorpej.\" 3. All advertising materials mentioning features or use of this software
156defd3c8Sthorpej.\"    must display the following acknowledgement:
166defd3c8Sthorpej.\"	This product includes software developed for the NetBSD Project
176defd3c8Sthorpej.\"	by Jason R. Thorpe.
186defd3c8Sthorpej.\" 4. The name of the author may not be used to endorse or promote products
196defd3c8Sthorpej.\"    derived from this software without specific prior written permission.
206defd3c8Sthorpej.\"
216defd3c8Sthorpej.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
226defd3c8Sthorpej.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
236defd3c8Sthorpej.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
246defd3c8Sthorpej.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
256defd3c8Sthorpej.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
266defd3c8Sthorpej.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
276defd3c8Sthorpej.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
286defd3c8Sthorpej.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
296defd3c8Sthorpej.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
306defd3c8Sthorpej.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
316defd3c8Sthorpej.\" SUCH DAMAGE.
326defd3c8Sthorpej.\"
3360123a6bSwiz.Dd March 5, 2017
346defd3c8Sthorpej.Dt DISK 9
35e4c16bfbSgarbled.Os
366defd3c8Sthorpej.Sh NAME
37c12c7ee6Smrg.Nm disk ,
38005a75ddSplunky.Nm disk_init ,
39c12c7ee6Smrg.Nm disk_attach ,
403579e266Sdyoung.Nm disk_begindetach ,
4165393351Swiz.Nm disk_detach ,
42005a75ddSplunky.Nm disk_destroy ,
43ba576b71Smlelstv.Nm disk_wait ,
44c12c7ee6Smrg.Nm disk_busy ,
45c12c7ee6Smrg.Nm disk_unbusy ,
467d611c43Shaad.Nm disk_isbusy ,
47c12c7ee6Smrg.Nm disk_find ,
480a0ac6a2Smlelstv.Nm disk_set_info
496defd3c8Sthorpej.Nd generic disk framework
506defd3c8Sthorpej.Sh SYNOPSIS
51472351e1Swiz.In sys/types.h
52472351e1Swiz.In sys/disklabel.h
53472351e1Swiz.In sys/disk.h
546defd3c8Sthorpej.Ft void
55005a75ddSplunky.Fn disk_init "struct disk *" "const char *name" "const struct dkdriver *driver"
56005a75ddSplunky.Ft void
576defd3c8Sthorpej.Fn disk_attach "struct disk *"
586defd3c8Sthorpej.Ft void
593579e266Sdyoung.Fn disk_begindetach "struct disk *" "int (*lastclose)(device_t)" "device_t self" "int flags"
603579e266Sdyoung.Ft void
61d1d8376bSpk.Fn disk_detach "struct disk *"
626defd3c8Sthorpej.Ft void
63005a75ddSplunky.Fn disk_destroy "struct disk *"
64005a75ddSplunky.Ft void
65ba576b71Smlelstv.Fn disk_wait "struct disk *"
66ba576b71Smlelstv.Ft void
676defd3c8Sthorpej.Fn disk_busy "struct disk *"
686defd3c8Sthorpej.Ft void
6906c8fdccSenami.Fn disk_unbusy "struct disk *" "long bcount" "int read"
707d611c43Shaad.Ft bool
717d611c43Shaad.Fn disk_isbusy "struct disk *"
726defd3c8Sthorpej.Ft struct disk *
73005a75ddSplunky.Fn disk_find "const char *"
74512f329fSscw.Ft void
750a0ac6a2Smlelstv.Fn disk_set_info "device_t" "struct disk *" "const char *type"
766defd3c8Sthorpej.Sh DESCRIPTION
7734a98169SperryThe
7834a98169Sperry.Nx
7934a98169Sperrygeneric disk framework is designed to provide flexible,
806defd3c8Sthorpejscalable, and consistent handling of disk state and metrics information.
816defd3c8SthorpejThe fundamental component of this framework is the
826defd3c8Sthorpej.Nm disk
836defd3c8Sthorpejstructure, which is defined as follows:
846defd3c8Sthorpej.Bd -literal
856defd3c8Sthorpejstruct disk {
866defd3c8Sthorpej	TAILQ_ENTRY(disk) dk_link;	/* link in global disklist */
87005a75ddSplunky	const char	*dk_name;	/* disk name */
88005a75ddSplunky	prop_dictionary_t dk_info;	/* reference to disk-info dictionary */
896defd3c8Sthorpej	int		dk_bopenmask;	/* block devices open */
906defd3c8Sthorpej	int		dk_copenmask;	/* character devices open */
916defd3c8Sthorpej	int		dk_openmask;	/* composite (bopen|copen) */
92005a75ddSplunky	int		dk_state;	/* label state   ### */
936defd3c8Sthorpej	int		dk_blkshift;	/* shift to convert DEV_BSIZE to blks */
946defd3c8Sthorpej	int		dk_byteshift;	/* shift to convert bytes to blks */
956defd3c8Sthorpej
966defd3c8Sthorpej	/*
976defd3c8Sthorpej	 * Metrics data; note that some metrics may have no meaning
986defd3c8Sthorpej	 * on certain types of disks.
996defd3c8Sthorpej	 */
100005a75ddSplunky	struct io_stats	*dk_stats;
1016defd3c8Sthorpej
102005a75ddSplunky	const struct dkdriver *dk_driver;	/* pointer to driver */
103005a75ddSplunky
104005a75ddSplunky	/*
105005a75ddSplunky	 * Information required to be the parent of a disk wedge.
106005a75ddSplunky	 */
107005a75ddSplunky	kmutex_t	dk_rawlock;	/* lock on these fields */
1082971e3abSabhinav	u_int		dk_rawopens;	/* # of opens of rawvp */
109005a75ddSplunky	struct vnode	*dk_rawvp;	/* vnode for the RAW_PART bdev */
110005a75ddSplunky
111005a75ddSplunky	kmutex_t	dk_openlock;	/* lock on these and openmask */
112005a75ddSplunky	u_int		dk_nwedges;	/* # of configured wedges */
113005a75ddSplunky					/* all wedges on this disk */
114005a75ddSplunky	LIST_HEAD(, dkwedge_softc) dk_wedges;
1156defd3c8Sthorpej
1166defd3c8Sthorpej	/*
1176defd3c8Sthorpej	 * Disk label information.  Storage for the in-core disk label
1186defd3c8Sthorpej	 * must be dynamically allocated, otherwise the size of this
1196defd3c8Sthorpej	 * structure becomes machine-dependent.
1206defd3c8Sthorpej	 */
1216defd3c8Sthorpej	daddr_t		dk_labelsector;		/* sector containing label */
1226defd3c8Sthorpej	struct disklabel *dk_label;	/* label */
1236defd3c8Sthorpej	struct cpu_disklabel *dk_cpulabel;
1246defd3c8Sthorpej};
1256defd3c8Sthorpej.Ed
1266defd3c8Sthorpej.Pp
1276defd3c8SthorpejThe system maintains a global linked-list of all disks attached to the
128770eef21Swizsystem.
129770eef21SwizThis list, called
1306defd3c8Sthorpej.Nm disklist ,
1316defd3c8Sthorpejmay grow or shrink over time as disks are dynamically added and removed
132770eef21Swizfrom the system.
133770eef21SwizDrivers which currently make use of the detachment
1346defd3c8Sthorpejcapability of the framework are the
1357f88d89fSjnemeth.Nm ccd ,
1367f88d89fSjnemeth.Nm dm ,
1377d611c43Shaadand
1387f88d89fSjnemeth.Nm vnd
1396defd3c8Sthorpejpseudo-device drivers.
1406defd3c8Sthorpej.Pp
1416defd3c8SthorpejThe following is a brief description of each function in the framework:
1422fbc2029Smlelstv.Bl -tag -width ".Fn disk_set_info"
143005a75ddSplunky.It Fn disk_init
144005a75ddSplunkyInitialize the disk structure.
1456defd3c8Sthorpej.It Fn disk_attach
1466defd3c8SthorpejAttach a disk; allocate storage for the disklabel, set the
1476defd3c8Sthorpej.Dq attached time
14865393351Swiztimestamp, insert the disk into the disklist, and increment the
1496defd3c8Sthorpejsystem disk count.
1503579e266Sdyoung.It Fn disk_begindetach
1513579e266SdyoungCheck whether the disk is open, and if not, return 0.
1523579e266SdyoungIf the disk is open, and
1533579e266Sdyoung.Dv DETACH_FORCE
1543579e266Sdyoungis not set in
1553579e266Sdyoung.Fa flags ,
1563579e266Sdyoungreturn
1573579e266Sdyoung.Dv EBUSY .
1583579e266SdyoungOtherwise, call the provided
1593579e266Sdyoung.Fa lastclose
1603579e266Sdyoungroutine
1613579e266Sdyoung.Po
1623579e266Sdyoungif not
1633579e266Sdyoung.Dv NULL
1643579e266Sdyoung.Pc
1653579e266Sdyoungand return its exit code.
166d1d8376bSpk.It Fn disk_detach
1674475e78cSjdolecekDetach a disk; free storage for the disklabel, remove the disk
168770eef21Swizfrom the disklist, and decrement the system disk count.
169770eef21SwizIf the count drops below zero, panic.
170005a75ddSplunky.It Fn disk_destroy
171005a75ddSplunkyRelease resources used by the disk structure when it is no longer
172005a75ddSplunkyrequired.
173ba576b71Smlelstv.It Fn disk_wait
174ba576b71SmlelstvDisk timings are measured by counting the number of queued
175ba576b71Smlelstvrequests (wait counter) and requests issued to the hardware (busy counter)
17660123a6bSwizand keeping timestamp when the counters change.
17760123a6bSwizThe time interval between
178ba576b71Smlelstvtwo changes of a counter is accumulated into a total and also multiplied
17960123a6bSwizby the counter value and the accumulated into a sum.
18060123a6bSwizBoth values can be
181ba576b71Smlelstvused to determine how much time is spent in the driver queue or in-flight
182ba576b71Smlelstvto the hardware as well as the average number of requests in either state.
183ba576b71Smlelstv.Fn disk_wait
184ba576b71Smlelstvincrement the disk's wait counter and handles the accumulation.
1856defd3c8Sthorpej.It Fn disk_busy
186ba576b71SmlelstvDecrements the disk's wait counter and increments the disk's
187ba576b71Smlelstv.Dq busy counter ,
18860123a6bSwizand handles either accumulation.
18960123a6bSwizIf the wait counter is still zero, it
190ba576b71Smlelstvis assumed that the driver hasn't been updated to call
191ba576b71Smlelstv.Fn disk_wait ,
192ba576b71Smlelstvthen only the values from the busy counter are available.
1936defd3c8Sthorpej.It Fn disk_unbusy
194ba576b71SmlelstvDecrement the disk's busy counter and handles the accumulation.
19506c8fdccSenamiThe third argument
19606c8fdccSenami.Ar read
19706c8fdccSenamispecifies the direction of I/O;
19806c8fdccSenamiif non-zero it means reading from the disk,
19906c8fdccSenamiotherwise it means writing to the disk.
2007d611c43Shaad.It Fn disk_isbusy
2017d611c43ShaadReturns
2027d611c43Shaad.Ar true
2037d611c43Shaadif disk is marked as busy and false if it is not.
2046defd3c8Sthorpej.It Fn disk_find
2056defd3c8SthorpejReturn a pointer to the disk structure corresponding to the name provided,
206e9d48278Swizor
207e9d48278Swiz.Dv NULL
208e9d48278Swizif the disk does not exist.
2090a0ac6a2Smlelstv.It Fn disk_set_info
2102fbc2029SmlelstvSetup disk-info dictionary and other dependent values of the disk structure,
2112fbc2029Smlelstvthe driver must have initialized the dk_geom member of
2120a0ac6a2Smlelstv.Fa struct disk
213e9d48278Swizwith suitable values.
214e9d48278SwizIf
2150a0ac6a2Smlelstv.Fa type
216e9d48278Swizis not
217e9d48278Swiz.Dv NULL ,
218e9d48278Swizit will be added to the dictionary.
2196defd3c8Sthorpej.El
2206defd3c8Sthorpej.Pp
2216defd3c8SthorpejThe functions typically called by device drivers are
222005a75ddSplunky.Fn disk_init
2236defd3c8Sthorpej.Fn disk_attach ,
2243579e266Sdyoung.Fn disk_begindetach ,
225d1d8376bSpk.Fn disk_detach ,
226005a75ddSplunky.Fn disk_destroy ,
227ba576b71Smlelstv.Fn disk_wait ,
2286defd3c8Sthorpej.Fn disk_busy ,
2296defd3c8Sthorpej.Fn disk_unbusy ,
2306defd3c8Sthorpejand
2312fbc2029Smlelstv.Fn disk_set_info .
2326defd3c8SthorpejThe function
2336defd3c8Sthorpej.Fn disk_find
2346defd3c8Sthorpejis provided as a utility function.
2351cc26678Sapb.Sh DISK IOCTLS
2361cc26678SapbThe following ioctls should be implemented by disk drivers:
2371cc26678Sapb.Bl -tag -width "xxxxxx"
2381cc26678Sapb.It Dv DIOCGDINFO "struct disklabel"
2391cc26678SapbGet disklabel.
2401cc26678Sapb.It Dv DIOCSDINFO "struct disklabel"
2411cc26678SapbSet in-memory disklabel.
2421cc26678Sapb.It Dv DIOCWDINFO "struct disklabel"
2437f88d89fSjnemethSet in-memory disklabel and write on-disk disklabel.
2441cc26678Sapb.It Dv DIOCGPART "struct partinfo"
2451cc26678SapbGet partition information.
2461cc26678SapbThis is used internally.
2471cc26678Sapb.It Dv DIOCRFORMAT "struct format_op"
2481cc26678SapbRead format.
2491cc26678Sapb.It Dv DIOCWFORMAT "struct format_op"
2501cc26678SapbWrite format.
2511cc26678Sapb.It Dv DIOCSSTEP "int"
2521cc26678SapbSet step rate.
2531cc26678Sapb.It Dv DIOCSRETRIES "int"
2541cc26678SapbSet number of retries.
2551cc26678Sapb.It Dv DIOCKLABEL "int"
2561cc26678SapbSpecify whether to keep or drop the in-memory disklabel
2571cc26678Sapbwhen the device is closed.
2581cc26678Sapb.It Dv DIOCWLABEL "int"
2591cc26678SapbEnable or disable writing to the part of the disk that contains the label.
2601cc26678Sapb.It Dv DIOCSBAD "struct dkbad"
2611cc26678SapbSet kernel dkbad.
2621cc26678Sapb.It Dv DIOCEJECT "int"
2631cc26678SapbEject removable disk.
2641cc26678Sapb.It Dv DIOCLOCK "int"
2651cc26678SapbLock or unlock disk pack.
2661cc26678SapbFor devices with removable media, locking is intended to prevent
2671cc26678Sapbthe operator from removing the media.
2681cc26678Sapb.It Dv DIOCGDEFLABEL "struct disklabel"
2691cc26678SapbGet default label.
2701cc26678Sapb.It Dv DIOCCLRLABEL
2711cc26678SapbClear disk label.
2721cc26678Sapb.It Dv DIOCGCACHE "int"
2731cc26678SapbGet status of disk read and write caches.
2741cc26678SapbThe result is a bitmask containing the following values:
2751cc26678Sapb.Bl -tag -width DKCACHE_RCHANGE
2761cc26678Sapb.It Dv DKCACHE_READ
2771cc26678SapbRead cache enabled.
2781cc26678Sapb.It Dv DKCACHE_WRITE
2791cc26678SapbWrite(back) cache enabled.
2801cc26678Sapb.It Dv DKCACHE_RCHANGE
2811cc26678SapbRead cache enable is changeable.
2821cc26678Sapb.It Dv DKCACHE_WCHANGE
2831cc26678SapbWrite cache enable is changeable.
2841cc26678Sapb.It Dv DKCACHE_SAVE
2851cc26678SapbCache parameters may be saved, so that they persist across reboots
2861cc26678Sapbor device detach/attach cycles.
2871cc26678Sapb.El
2881cc26678Sapb.It Dv DIOCSCACHE "int"
2891cc26678SapbSet status of disk read and write caches.
2901cc26678SapbThe input is a bitmask in the same format as used for
2911cc26678Sapb.Dv DIOCGCACHE .
2921cc26678Sapb.It Dv DIOCCACHESYNC "int"
2931cc26678SapbSynchronise the disk cache.
2941cc26678SapbThis causes information in the disk's write cache (if any)
2951cc26678Sapbto be flushed to stable storage.
2961cc26678SapbThe argument specifies whether or not to force a flush even if
2971cc26678Sapbthe kernel believes that there is no outstanding data.
2981cc26678Sapb.It Dv DIOCBSLIST "struct disk_badsecinfo"
2991cc26678SapbGet bad sector list.
3001cc26678Sapb.It Dv DIOCBSFLUSH
3011cc26678SapbFlush bad sector list.
3021cc26678Sapb.It Dv DIOCAWEDGE "struct dkwedge_info"
3031cc26678SapbAdd wedge.
3041cc26678Sapb.It Dv DIOCGWEDGEINFO "struct dkwedge_info"
3051cc26678SapbGet wedge information.
3061cc26678Sapb.It Dv DIOCDWEDGE "struct dkwedge_info"
3071cc26678SapbDelete wedge.
3081cc26678Sapb.It Dv DIOCLWEDGES "struct dkwedge_list"
3091cc26678SapbList wedges.
3101cc26678Sapb.It Dv DIOCGSTRATEGY "struct disk_strategy"
3111cc26678SapbGet disk buffer queue strategy.
3121cc26678Sapb.It Dv DIOCSSTRATEGY "struct disk_strategy"
3131cc26678SapbSet disk buffer queue strategy.
3141cc26678Sapb.It Dv DIOCGDISKINFO "struct plistref"
3151cc26678SapbGet disk-info dictionary.
31678d420c3Smlelstv.It Dv DIOCGMEDIASIZE "off_t"
31778d420c3SmlelstvGet disk size in bytes.
31878d420c3Smlelstv.It Dv DIOCGSECTORSIZE "u_int"
31978d420c3SmlelstvGet sector size in bytes.
3201cc26678Sapb.El
3216defd3c8Sthorpej.Sh USING THE FRAMEWORK
3226defd3c8SthorpejThis section includes a description on basic use of the framework
323770eef21Swizand example usage of its functions.
32443e0efbdSperryActual implementation of a device driver which uses the framework
325770eef21Swizmay vary.
3266defd3c8Sthorpej.Pp
3276defd3c8SthorpejEach device in the system uses a
3286defd3c8Sthorpej.Dq softc
3296defd3c8Sthorpejstructure which contains autoconfiguration and state information for that
330770eef21Swizdevice.
331770eef21SwizIn the case of disks, the softc should also contain one instance
33265393351Swizof the disk structure, e.g.:
3336defd3c8Sthorpej.Bd -literal
3346defd3c8Sthorpejstruct foo_softc {
335005a75ddSplunky	device_t	sc_dev;		/* generic device information */
336126dd689Sghudson	struct	disk	sc_dk;		/* generic disk information */
3376defd3c8Sthorpej	[ . . . more . . . ]
3386defd3c8Sthorpej};
3396defd3c8Sthorpej.Ed
3406defd3c8Sthorpej.Pp
3416defd3c8SthorpejIn order for the system to gather metrics data about a disk, the disk must
342770eef21Swizbe registered with the system.
343770eef21SwizThe
3446defd3c8Sthorpej.Fn disk_attach
3456defd3c8Sthorpejroutine performs all of the functions currently required to register a disk
3466defd3c8Sthorpejwith the system including allocation of disklabel storage space,
3476defd3c8Sthorpejrecording of the time since boot that the disk was attached, and insertion
348770eef21Swizinto the disklist.
349770eef21SwizNote that since this function allocates storage space for the disklabel,
350770eef21Swizit must be called before the disklabel is read from the media or used in
351770eef21Swizany other way.
352770eef21SwizBefore
3536defd3c8Sthorpej.Fn disk_attach
3546defd3c8Sthorpejis called, a portions of the disk structure must be initialized with
355770eef21Swizdata specific to that disk.
356770eef21SwizFor example, in the
3576defd3c8Sthorpej.Dq foo
3586defd3c8Sthorpejdisk driver, the following would be performed in the autoconfiguration
3596defd3c8Sthorpej.Dq attach
3606defd3c8Sthorpejroutine:
3616defd3c8Sthorpej.Bd -literal
3626defd3c8Sthorpejvoid
363005a75ddSplunkyfooattach(device_t parent, device_t self, void *aux)
3646defd3c8Sthorpej{
365005a75ddSplunky	struct foo_softc *sc = device_private(self);
3666defd3c8Sthorpej	[ . . . ]
3676defd3c8Sthorpej
3686defd3c8Sthorpej	/* Initialize and attach the disk structure. */
369*01869ca4Swiz	disk_init(&sc->sc_dk, device_xname(self), &foodkdriver);
370*01869ca4Swiz	disk_attach(&sc->sc_dk);
3716defd3c8Sthorpej
3726defd3c8Sthorpej	/* Read geometry and fill in pertinent parts of disklabel. */
3730a0ac6a2Smlelstv	/* Initialize geometry values of the disk structure */
3740a0ac6a2Smlelstv	[ . . . ]
375*01869ca4Swiz	disk_set_info(&self>, &sc->sc_dk, type);
3766defd3c8Sthorpej}
3776defd3c8Sthorpej.Ed
3786defd3c8Sthorpej.Pp
3796defd3c8SthorpejThe
3806defd3c8Sthorpej.Nm foodkdriver
3816defd3c8Sthorpejabove is the disk's
3826defd3c8Sthorpej.Dq driver
383770eef21Swizswitch.
3846e901747SmlelstvThis switch currently includes pointers to several driver entry points,
3856e901747Smlelstvwhere only the
3866e901747Smlelstv.Nm d_strategy
3876e901747Smlelstventry point is used by the disk framework.
388770eef21SwizThis switch needs to have global scope and should be initialized as follows:
3896defd3c8Sthorpej.Bd -literal
3906e901747Smlelstvvoid    (foostrategy)(struct buf *);
3916e901747Smlelstvvoid    (foominphys)(struct buf *);
3926e901747Smlelstvint     (fooopen)(dev_t, int, int, struct lwp *);
3936e901747Smlelstvint     (fooclose)(dev_t, int, int, struct lwp *);
3946e901747Smlelstvint     (foo_discard)(device_t, off_t, off_t);
3956e901747Smlelstvint     (foo_diskstart)(device_t, struct buf *);
3966e901747Smlelstvvoid    (foo_iosize)(device_t, int *);
3976e901747Smlelstvint     (foo_dumpblocks)(device_t, void *, daddr_t, int);
3986e901747Smlelstvint     (foo_lastclose)(device_t);
3996e901747Smlelstvint     (foo_firstopen)(device_t, dev_t, int, int);
4006e901747Smlelstvint     (foo_label)(device_t, struct disklabel *);
401005a75ddSplunky
402005a75ddSplunkyconst struct dkdriver foodkdriver = {
4036e901747Smlelstv	.d_open = fooopen,
4046e901747Smlelstv	.d_close = fooclose,
405005a75ddSplunky	.d_strategy = foostrategy,
4066e901747Smlelstv	.d_minphys = foominphys,
4076e901747Smlelstv	.d_discard = foo_discard,
4086e901747Smlelstv	.d_diskstart = foo_diskstart,	/* optional */
4096e901747Smlelstv	.d_dumpblocks = foo_dumpblocks,	/* optional */
4106e901747Smlelstv	.d_iosize = foo_iosize,		/* optional */
4116e901747Smlelstv	.d_firstopen = foo_firstopen,	/* optional */
4126e901747Smlelstv	.d_lastclose = foo_lastclose,	/* optional */
4136e901747Smlelstv	.d_label = foo_label,		/* optional */
414005a75ddSplunky};
4156defd3c8Sthorpej.Ed
4166defd3c8Sthorpej.Pp
417770eef21SwizOnce the disk is attached, metrics may be gathered on that disk.
418770eef21SwizIn order to gather metrics data, the driver must tell the framework when
419ba576b71Smlelstvthe disk queues, starts and stops operations.
420770eef21SwizThis functionality is provided by the
421ba576b71Smlelstv.Fn disk_wait ,
4226defd3c8Sthorpej.Fn disk_busy
4236defd3c8Sthorpejand
4246defd3c8Sthorpej.Fn disk_unbusy
425770eef21Swizroutines.
4267d611c43ShaadBecause
4277d611c43Shaad.Nm struct disk
4287f88d89fSjnemethis part of device driver private data it needs to be guarded.
4297f88d89fSjnemethMutual exclusion must be done by driver
430ba576b71Smlelstv.Fn disk_wait ,
4317d611c43Shaad.Fn disk_busy
4327d611c43Shaadand
4337d611c43Shaad.Fn disk_unbusy
4347d611c43Shaadare not thread safe.
435770eef21SwizThe
4366defd3c8Sthorpej.Fn disk_busy
4376defd3c8Sthorpejroutine should be called immediately before a command to the disk is
43865393351Swizsent, e.g.:
4396defd3c8Sthorpej.Bd -literal
4406defd3c8Sthorpejvoid
441ba576b71Smlelstvfoostrategy(struct buf *bp)
442ba576b71Smlelstv{
443ba576b71Smlelstv	[ . . . ]
444ba576b71Smlelstv
445*01869ca4Swiz	mutex_enter(&sc->sc_dk_mtx);
446*01869ca4Swiz	disk_wait(&sc->sc_dk);
447ba576b71Smlelstv
448ba576b71Smlelstv	/* Put buffer onto drive's transfer queue */
449ba576b71Smlelstv
450*01869ca4Swiz	mutex_exit(&sc->sc_dk_mtx);
451ba576b71Smlelstv
452ba576b71Smlelstv	foostart(sc);
453ba576b71Smlelstv}
454ba576b71Smlelstv
455ba576b71Smlelstvvoid
456ba576b71Smlelstvfoostart(struct foo_softc *sc)
4576defd3c8Sthorpej{
4586defd3c8Sthorpej	[ . . . ]
4596defd3c8Sthorpej
4606defd3c8Sthorpej	/* Get buffer from drive's transfer queue. */
4616defd3c8Sthorpej	[ . . . ]
4626defd3c8Sthorpej
4636defd3c8Sthorpej	/* Build command to send to drive. */
4646defd3c8Sthorpej	[ . . . ]
4656defd3c8Sthorpej
46610f36ab3Sjtc	/* Tell the disk framework we're going busy. */
467*01869ca4Swiz	mutex_enter(&sc->sc_dk_mtx);
468*01869ca4Swiz	disk_busy(&sc->sc_dk);
469*01869ca4Swiz	mutex_exit(&sc->sc_dk_mtx);
4706defd3c8Sthorpej
4716defd3c8Sthorpej	/* Send command to the drive. */
4726defd3c8Sthorpej	[ . . . ]
4736defd3c8Sthorpej}
4746defd3c8Sthorpej.Ed
4756defd3c8Sthorpej.Pp
476ba576b71SmlelstvThe routine
4776defd3c8Sthorpej.Fn disk_unbusy
478ba576b71Smlelstvperforms some consistency checks, such as ensuring that the calls to
4796defd3c8Sthorpej.Fn disk_busy
4806defd3c8Sthorpejand
4816defd3c8Sthorpej.Fn disk_unbusy
482770eef21Swizare balanced.
483ba576b71SmlelstvIt also performs the final steps of the metrics calcuation.
484ba576b71SmlelstvA byte count is added to the disk's running total, and if greater than
4856defd3c8Sthorpejzero, the number of transfers the disk has performed is incremented.
48606c8fdccSenamiThe third argument
48706c8fdccSenami.Ar read
48806c8fdccSenamispecifies the direction of I/O;
48906c8fdccSenamiif non-zero it means reading from the disk,
49006c8fdccSenamiotherwise it means writing to the disk.
4916defd3c8Sthorpej.Bd -literal
4926defd3c8Sthorpejvoid
4936defd3c8Sthorpejfoodone(xfer)
4946defd3c8Sthorpej	struct foo_xfer *xfer;
4956defd3c8Sthorpej{
496*01869ca4Swiz	struct foo_softc = (struct foo_softc *)xfer->xf_softc;
497*01869ca4Swiz	struct buf *bp = xfer->xf_buf;
4986defd3c8Sthorpej	long nbytes;
4996defd3c8Sthorpej	[ . . . ]
5006defd3c8Sthorpej
5016defd3c8Sthorpej	/*
502be6de197Swiz	 * Get number of bytes transferred.  If there is no buf
5036defd3c8Sthorpej	 * associated with the xfer, we are being called at the
5046defd3c8Sthorpej	 * end of a non-I/O command.
5056defd3c8Sthorpej	 */
5066defd3c8Sthorpej	if (bp == NULL)
5076defd3c8Sthorpej		nbytes = 0;
5086defd3c8Sthorpej	else
509*01869ca4Swiz		nbytes = bp->b_bcount - bp->b_resid;
5106defd3c8Sthorpej
5116defd3c8Sthorpej	[ . . . ]
5126defd3c8Sthorpej
513*01869ca4Swiz	mutex_enter(&sc->sc_dk_mtx);
5146defd3c8Sthorpej	/* Notify the disk framework that we've completed the transfer. */
515*01869ca4Swiz	disk_unbusy(&sc->sc_dk, nbytes,
516*01869ca4Swiz	    bp != NULL ? bp->b_flags & B_READ : 0);
517*01869ca4Swiz	mutex_exit(&sc->sc_dk_mtx);
5186defd3c8Sthorpej
5196defd3c8Sthorpej	[ . . . ]
5206defd3c8Sthorpej}
5216defd3c8Sthorpej.Ed
5226defd3c8Sthorpej.Pp
5237d611c43Shaad.Fn disk_isbusy
5247f88d89fSjnemethis used to get status of disk device it returns true if device is
5257f88d89fSjnemethcurrently busy and false if it is not.
5267f88d89fSjnemethLike
527ba576b71Smlelstv.Fn disk_wait ,
5287d611c43Shaad.Fn disk_busy
5297d611c43Shaadand
5306defd3c8Sthorpej.Fn disk_unbusy
5317d611c43Shaadit requires explicit locking from user side.
5326defd3c8Sthorpej.Sh CODE REFERENCES
5336defd3c8SthorpejThe disk framework itself is implemented within the file
53445a63ebcSjeremy.Pa sys/kern/subr_disk.c .
5356defd3c8SthorpejData structures and function prototypes for the framework are located in
53645a63ebcSjeremy.Pa sys/sys/disk.h .
5376defd3c8Sthorpej.Pp
53834a98169SperryThe
53934a98169Sperry.Nx
54043e0efbdSperrymachine-independent SCSI disk and CD-ROM drivers use the
541770eef21Swizdisk framework.
542770eef21SwizThey are located in
54345a63ebcSjeremy.Pa sys/scsi/sd.c
5446defd3c8Sthorpejand
54545a63ebcSjeremy.Pa sys/scsi/cd.c .
5466defd3c8Sthorpej.Pp
54734a98169SperryThe
54834a98169Sperry.Nx
5497f88d89fSjnemeth.Nm ccd ,
5507f88d89fSjnemeth.Nm dm ,
5517d611c43Shaadand
5527f88d89fSjnemeth.Nm vnd
55343e0efbdSperrydrivers use the detachment capability of the framework.
5546defd3c8SthorpejThey are located in
5557f88d89fSjnemeth.Pa sys/dev/ccd.c ,
5567f88d89fSjnemeth.Pa sys/dev/vnd.c ,
5576defd3c8Sthorpejand
5587d611c43Shaad.Pa sys/dev/dm/device-mapper.c .
5596defd3c8Sthorpej.Sh SEE ALSO
5606defd3c8Sthorpej.Xr ccd 4 ,
5617f88d89fSjnemeth.Xr dm 4 ,
5626e901747Smlelstv.Xr vnd 4 ,
56336a13280Swiz.Xr dksubr 9
5646defd3c8Sthorpej.Sh HISTORY
56534a98169SperryThe
56634a98169Sperry.Nx
56734a98169Sperrygeneric disk framework appeared in
56834a98169Sperry.Nx 1.2 .
5693f37d4c9Swiz.Sh AUTHORS
5703f37d4c9SwizThe
5713f37d4c9Swiz.Nx
5723f37d4c9Swizgeneric disk framework was architected and implemented by
5737dc9239dSgrant.An Jason R. Thorpe
57460123a6bSwiz.Aq Mt thorpej@NetBSD.org .
575