1da9e4f55SPoul-Henning Kamp /* 2da9e4f55SPoul-Henning Kamp * ---------------------------------------------------------------------------- 3da9e4f55SPoul-Henning Kamp * "THE BEER-WARE LICENSE" (Revision 42): 4da9e4f55SPoul-Henning Kamp * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you 5da9e4f55SPoul-Henning Kamp * can do whatever you want with this stuff. If we meet some day, and you think 6da9e4f55SPoul-Henning Kamp * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7da9e4f55SPoul-Henning Kamp * ---------------------------------------------------------------------------- 8da9e4f55SPoul-Henning Kamp * 9da9e4f55SPoul-Henning Kamp * $FreeBSD$ 10da9e4f55SPoul-Henning Kamp * 11da9e4f55SPoul-Henning Kamp */ 12da9e4f55SPoul-Henning Kamp 13417fb7f6SPoul-Henning Kamp #include "opt_geom.h" 14417fb7f6SPoul-Henning Kamp 15da9e4f55SPoul-Henning Kamp #include <sys/param.h> 16da9e4f55SPoul-Henning Kamp #include <sys/systm.h> 17f90c382cSPoul-Henning Kamp #include <sys/stdint.h> 189626b608SPoul-Henning Kamp #include <sys/bio.h> 19da9e4f55SPoul-Henning Kamp #include <sys/conf.h> 20da9e4f55SPoul-Henning Kamp #include <sys/disk.h> 21f90c382cSPoul-Henning Kamp #ifndef GEOM 22f90c382cSPoul-Henning Kamp #include <sys/kernel.h> 23f90c382cSPoul-Henning Kamp #include <sys/sysctl.h> 24da9e4f55SPoul-Henning Kamp #include <sys/malloc.h> 25445572c1SNeil Blakey-Milner #include <sys/sysctl.h> 268684f73aSPoul-Henning Kamp #include <machine/md_var.h> 273f54a085SPoul-Henning Kamp #include <sys/ctype.h> 283f54a085SPoul-Henning Kamp 29959b7375SPoul-Henning Kamp static MALLOC_DEFINE(M_DISK, "disk", "disk data"); 30da9e4f55SPoul-Henning Kamp 31da9e4f55SPoul-Henning Kamp static d_strategy_t diskstrategy; 32da9e4f55SPoul-Henning Kamp static d_open_t diskopen; 33da9e4f55SPoul-Henning Kamp static d_close_t diskclose; 34da9e4f55SPoul-Henning Kamp static d_ioctl_t diskioctl; 35da9e4f55SPoul-Henning Kamp static d_psize_t diskpsize; 36da9e4f55SPoul-Henning Kamp 374bd02a56SPoul-Henning Kamp static LIST_HEAD(, disk) disklist = LIST_HEAD_INITIALIZER(&disklist); 384bd02a56SPoul-Henning Kamp 394e4a7663SPoul-Henning Kamp void disk_dev_synth(dev_t dev); 404e4a7663SPoul-Henning Kamp 414e4a7663SPoul-Henning Kamp void 424e4a7663SPoul-Henning Kamp disk_dev_synth(dev_t dev) 434e4a7663SPoul-Henning Kamp { 444e4a7663SPoul-Henning Kamp struct disk *dp; 454e4a7663SPoul-Henning Kamp int u, s, p; 464e4a7663SPoul-Henning Kamp dev_t pdev; 474e4a7663SPoul-Henning Kamp 4820a3b67cSPoul-Henning Kamp if (dksparebits(dev)) 49b456f7e6SPoul-Henning Kamp return; 504e4a7663SPoul-Henning Kamp LIST_FOREACH(dp, &disklist, d_list) { 514e4a7663SPoul-Henning Kamp if (major(dev) != dp->d_devsw->d_maj) 524e4a7663SPoul-Henning Kamp continue; 534e4a7663SPoul-Henning Kamp u = dkunit(dev); 544e4a7663SPoul-Henning Kamp p = RAW_PART; 554e4a7663SPoul-Henning Kamp s = WHOLE_DISK_SLICE; 564e4a7663SPoul-Henning Kamp pdev = makedev(dp->d_devsw->d_maj, dkmakeminor(u, s, p)); 574e130067SPoul-Henning Kamp if (pdev->si_devsw == NULL) 584e130067SPoul-Henning Kamp return; /* Probably a unit we don't have */ 594e4a7663SPoul-Henning Kamp s = dkslice(dev); 604e4a7663SPoul-Henning Kamp p = dkpart(dev); 614e4a7663SPoul-Henning Kamp if (s == WHOLE_DISK_SLICE && p == RAW_PART) { 624e4a7663SPoul-Henning Kamp /* XXX: actually should not happen */ 634e4a7663SPoul-Henning Kamp dev = make_dev(pdev->si_devsw, dkmakeminor(u, s, p), 644e4a7663SPoul-Henning Kamp UID_ROOT, GID_OPERATOR, 0640, "%s%d", 654e4a7663SPoul-Henning Kamp dp->d_devsw->d_name, u); 664e4a7663SPoul-Henning Kamp dev_depends(pdev, dev); 674e4a7663SPoul-Henning Kamp return; 684e4a7663SPoul-Henning Kamp } 694e4a7663SPoul-Henning Kamp if (s == COMPATIBILITY_SLICE) { 704e4a7663SPoul-Henning Kamp dev = make_dev(pdev->si_devsw, dkmakeminor(u, s, p), 714e4a7663SPoul-Henning Kamp UID_ROOT, GID_OPERATOR, 0640, "%s%d%c", 724e4a7663SPoul-Henning Kamp dp->d_devsw->d_name, u, 'a' + p); 734e4a7663SPoul-Henning Kamp dev_depends(pdev, dev); 744e4a7663SPoul-Henning Kamp return; 754e4a7663SPoul-Henning Kamp } 76a2d7281cSPoul-Henning Kamp if (p != RAW_PART) { 774e4a7663SPoul-Henning Kamp dev = make_dev(pdev->si_devsw, dkmakeminor(u, s, p), 784e4a7663SPoul-Henning Kamp UID_ROOT, GID_OPERATOR, 0640, "%s%ds%d%c", 79a2d7281cSPoul-Henning Kamp dp->d_devsw->d_name, u, s - BASE_SLICE + 1, 80a2d7281cSPoul-Henning Kamp 'a' + p); 81a2d7281cSPoul-Henning Kamp } else { 82a2d7281cSPoul-Henning Kamp dev = make_dev(pdev->si_devsw, dkmakeminor(u, s, p), 83a2d7281cSPoul-Henning Kamp UID_ROOT, GID_OPERATOR, 0640, "%s%ds%d", 844e4a7663SPoul-Henning Kamp dp->d_devsw->d_name, u, s - BASE_SLICE + 1); 85a2d7281cSPoul-Henning Kamp make_dev_alias(dev, "%s%ds%dc", 86a2d7281cSPoul-Henning Kamp dp->d_devsw->d_name, u, s - BASE_SLICE + 1); 87a2d7281cSPoul-Henning Kamp } 88a2d7281cSPoul-Henning Kamp dev_depends(pdev, dev); 894e4a7663SPoul-Henning Kamp return; 904e4a7663SPoul-Henning Kamp } 914e4a7663SPoul-Henning Kamp } 924e4a7663SPoul-Henning Kamp 933f54a085SPoul-Henning Kamp static void 943f54a085SPoul-Henning Kamp disk_clone(void *arg, char *name, int namelen, dev_t *dev) 953f54a085SPoul-Henning Kamp { 963f54a085SPoul-Henning Kamp struct disk *dp; 973f54a085SPoul-Henning Kamp char const *d; 98417fb7f6SPoul-Henning Kamp char *e; 99417fb7f6SPoul-Henning Kamp int j, u, s, p; 1003f54a085SPoul-Henning Kamp dev_t pdev; 1013f54a085SPoul-Henning Kamp 1023f54a085SPoul-Henning Kamp if (*dev != NODEV) 1033f54a085SPoul-Henning Kamp return; 1043f54a085SPoul-Henning Kamp 1053f54a085SPoul-Henning Kamp LIST_FOREACH(dp, &disklist, d_list) { 1063f54a085SPoul-Henning Kamp d = dp->d_devsw->d_name; 107417fb7f6SPoul-Henning Kamp j = dev_stdclone(name, &e, d, &u); 108417fb7f6SPoul-Henning Kamp if (j == 0) 1093f54a085SPoul-Henning Kamp continue; 110f84ee0ffSPoul-Henning Kamp if (u > DKMAXUNIT) 111f84ee0ffSPoul-Henning Kamp continue; 1123f54a085SPoul-Henning Kamp p = RAW_PART; 1133f54a085SPoul-Henning Kamp s = WHOLE_DISK_SLICE; 1143f54a085SPoul-Henning Kamp pdev = makedev(dp->d_devsw->d_maj, dkmakeminor(u, s, p)); 1153f54a085SPoul-Henning Kamp if (pdev->si_disk == NULL) 1163f54a085SPoul-Henning Kamp continue; 117417fb7f6SPoul-Henning Kamp if (*e != '\0') { 118417fb7f6SPoul-Henning Kamp j = dev_stdclone(e, &e, "s", &s); 119417fb7f6SPoul-Henning Kamp if (j == 0) 1203f54a085SPoul-Henning Kamp s = COMPATIBILITY_SLICE; 121417fb7f6SPoul-Henning Kamp else if (j == 1 || j == 2) 122417fb7f6SPoul-Henning Kamp s += BASE_SLICE - 1; 123417fb7f6SPoul-Henning Kamp if (!*e) 124417fb7f6SPoul-Henning Kamp ; /* ad0s1 case */ 125417fb7f6SPoul-Henning Kamp else if (e[1] != '\0') 126417fb7f6SPoul-Henning Kamp return; /* can never be a disk name */ 127417fb7f6SPoul-Henning Kamp else if (*e < 'a' || *e > 'h') 128417fb7f6SPoul-Henning Kamp return; /* can never be a disk name */ 1293f54a085SPoul-Henning Kamp else 130417fb7f6SPoul-Henning Kamp p = *e - 'a'; 1313f54a085SPoul-Henning Kamp } 132417fb7f6SPoul-Henning Kamp if (s == WHOLE_DISK_SLICE && p == RAW_PART) { 133417fb7f6SPoul-Henning Kamp return; 134417fb7f6SPoul-Henning Kamp } else if (s >= BASE_SLICE && p != RAW_PART) { 1354e4a7663SPoul-Henning Kamp *dev = make_dev(pdev->si_devsw, dkmakeminor(u, s, p), 1364e4a7663SPoul-Henning Kamp UID_ROOT, GID_OPERATOR, 0640, "%s%ds%d%c", 137a2d7281cSPoul-Henning Kamp pdev->si_devsw->d_name, u, s - BASE_SLICE + 1, 138a2d7281cSPoul-Henning Kamp p + 'a'); 139a2d7281cSPoul-Henning Kamp } else if (s >= BASE_SLICE) { 140a2d7281cSPoul-Henning Kamp *dev = make_dev(pdev->si_devsw, dkmakeminor(u, s, p), 141a2d7281cSPoul-Henning Kamp UID_ROOT, GID_OPERATOR, 0640, "%s%ds%d", 142a2d7281cSPoul-Henning Kamp pdev->si_devsw->d_name, u, s - BASE_SLICE + 1); 143a2d7281cSPoul-Henning Kamp make_dev_alias(*dev, "%s%ds%dc", 144a2d7281cSPoul-Henning Kamp pdev->si_devsw->d_name, u, s - BASE_SLICE + 1); 145a2d7281cSPoul-Henning Kamp } else { 1463f54a085SPoul-Henning Kamp *dev = make_dev(pdev->si_devsw, dkmakeminor(u, s, p), 147417fb7f6SPoul-Henning Kamp UID_ROOT, GID_OPERATOR, 0640, "%s%d%c", 148417fb7f6SPoul-Henning Kamp pdev->si_devsw->d_name, u, p + 'a'); 1494e4a7663SPoul-Henning Kamp } 150a2d7281cSPoul-Henning Kamp dev_depends(pdev, *dev); 1513f54a085SPoul-Henning Kamp return; 1523f54a085SPoul-Henning Kamp } 1533f54a085SPoul-Henning Kamp } 1543f54a085SPoul-Henning Kamp 1555d10777cSWarner Losh static void 1565d10777cSWarner Losh inherit_raw(dev_t pdev, dev_t dev) 1575d10777cSWarner Losh { 1585d10777cSWarner Losh dev->si_disk = pdev->si_disk; 1595d10777cSWarner Losh dev->si_drv1 = pdev->si_drv1; 1605d10777cSWarner Losh dev->si_drv2 = pdev->si_drv2; 1615d10777cSWarner Losh dev->si_iosize_max = pdev->si_iosize_max; 1625d10777cSWarner Losh dev->si_bsize_phys = pdev->si_bsize_phys; 1635d10777cSWarner Losh dev->si_bsize_best = pdev->si_bsize_best; 1645d10777cSWarner Losh } 1655d10777cSWarner Losh 166da9e4f55SPoul-Henning Kamp dev_t 1672016e4e9SPoul-Henning Kamp disk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw, struct cdevsw *proto) 168da9e4f55SPoul-Henning Kamp { 1693f54a085SPoul-Henning Kamp static int once; 17022628ccfSPoul-Henning Kamp dev_t dev; 1713344c5a1SPoul-Henning Kamp 1723344c5a1SPoul-Henning Kamp if (!once) { 1733344c5a1SPoul-Henning Kamp EVENTHANDLER_REGISTER(dev_clone, disk_clone, 0, 1000); 1743344c5a1SPoul-Henning Kamp once++; 1753344c5a1SPoul-Henning Kamp } 176da9e4f55SPoul-Henning Kamp 1778684f73aSPoul-Henning Kamp bzero(dp, sizeof(*dp)); 1783febdd8fSPoul-Henning Kamp 1798576c652SPoul-Henning Kamp if (proto->d_open != diskopen) { 1802016e4e9SPoul-Henning Kamp *proto = *cdevsw; 1812016e4e9SPoul-Henning Kamp proto->d_open = diskopen; 1822016e4e9SPoul-Henning Kamp proto->d_close = diskclose; 1832016e4e9SPoul-Henning Kamp proto->d_ioctl = diskioctl; 1842016e4e9SPoul-Henning Kamp proto->d_strategy = diskstrategy; 1852016e4e9SPoul-Henning Kamp proto->d_psize = diskpsize; 1863febdd8fSPoul-Henning Kamp } 1873febdd8fSPoul-Henning Kamp 1888d67e113SJordan K. Hubbard if (bootverbose) 1893febdd8fSPoul-Henning Kamp printf("Creating DISK %s%d\n", cdevsw->d_name, unit); 190abd1f573SPoul-Henning Kamp dev = make_dev(proto, dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART), 1913f54a085SPoul-Henning Kamp UID_ROOT, GID_OPERATOR, 0640, "%s%d", cdevsw->d_name, unit); 1923febdd8fSPoul-Henning Kamp 193da9e4f55SPoul-Henning Kamp dev->si_disk = dp; 194da9e4f55SPoul-Henning Kamp dp->d_dev = dev; 1958db34b3aSPoul-Henning Kamp dp->d_dsflags = flags; 1962016e4e9SPoul-Henning Kamp dp->d_devsw = cdevsw; 1974bd02a56SPoul-Henning Kamp LIST_INSERT_HEAD(&disklist, dp, d_list); 1983344c5a1SPoul-Henning Kamp 199da9e4f55SPoul-Henning Kamp return (dev); 200da9e4f55SPoul-Henning Kamp } 201da9e4f55SPoul-Henning Kamp 20281661c94SPoul-Henning Kamp static int 20381661c94SPoul-Henning Kamp diskdumpconf(u_int onoff, dev_t dev, struct disk *dp) 2048684f73aSPoul-Henning Kamp { 20581661c94SPoul-Henning Kamp struct dumperinfo di; 2068684f73aSPoul-Henning Kamp struct disklabel *dl; 2078684f73aSPoul-Henning Kamp 20881661c94SPoul-Henning Kamp if (!onoff) 20981661c94SPoul-Henning Kamp return(set_dumper(NULL)); 2108684f73aSPoul-Henning Kamp dl = dsgetlabel(dev, dp->d_slice); 2118684f73aSPoul-Henning Kamp if (!dl) 2128684f73aSPoul-Henning Kamp return (ENXIO); 21381661c94SPoul-Henning Kamp bzero(&di, sizeof di); 21481661c94SPoul-Henning Kamp di.dumper = (dumper_t *)dp->d_devsw->d_dump; 21581661c94SPoul-Henning Kamp di.priv = dp->d_dev; 21681661c94SPoul-Henning Kamp di.blocksize = dl->d_secsize; 21781661c94SPoul-Henning Kamp di.mediaoffset = (off_t)(dl->d_partitions[dkpart(dev)].p_offset + 21881661c94SPoul-Henning Kamp dp->d_slice->dss_slices[dkslice(dev)].ds_offset) * DEV_BSIZE; 21981661c94SPoul-Henning Kamp di.mediasize = 22081661c94SPoul-Henning Kamp (off_t)(dl->d_partitions[dkpart(dev)].p_size) * DEV_BSIZE; 22181661c94SPoul-Henning Kamp return(set_dumper(&di)); 2228684f73aSPoul-Henning Kamp } 2238684f73aSPoul-Henning Kamp 2248684f73aSPoul-Henning Kamp void 2258684f73aSPoul-Henning Kamp disk_invalidate (struct disk *disk) 2268684f73aSPoul-Henning Kamp { 22747351d27SSøren Schmidt if (disk->d_slice) 2288684f73aSPoul-Henning Kamp dsgone(&disk->d_slice); 2298684f73aSPoul-Henning Kamp } 2308684f73aSPoul-Henning Kamp 231da9e4f55SPoul-Henning Kamp void 2321edde29eSPoul-Henning Kamp disk_destroy(dev_t dev) 233da9e4f55SPoul-Henning Kamp { 2344bd02a56SPoul-Henning Kamp LIST_REMOVE(dev->si_disk, d_list); 2354bd02a56SPoul-Henning Kamp bzero(dev->si_disk, sizeof(*dev->si_disk)); 23647351d27SSøren Schmidt dev->si_disk = NULL; 23747351d27SSøren Schmidt destroy_dev(dev); 238da9e4f55SPoul-Henning Kamp return; 239da9e4f55SPoul-Henning Kamp } 240da9e4f55SPoul-Henning Kamp 2414bd02a56SPoul-Henning Kamp struct disk * 2424bd02a56SPoul-Henning Kamp disk_enumerate(struct disk *disk) 2434bd02a56SPoul-Henning Kamp { 2444bd02a56SPoul-Henning Kamp if (!disk) 2454bd02a56SPoul-Henning Kamp return (LIST_FIRST(&disklist)); 2464bd02a56SPoul-Henning Kamp else 2474bd02a56SPoul-Henning Kamp return (LIST_NEXT(disk, d_list)); 2484bd02a56SPoul-Henning Kamp } 2494bd02a56SPoul-Henning Kamp 250445572c1SNeil Blakey-Milner static int 25182d9ae4eSPoul-Henning Kamp sysctl_disks(SYSCTL_HANDLER_ARGS) 252445572c1SNeil Blakey-Milner { 253445572c1SNeil Blakey-Milner struct disk *disk; 254445572c1SNeil Blakey-Milner int error, first; 255445572c1SNeil Blakey-Milner 256445572c1SNeil Blakey-Milner disk = NULL; 257445572c1SNeil Blakey-Milner first = 1; 258445572c1SNeil Blakey-Milner 259445572c1SNeil Blakey-Milner while ((disk = disk_enumerate(disk))) { 260445572c1SNeil Blakey-Milner if (!first) { 261445572c1SNeil Blakey-Milner error = SYSCTL_OUT(req, " ", 1); 262445572c1SNeil Blakey-Milner if (error) 263445572c1SNeil Blakey-Milner return error; 264445572c1SNeil Blakey-Milner } else { 265445572c1SNeil Blakey-Milner first = 0; 266445572c1SNeil Blakey-Milner } 267445572c1SNeil Blakey-Milner error = SYSCTL_OUT(req, disk->d_dev->si_name, strlen(disk->d_dev->si_name)); 268445572c1SNeil Blakey-Milner if (error) 269445572c1SNeil Blakey-Milner return error; 270445572c1SNeil Blakey-Milner } 271445572c1SNeil Blakey-Milner error = SYSCTL_OUT(req, "", 1); 272445572c1SNeil Blakey-Milner return error; 273445572c1SNeil Blakey-Milner } 274445572c1SNeil Blakey-Milner 27555f7c614SArchie Cobbs SYSCTL_PROC(_kern, OID_AUTO, disks, CTLTYPE_STRING | CTLFLAG_RD, 0, 0, 276445572c1SNeil Blakey-Milner sysctl_disks, "A", "names of available disks"); 277445572c1SNeil Blakey-Milner 2788684f73aSPoul-Henning Kamp /* 2798684f73aSPoul-Henning Kamp * The cdevsw functions 2808684f73aSPoul-Henning Kamp */ 2818684f73aSPoul-Henning Kamp 282da9e4f55SPoul-Henning Kamp static int 283b40ce416SJulian Elischer diskopen(dev_t dev, int oflags, int devtype, struct thread *td) 284da9e4f55SPoul-Henning Kamp { 285da9e4f55SPoul-Henning Kamp dev_t pdev; 286da9e4f55SPoul-Henning Kamp struct disk *dp; 287da9e4f55SPoul-Henning Kamp int error; 288da9e4f55SPoul-Henning Kamp 2898684f73aSPoul-Henning Kamp error = 0; 290da9e4f55SPoul-Henning Kamp pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 2918684f73aSPoul-Henning Kamp 292da9e4f55SPoul-Henning Kamp dp = pdev->si_disk; 293da9e4f55SPoul-Henning Kamp if (!dp) 294da9e4f55SPoul-Henning Kamp return (ENXIO); 2958684f73aSPoul-Henning Kamp 2968db34b3aSPoul-Henning Kamp while (dp->d_flags & DISKFLAG_LOCK) { 2978db34b3aSPoul-Henning Kamp dp->d_flags |= DISKFLAG_WANTED; 2981b4ce5ceSPoul-Henning Kamp error = tsleep(dp, PRIBIO | PCATCH, "diskopen", hz); 2991b4ce5ceSPoul-Henning Kamp if (error) 3001b4ce5ceSPoul-Henning Kamp return (error); 3018db34b3aSPoul-Henning Kamp } 3028db34b3aSPoul-Henning Kamp dp->d_flags |= DISKFLAG_LOCK; 3038db34b3aSPoul-Henning Kamp 30445604de3SPoul-Henning Kamp if (!dsisopen(dp->d_slice)) { 305dc722a14SSøren Schmidt if (!pdev->si_iosize_max) 30645604de3SPoul-Henning Kamp pdev->si_iosize_max = dev->si_iosize_max; 307b40ce416SJulian Elischer error = dp->d_devsw->d_open(pdev, oflags, devtype, td); 30845604de3SPoul-Henning Kamp } 30966c12520SPoul-Henning Kamp 31066c12520SPoul-Henning Kamp /* Inherit properties from the whole/raw dev_t */ 3115d10777cSWarner Losh inherit_raw(pdev, dev); 3128684f73aSPoul-Henning Kamp 313da9e4f55SPoul-Henning Kamp if (error) 3148db34b3aSPoul-Henning Kamp goto out; 315da9e4f55SPoul-Henning Kamp 3168db34b3aSPoul-Henning Kamp error = dsopen(dev, devtype, dp->d_dsflags, &dp->d_slice, &dp->d_label); 317da9e4f55SPoul-Henning Kamp 3188684f73aSPoul-Henning Kamp if (!dsisopen(dp->d_slice)) 319b40ce416SJulian Elischer dp->d_devsw->d_close(pdev, oflags, devtype, td); 3208db34b3aSPoul-Henning Kamp out: 3218db34b3aSPoul-Henning Kamp dp->d_flags &= ~DISKFLAG_LOCK; 3228db34b3aSPoul-Henning Kamp if (dp->d_flags & DISKFLAG_WANTED) { 3238db34b3aSPoul-Henning Kamp dp->d_flags &= ~DISKFLAG_WANTED; 3248db34b3aSPoul-Henning Kamp wakeup(dp); 3258db34b3aSPoul-Henning Kamp } 3268684f73aSPoul-Henning Kamp 327da9e4f55SPoul-Henning Kamp return(error); 328da9e4f55SPoul-Henning Kamp } 329da9e4f55SPoul-Henning Kamp 330da9e4f55SPoul-Henning Kamp static int 331b40ce416SJulian Elischer diskclose(dev_t dev, int fflag, int devtype, struct thread *td) 332da9e4f55SPoul-Henning Kamp { 333da9e4f55SPoul-Henning Kamp struct disk *dp; 334da9e4f55SPoul-Henning Kamp int error; 3355d10777cSWarner Losh dev_t pdev; 336da9e4f55SPoul-Henning Kamp 337da9e4f55SPoul-Henning Kamp error = 0; 3385d10777cSWarner Losh pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 3395d10777cSWarner Losh dp = pdev->si_disk; 340b417a1a8SSøren Schmidt if (!dp) 341b417a1a8SSøren Schmidt return (ENXIO); 34246a706dcSMike Smith dsclose(dev, devtype, dp->d_slice); 343b417a1a8SSøren Schmidt if (!dsisopen(dp->d_slice)) 344b40ce416SJulian Elischer error = dp->d_devsw->d_close(dp->d_dev, fflag, devtype, td); 345da9e4f55SPoul-Henning Kamp return (error); 346da9e4f55SPoul-Henning Kamp } 347da9e4f55SPoul-Henning Kamp 348da9e4f55SPoul-Henning Kamp static void 3498177437dSPoul-Henning Kamp diskstrategy(struct bio *bp) 350da9e4f55SPoul-Henning Kamp { 351da9e4f55SPoul-Henning Kamp dev_t pdev; 352da9e4f55SPoul-Henning Kamp struct disk *dp; 353da9e4f55SPoul-Henning Kamp 3548177437dSPoul-Henning Kamp pdev = dkmodpart(dkmodslice(bp->bio_dev, WHOLE_DISK_SLICE), RAW_PART); 3555d10777cSWarner Losh dp = pdev->si_disk; 356e0e0b661SPoul-Henning Kamp bp->bio_resid = bp->bio_bcount; 3575d10777cSWarner Losh if (dp != bp->bio_dev->si_disk) 3585d10777cSWarner Losh inherit_raw(pdev, bp->bio_dev); 359da9e4f55SPoul-Henning Kamp 360da9e4f55SPoul-Henning Kamp if (!dp) { 361a468031cSPoul-Henning Kamp biofinish(bp, NULL, ENXIO); 362da9e4f55SPoul-Henning Kamp return; 363da9e4f55SPoul-Henning Kamp } 364da9e4f55SPoul-Henning Kamp 365d685023eSPoul-Henning Kamp if (dscheck(bp, dp->d_slice) <= 0) { 366da9e4f55SPoul-Henning Kamp biodone(bp); 367da9e4f55SPoul-Henning Kamp return; 368da9e4f55SPoul-Henning Kamp } 369da9e4f55SPoul-Henning Kamp 370079f2df3SPoul-Henning Kamp if (bp->bio_bcount == 0) { 371079f2df3SPoul-Henning Kamp biodone(bp); 372079f2df3SPoul-Henning Kamp return; 373079f2df3SPoul-Henning Kamp } 374079f2df3SPoul-Henning Kamp 37567f3c95cSPoul-Henning Kamp KASSERT(dp->d_devsw != NULL, ("NULL devsw")); 37667f3c95cSPoul-Henning Kamp KASSERT(dp->d_devsw->d_strategy != NULL, ("NULL d_strategy")); 3772016e4e9SPoul-Henning Kamp dp->d_devsw->d_strategy(bp); 378da9e4f55SPoul-Henning Kamp return; 379da9e4f55SPoul-Henning Kamp 380da9e4f55SPoul-Henning Kamp } 381da9e4f55SPoul-Henning Kamp 382da9e4f55SPoul-Henning Kamp static int 383b40ce416SJulian Elischer diskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td) 384da9e4f55SPoul-Henning Kamp { 385da9e4f55SPoul-Henning Kamp struct disk *dp; 386da9e4f55SPoul-Henning Kamp int error; 38781661c94SPoul-Henning Kamp u_int u; 3885d10777cSWarner Losh dev_t pdev; 389da9e4f55SPoul-Henning Kamp 3905d10777cSWarner Losh pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 3915d10777cSWarner Losh dp = pdev->si_disk; 392b417a1a8SSøren Schmidt if (!dp) 393b417a1a8SSøren Schmidt return (ENXIO); 3947f086a08SPoul-Henning Kamp if (cmd == DIOCSKERNELDUMP) { 39581661c94SPoul-Henning Kamp u = *(u_int *)data; 39681661c94SPoul-Henning Kamp return (diskdumpconf(u, dev, dp)); 39781661c94SPoul-Henning Kamp } 3981bdb20a6SPoul-Henning Kamp if (cmd == DIOCGFRONTSTUFF) { 3991bdb20a6SPoul-Henning Kamp *(off_t *)data = 8192; /* XXX: crude but enough) */ 4001bdb20a6SPoul-Henning Kamp return (0); 4011bdb20a6SPoul-Henning Kamp } 402da9e4f55SPoul-Henning Kamp error = dsioctl(dev, cmd, data, fflag, &dp->d_slice); 403da9e4f55SPoul-Henning Kamp if (error == ENOIOCTL) 404b40ce416SJulian Elischer error = dp->d_devsw->d_ioctl(dev, cmd, data, fflag, td); 405da9e4f55SPoul-Henning Kamp return (error); 406da9e4f55SPoul-Henning Kamp } 407da9e4f55SPoul-Henning Kamp 408da9e4f55SPoul-Henning Kamp static int 409da9e4f55SPoul-Henning Kamp diskpsize(dev_t dev) 410da9e4f55SPoul-Henning Kamp { 411da9e4f55SPoul-Henning Kamp struct disk *dp; 4128684f73aSPoul-Henning Kamp dev_t pdev; 413da9e4f55SPoul-Henning Kamp 4148684f73aSPoul-Henning Kamp pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 4158684f73aSPoul-Henning Kamp dp = pdev->si_disk; 416a4fcac54SBruce Evans if (!dp) 417a4fcac54SBruce Evans return (-1); 4185d10777cSWarner Losh if (dp != dev->si_disk) { 4198684f73aSPoul-Henning Kamp dev->si_drv1 = pdev->si_drv1; 4208684f73aSPoul-Henning Kamp dev->si_drv2 = pdev->si_drv2; 4218684f73aSPoul-Henning Kamp /* XXX: don't set bp->b_dev->si_disk (?) */ 4228684f73aSPoul-Henning Kamp } 423da9e4f55SPoul-Henning Kamp return (dssize(dev, &dp->d_slice)); 424da9e4f55SPoul-Henning Kamp } 42585a219d2SJulian Elischer 42685a219d2SJulian Elischer SYSCTL_INT(_debug_sizeof, OID_AUTO, disklabel, CTLFLAG_RD, 42785a219d2SJulian Elischer 0, sizeof(struct disklabel), "sizeof(struct disklabel)"); 42885a219d2SJulian Elischer 42985a219d2SJulian Elischer SYSCTL_INT(_debug_sizeof, OID_AUTO, diskslices, CTLFLAG_RD, 43085a219d2SJulian Elischer 0, sizeof(struct diskslices), "sizeof(struct diskslices)"); 43185a219d2SJulian Elischer 43285a219d2SJulian Elischer SYSCTL_INT(_debug_sizeof, OID_AUTO, disk, CTLFLAG_RD, 43385a219d2SJulian Elischer 0, sizeof(struct disk), "sizeof(struct disk)"); 434417fb7f6SPoul-Henning Kamp 435417fb7f6SPoul-Henning Kamp #endif 436f90c382cSPoul-Henning Kamp 437f90c382cSPoul-Henning Kamp /*- 438f90c382cSPoul-Henning Kamp * Disk error is the preface to plaintive error messages 439f90c382cSPoul-Henning Kamp * about failing disk transfers. It prints messages of the form 440f90c382cSPoul-Henning Kamp * "hp0g: BLABLABLA cmd=read fsbn 12345 of 12344-12347" 441f90c382cSPoul-Henning Kamp * blkdone should be -1 if the position of the error is unknown. 442f90c382cSPoul-Henning Kamp * The message is printed with printf. 443f90c382cSPoul-Henning Kamp */ 444f90c382cSPoul-Henning Kamp void 445f90c382cSPoul-Henning Kamp disk_err(struct bio *bp, const char *what, int blkdone, int nl) 446f90c382cSPoul-Henning Kamp { 447f90c382cSPoul-Henning Kamp daddr_t sn; 448f90c382cSPoul-Henning Kamp 449f90c382cSPoul-Henning Kamp printf("%s: %s", devtoname(bp->bio_dev), what); 450f90c382cSPoul-Henning Kamp switch(bp->bio_cmd) { 451f90c382cSPoul-Henning Kamp case BIO_READ: printf("cmd=read"); break; 452f90c382cSPoul-Henning Kamp case BIO_WRITE: printf("cmd=write"); break; 453f90c382cSPoul-Henning Kamp case BIO_DELETE: printf("cmd=delete"); break; 454f90c382cSPoul-Henning Kamp case BIO_GETATTR: printf("cmd=getattr"); break; 455f90c382cSPoul-Henning Kamp case BIO_SETATTR: printf("cmd=setattr"); break; 456f90c382cSPoul-Henning Kamp default: printf("cmd=%x", bp->bio_cmd); break; 457f90c382cSPoul-Henning Kamp } 458f90c382cSPoul-Henning Kamp sn = bp->bio_blkno; 459f90c382cSPoul-Henning Kamp if (bp->bio_bcount <= DEV_BSIZE) { 460f90c382cSPoul-Henning Kamp printf("fsbn %jd%s", (intmax_t)sn, nl ? "\n" : ""); 461f90c382cSPoul-Henning Kamp return; 462f90c382cSPoul-Henning Kamp } 463f90c382cSPoul-Henning Kamp if (blkdone >= 0) { 464f90c382cSPoul-Henning Kamp sn += blkdone; 465f90c382cSPoul-Henning Kamp printf("fsbn %jd of ", (intmax_t)sn); 466f90c382cSPoul-Henning Kamp } 467f90c382cSPoul-Henning Kamp printf("%jd-%jd", (intmax_t)bp->bio_blkno, 468f90c382cSPoul-Henning Kamp (intmax_t)(bp->bio_blkno + (bp->bio_bcount - 1) / DEV_BSIZE)); 469f90c382cSPoul-Henning Kamp if (nl) 470f90c382cSPoul-Henning Kamp printf("\n"); 471f90c382cSPoul-Henning Kamp } 472