The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/subr_disk.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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$
   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/sysctl.h>
   22 #include <machine/md_var.h>
   23 #include <sys/ctype.h>
   24 
   25 static MALLOC_DEFINE(M_DISK, "disk", "disk data");
   26 
   27 static d_strategy_t diskstrategy;
   28 static d_open_t diskopen;
   29 static d_close_t diskclose; 
   30 static d_ioctl_t diskioctl;
   31 static d_psize_t diskpsize;
   32 
   33 static LIST_HEAD(, disk) disklist = LIST_HEAD_INITIALIZER(&disklist);
   34 
   35 static void
   36 inherit_raw(dev_t pdev, dev_t dev)
   37 {
   38         dev->si_disk = pdev->si_disk;
   39         dev->si_drv1 = pdev->si_drv1;
   40         dev->si_drv2 = pdev->si_drv2;
   41         dev->si_iosize_max = pdev->si_iosize_max;
   42         dev->si_bsize_phys = pdev->si_bsize_phys;
   43         dev->si_bsize_best = pdev->si_bsize_best;
   44 }
   45 
   46 dev_t
   47 disk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw, struct cdevsw *proto)
   48 {
   49         dev_t dev;
   50 
   51         bzero(dp, sizeof(*dp));
   52 
   53         dev = makedev(cdevsw->d_maj, 0);        
   54         if (!devsw(dev)) {
   55                 *proto = *cdevsw;
   56                 proto->d_open = diskopen;
   57                 proto->d_close = diskclose;
   58                 proto->d_ioctl = diskioctl;
   59                 proto->d_strategy = diskstrategy;
   60                 proto->d_psize = diskpsize;
   61                 cdevsw_add(proto);
   62         }
   63 
   64         if (bootverbose)
   65                 printf("Creating DISK %s%d\n", cdevsw->d_name, unit);
   66         dev = make_dev(proto, dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART),
   67             UID_ROOT, GID_OPERATOR, 0640, "%s%d", cdevsw->d_name, unit);
   68 
   69         dev->si_disk = dp;
   70         dp->d_dev = dev;
   71         dp->d_dsflags = flags;
   72         dp->d_devsw = cdevsw;
   73         LIST_INSERT_HEAD(&disklist, dp, d_list);
   74         return (dev);
   75 }
   76 
   77 int
   78 disk_dumpcheck(dev_t dev, u_int *count, u_int *blkno, u_int *secsize)
   79 {
   80         struct disk *dp;
   81         struct disklabel *dl;
   82         u_int boff;
   83 
   84         dp = dev->si_disk;
   85         if (!dp)
   86                 return (ENXIO);
   87         if (!dp->d_slice)
   88                 return (ENXIO);
   89         dl = dsgetlabel(dev, dp->d_slice);
   90         if (!dl)
   91                 return (ENXIO);
   92         *count = Maxmem * (PAGE_SIZE / dl->d_secsize);
   93         if (dumplo <= LABELSECTOR || 
   94             (dumplo + *count > dl->d_partitions[dkpart(dev)].p_size))
   95                 return (EINVAL);
   96         boff = dl->d_partitions[dkpart(dev)].p_offset +
   97             dp->d_slice->dss_slices[dkslice(dev)].ds_offset;
   98         *blkno = boff + dumplo;
   99         *secsize = dl->d_secsize;
  100         return (0);
  101         
  102 }
  103 
  104 void 
  105 disk_invalidate (struct disk *disk)
  106 {
  107         if (disk->d_slice)
  108                 dsgone(&disk->d_slice);
  109 }
  110 
  111 void
  112 disk_destroy(dev_t dev)
  113 {
  114         LIST_REMOVE(dev->si_disk, d_list);
  115         bzero(dev->si_disk, sizeof(*dev->si_disk));
  116         dev->si_disk = NULL;
  117         destroy_dev(dev);
  118         return;
  119 }
  120 
  121 struct disk *
  122 disk_enumerate(struct disk *disk)
  123 {
  124         if (!disk)
  125                 return (LIST_FIRST(&disklist));
  126         else
  127                 return (LIST_NEXT(disk, d_list));
  128 }
  129 
  130 static int
  131 sysctl_disks(SYSCTL_HANDLER_ARGS)
  132 {
  133         struct disk *disk;
  134         int error, first;
  135 
  136         disk = NULL;
  137         first = 1;
  138 
  139         while ((disk = disk_enumerate(disk))) {
  140                 if (!first) {
  141                         error = SYSCTL_OUT(req, " ", 1);
  142                         if (error)
  143                                 return error;
  144                 } else {
  145                         first = 0;
  146                 }
  147                 error = SYSCTL_OUT(req, disk->d_dev->si_name, strlen(disk->d_dev->si_name));
  148                 if (error)
  149                         return error;
  150         }
  151         error = SYSCTL_OUT(req, "", 1);
  152         return error;
  153 }
  154  
  155 SYSCTL_PROC(_kern, OID_AUTO, disks, CTLTYPE_STRING | CTLFLAG_RD, 0, NULL, 
  156     sysctl_disks, "A", "names of available disks");
  157 
  158 /*
  159  * The cdevsw functions
  160  */
  161 
  162 static int
  163 diskopen(dev_t dev, int oflags, int devtype, struct proc *p)
  164 {
  165         dev_t pdev;
  166         struct disk *dp;
  167         int error;
  168 
  169         error = 0;
  170         pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
  171 
  172         dp = pdev->si_disk;
  173         if (!dp)
  174                 return (ENXIO);
  175 
  176         while (dp->d_flags & DISKFLAG_LOCK) {
  177                 dp->d_flags |= DISKFLAG_WANTED;
  178                 error = tsleep(dp, PRIBIO | PCATCH, "diskopen", hz);
  179                 if (error)
  180                         return (error);
  181         }
  182         dp->d_flags |= DISKFLAG_LOCK;
  183 
  184         if (!dsisopen(dp->d_slice)) {
  185                 if (!pdev->si_iosize_max)
  186                         pdev->si_iosize_max = dev->si_iosize_max;
  187                 error = dp->d_devsw->d_open(pdev, oflags, devtype, p);
  188         }
  189 
  190         /* Inherit properties from the whole/raw dev_t */
  191         inherit_raw(pdev, dev);
  192 
  193         if (error)
  194                 goto out;
  195         
  196         error = dsopen(dev, devtype, dp->d_dsflags, &dp->d_slice, &dp->d_label);
  197 
  198         if (!dsisopen(dp->d_slice)) 
  199                 dp->d_devsw->d_close(pdev, oflags, devtype, p);
  200 out:    
  201         dp->d_flags &= ~DISKFLAG_LOCK;
  202         if (dp->d_flags & DISKFLAG_WANTED) {
  203                 dp->d_flags &= ~DISKFLAG_WANTED;
  204                 wakeup(dp);
  205         }
  206         
  207         return(error);
  208 }
  209 
  210 static int
  211 diskclose(dev_t dev, int fflag, int devtype, struct proc *p)
  212 {
  213         struct disk *dp;
  214         int error;
  215         dev_t pdev;
  216 
  217         error = 0;
  218         pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
  219         dp = pdev->si_disk;
  220         if (!dp)
  221                 return (ENXIO);
  222         dsclose(dev, devtype, dp->d_slice);
  223         if (!dsisopen(dp->d_slice))
  224                 error = dp->d_devsw->d_close(dp->d_dev, fflag, devtype, p);
  225         return (error);
  226 }
  227 
  228 static void
  229 diskstrategy(struct buf *bp)
  230 {
  231         dev_t pdev;
  232         struct disk *dp;
  233 
  234         pdev = dkmodpart(dkmodslice(bp->b_dev, WHOLE_DISK_SLICE), RAW_PART);
  235         dp = pdev->si_disk;
  236         if (dp != bp->b_dev->si_disk)
  237                 inherit_raw(pdev, bp->b_dev);
  238 
  239         if (!dp) {
  240                 bp->b_error = ENXIO;
  241                 bp->b_flags |= B_ERROR;
  242                 biodone(bp);
  243                 return;
  244         }
  245 
  246         if (dscheck(bp, dp->d_slice) <= 0) {
  247                 biodone(bp);
  248                 return;
  249         }
  250 
  251         dp->d_devsw->d_strategy(bp);
  252         return;
  253         
  254 }
  255 
  256 static int
  257 diskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
  258 {
  259         struct disk *dp;
  260         int error;
  261         dev_t pdev;
  262 
  263         pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
  264         dp = pdev->si_disk;
  265         if (!dp)
  266                 return (ENXIO);
  267         error = dsioctl(dev, cmd, data, fflag, &dp->d_slice);
  268         if (error == ENOIOCTL)
  269                 error = dp->d_devsw->d_ioctl(dev, cmd, data, fflag, p);
  270         return (error);
  271 }
  272 
  273 static int
  274 diskpsize(dev_t dev)
  275 {
  276         struct disk *dp;
  277         dev_t pdev;
  278 
  279         pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
  280         dp = pdev->si_disk;
  281         if (!dp)
  282                 return (-1);
  283         if (dp != dev->si_disk) {
  284                 dev->si_drv1 = pdev->si_drv1;
  285                 dev->si_drv2 = pdev->si_drv2;
  286                 /* XXX: don't set bp->b_dev->si_disk (?) */
  287         }
  288         return (dssize(dev, &dp->d_slice));
  289 }
  290 
  291 SYSCTL_DECL(_debug_sizeof);
  292 
  293 SYSCTL_INT(_debug_sizeof, OID_AUTO, disklabel, CTLFLAG_RD, 
  294     0, sizeof(struct disklabel), "sizeof(struct disklabel)");
  295 
  296 SYSCTL_INT(_debug_sizeof, OID_AUTO, diskslices, CTLFLAG_RD, 
  297     0, sizeof(struct diskslices), "sizeof(struct diskslices)");
  298 
  299 SYSCTL_INT(_debug_sizeof, OID_AUTO, disk, CTLFLAG_RD, 
  300     0, sizeof(struct disk), "sizeof(struct disk)");

Cache object: f019e82f7d93a75882e36233a772a8f0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.