subr_disk.c revision 56767
1130803Smarcel/* 246283Sdfr * ---------------------------------------------------------------------------- 3130803Smarcel * "THE BEER-WARE LICENSE" (Revision 42): 4130803Smarcel * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you 5130803Smarcel * can do whatever you want with this stuff. If we meet some day, and you think 646283Sdfr * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 746283Sdfr * ---------------------------------------------------------------------------- 8130803Smarcel * 946283Sdfr * $FreeBSD: head/sys/kern/subr_disk.c 56767 2000-01-28 20:49:43Z phk $ 10130803Smarcel * 11130803Smarcel */ 1246283Sdfr 1346283Sdfr#include <sys/param.h> 1446283Sdfr#include <sys/systm.h> 1546283Sdfr#include <sys/kernel.h> 1646283Sdfr#include <sys/sysctl.h> 1746283Sdfr#include <sys/buf.h> 1846283Sdfr#include <sys/conf.h> 1946283Sdfr#include <sys/disk.h> 2046283Sdfr#include <sys/malloc.h> 2146283Sdfr#include <machine/md_var.h> 2246283Sdfr 2346283SdfrMALLOC_DEFINE(M_DISK, "disk", "disk data"); 2446283Sdfr 2546283Sdfrstatic d_strategy_t diskstrategy; 2646283Sdfrstatic d_open_t diskopen; 2746283Sdfrstatic d_close_t diskclose; 2846283Sdfrstatic d_ioctl_t diskioctl; 2946283Sdfrstatic d_psize_t diskpsize; 3046283Sdfr 3146283Sdfrdev_t 3246283Sdfrdisk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw, struct cdevsw *proto) 3346283Sdfr{ 3446283Sdfr dev_t dev; 3546283Sdfr 3646283Sdfr bzero(dp, sizeof(*dp)); 3746283Sdfr 3846283Sdfr dev = makedev(cdevsw->d_maj, 0); 3946283Sdfr if (!devsw(dev)) { 4046283Sdfr *proto = *cdevsw; 4146283Sdfr proto->d_open = diskopen; 4246283Sdfr proto->d_close = diskclose; 4346283Sdfr proto->d_ioctl = diskioctl; 4446283Sdfr proto->d_strategy = diskstrategy; 4546283Sdfr proto->d_psize = diskpsize; 4646283Sdfr cdevsw_add(proto); 4746283Sdfr } 4846283Sdfr 4946283Sdfr if (bootverbose) 5046283Sdfr printf("Creating DISK %s%d\n", cdevsw->d_name, unit); 5146283Sdfr dev = make_dev(proto, dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART), 5246283Sdfr 0, 0, 0, "r%s%d", cdevsw->d_name, unit); 5346283Sdfr 5446283Sdfr dev->si_disk = dp; 5546283Sdfr dp->d_dev = dev; 5646283Sdfr dp->d_dsflags = flags; 5746283Sdfr dp->d_devsw = cdevsw; 5846283Sdfr return (dev); 5946283Sdfr} 6046283Sdfr 6146283Sdfrint 6246283Sdfrdisk_dumpcheck(dev_t dev, u_int *count, u_int *blkno, u_int *secsize) 6346283Sdfr{ 6446283Sdfr struct disk *dp; 6546283Sdfr struct disklabel *dl; 6646283Sdfr u_int boff; 6746283Sdfr 6846283Sdfr dp = dev->si_disk; 6946283Sdfr if (!dp) 7046283Sdfr return (ENXIO); 7146283Sdfr if (!dp->d_slice) 7246283Sdfr return (ENXIO); 7346283Sdfr dl = dsgetlabel(dev, dp->d_slice); 7446283Sdfr if (!dl) 7546283Sdfr return (ENXIO); 7646283Sdfr *count = (u_long)Maxmem * PAGE_SIZE / dl->d_secsize; 7746283Sdfr if (dumplo < 0 || 7846283Sdfr (dumplo + *count > dl->d_partitions[dkpart(dev)].p_size)) 7946283Sdfr return (EINVAL); 8046283Sdfr boff = dl->d_partitions[dkpart(dev)].p_offset + 8146283Sdfr dp->d_slice->dss_slices[dkslice(dev)].ds_offset; 8246283Sdfr *blkno = boff + dumplo; 8346283Sdfr *secsize = dl->d_secsize; 8446283Sdfr return (0); 8546283Sdfr 8646283Sdfr} 8746283Sdfr 8846283Sdfrvoid 8946283Sdfrdisk_invalidate (struct disk *disk) 9046283Sdfr{ 9146283Sdfr dsgone(&disk->d_slice); 9246283Sdfr} 9346283Sdfr 9446283Sdfrvoid 9546283Sdfrdisk_destroy(dev_t dev) 9646283Sdfr{ 9746283Sdfr return; 9846283Sdfr} 9946283Sdfr 10046283Sdfr/* 10146283Sdfr * The cdevsw functions 10246283Sdfr */ 10346283Sdfr 10446283Sdfrstatic int 10546283Sdfrdiskopen(dev_t dev, int oflags, int devtype, struct proc *p) 10646283Sdfr{ 10746283Sdfr dev_t pdev; 10846283Sdfr struct disk *dp; 10946283Sdfr int error; 11046283Sdfr 11146283Sdfr error = 0; 11246283Sdfr pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 11346283Sdfr 11446283Sdfr dp = pdev->si_disk; 11546283Sdfr if (!dp) 11646283Sdfr return (ENXIO); 11746283Sdfr 11846283Sdfr while (dp->d_flags & DISKFLAG_LOCK) { 11946283Sdfr dp->d_flags |= DISKFLAG_WANTED; 12046283Sdfr error = tsleep(dp, PRIBIO | PCATCH, "diskopen", hz); 12146283Sdfr if (error) 12246283Sdfr return (error); 12346283Sdfr } 12446283Sdfr dp->d_flags |= DISKFLAG_LOCK; 12546283Sdfr 12646283Sdfr if (!dsisopen(dp->d_slice)) { 12746283Sdfr if (!pdev->si_iosize_max) 12846283Sdfr pdev->si_iosize_max = dev->si_iosize_max; 12946283Sdfr error = dp->d_devsw->d_open(pdev, oflags, devtype, p); 13046283Sdfr } 13146283Sdfr 13246283Sdfr /* Inherit properties from the whole/raw dev_t */ 13346283Sdfr dev->si_disk = pdev->si_disk; 13446283Sdfr dev->si_drv1 = pdev->si_drv1; 13546283Sdfr dev->si_drv2 = pdev->si_drv2; 13646283Sdfr dev->si_iosize_max = pdev->si_iosize_max; 13746283Sdfr dev->si_bsize_phys = pdev->si_bsize_phys; 13846283Sdfr dev->si_bsize_best = pdev->si_bsize_best; 13946283Sdfr 14046283Sdfr if (error) 14146283Sdfr goto out; 14246283Sdfr 14346283Sdfr error = dsopen(dev, devtype, dp->d_dsflags, &dp->d_slice, &dp->d_label); 14446283Sdfr 14546283Sdfr if (!dsisopen(dp->d_slice)) 14646283Sdfr dp->d_devsw->d_close(pdev, oflags, devtype, p); 14746283Sdfrout: 14846283Sdfr dp->d_flags &= ~DISKFLAG_LOCK; 14946283Sdfr if (dp->d_flags & DISKFLAG_WANTED) { 15046283Sdfr dp->d_flags &= ~DISKFLAG_WANTED; 15146283Sdfr wakeup(dp); 15246283Sdfr } 15346283Sdfr 15446283Sdfr return(error); 15546283Sdfr} 15646283Sdfr 15746283Sdfrstatic int 15846283Sdfrdiskclose(dev_t dev, int fflag, int devtype, struct proc *p) 15946283Sdfr{ 16046283Sdfr struct disk *dp; 16146283Sdfr int error; 16246283Sdfr 16346283Sdfr error = 0; 16446283Sdfr dp = dev->si_disk; 16546283Sdfr dsclose(dev, devtype, dp->d_slice); 16646283Sdfr if (!dsisopen(dp->d_slice)) { 16746283Sdfr error = dp->d_devsw->d_close(dp->d_dev, fflag, devtype, p); 16846283Sdfr } 16946283Sdfr return (error); 17046283Sdfr} 17146283Sdfr 17246283Sdfrstatic void 17346283Sdfrdiskstrategy(struct buf *bp) 17446283Sdfr{ 17546283Sdfr dev_t pdev; 17646283Sdfr struct disk *dp; 17746283Sdfr 17846283Sdfr dp = bp->b_dev->si_disk; 17946283Sdfr if (!dp) { 18046283Sdfr pdev = dkmodpart(dkmodslice(bp->b_dev, WHOLE_DISK_SLICE), RAW_PART); 18146283Sdfr dp = bp->b_dev->si_disk = pdev->si_disk; 18246283Sdfr bp->b_dev->si_drv1 = pdev->si_drv1; 18346283Sdfr bp->b_dev->si_drv2 = pdev->si_drv2; 18446283Sdfr bp->b_dev->si_iosize_max = pdev->si_iosize_max; 18546283Sdfr bp->b_dev->si_bsize_phys = pdev->si_bsize_phys; 18646283Sdfr bp->b_dev->si_bsize_best = pdev->si_bsize_best; 18746283Sdfr } 18846283Sdfr 18946283Sdfr if (!dp) { 19046283Sdfr bp->b_error = ENXIO; 19146283Sdfr bp->b_flags |= B_ERROR; 19246283Sdfr biodone(bp); 19346283Sdfr return; 19446283Sdfr } 19546283Sdfr 19646283Sdfr if (dscheck(bp, dp->d_slice) <= 0) { 19746283Sdfr biodone(bp); 19846283Sdfr return; 19946283Sdfr } 20046283Sdfr 20146283Sdfr dp->d_devsw->d_strategy(bp); 20246283Sdfr return; 20346283Sdfr 20446283Sdfr} 20546283Sdfr 20646283Sdfrstatic int 20746283Sdfrdiskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p) 20846283Sdfr{ 20946283Sdfr struct disk *dp; 21046283Sdfr int error; 21146283Sdfr 21246283Sdfr dp = dev->si_disk; 21346283Sdfr error = dsioctl(dev, cmd, data, fflag, &dp->d_slice); 21446283Sdfr if (error == ENOIOCTL) 21546283Sdfr error = dp->d_devsw->d_ioctl(dev, cmd, data, fflag, p); 21646283Sdfr return (error); 21746283Sdfr} 21846283Sdfr 21946283Sdfrstatic int 22046283Sdfrdiskpsize(dev_t dev) 22146283Sdfr{ 22246283Sdfr struct disk *dp; 22346283Sdfr dev_t pdev; 22446283Sdfr 22546283Sdfr dp = dev->si_disk; 22646283Sdfr if (!dp) { 22746283Sdfr pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 22846283Sdfr dp = pdev->si_disk; 22946283Sdfr dev->si_drv1 = pdev->si_drv1; 23046283Sdfr dev->si_drv2 = pdev->si_drv2; 23146283Sdfr /* XXX: don't set bp->b_dev->si_disk (?) */ 23246283Sdfr } 23346283Sdfr return (dssize(dev, &dp->d_slice)); 23446283Sdfr} 23546283Sdfr 23646283SdfrSYSCTL_DECL(_debug_sizeof); 23746283Sdfr 23846283SdfrSYSCTL_INT(_debug_sizeof, OID_AUTO, disklabel, CTLFLAG_RD, 23946283Sdfr 0, sizeof(struct disklabel), "sizeof(struct disklabel)"); 24046283Sdfr 24146283SdfrSYSCTL_INT(_debug_sizeof, OID_AUTO, diskslices, CTLFLAG_RD, 24246283Sdfr 0, sizeof(struct diskslices), "sizeof(struct diskslices)"); 24346283Sdfr 24446283SdfrSYSCTL_INT(_debug_sizeof, OID_AUTO, disk, CTLFLAG_RD, 24546283Sdfr 0, sizeof(struct disk), "sizeof(struct disk)"); 24646283Sdfr