root/kern/subr_disk.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. disksort
  2. dkcksum
  3. initdisklabel
  4. checkdisklabel
  5. readdoslabel
  6. setdisklabel
  7. bounds_check_with_label
  8. diskerr
  9. disk_init
  10. disk_construct
  11. disk_attach
  12. disk_detach
  13. disk_busy
  14. disk_unbusy
  15. disk_lock
  16. disk_unlock
  17. dk_mountroot
  18. bufq_default_alloc
  19. bufq_default_free
  20. bufq_default_add
  21. bufq_default_get
  22. getdisk
  23. parsedisk
  24. setroot
  25. findblkmajor
  26. findblkname

    1 /*      $OpenBSD: subr_disk.c,v 1.64 2007/08/05 04:26:21 krw Exp $      */
    2 /*      $NetBSD: subr_disk.c,v 1.17 1996/03/16 23:17:08 christos Exp $  */
    3 
    4 /*
    5  * Copyright (c) 1995 Jason R. Thorpe.  All rights reserved.
    6  * Copyright (c) 1982, 1986, 1988, 1993
    7  *      The Regents of the University of California.  All rights reserved.
    8  * (c) UNIX System Laboratories, Inc.
    9  * All or some portions of this file are derived from material licensed
   10  * to the University of California by American Telephone and Telegraph
   11  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   12  * the permission of UNIX System Laboratories, Inc.
   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. Neither the name of the University nor the names of its contributors
   23  *    may be used to endorse or promote products derived from this software
   24  *    without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   36  * SUCH DAMAGE.
   37  *
   38  *      @(#)ufs_disksubr.c      8.5 (Berkeley) 1/21/94
   39  */
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/kernel.h>
   44 #include <sys/malloc.h>
   45 #include <sys/fcntl.h>
   46 #include <sys/buf.h>
   47 #include <sys/stat.h>
   48 #include <sys/syslog.h>
   49 #include <sys/device.h>
   50 #include <sys/time.h>
   51 #include <sys/disklabel.h>
   52 #include <sys/conf.h>
   53 #include <sys/lock.h>
   54 #include <sys/disk.h>
   55 #include <sys/reboot.h>
   56 #include <sys/dkio.h>
   57 #include <sys/dkstat.h>         /* XXX */
   58 #include <sys/proc.h>
   59 #include <uvm/uvm_extern.h>
   60 
   61 #include <dev/rndvar.h>
   62 #include <dev/cons.h>
   63 
   64 /*
   65  * A global list of all disks attached to the system.  May grow or
   66  * shrink over time.
   67  */
   68 struct  disklist_head disklist; /* TAILQ_HEAD */
   69 int     disk_count;             /* number of drives in global disklist */
   70 int     disk_change;            /* set if a disk has been attached/detached
   71                                  * since last we looked at this variable. This
   72                                  * is reset by hw_sysctl()
   73                                  */
   74 
   75 /*
   76  * Seek sort for disks.  We depend on the driver which calls us using b_resid
   77  * as the current cylinder number.
   78  *
   79  * The argument ap structure holds a b_actf activity chain pointer on which we
   80  * keep two queues, sorted in ascending cylinder order.  The first queue holds
   81  * those requests which are positioned after the current cylinder (in the first
   82  * request); the second holds requests which came in after their cylinder number
   83  * was passed.  Thus we implement a one way scan, retracting after reaching the
   84  * end of the drive to the first request on the second queue, at which time it
   85  * becomes the first queue.
   86  *
   87  * A one-way scan is natural because of the way UNIX read-ahead blocks are
   88  * allocated.
   89  */
   90 
   91 void
   92 disksort(struct buf *ap, struct buf *bp)
   93 {
   94         struct buf *bq;
   95 
   96         /* If the queue is empty, then it's easy. */
   97         if (ap->b_actf == NULL) {
   98                 bp->b_actf = NULL;
   99                 ap->b_actf = bp;
  100                 return;
  101         }
  102 
  103         /*
  104          * If we lie after the first (currently active) request, then we
  105          * must locate the second request list and add ourselves to it.
  106          */
  107         bq = ap->b_actf;
  108         if (bp->b_cylinder < bq->b_cylinder) {
  109                 while (bq->b_actf) {
  110                         /*
  111                          * Check for an ``inversion'' in the normally ascending
  112                          * cylinder numbers, indicating the start of the second
  113                          * request list.
  114                          */
  115                         if (bq->b_actf->b_cylinder < bq->b_cylinder) {
  116                                 /*
  117                                  * Search the second request list for the first
  118                                  * request at a larger cylinder number.  We go
  119                                  * before that; if there is no such request, we
  120                                  * go at end.
  121                                  */
  122                                 do {
  123                                         if (bp->b_cylinder <
  124                                             bq->b_actf->b_cylinder)
  125                                                 goto insert;
  126                                         if (bp->b_cylinder ==
  127                                             bq->b_actf->b_cylinder &&
  128                                             bp->b_blkno < bq->b_actf->b_blkno)
  129                                                 goto insert;
  130                                         bq = bq->b_actf;
  131                                 } while (bq->b_actf);
  132                                 goto insert;            /* after last */
  133                         }
  134                         bq = bq->b_actf;
  135                 }
  136                 /*
  137                  * No inversions... we will go after the last, and
  138                  * be the first request in the second request list.
  139                  */
  140                 goto insert;
  141         }
  142         /*
  143          * Request is at/after the current request...
  144          * sort in the first request list.
  145          */
  146         while (bq->b_actf) {
  147                 /*
  148                  * We want to go after the current request if there is an
  149                  * inversion after it (i.e. it is the end of the first
  150                  * request list), or if the next request is a larger cylinder
  151                  * than our request.
  152                  */
  153                 if (bq->b_actf->b_cylinder < bq->b_cylinder ||
  154                     bp->b_cylinder < bq->b_actf->b_cylinder ||
  155                     (bp->b_cylinder == bq->b_actf->b_cylinder &&
  156                     bp->b_blkno < bq->b_actf->b_blkno))
  157                         goto insert;
  158                 bq = bq->b_actf;
  159         }
  160         /*
  161          * Neither a second list nor a larger request... we go at the end of
  162          * the first list, which is the same as the end of the whole schebang.
  163          */
  164 insert: bp->b_actf = bq->b_actf;
  165         bq->b_actf = bp;
  166 }
  167 
  168 /*
  169  * Compute checksum for disk label.
  170  */
  171 u_int
  172 dkcksum(struct disklabel *lp)
  173 {
  174         u_int16_t *start, *end;
  175         u_int16_t sum = 0;
  176 
  177         start = (u_int16_t *)lp;
  178         end = (u_int16_t *)&lp->d_partitions[lp->d_npartitions];
  179         while (start < end)
  180                 sum ^= *start++;
  181         return (sum);
  182 }
  183 
  184 char *
  185 initdisklabel(struct disklabel *lp)
  186 {
  187         int i;
  188 
  189         /* minimal requirements for archetypal disk label */
  190         if (lp->d_secsize < DEV_BSIZE)
  191                 lp->d_secsize = DEV_BSIZE;
  192         if (DL_GETDSIZE(lp) == 0)
  193                 DL_SETDSIZE(lp, MAXDISKSIZE);
  194         if (lp->d_secpercyl == 0)
  195                 return ("invalid geometry");
  196         lp->d_npartitions = RAW_PART + 1;
  197         for (i = 0; i < RAW_PART; i++) {
  198                 DL_SETPSIZE(&lp->d_partitions[i], 0);
  199                 DL_SETPOFFSET(&lp->d_partitions[i], 0);
  200         }
  201         if (DL_GETPSIZE(&lp->d_partitions[RAW_PART]) == 0)
  202                 DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp));
  203         DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
  204         lp->d_version = 1;
  205         lp->d_bbsize = 8192;
  206         lp->d_sbsize = 64*1024;                 /* XXX ? */
  207         return (NULL);
  208 }
  209 
  210 /*
  211  * Check an incoming block to make sure it is a disklabel, convert it to
  212  * a newer version if needed, etc etc.
  213  */
  214 char *
  215 checkdisklabel(void *rlp, struct disklabel *lp)
  216 {
  217         struct disklabel *dlp = rlp;
  218         struct __partitionv0 *v0pp;
  219         struct partition *pp;
  220         daddr64_t disksize;
  221         char *msg = NULL;
  222         int i;
  223 
  224         if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC)
  225                 msg = "no disk label";
  226         else if (dlp->d_npartitions > MAXPARTITIONS)
  227                 msg = "unreasonable partition count";
  228         else if (dkcksum(dlp) != 0)
  229                 msg = "disk label corrupted";
  230 
  231         if (msg) {
  232                 u_int16_t *start, *end, sum = 0;
  233 
  234                 /* If it is byte-swapped, attempt to convert it */
  235                 if (swap32(dlp->d_magic) != DISKMAGIC ||
  236                     swap32(dlp->d_magic2) != DISKMAGIC ||
  237                     swap16(dlp->d_npartitions) > MAXPARTITIONS)
  238                         return (msg);
  239 
  240                 /*
  241                  * Need a byte-swap aware dkcksum varient
  242                  * inlined, because dkcksum uses a sub-field
  243                  */
  244                 start = (u_int16_t *)dlp;
  245                 end = (u_int16_t *)&dlp->d_partitions[
  246                     swap16(dlp->d_npartitions)];
  247                 while (start < end)
  248                         sum ^= *start++;
  249                 if (sum != 0)
  250                         return (msg);
  251 
  252                 dlp->d_magic = swap32(dlp->d_magic);
  253                 dlp->d_type = swap16(dlp->d_type);
  254                 dlp->d_subtype = swap16(dlp->d_subtype);
  255 
  256                 /* d_typename and d_packname are strings */
  257 
  258                 dlp->d_secsize = swap32(dlp->d_secsize);
  259                 dlp->d_nsectors = swap32(dlp->d_nsectors);
  260                 dlp->d_ntracks = swap32(dlp->d_ntracks);
  261                 dlp->d_ncylinders = swap32(dlp->d_ncylinders);
  262                 dlp->d_secpercyl = swap32(dlp->d_secpercyl);
  263                 dlp->d_secperunit = swap32(dlp->d_secperunit);
  264 
  265                 dlp->d_sparespertrack = swap16(dlp->d_sparespertrack);
  266                 dlp->d_sparespercyl = swap16(dlp->d_sparespercyl);
  267 
  268                 dlp->d_acylinders = swap32(dlp->d_acylinders);
  269 
  270                 dlp->d_rpm = swap16(dlp->d_rpm);
  271                 dlp->d_interleave = swap16(dlp->d_interleave);
  272                 dlp->d_trackskew = swap16(dlp->d_trackskew);
  273                 dlp->d_cylskew = swap16(dlp->d_cylskew);
  274                 dlp->d_headswitch = swap32(dlp->d_headswitch);
  275                 dlp->d_trkseek = swap32(dlp->d_trkseek);
  276                 dlp->d_flags = swap32(dlp->d_flags);
  277 
  278                 for (i = 0; i < NDDATA; i++)
  279                         dlp->d_drivedata[i] = swap32(dlp->d_drivedata[i]);
  280 
  281                 dlp->d_secperunith = swap16(dlp->d_secperunith);
  282                 dlp->d_version = swap16(dlp->d_version);
  283 
  284                 for (i = 0; i < NSPARE; i++)
  285                         dlp->d_spare[i] = swap32(dlp->d_spare[i]);
  286 
  287                 dlp->d_magic2 = swap32(dlp->d_magic2);
  288                 dlp->d_checksum = swap16(dlp->d_checksum);
  289 
  290                 dlp->d_npartitions = swap16(dlp->d_npartitions);
  291                 dlp->d_bbsize = swap32(dlp->d_bbsize);
  292                 dlp->d_sbsize = swap32(dlp->d_sbsize);
  293 
  294                 for (i = 0; i < MAXPARTITIONS; i++) {
  295                         pp = &dlp->d_partitions[i];
  296                         pp->p_size = swap32(pp->p_size);
  297                         pp->p_offset = swap32(pp->p_offset);
  298                         if (dlp->d_version == 0) {
  299                                 v0pp = (struct __partitionv0 *)pp;
  300                                 v0pp->p_fsize = swap32(v0pp->p_fsize);
  301                         } else {
  302                                 pp->p_offseth = swap16(pp->p_offseth);
  303                                 pp->p_sizeh = swap16(pp->p_sizeh);
  304                         }
  305                         pp->p_cpg = swap16(pp->p_cpg);
  306                 }
  307 
  308                 dlp->d_checksum = 0;
  309                 dlp->d_checksum = dkcksum(dlp);
  310                 msg = NULL;
  311         }
  312 
  313         /* XXX should verify lots of other fields and whine a lot */
  314 
  315         if (msg)
  316                 return (msg);
  317 
  318         /* Initial passed in lp contains the real disk size. */
  319         disksize = DL_GETDSIZE(lp);
  320 
  321         if (lp != dlp)
  322                 *lp = *dlp;
  323 
  324         if (lp->d_version == 0) {
  325                 lp->d_version = 1;
  326                 lp->d_secperunith = 0;
  327 
  328                 v0pp = (struct __partitionv0 *)lp->d_partitions;
  329                 pp = lp->d_partitions;
  330                 for (i = 0; i < lp->d_npartitions; i++, pp++, v0pp++) {
  331                         pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(v0pp->
  332                             p_fsize, v0pp->p_frag);
  333                         pp->p_offseth = 0;
  334                         pp->p_sizeh = 0;
  335                 }
  336         }
  337 
  338 #ifdef DEBUG
  339         if (DL_GETDSIZE(lp) != disksize)
  340                 printf("on-disk disklabel has incorrect disksize (%lld)\n",
  341                     DL_GETDSIZE(lp));
  342         if (DL_GETPSIZE(&lp->d_partitions[RAW_PART]) != disksize)
  343                 printf("on-disk disklabel RAW_PART has incorrect size (%lld)\n",
  344                     DL_GETPSIZE(&lp->d_partitions[RAW_PART]));
  345         if (DL_GETPOFFSET(&lp->d_partitions[RAW_PART]) != 0)
  346                 printf("on-disk disklabel RAW_PART offset != 0 (%lld)\n",
  347                     DL_GETPOFFSET(&lp->d_partitions[RAW_PART]));
  348 #endif
  349         DL_SETDSIZE(lp, disksize);
  350         DL_SETPSIZE(&lp->d_partitions[RAW_PART], disksize);
  351         DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
  352 
  353         lp->d_checksum = 0;
  354         lp->d_checksum = dkcksum(lp);
  355         return (msg);
  356 }
  357 
  358 /*
  359  * If dos partition table requested, attempt to load it and
  360  * find disklabel inside a DOS partition. Return buffer
  361  * for use in signalling errors if requested.
  362  *
  363  * We would like to check if each MBR has a valid BOOT_MAGIC, but
  364  * we cannot because it doesn't always exist. So.. we assume the
  365  * MBR is valid.
  366  */
  367 char *
  368 readdoslabel(struct buf *bp, void (*strat)(struct buf *),
  369     struct disklabel *lp, int *partoffp, int spoofonly)
  370 {
  371         struct dos_partition dp[NDOSPART], *dp2;
  372         u_int32_t extoff = 0;
  373         daddr64_t part_blkno = DOSBBSECTOR;
  374         int dospartoff = 0, i, ourpart = -1;
  375         int wander = 1, n = 0, loop = 0;
  376 
  377         if (lp->d_secpercyl == 0)
  378                 return ("invalid label, d_secpercyl == 0");
  379         if (lp->d_secsize == 0)
  380                 return ("invalid label, d_secsize == 0");
  381 
  382         /* do DOS partitions in the process of getting disklabel? */
  383 
  384         /*
  385          * Read dos partition table, follow extended partitions.
  386          * Map the partitions to disklabel entries i-p
  387          */
  388         while (wander && n < 8 && loop < 8) {
  389                 loop++;
  390                 wander = 0;
  391                 if (part_blkno < extoff)
  392                         part_blkno = extoff;
  393 
  394                 /* read boot record */
  395                 bp->b_blkno = part_blkno;
  396                 bp->b_bcount = lp->d_secsize;
  397                 bp->b_flags = B_BUSY | B_READ;
  398                 (*strat)(bp);
  399                 if (biowait(bp)) {
  400 /*wrong*/               if (partoffp)
  401 /*wrong*/                       *partoffp = -1;
  402                         return ("dos partition I/O error");
  403                 }
  404 
  405                 bcopy(bp->b_data + DOSPARTOFF, dp, sizeof(dp));
  406 
  407                 if (ourpart == -1 && part_blkno == DOSBBSECTOR) {
  408                         /* Search for our MBR partition */
  409                         for (dp2=dp, i=0; i < NDOSPART && ourpart == -1;
  410                             i++, dp2++)
  411                                 if (letoh32(dp2->dp_size) &&
  412                                     dp2->dp_typ == DOSPTYP_OPENBSD)
  413                                         ourpart = i;
  414                         if (ourpart == -1)
  415                                 goto donot;
  416                         /*
  417                          * This is our MBR partition. need sector
  418                          * address for SCSI/IDE, cylinder for
  419                          * ESDI/ST506/RLL
  420                          */
  421                         dp2 = &dp[ourpart];
  422                         dospartoff = letoh32(dp2->dp_start) + part_blkno;
  423 
  424                         /* found our OpenBSD partition, finish up */
  425                         if (partoffp)
  426                                 goto notfat;
  427 
  428                         if (lp->d_ntracks == 0)
  429                                 lp->d_ntracks = dp2->dp_ehd + 1;
  430                         if (lp->d_nsectors == 0)
  431                                 lp->d_nsectors = DPSECT(dp2->dp_esect);
  432                         if (lp->d_secpercyl == 0)
  433                                 lp->d_secpercyl = lp->d_ntracks *
  434                                     lp->d_nsectors;
  435                 }
  436 donot:
  437                 /*
  438                  * In case the disklabel read below fails, we want to
  439                  * provide a fake label in i-p.
  440                  */
  441                 for (dp2=dp, i=0; i < NDOSPART && n < 8; i++, dp2++) {
  442                         struct partition *pp = &lp->d_partitions[8+n];
  443 
  444                         if (dp2->dp_typ == DOSPTYP_OPENBSD)
  445                                 continue;
  446                         if (letoh32(dp2->dp_size) > DL_GETDSIZE(lp))
  447                                 continue;
  448                         if (letoh32(dp2->dp_start) > DL_GETDSIZE(lp))
  449                                 continue;
  450                         if (letoh32(dp2->dp_size) == 0)
  451                                 continue;
  452                         if (letoh32(dp2->dp_start))
  453                                 DL_SETPOFFSET(pp,
  454                                     letoh32(dp2->dp_start) + part_blkno);
  455 
  456                         DL_SETPSIZE(pp, letoh32(dp2->dp_size));
  457 
  458                         switch (dp2->dp_typ) {
  459                         case DOSPTYP_UNUSED:
  460                                 pp->p_fstype = FS_UNUSED;
  461                                 n++;
  462                                 break;
  463 
  464                         case DOSPTYP_LINUX:
  465                                 pp->p_fstype = FS_EXT2FS;
  466                                 n++;
  467                                 break;
  468 
  469                         case DOSPTYP_FAT12:
  470                         case DOSPTYP_FAT16S:
  471                         case DOSPTYP_FAT16B:
  472                         case DOSPTYP_FAT16L:
  473                         case DOSPTYP_FAT32:
  474                         case DOSPTYP_FAT32L:
  475                                 pp->p_fstype = FS_MSDOS;
  476                                 n++;
  477                                 break;
  478                         case DOSPTYP_EXTEND:
  479                         case DOSPTYP_EXTENDL:
  480                                 part_blkno = letoh32(dp2->dp_start) + extoff;
  481                                 if (!extoff) {
  482                                         extoff = letoh32(dp2->dp_start);
  483                                         part_blkno = 0;
  484                                 }
  485                                 wander = 1;
  486                                 break;
  487                         default:
  488                                 pp->p_fstype = FS_OTHER;
  489                                 n++;
  490                                 break;
  491                         }
  492                 }
  493         }
  494         lp->d_npartitions = MAXPARTITIONS;
  495 
  496         if (n == 0 && part_blkno == DOSBBSECTOR) {
  497                 u_int16_t fattest;
  498 
  499                 /* Check for a short jump instruction. */
  500                 fattest = ((bp->b_data[0] << 8) & 0xff00) |
  501                     (bp->b_data[2] & 0xff);
  502                 if (fattest != 0xeb90 && fattest != 0xe900)
  503                         goto notfat;
  504 
  505                 /* Check for a valid bytes per sector value. */
  506                 fattest = ((bp->b_data[12] << 8) & 0xff00) |
  507                     (bp->b_data[11] & 0xff);
  508                 if (fattest < 512 || fattest > 4096 || (fattest % 512 != 0))
  509                         goto notfat;
  510 
  511                 /* Check the end of sector marker. */
  512                 fattest = ((bp->b_data[510] << 8) & 0xff00) |
  513                     (bp->b_data[511] & 0xff);
  514                 if (fattest != 0x55aa)
  515                         goto notfat;
  516 
  517                 /* Looks like a FAT filesystem. Spoof 'i'. */
  518                 DL_SETPSIZE(&lp->d_partitions['i' - 'a'],
  519                     DL_GETPSIZE(&lp->d_partitions[RAW_PART]));
  520                 DL_SETPOFFSET(&lp->d_partitions['i' - 'a'], 0);
  521                 lp->d_partitions['i' - 'a'].p_fstype = FS_MSDOS;
  522         }
  523 notfat:
  524 
  525         /* record the OpenBSD partition's placement for the caller */
  526         if (partoffp)
  527                 *partoffp = dospartoff;
  528 
  529         /* don't read the on-disk label if we are in spoofed-only mode */
  530         if (spoofonly)
  531                 return (NULL);
  532 
  533         bp->b_blkno = dospartoff + DOS_LABELSECTOR;
  534         bp->b_bcount = lp->d_secsize;
  535         bp->b_flags = B_BUSY | B_READ;
  536         (*strat)(bp);
  537         if (biowait(bp))
  538                 return ("disk label I/O error");
  539 
  540         /* sub-MBR disklabels are always at a LABELOFFSET of 0 */
  541         return checkdisklabel(bp->b_data, lp);
  542 }
  543 
  544 /*
  545  * Check new disk label for sensibility
  546  * before setting it.
  547  */
  548 int
  549 setdisklabel(struct disklabel *olp, struct disklabel *nlp, u_int openmask)
  550 {
  551         int i;
  552         struct partition *opp, *npp;
  553 
  554         /* sanity clause */
  555         if (nlp->d_secpercyl == 0 || nlp->d_secsize == 0 ||
  556             (nlp->d_secsize % DEV_BSIZE) != 0)
  557                 return (EINVAL);
  558 
  559         /* special case to allow disklabel to be invalidated */
  560         if (nlp->d_magic == 0xffffffff) {
  561                 *olp = *nlp;
  562                 return (0);
  563         }
  564 
  565         if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC ||
  566             dkcksum(nlp) != 0)
  567                 return (EINVAL);
  568 
  569         /* XXX missing check if other dos partitions will be overwritten */
  570 
  571         while (openmask != 0) {
  572                 i = ffs(openmask) - 1;
  573                 openmask &= ~(1 << i);
  574                 if (nlp->d_npartitions <= i)
  575                         return (EBUSY);
  576                 opp = &olp->d_partitions[i];
  577                 npp = &nlp->d_partitions[i];
  578                 if (DL_GETPOFFSET(npp) != DL_GETPOFFSET(opp) ||
  579                     DL_GETPSIZE(npp) < DL_GETPSIZE(opp))
  580                         return (EBUSY);
  581                 /*
  582                  * Copy internally-set partition information
  583                  * if new label doesn't include it.             XXX
  584                  */
  585                 if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) {
  586                         npp->p_fstype = opp->p_fstype;
  587                         npp->p_fragblock = opp->p_fragblock;
  588                         npp->p_cpg = opp->p_cpg;
  589                 }
  590         }
  591         nlp->d_checksum = 0;
  592         nlp->d_checksum = dkcksum(nlp);
  593         *olp = *nlp;
  594         return (0);
  595 }
  596 
  597 /*
  598  * Determine the size of the transfer, and make sure it is within the
  599  * boundaries of the partition. Adjust transfer if needed, and signal errors or
  600  * early completion.
  601  */
  602 int
  603 bounds_check_with_label(struct buf *bp, struct disklabel *lp, int wlabel)
  604 {
  605 #define blockpersec(count, lp) ((count) * (((lp)->d_secsize) / DEV_BSIZE))
  606         struct partition *p = &lp->d_partitions[DISKPART(bp->b_dev)];
  607         daddr64_t sz = howmany(bp->b_bcount, DEV_BSIZE);
  608 
  609         /* avoid division by zero */
  610         if (lp->d_secpercyl == 0)
  611                 goto bad;
  612 
  613         /* beyond partition? */
  614         if (bp->b_blkno + sz > blockpersec(DL_GETPSIZE(p), lp)) {
  615                 sz = blockpersec(DL_GETPSIZE(p), lp) - bp->b_blkno;
  616                 if (sz == 0) {
  617                         /* If exactly at end of disk, return EOF. */
  618                         bp->b_resid = bp->b_bcount;
  619                         return (-1);
  620                 }
  621                 if (sz < 0)
  622                         /* If past end of disk, return EINVAL. */
  623                         goto bad;
  624 
  625                 /* Otherwise, truncate request. */
  626                 bp->b_bcount = sz << DEV_BSHIFT;
  627         }
  628 
  629         /* calculate cylinder for disksort to order transfers with */
  630         bp->b_cylinder = (bp->b_blkno + blockpersec(DL_GETPOFFSET(p), lp)) /
  631             blockpersec(lp->d_secpercyl, lp);
  632         return (1);
  633 
  634 bad:
  635         bp->b_error = EINVAL;
  636         bp->b_flags |= B_ERROR;
  637         return (-1);
  638 }
  639 
  640 /*
  641  * Disk error is the preface to plaintive error messages
  642  * about failing disk transfers.  It prints messages of the form
  643 
  644 hp0g: hard error reading fsbn 12345 of 12344-12347 (hp0 bn %d cn %d tn %d sn %d)
  645 
  646  * if the offset of the error in the transfer and a disk label
  647  * are both available.  blkdone should be -1 if the position of the error
  648  * is unknown; the disklabel pointer may be null from drivers that have not
  649  * been converted to use them.  The message is printed with printf
  650  * if pri is LOG_PRINTF, otherwise it uses log at the specified priority.
  651  * The message should be completed (with at least a newline) with printf
  652  * or addlog, respectively.  There is no trailing space.
  653  */
  654 void
  655 diskerr(struct buf *bp, char *dname, char *what, int pri, int blkdone,
  656     struct disklabel *lp)
  657 {
  658         int unit = DISKUNIT(bp->b_dev), part = DISKPART(bp->b_dev);
  659         int (*pr)(const char *, ...);
  660         char partname = 'a' + part;
  661         daddr64_t sn;
  662 
  663         if (pri != LOG_PRINTF) {
  664                 static const char fmt[] = "";
  665                 log(pri, fmt);
  666                 pr = addlog;
  667         } else
  668                 pr = printf;
  669         (*pr)("%s%d%c: %s %sing fsbn ", dname, unit, partname, what,
  670             bp->b_flags & B_READ ? "read" : "writ");
  671         sn = bp->b_blkno;
  672         if (bp->b_bcount <= DEV_BSIZE)
  673                 (*pr)("%lld", sn);
  674         else {
  675                 if (blkdone >= 0) {
  676                         sn += blkdone;
  677                         (*pr)("%lld of ", sn);
  678                 }
  679                 (*pr)("%lld-%lld", bp->b_blkno,
  680                     bp->b_blkno + (bp->b_bcount - 1) / DEV_BSIZE);
  681         }
  682         if (lp && (blkdone >= 0 || bp->b_bcount <= lp->d_secsize)) {
  683                 sn += DL_GETPOFFSET(&lp->d_partitions[part]);
  684                 (*pr)(" (%s%d bn %lld; cn %lld", dname, unit, sn,
  685                     sn / lp->d_secpercyl);
  686                 sn %= lp->d_secpercyl;
  687                 (*pr)(" tn %lld sn %lld)", sn / lp->d_nsectors,
  688                     sn % lp->d_nsectors);
  689         }
  690 }
  691 
  692 /*
  693  * Initialize the disklist.  Called by main() before autoconfiguration.
  694  */
  695 void
  696 disk_init(void)
  697 {
  698 
  699         TAILQ_INIT(&disklist);
  700         disk_count = disk_change = 0;
  701 }
  702 
  703 int
  704 disk_construct(struct disk *diskp, char *lockname)
  705 {
  706         rw_init(&diskp->dk_lock, lockname);
  707         
  708         diskp->dk_flags |= DKF_CONSTRUCTED;
  709             
  710         return (0);
  711 }
  712 
  713 /*
  714  * Attach a disk.
  715  */
  716 void
  717 disk_attach(struct disk *diskp)
  718 {
  719 
  720         if (!ISSET(diskp->dk_flags, DKF_CONSTRUCTED))
  721                 disk_construct(diskp, diskp->dk_name);
  722 
  723         /*
  724          * Allocate and initialize the disklabel structures.  Note that
  725          * it's not safe to sleep here, since we're probably going to be
  726          * called during autoconfiguration.
  727          */
  728         diskp->dk_label = malloc(sizeof(struct disklabel), M_DEVBUF, M_NOWAIT);
  729         if (diskp->dk_label == NULL)
  730                 panic("disk_attach: can't allocate storage for disklabel");
  731 
  732         bzero(diskp->dk_label, sizeof(struct disklabel));
  733 
  734         /*
  735          * Set the attached timestamp.
  736          */
  737         microuptime(&diskp->dk_attachtime);
  738 
  739         /*
  740          * Link into the disklist.
  741          */
  742         TAILQ_INSERT_TAIL(&disklist, diskp, dk_link);
  743         ++disk_count;
  744         disk_change = 1;
  745 }
  746 
  747 /*
  748  * Detach a disk.
  749  */
  750 void
  751 disk_detach(struct disk *diskp)
  752 {
  753 
  754         /*
  755          * Free the space used by the disklabel structures.
  756          */
  757         free(diskp->dk_label, M_DEVBUF);
  758 
  759         /*
  760          * Remove from the disklist.
  761          */
  762         TAILQ_REMOVE(&disklist, diskp, dk_link);
  763         disk_change = 1;
  764         if (--disk_count < 0)
  765                 panic("disk_detach: disk_count < 0");
  766 }
  767 
  768 /*
  769  * Increment a disk's busy counter.  If the counter is going from
  770  * 0 to 1, set the timestamp.
  771  */
  772 void
  773 disk_busy(struct disk *diskp)
  774 {
  775 
  776         /*
  777          * XXX We'd like to use something as accurate as microtime(),
  778          * but that doesn't depend on the system TOD clock.
  779          */
  780         if (diskp->dk_busy++ == 0) {
  781                 microuptime(&diskp->dk_timestamp);
  782         }
  783 }
  784 
  785 /*
  786  * Decrement a disk's busy counter, increment the byte count, total busy
  787  * time, and reset the timestamp.
  788  */
  789 void
  790 disk_unbusy(struct disk *diskp, long bcount, int read)
  791 {
  792         struct timeval dv_time, diff_time;
  793 
  794         if (diskp->dk_busy-- == 0)
  795                 printf("disk_unbusy: %s: dk_busy < 0\n", diskp->dk_name);
  796 
  797         microuptime(&dv_time);
  798 
  799         timersub(&dv_time, &diskp->dk_timestamp, &diff_time);
  800         timeradd(&diskp->dk_time, &diff_time, &diskp->dk_time);
  801 
  802         diskp->dk_timestamp = dv_time;
  803         if (bcount > 0) {
  804                 if (read) {
  805                         diskp->dk_rbytes += bcount;
  806                         diskp->dk_rxfer++;
  807                 } else {
  808                         diskp->dk_wbytes += bcount;
  809                         diskp->dk_wxfer++;
  810                 }
  811         } else
  812                 diskp->dk_seek++;
  813 
  814         add_disk_randomness(bcount ^ diff_time.tv_usec);
  815 }
  816 
  817 int
  818 disk_lock(struct disk *dk)
  819 {
  820         int error;
  821 
  822         error = rw_enter(&dk->dk_lock, RW_WRITE|RW_INTR);
  823 
  824         return (error);
  825 }
  826 
  827 void
  828 disk_unlock(struct disk *dk)
  829 {
  830         rw_exit(&dk->dk_lock);
  831 }
  832 
  833 int
  834 dk_mountroot(void)
  835 {
  836         dev_t rawdev, rrootdev;
  837         int part = DISKPART(rootdev);
  838         int (*mountrootfn)(void);
  839         struct disklabel dl;
  840         int error;
  841 
  842         rrootdev = blktochr(rootdev);
  843         rawdev = MAKEDISKDEV(major(rrootdev), DISKUNIT(rootdev), RAW_PART);
  844 #ifdef DEBUG
  845         printf("rootdev=0x%x rrootdev=0x%x rawdev=0x%x\n", rootdev,
  846             rrootdev, rawdev);
  847 #endif
  848 
  849         /*
  850          * open device, ioctl for the disklabel, and close it.
  851          */
  852         error = (cdevsw[major(rrootdev)].d_open)(rawdev, FREAD,
  853             S_IFCHR, curproc);
  854         if (error)
  855                 panic("cannot open disk, 0x%x/0x%x, error %d",
  856                     rootdev, rrootdev, error);
  857         error = (cdevsw[major(rrootdev)].d_ioctl)(rawdev, DIOCGDINFO,
  858             (caddr_t)&dl, FREAD, curproc);
  859         if (error)
  860                 panic("cannot read disk label, 0x%x/0x%x, error %d",
  861                     rootdev, rrootdev, error);
  862         (void) (cdevsw[major(rrootdev)].d_close)(rawdev, FREAD,
  863             S_IFCHR, curproc);
  864 
  865         if (DL_GETPSIZE(&dl.d_partitions[part]) == 0)
  866                 panic("root filesystem has size 0");
  867         switch (dl.d_partitions[part].p_fstype) {
  868 #ifdef EXT2FS
  869         case FS_EXT2FS:
  870                 {
  871                 extern int ext2fs_mountroot(void);
  872                 mountrootfn = ext2fs_mountroot;
  873                 }
  874                 break;
  875 #endif
  876 #ifdef FFS
  877         case FS_BSDFFS:
  878                 {
  879                 extern int ffs_mountroot(void);
  880                 mountrootfn = ffs_mountroot;
  881                 }
  882                 break;
  883 #endif
  884 #ifdef CD9660
  885         case FS_ISO9660:
  886                 {
  887                 extern int cd9660_mountroot(void);
  888                 mountrootfn = cd9660_mountroot;
  889                 }
  890                 break;
  891 #endif
  892         default:
  893 #ifdef FFS
  894                 { 
  895                 extern int ffs_mountroot(void);
  896 
  897                 printf("filesystem type %d not known.. assuming ffs\n",
  898                     dl.d_partitions[part].p_fstype);
  899                 mountrootfn = ffs_mountroot;
  900                 }
  901 #else
  902                 panic("disk 0x%x/0x%x filesystem type %d not known", 
  903                     rootdev, rrootdev, dl.d_partitions[part].p_fstype);
  904 #endif
  905         }
  906         return (*mountrootfn)();
  907 }
  908 
  909 struct bufq *
  910 bufq_default_alloc(void)
  911 {
  912         struct bufq_default *bq;
  913 
  914         bq = malloc(sizeof(*bq), M_DEVBUF, M_NOWAIT);
  915         if (bq == NULL)
  916                 panic("bufq_default_alloc: no memory");
  917 
  918         memset(bq, 0, sizeof(*bq));
  919         bq->bufq.bufq_free = bufq_default_free;
  920         bq->bufq.bufq_add = bufq_default_add;
  921         bq->bufq.bufq_get = bufq_default_get;
  922 
  923         return ((struct bufq *)bq);
  924 }
  925 
  926 void
  927 bufq_default_free(struct bufq *bq)
  928 {
  929         free(bq, M_DEVBUF);
  930 }
  931 
  932 void
  933 bufq_default_add(struct bufq *bq, struct buf *bp)
  934 {
  935         struct bufq_default *bufq = (struct bufq_default *)bq;
  936         struct proc *p = bp->b_proc;
  937         struct buf *head;
  938 
  939         if (p == NULL || p->p_nice < NZERO)
  940                 head = &bufq->bufq_head[0];
  941         else if (p->p_nice == NZERO)
  942                 head = &bufq->bufq_head[1];
  943         else
  944                 head = &bufq->bufq_head[2];
  945 
  946         disksort(head, bp);
  947 }
  948 
  949 struct buf *
  950 bufq_default_get(struct bufq *bq)
  951 {
  952         struct bufq_default *bufq = (struct bufq_default *)bq;
  953         struct buf *bp, *head;
  954         int i;
  955 
  956         for (i = 0; i < 3; i++) {
  957                 head = &bufq->bufq_head[i];
  958                 if ((bp = head->b_actf))
  959                         break;
  960         }
  961         if (bp == NULL)
  962                 return (NULL);
  963         head->b_actf = bp->b_actf;
  964         return (bp);
  965 }
  966 
  967 #ifdef RAMDISK_HOOKS
  968 static struct device fakerdrootdev = { DV_DISK, {}, NULL, 0, "rd0", NULL };
  969 #endif
  970 
  971 struct device *
  972 getdisk(char *str, int len, int defpart, dev_t *devp)
  973 {
  974         struct device *dv;
  975 
  976         if ((dv = parsedisk(str, len, defpart, devp)) == NULL) {
  977                 printf("use one of: exit");
  978 #ifdef RAMDISK_HOOKS
  979                 printf(" %s[a-p]", fakerdrootdev.dv_xname);
  980 #endif
  981                 TAILQ_FOREACH(dv, &alldevs, dv_list) {
  982                         if (dv->dv_class == DV_DISK)
  983                                 printf(" %s[a-p]", dv->dv_xname);
  984 #if defined(NFSCLIENT)
  985                         if (dv->dv_class == DV_IFNET)
  986                                 printf(" %s", dv->dv_xname);
  987 #endif
  988                 }
  989                 printf("\n");
  990         }
  991         return (dv);
  992 }
  993 
  994 struct device *
  995 parsedisk(char *str, int len, int defpart, dev_t *devp)
  996 {
  997         struct device *dv;
  998         char c;
  999         int majdev, part;
 1000 
 1001         if (len == 0)
 1002                 return (NULL);
 1003         c = str[len-1];
 1004         if (c >= 'a' && (c - 'a') < MAXPARTITIONS) {
 1005                 part = c - 'a';
 1006                 len -= 1;
 1007         } else
 1008                 part = defpart;
 1009 
 1010 #ifdef RAMDISK_HOOKS
 1011         if (strcmp(str, fakerdrootdev.dv_xname) == 0) {
 1012                 dv = &fakerdrootdev;
 1013                 goto gotdisk;
 1014         }
 1015 #endif
 1016 
 1017         TAILQ_FOREACH(dv, &alldevs, dv_list) {
 1018                 if (dv->dv_class == DV_DISK &&
 1019                     strncmp(str, dv->dv_xname, len) == 0 &&
 1020                     dv->dv_xname[len] == '\0') {
 1021 #ifdef RAMDISK_HOOKS
 1022 gotdisk:
 1023 #endif
 1024                         majdev = findblkmajor(dv);
 1025                         if (majdev < 0)
 1026                                 panic("parsedisk");
 1027                         *devp = MAKEDISKDEV(majdev, dv->dv_unit, part);
 1028                         break;
 1029                 }
 1030 #if defined(NFSCLIENT)
 1031                 if (dv->dv_class == DV_IFNET &&
 1032                     strncmp(str, dv->dv_xname, len) == 0 &&
 1033                     dv->dv_xname[len] == '\0') {
 1034                         *devp = NODEV;
 1035                         break;
 1036                 }
 1037 #endif
 1038         }
 1039 
 1040         return (dv);
 1041 }
 1042 
 1043 void
 1044 setroot(struct device *bootdv, int part, int exitflags)
 1045 {
 1046         int majdev, unit, len, s;
 1047         struct swdevt *swp;
 1048         struct device *rootdv, *dv;
 1049         dev_t nrootdev, nswapdev = NODEV, temp = NODEV;
 1050         char buf[128];
 1051 #if defined(NFSCLIENT)
 1052         extern char *nfsbootdevname;
 1053 #endif
 1054 
 1055         if (boothowto & RB_DFLTROOT)
 1056                 return;
 1057 
 1058 #ifdef RAMDISK_HOOKS
 1059         bootdv = &fakerdrootdev;
 1060         mountroot = NULL;
 1061         part = 0;
 1062 #endif
 1063 
 1064         /*
 1065          * If `swap generic' and we couldn't determine boot device,
 1066          * ask the user.
 1067          */
 1068         if (mountroot == NULL && bootdv == NULL)
 1069                 boothowto |= RB_ASKNAME;
 1070         if (boothowto & RB_ASKNAME) {
 1071                 while (1) {
 1072                         printf("root device");
 1073                         if (bootdv != NULL) {
 1074                                 printf(" (default %s", bootdv->dv_xname);
 1075                                 if (bootdv->dv_class == DV_DISK)
 1076                                         printf("%c", 'a' + part);
 1077                                 printf(")");
 1078                         }
 1079                         printf(": ");
 1080                         s = splhigh();
 1081                         cnpollc(TRUE);
 1082                         len = getsn(buf, sizeof(buf));
 1083                         cnpollc(FALSE);
 1084                         splx(s);
 1085                         if (strcmp(buf, "exit") == 0)
 1086                                 boot(exitflags);
 1087                         if (len == 0 && bootdv != NULL) {
 1088                                 strlcpy(buf, bootdv->dv_xname, sizeof buf);
 1089                                 len = strlen(buf);
 1090                         }
 1091                         if (len > 0 && buf[len - 1] == '*') {
 1092                                 buf[--len] = '\0';
 1093                                 dv = getdisk(buf, len, part, &nrootdev);
 1094                                 if (dv != NULL) {
 1095                                         rootdv = dv;
 1096                                         nswapdev = nrootdev;
 1097                                         goto gotswap;
 1098                                 }
 1099                         }
 1100                         dv = getdisk(buf, len, part, &nrootdev);
 1101                         if (dv != NULL) {
 1102                                 rootdv = dv;
 1103                                 break;
 1104                         }
 1105                 }
 1106 
 1107                 if (rootdv->dv_class == DV_IFNET)
 1108                         goto gotswap;
 1109 
 1110                 /* try to build swap device out of new root device */
 1111                 while (1) {
 1112                         printf("swap device");
 1113                         if (rootdv != NULL)
 1114                                 printf(" (default %s%s)", rootdv->dv_xname,
 1115                                     rootdv->dv_class == DV_DISK ? "b" : "");
 1116                         printf(": ");
 1117                         s = splhigh();
 1118                         cnpollc(TRUE);
 1119                         len = getsn(buf, sizeof(buf));
 1120                         cnpollc(FALSE);
 1121                         splx(s);
 1122                         if (strcmp(buf, "exit") == 0)
 1123                                 boot(exitflags);
 1124                         if (len == 0 && rootdv != NULL) {
 1125                                 switch (rootdv->dv_class) {
 1126                                 case DV_IFNET:
 1127                                         nswapdev = NODEV;
 1128                                         break;
 1129                                 case DV_DISK:
 1130                                         nswapdev = MAKEDISKDEV(major(nrootdev),
 1131                                             DISKUNIT(nrootdev), 1);
 1132                                         if (nswapdev == nrootdev)
 1133                                                 continue;
 1134                                         break;
 1135                                 default:
 1136                                         break;
 1137                                 }
 1138                                 break;
 1139                         }
 1140                         dv = getdisk(buf, len, 1, &nswapdev);
 1141                         if (dv) {
 1142                                 if (dv->dv_class == DV_IFNET)
 1143                                         nswapdev = NODEV;
 1144                                 if (nswapdev == nrootdev)
 1145                                         continue;
 1146                                 break;
 1147                         }
 1148                 }
 1149 gotswap:
 1150                 rootdev = nrootdev;
 1151                 dumpdev = nswapdev;
 1152                 swdevt[0].sw_dev = nswapdev;
 1153                 swdevt[1].sw_dev = NODEV;
 1154 #if defined(NFSCLIENT)
 1155         } else if (mountroot == nfs_mountroot) {
 1156                 rootdv = bootdv;
 1157                 rootdev = dumpdev = swapdev = NODEV;
 1158 #endif
 1159         } else if (mountroot == NULL) {
 1160                 /* `swap generic': Use the device the ROM told us to use */
 1161                 rootdv = bootdv;
 1162                 majdev = findblkmajor(rootdv);
 1163                 if (majdev >= 0) {
 1164                         /*
 1165                          * Root and swap are on the disk.
 1166                          * Assume swap is on partition b.
 1167                          */
 1168                         rootdev = MAKEDISKDEV(majdev, rootdv->dv_unit, part);
 1169                         nswapdev = MAKEDISKDEV(majdev, rootdv->dv_unit, 1);
 1170                 } else {
 1171                         /*
 1172                          * Root and swap are on a net.
 1173                          */
 1174                         nswapdev = NODEV;
 1175                 }
 1176                 dumpdev = nswapdev;
 1177                 swdevt[0].sw_dev = nswapdev;
 1178                 /* swdevt[1].sw_dev = NODEV; */
 1179         } else {
 1180                 /* Completely pre-configured, but we want rootdv .. */
 1181                 majdev = major(rootdev);
 1182                 if (findblkname(majdev) == NULL)
 1183                         return;
 1184                 unit = DISKUNIT(rootdev);
 1185                 part = DISKPART(rootdev);
 1186                 snprintf(buf, sizeof buf, "%s%d%c",
 1187                     findblkname(majdev), unit, 'a' + part);
 1188                 rootdv = parsedisk(buf, strlen(buf), 0, &nrootdev);
 1189         }
 1190 
 1191         switch (rootdv->dv_class) {
 1192 #if defined(NFSCLIENT)
 1193         case DV_IFNET:
 1194                 mountroot = nfs_mountroot;
 1195                 nfsbootdevname = rootdv->dv_xname;
 1196                 return;
 1197 #endif
 1198         case DV_DISK:
 1199                 mountroot = dk_mountroot;
 1200                 part = DISKPART(rootdev);
 1201                 break;
 1202         default:
 1203                 printf("can't figure root, hope your kernel is right\n");
 1204                 return;
 1205         }
 1206 
 1207         printf("root on %s%c", rootdv->dv_xname, 'a' + part);
 1208 
 1209         /*
 1210          * Make the swap partition on the root drive the primary swap.
 1211          */
 1212         for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
 1213                 if (major(rootdev) == major(swp->sw_dev) &&
 1214                     DISKUNIT(rootdev) == DISKUNIT(swp->sw_dev)) {
 1215                         temp = swdevt[0].sw_dev;
 1216                         swdevt[0].sw_dev = swp->sw_dev;
 1217                         swp->sw_dev = temp;
 1218                         break;
 1219                 }
 1220         }
 1221         if (swp->sw_dev != NODEV) {
 1222                 /*
 1223                  * If dumpdev was the same as the old primary swap device,
 1224                  * move it to the new primary swap device.
 1225                  */
 1226                 if (temp == dumpdev)
 1227                         dumpdev = swdevt[0].sw_dev;
 1228         }
 1229         if (swdevt[0].sw_dev != NODEV)
 1230                 printf(" swap on %s%d%c", findblkname(major(swdevt[0].sw_dev)),
 1231                     DISKUNIT(swdevt[0].sw_dev),
 1232                     'a' + DISKPART(swdevt[0].sw_dev));
 1233         if (dumpdev != NODEV)
 1234                 printf(" dump on %s%d%c", findblkname(major(dumpdev)),
 1235                     DISKUNIT(dumpdev), 'a' + DISKPART(dumpdev));
 1236         printf("\n");
 1237 }
 1238 
 1239 extern struct nam2blk nam2blk[];
 1240 
 1241 int
 1242 findblkmajor(struct device *dv)
 1243 {
 1244         char *name = dv->dv_xname;
 1245         int i;
 1246 
 1247         for (i = 0; nam2blk[i].name; i++)
 1248                 if (!strncmp(name, nam2blk[i].name, strlen(nam2blk[i].name)))
 1249                         return (nam2blk[i].maj);
 1250         return (-1);
 1251 }
 1252 
 1253 char *
 1254 findblkname(int maj)
 1255 {
 1256         int i;
 1257 
 1258         for (i = 0; nam2blk[i].name; i++)
 1259                 if (nam2blk[i].maj == maj)
 1260                         return (nam2blk[i].name);
 1261         return (NULL);
 1262 }

/* [<][>][^][v][top][bottom][index][help] */