subr_disk.c revision 52917
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 52917 1999-11-06 10:25:58Z 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 4951198Sphk printf("Creating DISK %s%d\n", cdevsw->d_name, unit); 5051243Sphk dev = make_dev(proto, dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART), 5151198Sphk 0, 0, 0, "r%s%d", cdevsw->d_name, unit); 5250565Sphk 5350565Sphk dev->si_disk = dp; 5450565Sphk dp->d_dev = dev; 5552917Sphk dp->d_dsflags = flags; 5651215Sphk dp->d_devsw = cdevsw; 5750565Sphk return (dev); 5850565Sphk} 5950565Sphk 6050728Sphkint 6150728Sphkdisk_dumpcheck(dev_t dev, u_int *count, u_int *blkno, u_int *secsize) 6250728Sphk{ 6350728Sphk struct disk *dp; 6450728Sphk struct disklabel *dl; 6550728Sphk u_int boff; 6650728Sphk 6750728Sphk dp = dev->si_disk; 6850728Sphk if (!dp) 6950728Sphk return (ENXIO); 7050728Sphk if (!dp->d_slice) 7150728Sphk return (ENXIO); 7250728Sphk dl = dsgetlabel(dev, dp->d_slice); 7350728Sphk if (!dl) 7450728Sphk return (ENXIO); 7550728Sphk *count = (u_long)Maxmem * PAGE_SIZE / dl->d_secsize; 7650728Sphk if (dumplo < 0 || 7750728Sphk (dumplo + *count > dl->d_partitions[dkpart(dev)].p_size)) 7850728Sphk return (EINVAL); 7950728Sphk boff = dl->d_partitions[dkpart(dev)].p_offset + 8050728Sphk dp->d_slice->dss_slices[dkslice(dev)].ds_offset; 8150728Sphk *blkno = boff + dumplo; 8250728Sphk *secsize = dl->d_secsize; 8350728Sphk return (0); 8450728Sphk 8550728Sphk} 8650728Sphk 8750728Sphkvoid 8850728Sphkdisk_invalidate (struct disk *disk) 8950728Sphk{ 9050728Sphk dsgone(&disk->d_slice); 9150728Sphk} 9250728Sphk 9350565Sphkvoid 9450565Sphkdisk_delete(dev_t dev) 9550565Sphk{ 9650565Sphk return; 9750565Sphk} 9850565Sphk 9950728Sphk/* 10050728Sphk * The cdevsw functions 10150728Sphk */ 10250728Sphk 10350565Sphkstatic int 10450565Sphkdiskopen(dev_t dev, int oflags, int devtype, struct proc *p) 10550565Sphk{ 10650565Sphk dev_t pdev; 10750565Sphk struct disk *dp; 10850565Sphk int error; 10950565Sphk 11050728Sphk error = 0; 11150565Sphk pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 11250728Sphk 11350565Sphk dp = pdev->si_disk; 11450565Sphk if (!dp) 11550565Sphk return (ENXIO); 11650728Sphk 11752917Sphk while (dp->d_flags & DISKFLAG_LOCK) { 11852917Sphk dp->d_flags |= DISKFLAG_WANTED; 11952917Sphk tsleep(dp, PRIBIO | PCATCH, "diskopen", hz); 12052917Sphk } 12152917Sphk dp->d_flags |= DISKFLAG_LOCK; 12252917Sphk 12351860Sphk if (!dsisopen(dp->d_slice)) { 12451878Ssos if (!pdev->si_iosize_max) 12551878Ssos pdev->si_iosize_max = dev->si_iosize_max; 12651826Sphk error = dp->d_devsw->d_open(pdev, oflags, devtype, p); 12751860Sphk } 12851826Sphk 12951826Sphk /* Inherit properties from the whole/raw dev_t */ 13051826Sphk dev->si_disk = pdev->si_disk; 13150728Sphk dev->si_drv1 = pdev->si_drv1; 13250728Sphk dev->si_drv2 = pdev->si_drv2; 13351826Sphk dev->si_iosize_max = pdev->si_iosize_max; 13451826Sphk dev->si_bsize_phys = pdev->si_bsize_phys; 13551826Sphk dev->si_bsize_best = pdev->si_bsize_best; 13650728Sphk 13750728Sphk if (error) 13852917Sphk goto out; 13950728Sphk 14052917Sphk error = dsopen(dev, devtype, dp->d_dsflags, &dp->d_slice, &dp->d_label); 14150565Sphk 14250728Sphk if (!dsisopen(dp->d_slice)) 14351924Sphk dp->d_devsw->d_close(pdev, oflags, devtype, p); 14452917Sphkout: 14552917Sphk dp->d_flags &= ~DISKFLAG_LOCK; 14652917Sphk if (dp->d_flags & DISKFLAG_WANTED) { 14752917Sphk dp->d_flags &= ~DISKFLAG_WANTED; 14852917Sphk wakeup(dp); 14952917Sphk } 15050728Sphk 15150565Sphk return(error); 15250565Sphk} 15350565Sphk 15450565Sphkstatic int 15550565Sphkdiskclose(dev_t dev, int fflag, int devtype, struct proc *p) 15650565Sphk{ 15750565Sphk struct disk *dp; 15850565Sphk int error; 15950565Sphk 16050565Sphk error = 0; 16150565Sphk dp = dev->si_disk; 16251822Sphk dsclose(dev, devtype, dp->d_slice); 16351826Sphk if (!dsisopen(dp->d_slice)) { 16451924Sphk error = dp->d_devsw->d_close(dp->d_dev, fflag, devtype, p); 16551826Sphk } 16650565Sphk return (error); 16750565Sphk} 16850565Sphk 16950565Sphkstatic void 17050565Sphkdiskstrategy(struct buf *bp) 17150565Sphk{ 17250565Sphk dev_t pdev; 17350565Sphk struct disk *dp; 17450565Sphk 17550565Sphk dp = bp->b_dev->si_disk; 17650565Sphk if (!dp) { 17750565Sphk pdev = dkmodpart(dkmodslice(bp->b_dev, WHOLE_DISK_SLICE), RAW_PART); 17851860Sphk dp = bp->b_dev->si_disk = pdev->si_disk; 17950565Sphk bp->b_dev->si_drv1 = pdev->si_drv1; 18050565Sphk bp->b_dev->si_drv2 = pdev->si_drv2; 18151860Sphk bp->b_dev->si_iosize_max = pdev->si_iosize_max; 18251860Sphk bp->b_dev->si_bsize_phys = pdev->si_bsize_phys; 18351860Sphk bp->b_dev->si_bsize_best = pdev->si_bsize_best; 18450565Sphk } 18550565Sphk 18650565Sphk if (!dp) { 18750565Sphk bp->b_error = ENXIO; 18850565Sphk bp->b_flags |= B_ERROR; 18950565Sphk biodone(bp); 19050565Sphk return; 19150565Sphk } 19250565Sphk 19350565Sphk if (dscheck(bp, dp->d_slice) < 0) { 19450565Sphk biodone(bp); 19550565Sphk return; 19650565Sphk } 19750565Sphk 19851215Sphk dp->d_devsw->d_strategy(bp); 19950565Sphk return; 20050565Sphk 20150565Sphk} 20250565Sphk 20350565Sphkstatic int 20450565Sphkdiskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p) 20550565Sphk{ 20650565Sphk struct disk *dp; 20750565Sphk int error; 20850565Sphk 20950565Sphk dp = dev->si_disk; 21050565Sphk error = dsioctl(dev, cmd, data, fflag, &dp->d_slice); 21150565Sphk if (error == ENOIOCTL) 21251215Sphk error = dp->d_devsw->d_ioctl(dev, cmd, data, fflag, p); 21350565Sphk return (error); 21450565Sphk} 21550565Sphk 21650565Sphkstatic int 21750565Sphkdiskpsize(dev_t dev) 21850565Sphk{ 21950565Sphk struct disk *dp; 22050728Sphk dev_t pdev; 22150565Sphk 22250565Sphk dp = dev->si_disk; 22350728Sphk if (!dp) { 22450728Sphk pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 22550728Sphk dp = pdev->si_disk; 22650728Sphk dev->si_drv1 = pdev->si_drv1; 22750728Sphk dev->si_drv2 = pdev->si_drv2; 22850728Sphk /* XXX: don't set bp->b_dev->si_disk (?) */ 22950728Sphk } 23050565Sphk return (dssize(dev, &dp->d_slice)); 23150565Sphk} 23251111Sjulian 23351111SjulianSYSCTL_DECL(_debug_sizeof); 23451111Sjulian 23551111SjulianSYSCTL_INT(_debug_sizeof, OID_AUTO, disklabel, CTLFLAG_RD, 23651111Sjulian 0, sizeof(struct disklabel), "sizeof(struct disklabel)"); 23751111Sjulian 23851111SjulianSYSCTL_INT(_debug_sizeof, OID_AUTO, diskslices, CTLFLAG_RD, 23951111Sjulian 0, sizeof(struct diskslices), "sizeof(struct diskslices)"); 24051111Sjulian 24151111SjulianSYSCTL_INT(_debug_sizeof, OID_AUTO, disk, CTLFLAG_RD, 24251111Sjulian 0, sizeof(struct disk), "sizeof(struct disk)"); 243