subr_disk.c revision 59623
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 59623 2000-04-25 10:51:18Z phk $ 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{ 9157325Ssos if (disk->d_slice) 9257325Ssos dsgone(&disk->d_slice); 9350728Sphk} 9450728Sphk 9550565Sphkvoid 9656767Sphkdisk_destroy(dev_t dev) 9750565Sphk{ 9857325Ssos dev->si_disk = NULL; 9957325Ssos destroy_dev(dev); 10050565Sphk return; 10150565Sphk} 10250565Sphk 10350728Sphk/* 10450728Sphk * The cdevsw functions 10550728Sphk */ 10650728Sphk 10750565Sphkstatic int 10850565Sphkdiskopen(dev_t dev, int oflags, int devtype, struct proc *p) 10950565Sphk{ 11050565Sphk dev_t pdev; 11150565Sphk struct disk *dp; 11250565Sphk int error; 11350565Sphk 11450728Sphk error = 0; 11550565Sphk pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 11650728Sphk 11750565Sphk dp = pdev->si_disk; 11850565Sphk if (!dp) 11950565Sphk return (ENXIO); 12050728Sphk 12152917Sphk while (dp->d_flags & DISKFLAG_LOCK) { 12252917Sphk dp->d_flags |= DISKFLAG_WANTED; 12354815Sphk error = tsleep(dp, PRIBIO | PCATCH, "diskopen", hz); 12454815Sphk if (error) 12554815Sphk return (error); 12652917Sphk } 12752917Sphk dp->d_flags |= DISKFLAG_LOCK; 12852917Sphk 12951860Sphk if (!dsisopen(dp->d_slice)) { 13051878Ssos if (!pdev->si_iosize_max) 13151878Ssos pdev->si_iosize_max = dev->si_iosize_max; 13251826Sphk error = dp->d_devsw->d_open(pdev, oflags, devtype, p); 13351860Sphk } 13451826Sphk 13551826Sphk /* Inherit properties from the whole/raw dev_t */ 13651826Sphk dev->si_disk = pdev->si_disk; 13750728Sphk dev->si_drv1 = pdev->si_drv1; 13850728Sphk dev->si_drv2 = pdev->si_drv2; 13951826Sphk dev->si_iosize_max = pdev->si_iosize_max; 14051826Sphk dev->si_bsize_phys = pdev->si_bsize_phys; 14151826Sphk dev->si_bsize_best = pdev->si_bsize_best; 14250728Sphk 14350728Sphk if (error) 14452917Sphk goto out; 14550728Sphk 14652917Sphk error = dsopen(dev, devtype, dp->d_dsflags, &dp->d_slice, &dp->d_label); 14750565Sphk 14850728Sphk if (!dsisopen(dp->d_slice)) 14951924Sphk dp->d_devsw->d_close(pdev, oflags, devtype, p); 15052917Sphkout: 15152917Sphk dp->d_flags &= ~DISKFLAG_LOCK; 15252917Sphk if (dp->d_flags & DISKFLAG_WANTED) { 15352917Sphk dp->d_flags &= ~DISKFLAG_WANTED; 15452917Sphk wakeup(dp); 15552917Sphk } 15650728Sphk 15750565Sphk return(error); 15850565Sphk} 15950565Sphk 16050565Sphkstatic int 16150565Sphkdiskclose(dev_t dev, int fflag, int devtype, struct proc *p) 16250565Sphk{ 16350565Sphk struct disk *dp; 16450565Sphk int error; 16550565Sphk 16650565Sphk error = 0; 16750565Sphk dp = dev->si_disk; 16851822Sphk dsclose(dev, devtype, dp->d_slice); 16951826Sphk if (!dsisopen(dp->d_slice)) { 17051924Sphk error = dp->d_devsw->d_close(dp->d_dev, fflag, devtype, p); 17151826Sphk } 17250565Sphk return (error); 17350565Sphk} 17450565Sphk 17550565Sphkstatic void 17659249Sphkdiskstrategy(struct bio *bp) 17750565Sphk{ 17850565Sphk dev_t pdev; 17950565Sphk struct disk *dp; 18050565Sphk 18159249Sphk dp = bp->bio_dev->si_disk; 18250565Sphk if (!dp) { 18359249Sphk pdev = dkmodpart(dkmodslice(bp->bio_dev, WHOLE_DISK_SLICE), RAW_PART); 18459249Sphk dp = bp->bio_dev->si_disk = pdev->si_disk; 18559249Sphk bp->bio_dev->si_drv1 = pdev->si_drv1; 18659249Sphk bp->bio_dev->si_drv2 = pdev->si_drv2; 18759249Sphk bp->bio_dev->si_iosize_max = pdev->si_iosize_max; 18859249Sphk bp->bio_dev->si_bsize_phys = pdev->si_bsize_phys; 18959249Sphk bp->bio_dev->si_bsize_best = pdev->si_bsize_best; 19050565Sphk } 19150565Sphk 19250565Sphk if (!dp) { 19359249Sphk bp->bio_error = ENXIO; 19459249Sphk bp->bio_flags |= BIO_ERROR; 19550565Sphk biodone(bp); 19650565Sphk return; 19750565Sphk } 19850565Sphk 19955763Sphk if (dscheck(bp, dp->d_slice) <= 0) { 20050565Sphk biodone(bp); 20150565Sphk return; 20250565Sphk } 20350565Sphk 20459623Sphk KASSERT(dp->d_devsw != NULL, ("NULL devsw")); 20559623Sphk KASSERT(dp->d_devsw->d_strategy != NULL, ("NULL d_strategy")); 20651215Sphk dp->d_devsw->d_strategy(bp); 20750565Sphk return; 20850565Sphk 20950565Sphk} 21050565Sphk 21150565Sphkstatic int 21250565Sphkdiskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p) 21350565Sphk{ 21450565Sphk struct disk *dp; 21550565Sphk int error; 21650565Sphk 21750565Sphk dp = dev->si_disk; 21850565Sphk error = dsioctl(dev, cmd, data, fflag, &dp->d_slice); 21950565Sphk if (error == ENOIOCTL) 22051215Sphk error = dp->d_devsw->d_ioctl(dev, cmd, data, fflag, p); 22150565Sphk return (error); 22250565Sphk} 22350565Sphk 22450565Sphkstatic int 22550565Sphkdiskpsize(dev_t dev) 22650565Sphk{ 22750565Sphk struct disk *dp; 22850728Sphk dev_t pdev; 22950565Sphk 23050565Sphk dp = dev->si_disk; 23150728Sphk if (!dp) { 23250728Sphk pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 23350728Sphk dp = pdev->si_disk; 23457850Sbde if (!dp) 23557850Sbde return (-1); 23650728Sphk dev->si_drv1 = pdev->si_drv1; 23750728Sphk dev->si_drv2 = pdev->si_drv2; 23850728Sphk /* XXX: don't set bp->b_dev->si_disk (?) */ 23950728Sphk } 24050565Sphk return (dssize(dev, &dp->d_slice)); 24150565Sphk} 24251111Sjulian 24351111SjulianSYSCTL_DECL(_debug_sizeof); 24451111Sjulian 24551111SjulianSYSCTL_INT(_debug_sizeof, OID_AUTO, disklabel, CTLFLAG_RD, 24651111Sjulian 0, sizeof(struct disklabel), "sizeof(struct disklabel)"); 24751111Sjulian 24851111SjulianSYSCTL_INT(_debug_sizeof, OID_AUTO, diskslices, CTLFLAG_RD, 24951111Sjulian 0, sizeof(struct diskslices), "sizeof(struct diskslices)"); 25051111Sjulian 25151111SjulianSYSCTL_INT(_debug_sizeof, OID_AUTO, disk, CTLFLAG_RD, 25251111Sjulian 0, sizeof(struct disk), "sizeof(struct disk)"); 253