subr_disk.c revision 53437
150565Sphk/* 250565Sphk * ---------------------------------------------------------------------------- 350565Sphk * "THE BEER-WARE LICENSE" (Revision 42): 450565Sphk * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you 550565Sphk * can do whatever you want with this stuff. If we meet some day, and you think 650565Sphk * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 750565Sphk * ---------------------------------------------------------------------------- 850565Sphk * 950565Sphk * $FreeBSD: head/sys/kern/subr_disk.c 53437 1999-11-19 23:34:01Z jkh $ 1050565Sphk * 1150565Sphk */ 1250565Sphk 1350565Sphk#include <sys/param.h> 1450565Sphk#include <sys/systm.h> 1550565Sphk#include <sys/kernel.h> 1651111Sjulian#include <sys/sysctl.h> 1750565Sphk#include <sys/buf.h> 1850565Sphk#include <sys/conf.h> 1950565Sphk#include <sys/disk.h> 2050565Sphk#include <sys/malloc.h> 2150728Sphk#include <machine/md_var.h> 2250565Sphk 2350565SphkMALLOC_DEFINE(M_DISK, "disk", "disk data"); 2450565Sphk 2550565Sphkstatic d_strategy_t diskstrategy; 2650565Sphkstatic d_open_t diskopen; 2750565Sphkstatic d_close_t diskclose; 2850565Sphkstatic d_ioctl_t diskioctl; 2950565Sphkstatic d_psize_t diskpsize; 3050565Sphk 3150565Sphkdev_t 3251215Sphkdisk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw, struct cdevsw *proto) 3350565Sphk{ 3450565Sphk dev_t dev; 3550565Sphk 3651198Sphk bzero(dp, sizeof(*dp)); 3751198Sphk 3850565Sphk dev = makedev(cdevsw->d_maj, 0); 3951198Sphk if (!devsw(dev)) { 4051215Sphk *proto = *cdevsw; 4151215Sphk proto->d_open = diskopen; 4251215Sphk proto->d_close = diskclose; 4351215Sphk proto->d_ioctl = diskioctl; 4451215Sphk proto->d_strategy = diskstrategy; 4551215Sphk proto->d_psize = diskpsize; 4651215Sphk cdevsw_add(proto); 4750565Sphk } 4850565Sphk 4953437Sjkh if (bootverbose) 5053437Sjkh printf("Creating DISK %s%d\n", cdevsw->d_name, unit); 5151243Sphk dev = make_dev(proto, dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART), 5251198Sphk 0, 0, 0, "r%s%d", cdevsw->d_name, unit); 5350565Sphk 5450565Sphk dev->si_disk = dp; 5550565Sphk dp->d_dev = dev; 5652917Sphk dp->d_dsflags = flags; 5751215Sphk dp->d_devsw = cdevsw; 5850565Sphk return (dev); 5950565Sphk} 6050565Sphk 6150728Sphkint 6250728Sphkdisk_dumpcheck(dev_t dev, u_int *count, u_int *blkno, u_int *secsize) 6350728Sphk{ 6450728Sphk struct disk *dp; 6550728Sphk struct disklabel *dl; 6650728Sphk u_int boff; 6750728Sphk 6850728Sphk dp = dev->si_disk; 6950728Sphk if (!dp) 7050728Sphk return (ENXIO); 7150728Sphk if (!dp->d_slice) 7250728Sphk return (ENXIO); 7350728Sphk dl = dsgetlabel(dev, dp->d_slice); 7450728Sphk if (!dl) 7550728Sphk return (ENXIO); 7650728Sphk *count = (u_long)Maxmem * PAGE_SIZE / dl->d_secsize; 7750728Sphk if (dumplo < 0 || 7850728Sphk (dumplo + *count > dl->d_partitions[dkpart(dev)].p_size)) 7950728Sphk return (EINVAL); 8050728Sphk boff = dl->d_partitions[dkpart(dev)].p_offset + 8150728Sphk dp->d_slice->dss_slices[dkslice(dev)].ds_offset; 8250728Sphk *blkno = boff + dumplo; 8350728Sphk *secsize = dl->d_secsize; 8450728Sphk return (0); 8550728Sphk 8650728Sphk} 8750728Sphk 8850728Sphkvoid 8950728Sphkdisk_invalidate (struct disk *disk) 9050728Sphk{ 9150728Sphk dsgone(&disk->d_slice); 9250728Sphk} 9350728Sphk 9450565Sphkvoid 9550565Sphkdisk_delete(dev_t dev) 9650565Sphk{ 9750565Sphk return; 9850565Sphk} 9950565Sphk 10050728Sphk/* 10150728Sphk * The cdevsw functions 10250728Sphk */ 10350728Sphk 10450565Sphkstatic int 10550565Sphkdiskopen(dev_t dev, int oflags, int devtype, struct proc *p) 10650565Sphk{ 10750565Sphk dev_t pdev; 10850565Sphk struct disk *dp; 10950565Sphk int error; 11050565Sphk 11150728Sphk error = 0; 11250565Sphk pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 11350728Sphk 11450565Sphk dp = pdev->si_disk; 11550565Sphk if (!dp) 11650565Sphk return (ENXIO); 11750728Sphk 11852917Sphk while (dp->d_flags & DISKFLAG_LOCK) { 11952917Sphk dp->d_flags |= DISKFLAG_WANTED; 12052917Sphk tsleep(dp, PRIBIO | PCATCH, "diskopen", hz); 12152917Sphk } 12252917Sphk dp->d_flags |= DISKFLAG_LOCK; 12352917Sphk 12451860Sphk if (!dsisopen(dp->d_slice)) { 12551878Ssos if (!pdev->si_iosize_max) 12651878Ssos pdev->si_iosize_max = dev->si_iosize_max; 12751826Sphk error = dp->d_devsw->d_open(pdev, oflags, devtype, p); 12851860Sphk } 12951826Sphk 13051826Sphk /* Inherit properties from the whole/raw dev_t */ 13151826Sphk dev->si_disk = pdev->si_disk; 13250728Sphk dev->si_drv1 = pdev->si_drv1; 13350728Sphk dev->si_drv2 = pdev->si_drv2; 13451826Sphk dev->si_iosize_max = pdev->si_iosize_max; 13551826Sphk dev->si_bsize_phys = pdev->si_bsize_phys; 13651826Sphk dev->si_bsize_best = pdev->si_bsize_best; 13750728Sphk 13850728Sphk if (error) 13952917Sphk goto out; 14050728Sphk 14152917Sphk error = dsopen(dev, devtype, dp->d_dsflags, &dp->d_slice, &dp->d_label); 14250565Sphk 14350728Sphk if (!dsisopen(dp->d_slice)) 14451924Sphk dp->d_devsw->d_close(pdev, oflags, devtype, p); 14552917Sphkout: 14652917Sphk dp->d_flags &= ~DISKFLAG_LOCK; 14752917Sphk if (dp->d_flags & DISKFLAG_WANTED) { 14852917Sphk dp->d_flags &= ~DISKFLAG_WANTED; 14952917Sphk wakeup(dp); 15052917Sphk } 15150728Sphk 15250565Sphk return(error); 15350565Sphk} 15450565Sphk 15550565Sphkstatic int 15650565Sphkdiskclose(dev_t dev, int fflag, int devtype, struct proc *p) 15750565Sphk{ 15850565Sphk struct disk *dp; 15950565Sphk int error; 16050565Sphk 16150565Sphk error = 0; 16250565Sphk dp = dev->si_disk; 16351822Sphk dsclose(dev, devtype, dp->d_slice); 16451826Sphk if (!dsisopen(dp->d_slice)) { 16551924Sphk error = dp->d_devsw->d_close(dp->d_dev, fflag, devtype, p); 16651826Sphk } 16750565Sphk return (error); 16850565Sphk} 16950565Sphk 17050565Sphkstatic void 17150565Sphkdiskstrategy(struct buf *bp) 17250565Sphk{ 17350565Sphk dev_t pdev; 17450565Sphk struct disk *dp; 17550565Sphk 17650565Sphk dp = bp->b_dev->si_disk; 17750565Sphk if (!dp) { 17850565Sphk pdev = dkmodpart(dkmodslice(bp->b_dev, WHOLE_DISK_SLICE), RAW_PART); 17951860Sphk dp = bp->b_dev->si_disk = pdev->si_disk; 18050565Sphk bp->b_dev->si_drv1 = pdev->si_drv1; 18150565Sphk bp->b_dev->si_drv2 = pdev->si_drv2; 18251860Sphk bp->b_dev->si_iosize_max = pdev->si_iosize_max; 18351860Sphk bp->b_dev->si_bsize_phys = pdev->si_bsize_phys; 18451860Sphk bp->b_dev->si_bsize_best = pdev->si_bsize_best; 18550565Sphk } 18650565Sphk 18750565Sphk if (!dp) { 18850565Sphk bp->b_error = ENXIO; 18950565Sphk bp->b_flags |= B_ERROR; 19050565Sphk biodone(bp); 19150565Sphk return; 19250565Sphk } 19350565Sphk 19450565Sphk if (dscheck(bp, dp->d_slice) < 0) { 19550565Sphk biodone(bp); 19650565Sphk return; 19750565Sphk } 19850565Sphk 19951215Sphk dp->d_devsw->d_strategy(bp); 20050565Sphk return; 20150565Sphk 20250565Sphk} 20350565Sphk 20450565Sphkstatic int 20550565Sphkdiskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p) 20650565Sphk{ 20750565Sphk struct disk *dp; 20850565Sphk int error; 20950565Sphk 21050565Sphk dp = dev->si_disk; 21150565Sphk error = dsioctl(dev, cmd, data, fflag, &dp->d_slice); 21250565Sphk if (error == ENOIOCTL) 21351215Sphk error = dp->d_devsw->d_ioctl(dev, cmd, data, fflag, p); 21450565Sphk return (error); 21550565Sphk} 21650565Sphk 21750565Sphkstatic int 21850565Sphkdiskpsize(dev_t dev) 21950565Sphk{ 22050565Sphk struct disk *dp; 22150728Sphk dev_t pdev; 22250565Sphk 22350565Sphk dp = dev->si_disk; 22450728Sphk if (!dp) { 22550728Sphk pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 22650728Sphk dp = pdev->si_disk; 22750728Sphk dev->si_drv1 = pdev->si_drv1; 22850728Sphk dev->si_drv2 = pdev->si_drv2; 22950728Sphk /* XXX: don't set bp->b_dev->si_disk (?) */ 23050728Sphk } 23150565Sphk return (dssize(dev, &dp->d_slice)); 23250565Sphk} 23351111Sjulian 23451111SjulianSYSCTL_DECL(_debug_sizeof); 23551111Sjulian 23651111SjulianSYSCTL_INT(_debug_sizeof, OID_AUTO, disklabel, CTLFLAG_RD, 23751111Sjulian 0, sizeof(struct disklabel), "sizeof(struct disklabel)"); 23851111Sjulian 23951111SjulianSYSCTL_INT(_debug_sizeof, OID_AUTO, diskslices, CTLFLAG_RD, 24051111Sjulian 0, sizeof(struct diskslices), "sizeof(struct diskslices)"); 24151111Sjulian 24251111SjulianSYSCTL_INT(_debug_sizeof, OID_AUTO, disk, CTLFLAG_RD, 24351111Sjulian 0, sizeof(struct disk), "sizeof(struct disk)"); 244