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_diskslice.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  * Copyright (c) 1994 Bruce D. Evans.
    3  * All rights reserved.
    4  *
    5  * Copyright (c) 1990 The Regents of the University of California.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to Berkeley by
    9  * William Jolitz.
   10  *
   11  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
   12  * All rights reserved.
   13  *
   14  * Redistribution and use in source and binary forms, with or without
   15  * modification, are permitted provided that the following conditions
   16  * are met:
   17  * 1. Redistributions of source code must retain the above copyright
   18  *    notice, this list of conditions and the following disclaimer.
   19  * 2. Redistributions in binary form must reproduce the above copyright
   20  *    notice, this list of conditions and the following disclaimer in the
   21  *    documentation and/or other materials provided with the distribution.
   22  * 3. All advertising materials mentioning features or use of this software
   23  *    must display the following acknowledgement:
   24  *      This product includes software developed by the University of
   25  *      California, Berkeley and its contributors.
   26  * 4. Neither the name of the University nor the names of its contributors
   27  *    may be used to endorse or promote products derived from this software
   28  *    without specific prior written permission.
   29  *
   30  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   31  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   32  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   33  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   34  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   35  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   36  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   37  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   38  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   39  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   40  * SUCH DAMAGE.
   41  *
   42  *      from: @(#)wd.c  7.2 (Berkeley) 5/9/91
   43  *      from: wd.c,v 1.55 1994/10/22 01:57:12 phk Exp $
   44  *      from: @(#)ufs_disksubr.c        7.16 (Berkeley) 5/4/91
   45  *      from: ufs_disksubr.c,v 1.8 1994/06/07 01:21:39 phk Exp $
   46  * $FreeBSD$
   47  */
   48 
   49 #include "opt_devfs.h"
   50 
   51 #include <stddef.h>
   52 
   53 #include <sys/param.h>
   54 #include <sys/buf.h>
   55 #include <sys/conf.h>
   56 #ifdef DEVFS
   57 #include <sys/devfsext.h>
   58 #endif
   59 #include <sys/disklabel.h>
   60 #include <sys/diskslice.h>
   61 #include <sys/dkbad.h>
   62 #include <sys/fcntl.h>
   63 #include <sys/malloc.h>
   64 #include <sys/stat.h>
   65 #include <sys/syslog.h>
   66 #include <sys/systm.h>
   67 #include <sys/vnode.h>
   68 
   69 #include <ufs/ffs/fs.h>
   70 
   71 #define TRACE(str)      do { if (ds_debug) printf str; } while (0)
   72 
   73 typedef u_char  bool_t;
   74 
   75 static volatile bool_t ds_debug;
   76 
   77 static struct disklabel *clone_label __P((struct disklabel *lp));
   78 static void dsiodone __P((struct buf *bp));
   79 static char *fixlabel __P((char *sname, struct diskslice *sp,
   80                            struct disklabel *lp, int writeflag));
   81 static void free_ds_label __P((struct diskslices *ssp, int slice));
   82 #ifdef DEVFS
   83 static void free_ds_labeldevs __P((struct diskslices *ssp, int slice));
   84 #endif
   85 static void partition_info __P((char *sname, int part, struct partition *pp));
   86 static void slice_info __P((char *sname, struct diskslice *sp));
   87 static void set_ds_bad __P((struct diskslices *ssp, int slice,
   88                             struct dkbad_intern *btp));
   89 static void set_ds_label __P((struct diskslices *ssp, int slice,
   90                               struct disklabel *lp));
   91 #ifdef DEVFS
   92 static void set_ds_labeldevs __P((char *dname, dev_t dev,
   93                                   struct diskslices *ssp));
   94 static void set_ds_labeldevs_unaliased __P((char *dname, dev_t dev,
   95                                             struct diskslices *ssp));
   96 #endif
   97 static void set_ds_wlabel __P((struct diskslices *ssp, int slice,
   98                                int wlabel));
   99 
  100 /*
  101  * Duplicate a label for the whole disk, and initialize defaults in the
  102  * copy for fields that are not already initialized.  The caller only
  103  * needs to initialize d_secsize and d_secperunit, and zero the fields
  104  * that are to be defaulted.
  105  */
  106 static struct disklabel *
  107 clone_label(lp)
  108         struct disklabel *lp;
  109 {
  110         struct disklabel *lp1;
  111 
  112         lp1 = malloc(sizeof *lp1, M_DEVBUF, M_WAITOK);
  113         *lp1 = *lp;
  114         lp = NULL;
  115         if (lp1->d_typename[0] == '\0')
  116                 strncpy(lp1->d_typename, "amnesiac", sizeof(lp1->d_typename));
  117         if (lp1->d_packname[0] == '\0')
  118                 strncpy(lp1->d_packname, "fictitious", sizeof(lp1->d_packname));
  119         if (lp1->d_nsectors == 0)
  120                 lp1->d_nsectors = 32;
  121         if (lp1->d_ntracks == 0)
  122                 lp1->d_ntracks = 64;
  123         lp1->d_secpercyl = lp1->d_nsectors * lp1->d_ntracks;
  124         lp1->d_ncylinders = lp1->d_secperunit / lp1->d_secpercyl;
  125         if (lp1->d_rpm == 0)
  126                 lp1->d_rpm = 3600;
  127         if (lp1->d_interleave == 0)
  128                 lp1->d_interleave = 1;
  129         if (lp1->d_npartitions < RAW_PART + 1)
  130                 lp1->d_npartitions = MAXPARTITIONS;
  131         if (lp1->d_bbsize == 0)
  132                 lp1->d_bbsize = BBSIZE;
  133         if (lp1->d_sbsize == 0)
  134                 lp1->d_sbsize = SBSIZE;
  135         lp1->d_partitions[RAW_PART].p_size = lp1->d_secperunit;
  136         lp1->d_magic = DISKMAGIC;
  137         lp1->d_magic2 = DISKMAGIC;
  138         lp1->d_checksum = dkcksum(lp1);
  139         return (lp1);
  140 }
  141 
  142 /*
  143  * Determine the size of the transfer, and make sure it is
  144  * within the boundaries of the partition. Adjust transfer
  145  * if needed, and signal errors or early completion.
  146  *
  147  * XXX TODO:
  148  *      o Do bad sector remapping.  May need to split buffer.
  149  *      o Split buffers that are too big for the device.
  150  *      o Check for overflow.
  151  *      o Finish cleaning this up.
  152  */
  153 int
  154 dscheck(bp, ssp)
  155         struct buf *bp;
  156         struct diskslices *ssp;
  157 {
  158         daddr_t blkno;
  159         u_long  endsecno;
  160         daddr_t labelsect;
  161         struct disklabel *lp;
  162         char *msg;
  163         long    nsec;
  164         struct partition *pp;
  165         daddr_t secno;
  166         daddr_t slicerel_secno;
  167         struct diskslice *sp;
  168         int s;
  169 
  170         blkno = bp->b_blkno;
  171         if (blkno < 0) {
  172                 printf("dscheck: negative b_blkno %ld\n", (long)blkno);
  173                 bp->b_error = EINVAL;
  174                 goto bad;
  175         }
  176         sp = &ssp->dss_slices[dkslice(bp->b_dev)];
  177         lp = sp->ds_label;
  178         if (ssp->dss_secmult == 1) {
  179                 if (bp->b_bcount % (u_long)DEV_BSIZE)
  180                         goto bad_bcount;
  181                 secno = blkno;
  182                 nsec = bp->b_bcount >> DEV_BSHIFT;
  183         } else if (ssp->dss_secshift != -1) {
  184                 if (bp->b_bcount & (ssp->dss_secsize - 1))
  185                         goto bad_bcount;
  186                 if (blkno & (ssp->dss_secmult - 1))
  187                         goto bad_blkno;
  188                 secno = blkno >> ssp->dss_secshift;
  189                 nsec = bp->b_bcount >> (DEV_BSHIFT + ssp->dss_secshift);
  190         } else {
  191                 if (bp->b_bcount % ssp->dss_secsize)
  192                         goto bad_bcount;
  193                 if (blkno % ssp->dss_secmult)
  194                         goto bad_blkno;
  195                 secno = blkno / ssp->dss_secmult;
  196                 nsec = bp->b_bcount / ssp->dss_secsize;
  197         }
  198         if (lp == NULL) {
  199                 labelsect = -LABELSECTOR - 1;
  200                 endsecno = sp->ds_size;
  201                 slicerel_secno = secno;
  202         } else {
  203                 labelsect = lp->d_partitions[LABEL_PART].p_offset;
  204 if (labelsect != 0) Debugger("labelsect != 0 in dscheck()");
  205                 pp = &lp->d_partitions[dkpart(bp->b_dev)];
  206                 endsecno = pp->p_size;
  207                 slicerel_secno = pp->p_offset + secno;
  208                 if (sp->ds_bad != NULL && ds_debug) {
  209                         daddr_t newsecno;
  210 
  211                         newsecno = transbad144(sp->ds_bad, slicerel_secno);
  212                         if (newsecno != slicerel_secno)
  213                                 printf("should map bad sector %ld -> %ld\n",
  214                                        (long)slicerel_secno, (long)newsecno);
  215                 }
  216         }
  217 
  218         /* overwriting disk label ? */
  219         /* XXX should also protect bootstrap in first 8K */
  220         if (slicerel_secno <= LABELSECTOR + labelsect &&
  221 #if LABELSECTOR != 0
  222             slicerel_secno + nsec > LABELSECTOR + labelsect &&
  223 #endif
  224             (bp->b_flags & B_READ) == 0 && sp->ds_wlabel == 0) {
  225                 bp->b_error = EROFS;
  226                 goto bad;
  227         }
  228 
  229 #if defined(DOSBBSECTOR) && defined(notyet)
  230         /* overwriting master boot record? */
  231         if (slicerel_secno <= DOSBBSECTOR && (bp->b_flags & B_READ) == 0 &&
  232             sp->ds_wlabel == 0) {
  233                 bp->b_error = EROFS;
  234                 goto bad;
  235         }
  236 #endif
  237 
  238         /* beyond partition? */
  239         if (secno + nsec > endsecno) {
  240                 /* if exactly at end of disk, return an EOF */
  241                 if (secno == endsecno) {
  242                         bp->b_resid = bp->b_bcount;
  243                         return (0);
  244                 }
  245                 /* or truncate if part of it fits */
  246                 nsec = endsecno - secno;
  247                 if (nsec <= 0) {
  248                         bp->b_error = EINVAL;
  249                         goto bad;
  250                 }
  251                 bp->b_bcount = nsec * ssp->dss_secsize;
  252         }
  253 
  254         bp->b_pblkno = sp->ds_offset + slicerel_secno;
  255 
  256         /*
  257          * Snoop on label accesses if the slice offset is nonzero.  Fudge
  258          * offsets in the label to keep the in-core label coherent with
  259          * the on-disk one.
  260          */
  261         if (slicerel_secno <= LABELSECTOR + labelsect
  262 #if LABELSECTOR != 0
  263             && slicerel_secno + nsec > LABELSECTOR + labelsect
  264 #endif
  265             && sp->ds_offset != 0) {
  266                 struct iodone_chain *ic;
  267 
  268                 ic = malloc(sizeof *ic , M_DEVBUF, M_WAITOK);
  269                 ic->ic_prev_flags = bp->b_flags;
  270                 ic->ic_prev_iodone = bp->b_iodone;
  271                 ic->ic_prev_iodone_chain = bp->b_iodone_chain;
  272                 ic->ic_args[0].ia_long = (LABELSECTOR + labelsect -
  273                     slicerel_secno) * ssp->dss_secsize;
  274                 ic->ic_args[1].ia_ptr = sp;
  275                 bp->b_flags |= B_CALL;
  276                 bp->b_iodone = dsiodone;
  277                 bp->b_iodone_chain = ic;
  278                 if (!(bp->b_flags & B_READ)) {
  279                         /*
  280                          * XXX even disklabel(8) writes directly so we need
  281                          * to adjust writes.  Perhaps we should drop support
  282                          * for DIOCWLABEL (always write protect labels) and
  283                          * require the use of DIOCWDINFO.
  284                          *
  285                          * XXX probably need to copy the data to avoid even
  286                          * temporarily corrupting the in-core copy.
  287                          */
  288                         if (bp->b_vp != NULL) {
  289                                 s = splbio();
  290                                 bp->b_vp->v_numoutput++;
  291                                 splx(s);
  292                         }
  293                         /* XXX need name here. */
  294                         msg = fixlabel((char *)NULL, sp,
  295                                        (struct disklabel *)
  296                                        (bp->b_data + ic->ic_args[0].ia_long),
  297                                        TRUE);
  298                         if (msg != NULL) {
  299                                 printf("%s\n", msg);
  300                                 bp->b_error = EROFS;
  301                                 goto bad;
  302                         }
  303                 }
  304         }
  305         return (1);
  306 
  307 bad_bcount:
  308         printf("dscheck: b_bcount %ld is not on a sector boundary (ssize %d)\n",
  309             bp->b_bcount, ssp->dss_secsize);
  310         bp->b_error = EINVAL;
  311         goto bad;
  312 
  313 bad_blkno:
  314         printf("dscheck: b_blkno %ld is not on a sector boundary (ssize %d)\n",
  315             (long)blkno, ssp->dss_secsize);
  316         bp->b_error = EINVAL;
  317         goto bad;
  318 
  319 bad:
  320         bp->b_resid = bp->b_bcount;
  321         bp->b_flags |= B_ERROR;
  322         return (-1);
  323 }
  324 
  325 void
  326 dsclose(dev, mode, ssp)
  327         dev_t   dev;
  328         int     mode;
  329         struct diskslices *ssp;
  330 {
  331         u_char  mask;
  332         struct diskslice *sp;
  333 
  334         sp = &ssp->dss_slices[dkslice(dev)];
  335         mask = 1 << dkpart(dev);
  336         switch (mode) {
  337         case S_IFBLK:
  338                 sp->ds_bopenmask &= ~mask;
  339                 break;
  340         case S_IFCHR:
  341                 sp->ds_copenmask &= ~mask;
  342                 break;
  343         }
  344         sp->ds_openmask = sp->ds_bopenmask | sp->ds_copenmask;
  345 }
  346 
  347 void
  348 dsgone(sspp)
  349         struct diskslices **sspp;
  350 {
  351         int     slice;
  352         struct diskslice *sp;
  353         struct diskslices *ssp;
  354 
  355         for (slice = 0, ssp = *sspp; slice < ssp->dss_nslices; slice++) {
  356                 sp = &ssp->dss_slices[slice];
  357                 if (sp->ds_bad != NULL) {
  358                         free(sp->ds_bad, M_DEVBUF);
  359                         set_ds_bad(ssp, slice, (struct dkbad_intern *)NULL);
  360                 }
  361 #ifdef DEVFS
  362                 if (sp->ds_bdev != NULL)
  363                         devfs_remove_dev(sp->ds_bdev);
  364                 if (sp->ds_cdev != NULL)
  365                         devfs_remove_dev(sp->ds_cdev);
  366 #endif
  367                 free_ds_label(ssp, slice);
  368         }
  369         free(ssp, M_DEVBUF);
  370         *sspp = NULL;
  371 }
  372 
  373 /*
  374  * For the "write" commands (DIOCSBAD, DIOCSDINFO and DIOCWDINFO), this
  375  * is subject to the same restriction as dsopen().
  376  */
  377 int
  378 dsioctl(dname, dev, cmd, data, flags, sspp, strat, setgeom)
  379         char    *dname;
  380         dev_t   dev;
  381         u_long  cmd;
  382         caddr_t data;
  383         int     flags;
  384         struct diskslices **sspp;
  385         d_strategy_t *strat;
  386         ds_setgeom_t *setgeom;
  387 {
  388         int     error;
  389         struct disklabel *lp;
  390         int     old_wlabel;
  391         u_char  openmask;
  392         int     part;
  393         int     slice;
  394         struct diskslice *sp;
  395         struct diskslices *ssp;
  396 
  397         slice = dkslice(dev);
  398         ssp = *sspp;
  399         sp = &ssp->dss_slices[slice];
  400         lp = sp->ds_label;
  401         switch (cmd) {
  402 
  403         case DIOCGDINFO:
  404                 if (lp == NULL)
  405                         return (EINVAL);
  406                 *(struct disklabel *)data = *lp;
  407                 return (0);
  408 
  409 #ifdef notyet
  410         case DIOCGDINFOP:
  411                 if (lp == NULL)
  412                         return (EINVAL);
  413                 *(struct disklabel **)data = lp;
  414                 return (0);
  415 #endif
  416 
  417         case DIOCGPART:
  418                 if (lp == NULL)
  419                         return (EINVAL);
  420                 ((struct partinfo *)data)->disklab = lp;
  421                 ((struct partinfo *)data)->part
  422                         = &lp->d_partitions[dkpart(dev)];
  423                 return (0);
  424 
  425         case DIOCGSLICEINFO:
  426                 bcopy(ssp, data, (char *)&ssp->dss_slices[ssp->dss_nslices] -
  427                                  (char *)ssp);
  428                 return (0);
  429 
  430         case DIOCSBAD:
  431                 if (slice == WHOLE_DISK_SLICE)
  432                         return (ENODEV);
  433                 if (!(flags & FWRITE))
  434                         return (EBADF);
  435                 if (lp == NULL)
  436                         return (EINVAL);
  437                 if (sp->ds_bad != NULL)
  438                         free(sp->ds_bad, M_DEVBUF);
  439                 set_ds_bad(ssp, slice, internbad144((struct dkbad *)data, lp));
  440                 return (0);
  441 
  442         case DIOCSDINFO:
  443                 if (slice == WHOLE_DISK_SLICE)
  444                         return (ENODEV);
  445                 if (!(flags & FWRITE))
  446                         return (EBADF);
  447                 lp = malloc(sizeof *lp, M_DEVBUF, M_WAITOK);
  448                 if (sp->ds_label == NULL)
  449                         bzero(lp, sizeof *lp);
  450                 else
  451                         bcopy(sp->ds_label, lp, sizeof *lp);
  452                 if (sp->ds_label == NULL)
  453                         openmask = 0;
  454                 else {
  455                         openmask = sp->ds_openmask;
  456                         if (slice == COMPATIBILITY_SLICE)
  457                                 openmask |= ssp->dss_slices[
  458                                     ssp->dss_first_bsd_slice].ds_openmask;
  459                         else if (slice == ssp->dss_first_bsd_slice)
  460                                 openmask |= ssp->dss_slices[
  461                                     COMPATIBILITY_SLICE].ds_openmask;
  462                 }
  463                 error = setdisklabel(lp, (struct disklabel *)data,
  464                                      (u_long)openmask);
  465                 /* XXX why doesn't setdisklabel() check this? */
  466                 if (error == 0 && lp->d_partitions[RAW_PART].p_offset != 0)
  467                         error = EXDEV;
  468                 if (error == 0) {
  469                         if (lp->d_secperunit > sp->ds_size)
  470                                 error = ENOSPC;
  471                         for (part = 0; part < lp->d_npartitions; part++)
  472                                 if (lp->d_partitions[part].p_size > sp->ds_size)
  473                                         error = ENOSPC;
  474                 }
  475 #if 0 /* XXX */
  476                 if (error != 0 && setgeom != NULL)
  477                         error = setgeom(lp);
  478 #endif
  479                 if (error != 0) {
  480                         free(lp, M_DEVBUF);
  481                         return (error);
  482                 }
  483                 free_ds_label(ssp, slice);
  484                 set_ds_label(ssp, slice, lp);
  485 #ifdef DEVFS
  486                 set_ds_labeldevs(dname, dev, ssp);
  487 #endif
  488                 return (0);
  489 
  490         case DIOCSYNCSLICEINFO:
  491                 if (slice != WHOLE_DISK_SLICE || dkpart(dev) != RAW_PART)
  492                         return (EINVAL);
  493                 if (!*(int *)data)
  494                         for (slice = 0; slice < ssp->dss_nslices; slice++) {
  495                                 openmask = ssp->dss_slices[slice].ds_openmask;
  496                                 if (openmask
  497                                     && (slice != WHOLE_DISK_SLICE
  498                                         || openmask & ~(1 << RAW_PART)))
  499                                         return (EBUSY);
  500                         }
  501 
  502                 /*
  503                  * Temporarily forget the current slices struct and read
  504                  * the current one.
  505                  * XXX should wait for current accesses on this disk to
  506                  * complete, then lock out future accesses and opens.
  507                  */
  508                 *sspp = NULL;
  509                 lp = malloc(sizeof *lp, M_DEVBUF, M_WAITOK);
  510                 *lp = *ssp->dss_slices[WHOLE_DISK_SLICE].ds_label;
  511                 error = dsopen(dname, dev,
  512                                ssp->dss_slices[WHOLE_DISK_SLICE].ds_copenmask
  513                                & (1 << RAW_PART) ? S_IFCHR : S_IFBLK,
  514                                ssp->dss_oflags, sspp, lp, strat, setgeom,
  515                                ssp->dss_cdevsw);
  516                 if (error != 0) {
  517                         free(lp, M_DEVBUF);
  518                         *sspp = ssp;
  519                         return (error);
  520                 }
  521 
  522                 /*
  523                  * Reopen everything.  This is a no-op except in the "force"
  524                  * case and when the raw bdev and cdev are both open.  Abort
  525                  * if anything fails.
  526                  */
  527                 for (slice = 0; slice < ssp->dss_nslices; slice++) {
  528                         for (openmask = ssp->dss_slices[slice].ds_bopenmask,
  529                              part = 0; openmask; openmask >>= 1, part++) {
  530                                 if (!(openmask & 1))
  531                                         continue;
  532                                 error = dsopen(dname,
  533                                                dkmodslice(dkmodpart(dev, part),
  534                                                           slice),
  535                                                S_IFBLK, ssp->dss_oflags, sspp,
  536                                                lp, strat, setgeom,
  537                                                ssp->dss_cdevsw);
  538                                 if (error != 0) {
  539                                         /* XXX should free devfs toks. */
  540                                         free(lp, M_DEVBUF);
  541                                         /* XXX should restore devfs toks. */
  542                                         *sspp = ssp;
  543                                         return (EBUSY);
  544                                 }
  545                         }
  546                         for (openmask = ssp->dss_slices[slice].ds_copenmask,
  547                              part = 0; openmask; openmask >>= 1, part++) {
  548                                 if (!(openmask & 1))
  549                                         continue;
  550                                 error = dsopen(dname,
  551                                                dkmodslice(dkmodpart(dev, part),
  552                                                           slice),
  553                                                S_IFCHR, ssp->dss_oflags, sspp,
  554                                                lp, strat, setgeom,
  555                                                ssp->dss_cdevsw);
  556                                 if (error != 0) {
  557                                         /* XXX should free devfs toks. */
  558                                         free(lp, M_DEVBUF);
  559                                         /* XXX should restore devfs toks. */
  560                                         *sspp = ssp;
  561                                         return (EBUSY);
  562                                 }
  563                         }
  564                 }
  565 
  566                 /* XXX devfs tokens? */
  567                 free(lp, M_DEVBUF);
  568                 dsgone(&ssp);
  569                 return (0);
  570 
  571         case DIOCWDINFO:
  572                 error = dsioctl(dname, dev, DIOCSDINFO, data, flags, &ssp,
  573                                 strat, setgeom);
  574                 if (error != 0)
  575                         return (error);
  576                 /*
  577                  * XXX this used to hack on dk_openpart to fake opening
  578                  * partition 0 in case that is used instead of dkpart(dev).
  579                  */
  580                 old_wlabel = sp->ds_wlabel;
  581                 set_ds_wlabel(ssp, slice, TRUE);
  582                 error = writedisklabel(dev, strat, sp->ds_label);
  583                 /* XXX should invalidate in-core label if write failed. */
  584                 set_ds_wlabel(ssp, slice, old_wlabel);
  585                 return (error);
  586 
  587         case DIOCWLABEL:
  588 #ifndef __alpha__
  589                 if (slice == WHOLE_DISK_SLICE)
  590                         return (ENODEV);
  591 #endif
  592                 if (!(flags & FWRITE))
  593                         return (EBADF);
  594                 set_ds_wlabel(ssp, slice, *(int *)data != 0);
  595                 return (0);
  596 
  597         default:
  598                 return (ENOIOCTL);
  599         }
  600 }
  601 
  602 static void
  603 dsiodone(bp)
  604         struct buf *bp;
  605 {
  606         struct iodone_chain *ic;
  607         char *msg;
  608 
  609         ic = bp->b_iodone_chain;
  610         bp->b_flags = (ic->ic_prev_flags & B_CALL)
  611                       | (bp->b_flags & ~(B_CALL | B_DONE));
  612         bp->b_iodone = ic->ic_prev_iodone;
  613         bp->b_iodone_chain = ic->ic_prev_iodone_chain;
  614         if (!(bp->b_flags & B_READ)
  615             || (!(bp->b_flags & B_ERROR) && bp->b_error == 0)) {
  616                 msg = fixlabel((char *)NULL, ic->ic_args[1].ia_ptr,
  617                                (struct disklabel *)
  618                                (bp->b_data + ic->ic_args[0].ia_long),
  619                                FALSE);
  620                 if (msg != NULL)
  621                         printf("%s\n", msg);
  622         }
  623         free(ic, M_DEVBUF);
  624         biodone(bp);
  625 }
  626 
  627 int
  628 dsisopen(ssp)
  629         struct diskslices *ssp;
  630 {
  631         int     slice;
  632 
  633         if (ssp == NULL)
  634                 return (0);
  635         for (slice = 0; slice < ssp->dss_nslices; slice++)
  636                 if (ssp->dss_slices[slice].ds_openmask)
  637                         return (1);
  638         return (0);
  639 }
  640 
  641 /*
  642  * Allocate a slices "struct" and initialize it to contain only an empty
  643  * compatibility slice (pointing to itself), a whole disk slice (covering
  644  * the disk as described by the label), and (nslices - BASE_SLICES) empty
  645  * slices beginning at BASE_SLICE.
  646  */
  647 struct diskslices *
  648 dsmakeslicestruct(nslices, lp)
  649         int nslices;
  650         struct disklabel *lp;
  651 {
  652         struct diskslice *sp;
  653         struct diskslices *ssp;
  654 
  655         ssp = malloc(offsetof(struct diskslices, dss_slices) +
  656                      nslices * sizeof *sp, M_DEVBUF, M_WAITOK);
  657         ssp->dss_cdevsw = NULL;
  658         ssp->dss_first_bsd_slice = COMPATIBILITY_SLICE;
  659         ssp->dss_nslices = nslices;
  660         ssp->dss_oflags = 0;
  661         ssp->dss_secmult = lp->d_secsize / DEV_BSIZE;
  662         if (ssp->dss_secmult & (ssp->dss_secmult - 1))
  663                 ssp->dss_secshift = -1;
  664         else
  665                 ssp->dss_secshift = ffs(ssp->dss_secmult) - 1;
  666         ssp->dss_secsize = lp->d_secsize;
  667         sp = &ssp->dss_slices[0];
  668         bzero(sp, nslices * sizeof *sp);
  669         sp[WHOLE_DISK_SLICE].ds_size = lp->d_secperunit;
  670         return (ssp);
  671 }
  672 
  673 char *
  674 dsname(dname, unit, slice, part, partname)
  675         char    *dname;
  676         int     unit;
  677         int     slice;
  678         int     part;
  679         char    *partname;
  680 {
  681         static char name[32];
  682 
  683         if (strlen(dname) > 16)
  684                 dname = "nametoolong";
  685         snprintf(name, sizeof(name), "%s%d", dname, unit);
  686         partname[0] = '\0';
  687         if (slice != WHOLE_DISK_SLICE || part != RAW_PART) {
  688                 partname[0] = 'a' + part;
  689                 partname[1] = '\0';
  690                 if (slice != COMPATIBILITY_SLICE)
  691                         snprintf(name + strlen(name),
  692                             sizeof(name) - strlen(name), "s%d", slice - 1);
  693         }
  694         return (name);
  695 }
  696 
  697 /*
  698  * This should only be called when the unit is inactive and the strategy
  699  * routine should not allow it to become active unless we call it.  Our
  700  * strategy routine must be special to allow activity.
  701  */
  702 int
  703 dsopen(dname, dev, mode, flags, sspp, lp, strat, setgeom, cdevsw)
  704         char    *dname;
  705         dev_t   dev;
  706         int     mode;
  707         u_int   flags;
  708         struct diskslices **sspp;
  709         struct disklabel *lp;
  710         d_strategy_t *strat;
  711         ds_setgeom_t *setgeom;
  712         struct cdevsw *cdevsw;
  713 {
  714         struct dkbad *btp;
  715         dev_t   dev1;
  716         int     error;
  717         struct disklabel *lp1;
  718         char    *msg;
  719         u_char  mask;
  720 #ifdef DEVFS
  721         int     mynor;
  722 #endif
  723         bool_t  need_init;
  724         int     part;
  725         char    partname[2];
  726         int     slice;
  727         char    *sname;
  728         struct diskslice *sp;
  729         struct diskslices *ssp;
  730         int     unit;
  731 
  732         if (lp->d_secsize % DEV_BSIZE)
  733                 return (EINVAL);
  734 
  735         /*
  736          * XXX reinitialize the slice table unless there is an open device
  737          * on the unit.  This should only be done if the media has changed.
  738          */
  739         ssp = *sspp;
  740         need_init = !dsisopen(ssp);
  741         if (ssp != NULL && need_init)
  742                 dsgone(sspp);
  743         if (need_init) {
  744                 /*
  745                  * Allocate a minimal slices "struct".  This will become
  746                  * the final slices "struct" if we don't want real slices
  747                  * or if we can't find any real slices.
  748                  */
  749                 *sspp = dsmakeslicestruct(BASE_SLICE, lp);
  750 
  751                 if (!(flags & DSO_ONESLICE)) {
  752                         TRACE(("dsinit\n"));
  753                         error = dsinit(dname, dev, strat, lp, sspp);
  754                         if (error != 0) {
  755                                 dsgone(sspp);
  756                                 return (error);
  757                         }
  758                 }
  759                 ssp = *sspp;
  760                 ssp->dss_oflags = flags;
  761 #ifdef DEVFS
  762                 ssp->dss_cdevsw = cdevsw;
  763 #endif
  764 
  765                 /*
  766                  * If there are no real slices, then make the compatiblity
  767                  * slice cover the whole disk.
  768                  */
  769                 if (ssp->dss_nslices == BASE_SLICE)
  770                         ssp->dss_slices[COMPATIBILITY_SLICE].ds_size
  771                                 = lp->d_secperunit;
  772 
  773                 /* Point the compatibility slice at the BSD slice, if any. */
  774                 for (slice = BASE_SLICE; slice < ssp->dss_nslices; slice++) {
  775                         sp = &ssp->dss_slices[slice];
  776                         if (sp->ds_type == DOSPTYP_386BSD /* XXX */) {
  777                                 ssp->dss_first_bsd_slice = slice;
  778                                 ssp->dss_slices[COMPATIBILITY_SLICE].ds_offset
  779                                         = sp->ds_offset;
  780                                 ssp->dss_slices[COMPATIBILITY_SLICE].ds_size
  781                                         = sp->ds_size;
  782                                 ssp->dss_slices[COMPATIBILITY_SLICE].ds_type
  783                                         = sp->ds_type;
  784                                 break;
  785                         }
  786                 }
  787 
  788                 ssp->dss_slices[WHOLE_DISK_SLICE].ds_label = clone_label(lp);
  789                 ssp->dss_slices[WHOLE_DISK_SLICE].ds_wlabel = TRUE;
  790                 if (setgeom != NULL) {
  791                         error = setgeom(lp);
  792                         if (error != 0) {
  793                                 dsgone(sspp);
  794                                 return (error);
  795                         }
  796                 }
  797         }
  798 
  799         unit = dkunit(dev);
  800 
  801         /*
  802          * Initialize secondary info for all slices.  It is needed for more
  803          * than the current slice in the DEVFS case.
  804          */
  805         for (slice = 0; slice < ssp->dss_nslices; slice++) {
  806                 sp = &ssp->dss_slices[slice];
  807                 if (sp->ds_label != NULL
  808 #ifdef __alpha__
  809                     && slice != WHOLE_DISK_SLICE
  810 #endif
  811                     )
  812                         continue;
  813                 dev1 = dkmodslice(dkmodpart(dev, RAW_PART), slice);
  814                 sname = dsname(dname, unit, slice, RAW_PART, partname);
  815 #ifdef DEVFS
  816                 if (slice != COMPATIBILITY_SLICE && sp->ds_bdev == NULL
  817                     && sp->ds_size != 0) {
  818                         mynor = minor(dev1);
  819                         sp->ds_bdev =
  820                                 devfs_add_devswf(bdevsw, mynor, DV_BLK,
  821                                                  UID_ROOT, GID_OPERATOR, 0640,
  822                                                  "%s", sname);
  823                         sp->ds_cdev =
  824                                 devfs_add_devswf(cdevsw, mynor, DV_CHR,
  825                                                  UID_ROOT, GID_OPERATOR, 0640,
  826                                                  "r%s", sname);
  827                 }
  828 #endif
  829                 /*
  830                  * XXX this should probably only be done for the need_init
  831                  * case, but there may be a problem with DIOCSYNCSLICEINFO.
  832                  */
  833                 set_ds_wlabel(ssp, slice, TRUE);        /* XXX invert */
  834                 lp1 = clone_label(lp);
  835                 TRACE(("readdisklabel\n"));
  836                 if (flags & DSO_NOLABELS)
  837                         msg = NULL;
  838                 else
  839                         msg = readdisklabel(dev1, strat, lp1);
  840 #if 0 /* XXX */
  841                 if (msg == NULL && setgeom != NULL && setgeom(lp1) != 0)
  842                         msg = "setgeom failed";
  843 #endif
  844                 if (msg == NULL)
  845                         msg = fixlabel(sname, sp, lp1, FALSE);
  846                 if (msg == NULL && lp1->d_secsize != ssp->dss_secsize)
  847                         msg = "inconsistent sector size";
  848                 if (msg != NULL) {
  849                         free(lp1, M_DEVBUF);
  850                         if (sp->ds_type == DOSPTYP_386BSD /* XXX */)
  851                                 log(LOG_WARNING, "%s: cannot find label (%s)\n",
  852                                     sname, msg);
  853                         continue;
  854                 }
  855                 if (lp1->d_flags & D_BADSECT) {
  856                         btp = malloc(sizeof *btp, M_DEVBUF, M_WAITOK);
  857                         TRACE(("readbad144\n"));
  858                         msg = readbad144(dev1, strat, lp1, btp);
  859                         if (msg != NULL) {
  860                                 log(LOG_WARNING,
  861                                     "%s: cannot find bad sector table (%s)\n",
  862                                     sname, msg);
  863                                 free(btp, M_DEVBUF);
  864                                 free(lp1, M_DEVBUF);
  865                                 continue;
  866                         }
  867                         set_ds_bad(ssp, slice, internbad144(btp, lp1));
  868                         free(btp, M_DEVBUF);
  869                         if (sp->ds_bad == NULL) {
  870                                 free(lp1, M_DEVBUF);
  871                                 continue;
  872                         }
  873                 }
  874                 set_ds_label(ssp, slice, lp1);
  875 #ifdef DEVFS
  876                 set_ds_labeldevs(dname, dev1, ssp);
  877 #endif
  878                 set_ds_wlabel(ssp, slice, FALSE);
  879         }
  880 
  881         slice = dkslice(dev);
  882         if (slice >= ssp->dss_nslices)
  883                 return (ENXIO);
  884         sp = &ssp->dss_slices[slice];
  885         part = dkpart(dev);
  886         if (part != RAW_PART
  887             && (sp->ds_label == NULL || part >= sp->ds_label->d_npartitions))
  888                 return (EINVAL);        /* XXX needs translation */
  889         mask = 1 << part;
  890         switch (mode) {
  891         case S_IFBLK:
  892                 sp->ds_bopenmask |= mask;
  893                 break;
  894         case S_IFCHR:
  895                 sp->ds_copenmask |= mask;
  896                 break;
  897         }
  898         sp->ds_openmask = sp->ds_bopenmask | sp->ds_copenmask;
  899         return (0);
  900 }
  901 
  902 int
  903 dssize(dev, sspp, dopen, dclose)
  904         dev_t   dev;
  905         struct diskslices **sspp;
  906         d_open_t dopen;
  907         d_close_t dclose;
  908 {
  909         struct disklabel *lp;
  910         int     part;
  911         int     slice;
  912         struct diskslices *ssp;
  913 
  914         slice = dkslice(dev);
  915         part = dkpart(dev);
  916         ssp = *sspp;
  917         if (ssp == NULL || slice >= ssp->dss_nslices
  918             || !(ssp->dss_slices[slice].ds_bopenmask & (1 << part))) {
  919                 if (dopen(dev, FREAD, S_IFBLK, (struct proc *)NULL) != 0)
  920                         return (-1);
  921                 dclose(dev, FREAD, S_IFBLK, (struct proc *)NULL);
  922                 ssp = *sspp;
  923         }
  924         lp = ssp->dss_slices[slice].ds_label;
  925         if (lp == NULL)
  926                 return (-1);
  927         return ((int)lp->d_partitions[part].p_size);
  928 }
  929 
  930 static void
  931 free_ds_label(ssp, slice)
  932         struct diskslices *ssp;
  933         int     slice;
  934 {
  935         struct disklabel *lp;
  936         struct diskslice *sp;
  937 
  938         sp = &ssp->dss_slices[slice];
  939         lp = sp->ds_label;
  940         if (lp == NULL)
  941                 return;
  942 #ifdef DEVFS
  943         free_ds_labeldevs(ssp, slice);
  944         if (slice == COMPATIBILITY_SLICE)
  945                 free_ds_labeldevs(ssp, ssp->dss_first_bsd_slice);
  946         else if (slice == ssp->dss_first_bsd_slice)
  947                 free_ds_labeldevs(ssp, COMPATIBILITY_SLICE);
  948 #endif
  949         free(lp, M_DEVBUF);
  950         set_ds_label(ssp, slice, (struct disklabel *)NULL);
  951 }
  952 
  953 #ifdef DEVFS
  954 static void
  955 free_ds_labeldevs(ssp, slice)
  956         struct diskslices *ssp;
  957         int     slice;
  958 {
  959         struct disklabel *lp;
  960         int     part;
  961         struct diskslice *sp;
  962 
  963         sp = &ssp->dss_slices[slice];
  964         lp = sp->ds_label;
  965         if (lp == NULL)
  966                 return;
  967         for (part = 0; part < lp->d_npartitions; part++) {
  968                 if (sp->ds_bdevs[part] != NULL) {
  969                         devfs_remove_dev(sp->ds_bdevs[part]);
  970                         sp->ds_bdevs[part] = NULL;
  971                 }
  972                 if (sp->ds_cdevs[part] != NULL) {
  973                         devfs_remove_dev(sp->ds_cdevs[part]);
  974                         sp->ds_cdevs[part] = NULL;
  975                 }
  976         }
  977 }
  978 #endif
  979 
  980 static char *
  981 fixlabel(sname, sp, lp, writeflag)
  982         char    *sname;
  983         struct diskslice *sp;
  984         struct disklabel *lp;
  985         int     writeflag;
  986 {
  987         u_long  end;
  988         u_long  offset;
  989         int     part;
  990         struct partition *pp;
  991         u_long  start;
  992         bool_t  warned;
  993 
  994         /* These errors "can't happen" so don't bother reporting details. */
  995         if (lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC)
  996                 return ("fixlabel: invalid magic");
  997         if (dkcksum(lp) != 0)
  998                 return ("fixlabel: invalid checksum");
  999 
 1000         pp = &lp->d_partitions[RAW_PART];
 1001         if (writeflag) {
 1002                 start = 0;
 1003                 offset = sp->ds_offset;
 1004         } else {
 1005                 start = sp->ds_offset;
 1006                 offset = -sp->ds_offset;
 1007         }
 1008         if (pp->p_offset != start) {
 1009                 if (sname != NULL) {
 1010                         printf(
 1011 "%s: rejecting BSD label: raw partition offset != slice offset\n",
 1012                                sname);
 1013                         slice_info(sname, sp);
 1014                         partition_info(sname, RAW_PART, pp);
 1015                 }
 1016                 return ("fixlabel: raw partition offset != slice offset");
 1017         }
 1018         if (pp->p_size != sp->ds_size) {
 1019                 if (sname != NULL) {
 1020                         printf("%s: raw partition size != slice size\n", sname);
 1021                         slice_info(sname, sp);
 1022                         partition_info(sname, RAW_PART, pp);
 1023                 }
 1024                 if (pp->p_size > sp->ds_size) {
 1025                         if (sname == NULL)
 1026                                 return ("fixlabel: raw partition size > slice size");
 1027                         printf("%s: truncating raw partition\n", sname);
 1028                         pp->p_size = sp->ds_size;
 1029                 }
 1030         }
 1031         end = start + sp->ds_size;
 1032         if (start > end)
 1033                 return ("fixlabel: slice wraps");
 1034         if (lp->d_secpercyl <= 0)
 1035                 return ("fixlabel: d_secpercyl <= 0");
 1036         pp -= RAW_PART;
 1037         warned = FALSE;
 1038         for (part = 0; part < lp->d_npartitions; part++, pp++) {
 1039                 if (pp->p_offset != 0 || pp->p_size != 0) {
 1040                         if (pp->p_offset < start
 1041                             || pp->p_offset + pp->p_size > end
 1042                             || pp->p_offset + pp->p_size < pp->p_offset) {
 1043                                 if (sname != NULL) {
 1044                                         printf(
 1045 "%s: rejecting partition in BSD label: it isn't entirely within the slice\n",
 1046                                                sname);
 1047                                         if (!warned) {
 1048                                                 slice_info(sname, sp);
 1049                                                 warned = TRUE;
 1050                                         }
 1051                                         partition_info(sname, part, pp);
 1052                                 }
 1053                                 /* XXX else silently discard junk. */
 1054                                 bzero(pp, sizeof *pp);
 1055                         } else
 1056                                 pp->p_offset += offset;
 1057                 }
 1058         }
 1059         lp->d_ncylinders = sp->ds_size / lp->d_secpercyl;
 1060         lp->d_secperunit = sp->ds_size;
 1061         lp->d_checksum = 0;
 1062         lp->d_checksum = dkcksum(lp);
 1063         return (NULL);
 1064 }
 1065 
 1066 static void
 1067 partition_info(sname, part, pp)
 1068         char    *sname;
 1069         int     part;
 1070         struct partition *pp;
 1071 {
 1072         printf("%s%c: start %lu, end %lu, size %lu\n", sname, 'a' + part,
 1073                (u_long)pp->p_offset, (u_long)(pp->p_offset + pp->p_size - 1),
 1074                (u_long)pp->p_size);
 1075 }
 1076 
 1077 static void
 1078 slice_info(sname, sp)
 1079         char    *sname;
 1080         struct diskslice *sp;
 1081 {
 1082         printf("%s: start %lu, end %lu, size %lu\n", sname,
 1083                sp->ds_offset, sp->ds_offset + sp->ds_size - 1, sp->ds_size);
 1084 }
 1085 
 1086 /*
 1087  * Most changes to ds_bad, ds_label and ds_wlabel are made using the
 1088  * following functions to ensure coherency of the compatibility slice
 1089  * with the first BSD slice.  The openmask fields are _not_ shared and
 1090  * the other fields (ds_offset and ds_size) aren't changed after they
 1091  * are initialized.
 1092  */
 1093 static void
 1094 set_ds_bad(ssp, slice, btp)
 1095         struct diskslices *ssp;
 1096         int     slice;
 1097         struct dkbad_intern *btp;
 1098 {
 1099         ssp->dss_slices[slice].ds_bad = btp;
 1100         if (slice == COMPATIBILITY_SLICE)
 1101                 ssp->dss_slices[ssp->dss_first_bsd_slice].ds_bad = btp;
 1102         else if (slice == ssp->dss_first_bsd_slice)
 1103                 ssp->dss_slices[COMPATIBILITY_SLICE].ds_bad = btp;
 1104 }
 1105 
 1106 static void
 1107 set_ds_label(ssp, slice, lp)
 1108         struct diskslices *ssp;
 1109         int     slice;
 1110         struct disklabel *lp;
 1111 {
 1112         ssp->dss_slices[slice].ds_label = lp;
 1113         if (slice == COMPATIBILITY_SLICE)
 1114                 ssp->dss_slices[ssp->dss_first_bsd_slice].ds_label = lp;
 1115         else if (slice == ssp->dss_first_bsd_slice)
 1116                 ssp->dss_slices[COMPATIBILITY_SLICE].ds_label = lp;
 1117 }
 1118 
 1119 #ifdef DEVFS
 1120 static void
 1121 set_ds_labeldevs(dname, dev, ssp)
 1122         char    *dname;
 1123         dev_t   dev;
 1124         struct diskslices *ssp;
 1125 {
 1126         int     slice;
 1127 
 1128         set_ds_labeldevs_unaliased(dname, dev, ssp);
 1129         if (ssp->dss_first_bsd_slice == COMPATIBILITY_SLICE)
 1130                 return;
 1131         slice = dkslice(dev);
 1132         if (slice == COMPATIBILITY_SLICE)
 1133                 set_ds_labeldevs_unaliased(dname,
 1134                         dkmodslice(dev, ssp->dss_first_bsd_slice), ssp);
 1135         else if (slice == ssp->dss_first_bsd_slice)
 1136                 set_ds_labeldevs_unaliased(dname,
 1137                         dkmodslice(dev, COMPATIBILITY_SLICE), ssp);
 1138 }
 1139 
 1140 static void
 1141 set_ds_labeldevs_unaliased(dname, dev, ssp)
 1142         char    *dname;
 1143         dev_t   dev;
 1144         struct diskslices *ssp;
 1145 {
 1146         struct disklabel *lp;
 1147         int     mynor;
 1148         int     part;
 1149         char    partname[2];
 1150         struct partition *pp;
 1151         int     slice;
 1152         char    *sname;
 1153         struct diskslice *sp;
 1154  
 1155         slice = dkslice(dev);
 1156         sp = &ssp->dss_slices[slice];
 1157         if (sp->ds_size == 0)
 1158                 return;
 1159         lp = sp->ds_label;
 1160         for (part = 0; part < lp->d_npartitions; part++) {
 1161                 pp = &lp->d_partitions[part];
 1162                 if (pp->p_size == 0)
 1163                         continue;
 1164                 sname = dsname(dname, dkunit(dev), slice, part, partname);
 1165                 if (part == RAW_PART && sp->ds_bdev != NULL) {
 1166                         sp->ds_bdevs[part] =
 1167                                 devfs_makelink(sp->ds_bdev,
 1168                                            "%s%s", sname, partname);
 1169                         sp->ds_cdevs[part] =
 1170                                 devfs_makelink(sp->ds_cdev,
 1171                                            "r%s%s", sname, partname);
 1172                 } else {
 1173                         mynor = minor(dkmodpart(dev, part));
 1174                         sp->ds_bdevs[part] =
 1175                                 devfs_add_devswf(ssp->dss_cdevsw, mynor, DV_BLK,
 1176                                                  UID_ROOT, GID_OPERATOR, 0640,
 1177                                                  "%s%s", sname, partname);
 1178                         sp->ds_cdevs[part] =
 1179                                 devfs_add_devswf(ssp->dss_cdevsw, mynor, DV_CHR,
 1180                                                  UID_ROOT, GID_OPERATOR, 0640,
 1181                                                  "r%s%s", sname, partname);
 1182                 }
 1183         }
 1184 }
 1185 #endif /* DEVFS */
 1186 
 1187 static void
 1188 set_ds_wlabel(ssp, slice, wlabel)
 1189         struct diskslices *ssp;
 1190         int     slice;
 1191         int     wlabel;
 1192 {
 1193         ssp->dss_slices[slice].ds_wlabel = wlabel;
 1194         if (slice == COMPATIBILITY_SLICE)
 1195                 ssp->dss_slices[ssp->dss_first_bsd_slice].ds_wlabel = wlabel;
 1196         else if (slice == ssp->dss_first_bsd_slice)
 1197                 ssp->dss_slices[COMPATIBILITY_SLICE].ds_wlabel = wlabel;
 1198 }

Cache object: 43e426421406aaa9246a1cc603b47671


[ 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.