xref: /freebsd/sys/kern/subr_disk.c (revision 417fb7f6fa51f6a83e32d51c6872ad6829e7b17a)
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 #ifndef GEOM
15417fb7f6SPoul-Henning Kamp 
16da9e4f55SPoul-Henning Kamp #include <sys/param.h>
17da9e4f55SPoul-Henning Kamp #include <sys/systm.h>
18da9e4f55SPoul-Henning Kamp #include <sys/kernel.h>
1985a219d2SJulian Elischer #include <sys/sysctl.h>
209626b608SPoul-Henning Kamp #include <sys/bio.h>
21da9e4f55SPoul-Henning Kamp #include <sys/conf.h>
22da9e4f55SPoul-Henning Kamp #include <sys/disk.h>
23da9e4f55SPoul-Henning Kamp #include <sys/malloc.h>
24445572c1SNeil Blakey-Milner #include <sys/sysctl.h>
258684f73aSPoul-Henning Kamp #include <machine/md_var.h>
263f54a085SPoul-Henning Kamp #include <sys/ctype.h>
273f54a085SPoul-Henning Kamp 
28959b7375SPoul-Henning Kamp static MALLOC_DEFINE(M_DISK, "disk", "disk data");
29da9e4f55SPoul-Henning Kamp 
30da9e4f55SPoul-Henning Kamp static d_strategy_t diskstrategy;
31da9e4f55SPoul-Henning Kamp static d_open_t diskopen;
32da9e4f55SPoul-Henning Kamp static d_close_t diskclose;
33da9e4f55SPoul-Henning Kamp static d_ioctl_t diskioctl;
34da9e4f55SPoul-Henning Kamp static d_psize_t diskpsize;
35da9e4f55SPoul-Henning Kamp 
364bd02a56SPoul-Henning Kamp static LIST_HEAD(, disk) disklist = LIST_HEAD_INITIALIZER(&disklist);
374bd02a56SPoul-Henning Kamp 
384e4a7663SPoul-Henning Kamp void disk_dev_synth(dev_t dev);
394e4a7663SPoul-Henning Kamp 
404e4a7663SPoul-Henning Kamp void
414e4a7663SPoul-Henning Kamp disk_dev_synth(dev_t dev)
424e4a7663SPoul-Henning Kamp {
434e4a7663SPoul-Henning Kamp 	struct disk *dp;
444e4a7663SPoul-Henning Kamp 	int u, s, p;
454e4a7663SPoul-Henning Kamp 	dev_t pdev;
464e4a7663SPoul-Henning Kamp 
4720a3b67cSPoul-Henning Kamp 	if (dksparebits(dev))
48b456f7e6SPoul-Henning Kamp 		return;
494e4a7663SPoul-Henning Kamp 	LIST_FOREACH(dp, &disklist, d_list) {
504e4a7663SPoul-Henning Kamp 		if (major(dev) != dp->d_devsw->d_maj)
514e4a7663SPoul-Henning Kamp 			continue;
524e4a7663SPoul-Henning Kamp 		u = dkunit(dev);
534e4a7663SPoul-Henning Kamp 		p = RAW_PART;
544e4a7663SPoul-Henning Kamp 		s = WHOLE_DISK_SLICE;
554e4a7663SPoul-Henning Kamp 		pdev = makedev(dp->d_devsw->d_maj, dkmakeminor(u, s, p));
564e130067SPoul-Henning Kamp 		if (pdev->si_devsw == NULL)
574e130067SPoul-Henning Kamp 			return;		/* Probably a unit we don't have */
584e4a7663SPoul-Henning Kamp 		s = dkslice(dev);
594e4a7663SPoul-Henning Kamp 		p = dkpart(dev);
604e4a7663SPoul-Henning Kamp 		if (s == WHOLE_DISK_SLICE && p == RAW_PART) {
614e4a7663SPoul-Henning Kamp 			/* XXX: actually should not happen */
624e4a7663SPoul-Henning Kamp 			dev = make_dev(pdev->si_devsw, dkmakeminor(u, s, p),
634e4a7663SPoul-Henning Kamp 			    UID_ROOT, GID_OPERATOR, 0640, "%s%d",
644e4a7663SPoul-Henning Kamp 				dp->d_devsw->d_name, u);
654e4a7663SPoul-Henning Kamp 			dev_depends(pdev, dev);
664e4a7663SPoul-Henning Kamp 			return;
674e4a7663SPoul-Henning Kamp 		}
684e4a7663SPoul-Henning Kamp 		if (s == COMPATIBILITY_SLICE) {
694e4a7663SPoul-Henning Kamp 			dev = make_dev(pdev->si_devsw, dkmakeminor(u, s, p),
704e4a7663SPoul-Henning Kamp 			    UID_ROOT, GID_OPERATOR, 0640, "%s%d%c",
714e4a7663SPoul-Henning Kamp 				dp->d_devsw->d_name, u, 'a' + p);
724e4a7663SPoul-Henning Kamp 			dev_depends(pdev, dev);
734e4a7663SPoul-Henning Kamp 			return;
744e4a7663SPoul-Henning Kamp 		}
75a2d7281cSPoul-Henning Kamp 		if (p != RAW_PART) {
764e4a7663SPoul-Henning Kamp 			dev = make_dev(pdev->si_devsw, dkmakeminor(u, s, p),
774e4a7663SPoul-Henning Kamp 			    UID_ROOT, GID_OPERATOR, 0640, "%s%ds%d%c",
78a2d7281cSPoul-Henning Kamp 				dp->d_devsw->d_name, u, s - BASE_SLICE + 1,
79a2d7281cSPoul-Henning Kamp 				'a' + p);
80a2d7281cSPoul-Henning Kamp 		} else {
81a2d7281cSPoul-Henning Kamp 			dev = make_dev(pdev->si_devsw, dkmakeminor(u, s, p),
82a2d7281cSPoul-Henning Kamp 			    UID_ROOT, GID_OPERATOR, 0640, "%s%ds%d",
834e4a7663SPoul-Henning Kamp 				dp->d_devsw->d_name, u, s - BASE_SLICE + 1);
84a2d7281cSPoul-Henning Kamp 			make_dev_alias(dev, "%s%ds%dc",
85a2d7281cSPoul-Henning Kamp 			    dp->d_devsw->d_name, u, s - BASE_SLICE + 1);
86a2d7281cSPoul-Henning Kamp 		}
87a2d7281cSPoul-Henning Kamp 		dev_depends(pdev, dev);
884e4a7663SPoul-Henning Kamp 		return;
894e4a7663SPoul-Henning Kamp 	}
904e4a7663SPoul-Henning Kamp }
914e4a7663SPoul-Henning Kamp 
923f54a085SPoul-Henning Kamp static void
933f54a085SPoul-Henning Kamp disk_clone(void *arg, char *name, int namelen, dev_t *dev)
943f54a085SPoul-Henning Kamp {
953f54a085SPoul-Henning Kamp 	struct disk *dp;
963f54a085SPoul-Henning Kamp 	char const *d;
97417fb7f6SPoul-Henning Kamp 	char *e;
98417fb7f6SPoul-Henning Kamp 	int j, u, s, p;
993f54a085SPoul-Henning Kamp 	dev_t pdev;
1003f54a085SPoul-Henning Kamp 
1013f54a085SPoul-Henning Kamp 	if (*dev != NODEV)
1023f54a085SPoul-Henning Kamp 		return;
1033f54a085SPoul-Henning Kamp 
1043f54a085SPoul-Henning Kamp 	LIST_FOREACH(dp, &disklist, d_list) {
1053f54a085SPoul-Henning Kamp 		d = dp->d_devsw->d_name;
106417fb7f6SPoul-Henning Kamp 		j = dev_stdclone(name, &e, d, &u);
107417fb7f6SPoul-Henning Kamp 		if (j == 0)
1083f54a085SPoul-Henning Kamp 			continue;
109f84ee0ffSPoul-Henning Kamp 		if (u > DKMAXUNIT)
110f84ee0ffSPoul-Henning Kamp 			continue;
1113f54a085SPoul-Henning Kamp 		p = RAW_PART;
1123f54a085SPoul-Henning Kamp 		s = WHOLE_DISK_SLICE;
1133f54a085SPoul-Henning Kamp 		pdev = makedev(dp->d_devsw->d_maj, dkmakeminor(u, s, p));
1143f54a085SPoul-Henning Kamp 		if (pdev->si_disk == NULL)
1153f54a085SPoul-Henning Kamp 			continue;
116417fb7f6SPoul-Henning Kamp 		if (*e != '\0') {
117417fb7f6SPoul-Henning Kamp 			j = dev_stdclone(e, &e, "s", &s);
118417fb7f6SPoul-Henning Kamp 			if (j == 0)
1193f54a085SPoul-Henning Kamp 				s = COMPATIBILITY_SLICE;
120417fb7f6SPoul-Henning Kamp 			else if (j == 1 || j == 2)
121417fb7f6SPoul-Henning Kamp 				s += BASE_SLICE - 1;
122417fb7f6SPoul-Henning Kamp 			if (!*e)
123417fb7f6SPoul-Henning Kamp 				;		/* ad0s1 case */
124417fb7f6SPoul-Henning Kamp 			else if (e[1] != '\0')
125417fb7f6SPoul-Henning Kamp 				return;		/* can never be a disk name */
126417fb7f6SPoul-Henning Kamp 			else if (*e < 'a' || *e > 'h')
127417fb7f6SPoul-Henning Kamp 				return;		/* can never be a disk name */
1283f54a085SPoul-Henning Kamp 			else
129417fb7f6SPoul-Henning Kamp 				p = *e - 'a';
1303f54a085SPoul-Henning Kamp 		}
131417fb7f6SPoul-Henning Kamp 		if (s == WHOLE_DISK_SLICE && p == RAW_PART) {
132417fb7f6SPoul-Henning Kamp 			return;
133417fb7f6SPoul-Henning Kamp 		} else if (s >= BASE_SLICE && p != RAW_PART) {
1344e4a7663SPoul-Henning Kamp 			*dev = make_dev(pdev->si_devsw, dkmakeminor(u, s, p),
1354e4a7663SPoul-Henning Kamp 			    UID_ROOT, GID_OPERATOR, 0640, "%s%ds%d%c",
136a2d7281cSPoul-Henning Kamp 			    pdev->si_devsw->d_name, u, s - BASE_SLICE + 1,
137a2d7281cSPoul-Henning Kamp 			    p + 'a');
138a2d7281cSPoul-Henning Kamp 		} else if (s >= BASE_SLICE) {
139a2d7281cSPoul-Henning Kamp 			*dev = make_dev(pdev->si_devsw, dkmakeminor(u, s, p),
140a2d7281cSPoul-Henning Kamp 			    UID_ROOT, GID_OPERATOR, 0640, "%s%ds%d",
141a2d7281cSPoul-Henning Kamp 			    pdev->si_devsw->d_name, u, s - BASE_SLICE + 1);
142a2d7281cSPoul-Henning Kamp 			make_dev_alias(*dev, "%s%ds%dc",
143a2d7281cSPoul-Henning Kamp 			    pdev->si_devsw->d_name, u, s - BASE_SLICE + 1);
144a2d7281cSPoul-Henning Kamp 		} else {
1453f54a085SPoul-Henning Kamp 			*dev = make_dev(pdev->si_devsw, dkmakeminor(u, s, p),
146417fb7f6SPoul-Henning Kamp 			    UID_ROOT, GID_OPERATOR, 0640, "%s%d%c",
147417fb7f6SPoul-Henning Kamp 			    pdev->si_devsw->d_name, u, p + 'a');
1484e4a7663SPoul-Henning Kamp 		}
149a2d7281cSPoul-Henning Kamp 		dev_depends(pdev, *dev);
1503f54a085SPoul-Henning Kamp 		return;
1513f54a085SPoul-Henning Kamp 	}
1523f54a085SPoul-Henning Kamp }
1533f54a085SPoul-Henning Kamp 
1545d10777cSWarner Losh static void
1555d10777cSWarner Losh inherit_raw(dev_t pdev, dev_t dev)
1565d10777cSWarner Losh {
1575d10777cSWarner Losh 	dev->si_disk = pdev->si_disk;
1585d10777cSWarner Losh 	dev->si_drv1 = pdev->si_drv1;
1595d10777cSWarner Losh 	dev->si_drv2 = pdev->si_drv2;
1605d10777cSWarner Losh 	dev->si_iosize_max = pdev->si_iosize_max;
1615d10777cSWarner Losh 	dev->si_bsize_phys = pdev->si_bsize_phys;
1625d10777cSWarner Losh 	dev->si_bsize_best = pdev->si_bsize_best;
1635d10777cSWarner Losh }
1645d10777cSWarner Losh 
165da9e4f55SPoul-Henning Kamp dev_t
1662016e4e9SPoul-Henning Kamp disk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw, struct cdevsw *proto)
167da9e4f55SPoul-Henning Kamp {
1683f54a085SPoul-Henning Kamp 	static int once;
16922628ccfSPoul-Henning Kamp 	dev_t dev;
1703344c5a1SPoul-Henning Kamp 
1713344c5a1SPoul-Henning Kamp 	if (!once) {
1723344c5a1SPoul-Henning Kamp 		EVENTHANDLER_REGISTER(dev_clone, disk_clone, 0, 1000);
1733344c5a1SPoul-Henning Kamp 		once++;
1743344c5a1SPoul-Henning Kamp 	}
175da9e4f55SPoul-Henning Kamp 
1768684f73aSPoul-Henning Kamp 	bzero(dp, sizeof(*dp));
1773febdd8fSPoul-Henning Kamp 
1788576c652SPoul-Henning Kamp 	if (proto->d_open != diskopen) {
1792016e4e9SPoul-Henning Kamp 		*proto = *cdevsw;
1802016e4e9SPoul-Henning Kamp 		proto->d_open = diskopen;
1812016e4e9SPoul-Henning Kamp 		proto->d_close = diskclose;
1822016e4e9SPoul-Henning Kamp 		proto->d_ioctl = diskioctl;
1832016e4e9SPoul-Henning Kamp 		proto->d_strategy = diskstrategy;
1842016e4e9SPoul-Henning Kamp 		proto->d_psize = diskpsize;
1853febdd8fSPoul-Henning Kamp 	}
1863febdd8fSPoul-Henning Kamp 
1878d67e113SJordan K. Hubbard 	if (bootverbose)
1883febdd8fSPoul-Henning Kamp 		printf("Creating DISK %s%d\n", cdevsw->d_name, unit);
189abd1f573SPoul-Henning Kamp 	dev = make_dev(proto, dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART),
1903f54a085SPoul-Henning Kamp 	    UID_ROOT, GID_OPERATOR, 0640, "%s%d", cdevsw->d_name, unit);
1913febdd8fSPoul-Henning Kamp 
192da9e4f55SPoul-Henning Kamp 	dev->si_disk = dp;
193da9e4f55SPoul-Henning Kamp 	dp->d_dev = dev;
1948db34b3aSPoul-Henning Kamp 	dp->d_dsflags = flags;
1952016e4e9SPoul-Henning Kamp 	dp->d_devsw = cdevsw;
1964bd02a56SPoul-Henning Kamp 	LIST_INSERT_HEAD(&disklist, dp, d_list);
1973344c5a1SPoul-Henning Kamp 
198da9e4f55SPoul-Henning Kamp 	return (dev);
199da9e4f55SPoul-Henning Kamp }
200da9e4f55SPoul-Henning Kamp 
2018684f73aSPoul-Henning Kamp int
2028684f73aSPoul-Henning Kamp disk_dumpcheck(dev_t dev, u_int *count, u_int *blkno, u_int *secsize)
2038684f73aSPoul-Henning Kamp {
2048684f73aSPoul-Henning Kamp 	struct disk *dp;
2058684f73aSPoul-Henning Kamp 	struct disklabel *dl;
2068684f73aSPoul-Henning Kamp 	u_int boff;
2078684f73aSPoul-Henning Kamp 
2088684f73aSPoul-Henning Kamp 	dp = dev->si_disk;
2098684f73aSPoul-Henning Kamp 	if (!dp)
2108684f73aSPoul-Henning Kamp 		return (ENXIO);
2118684f73aSPoul-Henning Kamp 	if (!dp->d_slice)
2128684f73aSPoul-Henning Kamp 		return (ENXIO);
2138684f73aSPoul-Henning Kamp 	dl = dsgetlabel(dev, dp->d_slice);
2148684f73aSPoul-Henning Kamp 	if (!dl)
2158684f73aSPoul-Henning Kamp 		return (ENXIO);
216a572c95cSBruce Evans 	*count = Maxmem * (PAGE_SIZE / dl->d_secsize);
217a572c95cSBruce Evans 	if (dumplo <= LABELSECTOR ||
2188684f73aSPoul-Henning Kamp 	    (dumplo + *count > dl->d_partitions[dkpart(dev)].p_size))
2198684f73aSPoul-Henning Kamp 		return (EINVAL);
2208684f73aSPoul-Henning Kamp 	boff = dl->d_partitions[dkpart(dev)].p_offset +
2218684f73aSPoul-Henning Kamp 	    dp->d_slice->dss_slices[dkslice(dev)].ds_offset;
2228684f73aSPoul-Henning Kamp 	*blkno = boff + dumplo;
2238684f73aSPoul-Henning Kamp 	*secsize = dl->d_secsize;
2248684f73aSPoul-Henning Kamp 	return (0);
2258684f73aSPoul-Henning Kamp 
2268684f73aSPoul-Henning Kamp }
2278684f73aSPoul-Henning Kamp 
2288684f73aSPoul-Henning Kamp void
2298684f73aSPoul-Henning Kamp disk_invalidate (struct disk *disk)
2308684f73aSPoul-Henning Kamp {
23147351d27SSøren Schmidt 	if (disk->d_slice)
2328684f73aSPoul-Henning Kamp 		dsgone(&disk->d_slice);
2338684f73aSPoul-Henning Kamp }
2348684f73aSPoul-Henning Kamp 
235da9e4f55SPoul-Henning Kamp void
2361edde29eSPoul-Henning Kamp disk_destroy(dev_t dev)
237da9e4f55SPoul-Henning Kamp {
2384bd02a56SPoul-Henning Kamp 	LIST_REMOVE(dev->si_disk, d_list);
2394bd02a56SPoul-Henning Kamp 	bzero(dev->si_disk, sizeof(*dev->si_disk));
24047351d27SSøren Schmidt     	dev->si_disk = NULL;
24147351d27SSøren Schmidt 	destroy_dev(dev);
242da9e4f55SPoul-Henning Kamp 	return;
243da9e4f55SPoul-Henning Kamp }
244da9e4f55SPoul-Henning Kamp 
2454bd02a56SPoul-Henning Kamp struct disk *
2464bd02a56SPoul-Henning Kamp disk_enumerate(struct disk *disk)
2474bd02a56SPoul-Henning Kamp {
2484bd02a56SPoul-Henning Kamp 	if (!disk)
2494bd02a56SPoul-Henning Kamp 		return (LIST_FIRST(&disklist));
2504bd02a56SPoul-Henning Kamp 	else
2514bd02a56SPoul-Henning Kamp 		return (LIST_NEXT(disk, d_list));
2524bd02a56SPoul-Henning Kamp }
2534bd02a56SPoul-Henning Kamp 
254445572c1SNeil Blakey-Milner static int
25582d9ae4eSPoul-Henning Kamp sysctl_disks(SYSCTL_HANDLER_ARGS)
256445572c1SNeil Blakey-Milner {
257445572c1SNeil Blakey-Milner 	struct disk *disk;
258445572c1SNeil Blakey-Milner 	int error, first;
259445572c1SNeil Blakey-Milner 
260445572c1SNeil Blakey-Milner 	disk = NULL;
261445572c1SNeil Blakey-Milner 	first = 1;
262445572c1SNeil Blakey-Milner 
263445572c1SNeil Blakey-Milner 	while ((disk = disk_enumerate(disk))) {
264445572c1SNeil Blakey-Milner 		if (!first) {
265445572c1SNeil Blakey-Milner 			error = SYSCTL_OUT(req, " ", 1);
266445572c1SNeil Blakey-Milner 			if (error)
267445572c1SNeil Blakey-Milner 				return error;
268445572c1SNeil Blakey-Milner 		} else {
269445572c1SNeil Blakey-Milner 			first = 0;
270445572c1SNeil Blakey-Milner 		}
271445572c1SNeil Blakey-Milner 		error = SYSCTL_OUT(req, disk->d_dev->si_name, strlen(disk->d_dev->si_name));
272445572c1SNeil Blakey-Milner 		if (error)
273445572c1SNeil Blakey-Milner 			return error;
274445572c1SNeil Blakey-Milner 	}
275445572c1SNeil Blakey-Milner 	error = SYSCTL_OUT(req, "", 1);
276445572c1SNeil Blakey-Milner 	return error;
277445572c1SNeil Blakey-Milner }
278445572c1SNeil Blakey-Milner 
279445572c1SNeil Blakey-Milner SYSCTL_PROC(_kern, OID_AUTO, disks, CTLTYPE_STRING | CTLFLAG_RD, 0, NULL,
280445572c1SNeil Blakey-Milner     sysctl_disks, "A", "names of available disks");
281445572c1SNeil Blakey-Milner 
2828684f73aSPoul-Henning Kamp /*
2838684f73aSPoul-Henning Kamp  * The cdevsw functions
2848684f73aSPoul-Henning Kamp  */
2858684f73aSPoul-Henning Kamp 
286da9e4f55SPoul-Henning Kamp static int
287b40ce416SJulian Elischer diskopen(dev_t dev, int oflags, int devtype, struct thread *td)
288da9e4f55SPoul-Henning Kamp {
289da9e4f55SPoul-Henning Kamp 	dev_t pdev;
290da9e4f55SPoul-Henning Kamp 	struct disk *dp;
291da9e4f55SPoul-Henning Kamp 	int error;
292da9e4f55SPoul-Henning Kamp 
2938684f73aSPoul-Henning Kamp 	error = 0;
294da9e4f55SPoul-Henning Kamp 	pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
2958684f73aSPoul-Henning Kamp 
296da9e4f55SPoul-Henning Kamp 	dp = pdev->si_disk;
297da9e4f55SPoul-Henning Kamp 	if (!dp)
298da9e4f55SPoul-Henning Kamp 		return (ENXIO);
2998684f73aSPoul-Henning Kamp 
3008db34b3aSPoul-Henning Kamp 	while (dp->d_flags & DISKFLAG_LOCK) {
3018db34b3aSPoul-Henning Kamp 		dp->d_flags |= DISKFLAG_WANTED;
3021b4ce5ceSPoul-Henning Kamp 		error = tsleep(dp, PRIBIO | PCATCH, "diskopen", hz);
3031b4ce5ceSPoul-Henning Kamp 		if (error)
3041b4ce5ceSPoul-Henning Kamp 			return (error);
3058db34b3aSPoul-Henning Kamp 	}
3068db34b3aSPoul-Henning Kamp 	dp->d_flags |= DISKFLAG_LOCK;
3078db34b3aSPoul-Henning Kamp 
30845604de3SPoul-Henning Kamp 	if (!dsisopen(dp->d_slice)) {
309dc722a14SSøren Schmidt 		if (!pdev->si_iosize_max)
31045604de3SPoul-Henning Kamp 			pdev->si_iosize_max = dev->si_iosize_max;
311b40ce416SJulian Elischer 		error = dp->d_devsw->d_open(pdev, oflags, devtype, td);
31245604de3SPoul-Henning Kamp 	}
31366c12520SPoul-Henning Kamp 
31466c12520SPoul-Henning Kamp 	/* Inherit properties from the whole/raw dev_t */
3155d10777cSWarner Losh 	inherit_raw(pdev, dev);
3168684f73aSPoul-Henning Kamp 
317da9e4f55SPoul-Henning Kamp 	if (error)
3188db34b3aSPoul-Henning Kamp 		goto out;
319da9e4f55SPoul-Henning Kamp 
3208db34b3aSPoul-Henning Kamp 	error = dsopen(dev, devtype, dp->d_dsflags, &dp->d_slice, &dp->d_label);
321da9e4f55SPoul-Henning Kamp 
3228684f73aSPoul-Henning Kamp 	if (!dsisopen(dp->d_slice))
323b40ce416SJulian Elischer 		dp->d_devsw->d_close(pdev, oflags, devtype, td);
3248db34b3aSPoul-Henning Kamp out:
3258db34b3aSPoul-Henning Kamp 	dp->d_flags &= ~DISKFLAG_LOCK;
3268db34b3aSPoul-Henning Kamp 	if (dp->d_flags & DISKFLAG_WANTED) {
3278db34b3aSPoul-Henning Kamp 		dp->d_flags &= ~DISKFLAG_WANTED;
3288db34b3aSPoul-Henning Kamp 		wakeup(dp);
3298db34b3aSPoul-Henning Kamp 	}
3308684f73aSPoul-Henning Kamp 
331da9e4f55SPoul-Henning Kamp 	return(error);
332da9e4f55SPoul-Henning Kamp }
333da9e4f55SPoul-Henning Kamp 
334da9e4f55SPoul-Henning Kamp static int
335b40ce416SJulian Elischer diskclose(dev_t dev, int fflag, int devtype, struct thread *td)
336da9e4f55SPoul-Henning Kamp {
337da9e4f55SPoul-Henning Kamp 	struct disk *dp;
338da9e4f55SPoul-Henning Kamp 	int error;
3395d10777cSWarner Losh 	dev_t pdev;
340da9e4f55SPoul-Henning Kamp 
341da9e4f55SPoul-Henning Kamp 	error = 0;
3425d10777cSWarner Losh 	pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
3435d10777cSWarner Losh 	dp = pdev->si_disk;
344b417a1a8SSøren Schmidt 	if (!dp)
345b417a1a8SSøren Schmidt 		return (ENXIO);
34646a706dcSMike Smith 	dsclose(dev, devtype, dp->d_slice);
347b417a1a8SSøren Schmidt 	if (!dsisopen(dp->d_slice))
348b40ce416SJulian Elischer 		error = dp->d_devsw->d_close(dp->d_dev, fflag, devtype, td);
349da9e4f55SPoul-Henning Kamp 	return (error);
350da9e4f55SPoul-Henning Kamp }
351da9e4f55SPoul-Henning Kamp 
352da9e4f55SPoul-Henning Kamp static void
3538177437dSPoul-Henning Kamp diskstrategy(struct bio *bp)
354da9e4f55SPoul-Henning Kamp {
355da9e4f55SPoul-Henning Kamp 	dev_t pdev;
356da9e4f55SPoul-Henning Kamp 	struct disk *dp;
357da9e4f55SPoul-Henning Kamp 
3588177437dSPoul-Henning Kamp 	pdev = dkmodpart(dkmodslice(bp->bio_dev, WHOLE_DISK_SLICE), RAW_PART);
3595d10777cSWarner Losh 	dp = pdev->si_disk;
360e0e0b661SPoul-Henning Kamp 	bp->bio_resid = bp->bio_bcount;
3615d10777cSWarner Losh 	if (dp != bp->bio_dev->si_disk)
3625d10777cSWarner Losh 		inherit_raw(pdev, bp->bio_dev);
363da9e4f55SPoul-Henning Kamp 
364da9e4f55SPoul-Henning Kamp 	if (!dp) {
365a468031cSPoul-Henning Kamp 		biofinish(bp, NULL, ENXIO);
366da9e4f55SPoul-Henning Kamp 		return;
367da9e4f55SPoul-Henning Kamp 	}
368da9e4f55SPoul-Henning Kamp 
369d685023eSPoul-Henning Kamp 	if (dscheck(bp, dp->d_slice) <= 0) {
370da9e4f55SPoul-Henning Kamp 		biodone(bp);
371da9e4f55SPoul-Henning Kamp 		return;
372da9e4f55SPoul-Henning Kamp 	}
373da9e4f55SPoul-Henning Kamp 
374079f2df3SPoul-Henning Kamp 	if (bp->bio_bcount == 0) {
375079f2df3SPoul-Henning Kamp 		biodone(bp);
376079f2df3SPoul-Henning Kamp 		return;
377079f2df3SPoul-Henning Kamp 	}
378079f2df3SPoul-Henning Kamp 
37967f3c95cSPoul-Henning Kamp 	KASSERT(dp->d_devsw != NULL, ("NULL devsw"));
38067f3c95cSPoul-Henning Kamp 	KASSERT(dp->d_devsw->d_strategy != NULL, ("NULL d_strategy"));
3812016e4e9SPoul-Henning Kamp 	dp->d_devsw->d_strategy(bp);
382da9e4f55SPoul-Henning Kamp 	return;
383da9e4f55SPoul-Henning Kamp 
384da9e4f55SPoul-Henning Kamp }
385da9e4f55SPoul-Henning Kamp 
386da9e4f55SPoul-Henning Kamp static int
387b40ce416SJulian Elischer diskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
388da9e4f55SPoul-Henning Kamp {
389da9e4f55SPoul-Henning Kamp 	struct disk *dp;
390da9e4f55SPoul-Henning Kamp 	int error;
3915d10777cSWarner Losh 	dev_t pdev;
392da9e4f55SPoul-Henning Kamp 
3935d10777cSWarner Losh 	pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
3945d10777cSWarner Losh 	dp = pdev->si_disk;
395b417a1a8SSøren Schmidt 	if (!dp)
396b417a1a8SSøren Schmidt 		return (ENXIO);
397da9e4f55SPoul-Henning Kamp 	error = dsioctl(dev, cmd, data, fflag, &dp->d_slice);
398da9e4f55SPoul-Henning Kamp 	if (error == ENOIOCTL)
399b40ce416SJulian Elischer 		error = dp->d_devsw->d_ioctl(dev, cmd, data, fflag, td);
400da9e4f55SPoul-Henning Kamp 	return (error);
401da9e4f55SPoul-Henning Kamp }
402da9e4f55SPoul-Henning Kamp 
403da9e4f55SPoul-Henning Kamp static int
404da9e4f55SPoul-Henning Kamp diskpsize(dev_t dev)
405da9e4f55SPoul-Henning Kamp {
406da9e4f55SPoul-Henning Kamp 	struct disk *dp;
4078684f73aSPoul-Henning Kamp 	dev_t pdev;
408da9e4f55SPoul-Henning Kamp 
4098684f73aSPoul-Henning Kamp 	pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
4108684f73aSPoul-Henning Kamp 	dp = pdev->si_disk;
411a4fcac54SBruce Evans 	if (!dp)
412a4fcac54SBruce Evans 		return (-1);
4135d10777cSWarner Losh 	if (dp != dev->si_disk) {
4148684f73aSPoul-Henning Kamp 		dev->si_drv1 = pdev->si_drv1;
4158684f73aSPoul-Henning Kamp 		dev->si_drv2 = pdev->si_drv2;
4168684f73aSPoul-Henning Kamp 		/* XXX: don't set bp->b_dev->si_disk (?) */
4178684f73aSPoul-Henning Kamp 	}
418da9e4f55SPoul-Henning Kamp 	return (dssize(dev, &dp->d_slice));
419da9e4f55SPoul-Henning Kamp }
42085a219d2SJulian Elischer 
42185a219d2SJulian Elischer SYSCTL_INT(_debug_sizeof, OID_AUTO, disklabel, CTLFLAG_RD,
42285a219d2SJulian Elischer     0, sizeof(struct disklabel), "sizeof(struct disklabel)");
42385a219d2SJulian Elischer 
42485a219d2SJulian Elischer SYSCTL_INT(_debug_sizeof, OID_AUTO, diskslices, CTLFLAG_RD,
42585a219d2SJulian Elischer     0, sizeof(struct diskslices), "sizeof(struct diskslices)");
42685a219d2SJulian Elischer 
42785a219d2SJulian Elischer SYSCTL_INT(_debug_sizeof, OID_AUTO, disk, CTLFLAG_RD,
42885a219d2SJulian Elischer     0, sizeof(struct disk), "sizeof(struct disk)");
429417fb7f6SPoul-Henning Kamp 
430417fb7f6SPoul-Henning Kamp #endif
431