2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
9 * $FreeBSD: src/sys/kern/subr_disk.c,v 1.20.2.6 2001/10/05 07:14:57 peter Exp $
10 * $DragonFly: src/sys/kern/subr_disk.c,v 1.3 2003/06/23 17:55:41 dillon Exp $
14 #include <sys/param.h>
15 #include <sys/systm.h>
16 #include <sys/kernel.h>
17 #include <sys/sysctl.h>
21 #include <sys/malloc.h>
22 #include <sys/sysctl.h>
23 #include <machine/md_var.h>
24 #include <sys/ctype.h>
26 static MALLOC_DEFINE(M_DISK, "disk", "disk data");
28 static d_strategy_t diskstrategy;
29 static d_open_t diskopen;
30 static d_close_t diskclose;
31 static d_ioctl_t diskioctl;
32 static d_psize_t diskpsize;
34 static LIST_HEAD(, disk) disklist = LIST_HEAD_INITIALIZER(&disklist);
37 inherit_raw(dev_t pdev, dev_t dev)
39 dev->si_disk = pdev->si_disk;
40 dev->si_drv1 = pdev->si_drv1;
41 dev->si_drv2 = pdev->si_drv2;
42 dev->si_iosize_max = pdev->si_iosize_max;
43 dev->si_bsize_phys = pdev->si_bsize_phys;
44 dev->si_bsize_best = pdev->si_bsize_best;
48 disk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw, struct cdevsw *proto)
52 bzero(dp, sizeof(*dp));
54 dev = makedev(cdevsw->d_maj, 0);
57 proto->d_open = diskopen;
58 proto->d_close = diskclose;
59 proto->d_ioctl = diskioctl;
60 proto->d_strategy = diskstrategy;
61 proto->d_psize = diskpsize;
66 printf("Creating DISK %s%d\n", cdevsw->d_name, unit);
67 dev = make_dev(proto, dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART),
68 UID_ROOT, GID_OPERATOR, 0640, "%s%d", cdevsw->d_name, unit);
72 dp->d_dsflags = flags;
74 LIST_INSERT_HEAD(&disklist, dp, d_list);
79 disk_dumpcheck(dev_t dev, u_int *count, u_int *blkno, u_int *secsize)
90 dl = dsgetlabel(dev, dp->d_slice);
93 *count = Maxmem * (PAGE_SIZE / dl->d_secsize);
94 if (dumplo <= LABELSECTOR ||
95 (dumplo + *count > dl->d_partitions[dkpart(dev)].p_size))
97 boff = dl->d_partitions[dkpart(dev)].p_offset +
98 dp->d_slice->dss_slices[dkslice(dev)].ds_offset;
99 *blkno = boff + dumplo;
100 *secsize = dl->d_secsize;
106 disk_invalidate (struct disk *disk)
109 dsgone(&disk->d_slice);
113 disk_destroy(dev_t dev)
115 LIST_REMOVE(dev->si_disk, d_list);
116 bzero(dev->si_disk, sizeof(*dev->si_disk));
123 disk_enumerate(struct disk *disk)
126 return (LIST_FIRST(&disklist));
128 return (LIST_NEXT(disk, d_list));
132 sysctl_disks(SYSCTL_HANDLER_ARGS)
140 while ((disk = disk_enumerate(disk))) {
142 error = SYSCTL_OUT(req, " ", 1);
148 error = SYSCTL_OUT(req, disk->d_dev->si_name, strlen(disk->d_dev->si_name));
152 error = SYSCTL_OUT(req, "", 1);
156 SYSCTL_PROC(_kern, OID_AUTO, disks, CTLTYPE_STRING | CTLFLAG_RD, 0, NULL,
157 sysctl_disks, "A", "names of available disks");
160 * The cdevsw functions
164 diskopen(dev_t dev, int oflags, int devtype, struct thread *td)
171 pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
177 while (dp->d_flags & DISKFLAG_LOCK) {
178 dp->d_flags |= DISKFLAG_WANTED;
179 error = tsleep(dp, PRIBIO | PCATCH, "diskopen", hz);
183 dp->d_flags |= DISKFLAG_LOCK;
185 if (!dsisopen(dp->d_slice)) {
186 if (!pdev->si_iosize_max)
187 pdev->si_iosize_max = dev->si_iosize_max;
188 error = dp->d_devsw->d_open(pdev, oflags, devtype, td);
191 /* Inherit properties from the whole/raw dev_t */
192 inherit_raw(pdev, dev);
197 error = dsopen(dev, devtype, dp->d_dsflags, &dp->d_slice, &dp->d_label);
199 if (!dsisopen(dp->d_slice))
200 dp->d_devsw->d_close(pdev, oflags, devtype, td);
202 dp->d_flags &= ~DISKFLAG_LOCK;
203 if (dp->d_flags & DISKFLAG_WANTED) {
204 dp->d_flags &= ~DISKFLAG_WANTED;
212 diskclose(dev_t dev, int fflag, int devtype, struct thread *td)
219 pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
223 dsclose(dev, devtype, dp->d_slice);
224 if (!dsisopen(dp->d_slice))
225 error = dp->d_devsw->d_close(dp->d_dev, fflag, devtype, td);
230 diskstrategy(struct buf *bp)
235 pdev = dkmodpart(dkmodslice(bp->b_dev, WHOLE_DISK_SLICE), RAW_PART);
237 if (dp != bp->b_dev->si_disk)
238 inherit_raw(pdev, bp->b_dev);
242 bp->b_flags |= B_ERROR;
247 if (dscheck(bp, dp->d_slice) <= 0) {
252 dp->d_devsw->d_strategy(bp);
258 diskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
264 pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
268 error = dsioctl(dev, cmd, data, fflag, &dp->d_slice);
269 if (error == ENOIOCTL)
270 error = dp->d_devsw->d_ioctl(dev, cmd, data, fflag, td);
280 pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
284 if (dp != dev->si_disk) {
285 dev->si_drv1 = pdev->si_drv1;
286 dev->si_drv2 = pdev->si_drv2;
287 /* XXX: don't set bp->b_dev->si_disk (?) */
289 return (dssize(dev, &dp->d_slice));
292 SYSCTL_DECL(_debug_sizeof);
294 SYSCTL_INT(_debug_sizeof, OID_AUTO, disklabel, CTLFLAG_RD,
295 0, sizeof(struct disklabel), "sizeof(struct disklabel)");
297 SYSCTL_INT(_debug_sizeof, OID_AUTO, diskslices, CTLFLAG_RD,
298 0, sizeof(struct diskslices), "sizeof(struct diskslices)");
300 SYSCTL_INT(_debug_sizeof, OID_AUTO, disk, CTLFLAG_RD,
301 0, sizeof(struct disk), "sizeof(struct disk)");