subr_disk.c revision 51878
1/* 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 * ---------------------------------------------------------------------------- 8 * 9 * $FreeBSD: head/sys/kern/subr_disk.c 51878 1999-10-02 20:21:49Z sos $ 10 * 11 */ 12 13#include <sys/param.h> 14#include <sys/systm.h> 15#include <sys/kernel.h> 16#include <sys/sysctl.h> 17#include <sys/buf.h> 18#include <sys/conf.h> 19#include <sys/disk.h> 20#include <sys/malloc.h> 21#include <sys/vnode.h> 22#include <machine/md_var.h> 23 24MALLOC_DEFINE(M_DISK, "disk", "disk data"); 25 26static d_strategy_t diskstrategy; 27static d_open_t diskopen; 28static d_close_t diskclose; 29static d_ioctl_t diskioctl; 30static d_psize_t diskpsize; 31 32dev_t 33disk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw, struct cdevsw *proto) 34{ 35 dev_t dev; 36 37 bzero(dp, sizeof(*dp)); 38 39 dev = makedev(cdevsw->d_maj, 0); 40 if (!devsw(dev)) { 41 *proto = *cdevsw; 42 proto->d_open = diskopen; 43 proto->d_close = diskclose; 44 proto->d_ioctl = diskioctl; 45 proto->d_strategy = diskstrategy; 46 proto->d_psize = diskpsize; 47 cdevsw_add(proto); 48 } 49 50 printf("Creating DISK %s%d\n", cdevsw->d_name, unit); 51 dev = make_dev(proto, dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART), 52 0, 0, 0, "r%s%d", cdevsw->d_name, unit); 53 54 dev->si_disk = dp; 55 dp->d_dev = dev; 56 dp->d_flags = flags; 57 dp->d_devsw = cdevsw; 58 return (dev); 59} 60 61int 62disk_dumpcheck(dev_t dev, u_int *count, u_int *blkno, u_int *secsize) 63{ 64 struct disk *dp; 65 struct disklabel *dl; 66 u_int boff; 67 68 dp = dev->si_disk; 69 if (!dp) 70 return (ENXIO); 71 if (!dp->d_slice) 72 return (ENXIO); 73 dl = dsgetlabel(dev, dp->d_slice); 74 if (!dl) 75 return (ENXIO); 76 *count = (u_long)Maxmem * PAGE_SIZE / dl->d_secsize; 77 if (dumplo < 0 || 78 (dumplo + *count > dl->d_partitions[dkpart(dev)].p_size)) 79 return (EINVAL); 80 boff = dl->d_partitions[dkpart(dev)].p_offset + 81 dp->d_slice->dss_slices[dkslice(dev)].ds_offset; 82 *blkno = boff + dumplo; 83 *secsize = dl->d_secsize; 84 return (0); 85 86} 87 88void 89disk_invalidate (struct disk *disk) 90{ 91 dsgone(&disk->d_slice); 92} 93 94void 95disk_delete(dev_t dev) 96{ 97 return; 98} 99 100/* 101 * The cdevsw functions 102 */ 103 104static int 105diskopen(dev_t dev, int oflags, int devtype, struct proc *p) 106{ 107 dev_t pdev; 108 struct disk *dp; 109 int error; 110 111 error = 0; 112 pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 113 114 dp = pdev->si_disk; 115 if (!dp) 116 return (ENXIO); 117 118 if (!dsisopen(dp->d_slice)) { 119 if (!pdev->si_iosize_max) 120 pdev->si_iosize_max = dev->si_iosize_max; 121 error = dp->d_devsw->d_open(pdev, oflags, devtype, p); 122 } 123 124 /* Inherit properties from the whole/raw dev_t */ 125 dev->si_disk = pdev->si_disk; 126 dev->si_drv1 = pdev->si_drv1; 127 dev->si_drv2 = pdev->si_drv2; 128 dev->si_iosize_max = pdev->si_iosize_max; 129 dev->si_bsize_phys = pdev->si_bsize_phys; 130 dev->si_bsize_best = pdev->si_bsize_best; 131 132 if (error) 133 return(error); 134 135 error = dsopen(dev, devtype, dp->d_flags, &dp->d_slice, &dp->d_label); 136 137 if (!dsisopen(dp->d_slice)) 138 dp->d_devsw->d_close(dev, oflags, devtype, p); 139 140 return(error); 141} 142 143static int 144diskclose(dev_t dev, int fflag, int devtype, struct proc *p) 145{ 146 struct disk *dp; 147 int error; 148 dev_t pdev; 149 150 error = 0; 151 dp = dev->si_disk; 152 dsclose(dev, devtype, dp->d_slice); 153 if (!dsisopen(dp->d_slice)) { 154 pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 155 error = dp->d_devsw->d_close(pdev, fflag, devtype, p); 156 } 157 return (error); 158} 159 160static void 161diskstrategy(struct buf *bp) 162{ 163 dev_t pdev; 164 struct disk *dp; 165 166 dp = bp->b_dev->si_disk; 167 if (!dp) { 168 pdev = dkmodpart(dkmodslice(bp->b_dev, WHOLE_DISK_SLICE), RAW_PART); 169 dp = bp->b_dev->si_disk = pdev->si_disk; 170 bp->b_dev->si_drv1 = pdev->si_drv1; 171 bp->b_dev->si_drv2 = pdev->si_drv2; 172 bp->b_dev->si_iosize_max = pdev->si_iosize_max; 173 bp->b_dev->si_bsize_phys = pdev->si_bsize_phys; 174 bp->b_dev->si_bsize_best = pdev->si_bsize_best; 175 } 176 177 if (!dp) { 178 bp->b_error = ENXIO; 179 bp->b_flags |= B_ERROR; 180 biodone(bp); 181 return; 182 } 183 184 if (dscheck(bp, dp->d_slice) < 0) { 185 biodone(bp); 186 return; 187 } 188 189 dp->d_devsw->d_strategy(bp); 190 return; 191 192} 193 194static int 195diskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p) 196{ 197 struct disk *dp; 198 int error; 199 200 dp = dev->si_disk; 201 error = dsioctl(dev, cmd, data, fflag, &dp->d_slice); 202 if (error == ENOIOCTL) 203 error = dp->d_devsw->d_ioctl(dev, cmd, data, fflag, p); 204 return (error); 205} 206 207static int 208diskpsize(dev_t dev) 209{ 210 struct disk *dp; 211 dev_t pdev; 212 213 dp = dev->si_disk; 214 if (!dp) { 215 pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 216 dp = pdev->si_disk; 217 dev->si_drv1 = pdev->si_drv1; 218 dev->si_drv2 = pdev->si_drv2; 219 /* XXX: don't set bp->b_dev->si_disk (?) */ 220 } 221 return (dssize(dev, &dp->d_slice)); 222} 223 224SYSCTL_DECL(_debug_sizeof); 225 226SYSCTL_INT(_debug_sizeof, OID_AUTO, disklabel, CTLFLAG_RD, 227 0, sizeof(struct disklabel), "sizeof(struct disklabel)"); 228 229SYSCTL_INT(_debug_sizeof, OID_AUTO, diskslices, CTLFLAG_RD, 230 0, sizeof(struct diskslices), "sizeof(struct diskslices)"); 231 232SYSCTL_INT(_debug_sizeof, OID_AUTO, disk, CTLFLAG_RD, 233 0, sizeof(struct disk), "sizeof(struct disk)"); 234