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