# 2.11BSD#431 - /usr/src/sys/sys/ufs_disksubr.c

##### Functions

    dkcksum           X
    dkoverlapchk      X
    ioctldisklabel    X
    partition_check   X
    readdisklabel     X
    setdisklabel      X
    writedisklabel    X

##### Macros

    RAWPART           X

       1: /*
       2:  * Copyright (c) 1982, 1986, 1988, 1993
       3:  *	The Regents of the University of California.  All rights reserved.
       4:  * (c) UNIX System Laboratories, Inc.
       5:  * All or some portions of this file are derived from material licensed
       6:  * to the University of California by American Telephone and Telegraph
       7:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
       8:  * the permission of UNIX System Laboratories, Inc.
       9:  *
      10:  * Redistribution and use in source and binary forms, with or without
      11:  * modification, are permitted provided that the following conditions
      12:  * are met:
      13:  * 1. Redistributions of source code must retain the above copyright
      14:  *    notice, this list of conditions and the following disclaimer.
      15:  * 2. Redistributions in binary form must reproduce the above copyright
      16:  *    notice, this list of conditions and the following disclaimer in the
      17:  *    documentation and/or other materials provided with the distribution.
      18:  * 3. All advertising materials mentioning features or use of this software
      19:  *    must display the following acknowledgement:
      20:  *	This product includes software developed by the University of
      21:  *	California, Berkeley and its contributors.
      22:  * 4. 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.5 (2.11BSD GTE) 1998/4/3
      39:  */
      40:
      41: #include <errno.h>
      42: #include <syslog.h>
      43: #include <sys/param.h>
      44: #include <sys/user.h>
      45: #include <sys/systm.h>
      46: #include <machine/seg.h>
      47: #include <sys/buf.h>
      48: #include <sys/file.h>
      49: #include <sys/ioctl.h>
      50: #include <sys/disklabel.h>
      51: #include <sys/disk.h>
      52:
      53: /*
      54:  * Attempt to read a disk label from a device using the indicated stategy
      55:  * routine.  The label must be partly set up before this: secpercyl and
      56:  * anything required in the strategy routine (e.g., sector size) must be
      57:  * filled in before calling us.  Returns NULL on success and an error
      58:  * string on failure.
      59:  */
      60: char *
      61: readdisklabel(dev, strat, lp)
      62:     dev_t dev;
      63:     int (*strat)();
      64:     register struct disklabel *lp;
      65:     {
      66:     register struct buf *bp;
      67:     struct disklabel *dlp;
      68:     char *msg = NULL;
      69:
      70:     if  (lp->d_secperunit == 0)
      71:         lp->d_secperunit = 0x1fffffffL;
      72:     lp->d_npartitions = 1;
      73:     if  (lp->d_partitions[0].p_size == 0)
      74:         lp->d_partitions[0].p_size = 0x1fffffffL;
      75:     lp->d_partitions[0].p_offset = 0;
      76:
      77:     bp = geteblk();
      78:     bp->b_dev = dev;
      79:     bp->b_blkno = LABELSECTOR;
      80:     bp->b_bcount = lp->d_secsize;   /* Probably should wire this to 512 */
      81:     bp->b_flags = B_BUSY | B_READ;
      82:     bp->b_cylin = LABELSECTOR / lp->d_secpercyl;
      83:     (*strat)(bp);
      84:     biowait(bp);
      85:     if  (u.u_error)
      86:         msg = "I/O error";
      87:     else
      88:         {
      89:         dlp = (struct disklabel *)mapin(bp);
      90:         if  (dlp->d_magic != DISKMAGIC ||
      91:                 dlp->d_magic2 != DISKMAGIC)
      92:             {
      93:             if  (msg == NULL)
      94:                 msg = "no disk label";
      95:             }
      96:         else if (dlp->d_npartitions > MAXPARTITIONS || dkcksum(dlp))
      97:             msg = "disk label corrupted";
      98:         else
      99:             bcopy(dlp, lp, sizeof (struct disklabel));
     100:         mapout(bp);
     101:         }
     102:     bp->b_flags = B_INVAL | B_AGE;
     103:     brelse(bp);
     104:     return(msg);
     105:     }
     106:
     107: /*
     108:  * Check new disk label for sensibility before setting it.  'olp' must point
     109:  * to a kernel resident (or mapped in) label.  'nlp' points to the new label
     110:  * usually present on the stack (having been passed in via ioctl from an
     111:  * application).
     112:  */
     113: int
     114: setdisklabel(olp, nlp, openmask)
     115:     struct disklabel *olp;
     116:     register struct disklabel *nlp;
     117:     u_short openmask;
     118: {
     119:     int i;
     120:     register struct partition *opp, *npp;
     121:
     122:     if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC ||
     123:         dkcksum(nlp) != 0)
     124:         return (EINVAL);
     125:     while ((i = ffs((long)openmask)) != 0) {
     126:         i--;
     127:         openmask &= ~(1 << i);
     128:         if (nlp->d_npartitions <= i)
     129:             return (EBUSY);
     130:         opp = &olp->d_partitions[i];
     131:         npp = &nlp->d_partitions[i];
     132:         if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size)
     133:             return (EBUSY);
     134:         /*
     135: 		 * Copy internally-set partition information
     136: 		 * if new label doesn't include it.		XXX
     137: 		 */
     138:         if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) {
     139:             npp->p_fstype = opp->p_fstype;
     140:             npp->p_fsize = opp->p_fsize;
     141:             npp->p_frag = opp->p_frag;
     142:         }
     143:     }
     144:     nlp->d_checksum = 0;
     145:     nlp->d_checksum = dkcksum(nlp);
     146:     bcopy(nlp, olp, sizeof (struct disklabel));
     147:     return (0);
     148: }
     149:
     150: /*
     151:  * Write disk label back to device after modification.
     152:  */
     153: int
     154: writedisklabel(dev, strat, lp)
     155:     dev_t dev;
     156:     int (*strat)();
     157:     register struct disklabel *lp;
     158: {
     159:     struct buf *bp;
     160:     struct disklabel *dlp;
     161:     int labelpart;
     162:     int error = 0;
     163:
     164:     labelpart = dkpart(dev);
     165:     if (lp->d_partitions[labelpart].p_offset != 0) {
     166:         if (lp->d_partitions[0].p_offset != 0)
     167:             return (EXDEV);         /* not quite right */
     168:         labelpart = 0;
     169:     }
     170:     bp = geteblk();
     171:     bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), labelpart));
     172:     bp->b_blkno = LABELSECTOR;
     173:     bp->b_bcount = lp->d_secsize;   /* probably should wire to 512 */
     174:     bp->b_flags = B_READ;
     175:     (*strat)(bp);
     176:     biowait(bp);
     177:     if (u.u_error)
     178:         goto done;
     179:     dlp = (struct disklabel *)mapin(bp);
     180:     if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
     181:         dkcksum(dlp) == 0) {
     182:         bcopy(lp, dlp, sizeof (struct disklabel));
     183:         mapout(bp);
     184:         bp->b_flags = B_WRITE;
     185:         (*strat)(bp);
     186:         biowait(bp);
     187:         error = u.u_error;
     188:     } else {
     189:         error = ESRCH;
     190:         mapout(bp);
     191:     }
     192: done:
     193:     brelse(bp);
     194:     return(error);
     195: }
     196:
     197: /*
     198:  * Compute checksum for disk label.
     199:  */
     200: dkcksum(lp)
     201:     struct disklabel *lp;
     202: {
     203:     register u_short *start, *end;
     204:     register u_short sum = 0;
     205:
     206:     start = (u_short *)lp;
     207:     end = (u_short *)&lp->d_partitions[lp->d_npartitions];
     208:     while (start < end)
     209:         sum ^= *start++;
     210:     return (sum);
     211: }
     212:
     213: /*
     214:  * This is new for 2.11BSD.  It is a common routine that checks for
     215:  * opening a partition that overlaps other currently open partitions.
     216:  *
     217:  * NOTE: if 'c' is not the entire drive (as is the case with the old,
     218:  * nonstandard, haphazard and overlapping partition tables) the warning
     219:  * message will be erroneously issued in some valid situations.
     220: */
     221:
     222: #define RAWPART 2   /* 'c' */  /* XXX */
     223:
     224: dkoverlapchk(openmask, dev, label, name)
     225:     int openmask;
     226:     dev_t   dev;
     227:     memaddr label;
     228:     char    *name;
     229:     {
     230:     int unit = dkunit(dev);
     231:     int part = dkpart(dev);
     232:     int partmask = 1 << part;
     233:     int i;
     234:     daddr_t start, end;
     235:     register struct disklabel *lp = (struct disklabel *)SEG5;
     236:     register struct partition *pp;
     237:
     238:     if  ((openmask & partmask) == 0 && part != RAWPART)
     239:         {
     240:         mapseg5(label, LABELDESC);
     241:         pp = &lp->d_partitions[part];
     242:         start = pp->p_offset;
     243:         end = pp->p_offset + pp->p_size;
     244:         i = 0;
     245:         for (pp = lp->d_partitions; i < lp->d_npartitions; pp++,i++)
     246:             {
     247:             if  (pp->p_offset + pp->p_size <= start ||
     248:                  pp->p_offset >= end || i == RAWPART)
     249:                 continue;
     250:             if  (openmask & (1 << i))
     251:                 log(LOG_WARNING,
     252:                     "%s%d%c: overlaps open part (%c)\n",
     253:                     name, unit, part + 'a', i + 'a');
     254:             }
     255:         normalseg5();
     256:         }
     257:     return(0);
     258:     }
     259:
     260: /*
     261:  * It was noticed that the ioctl processing of disklabels was the same
     262:  * for every disk driver.  Disk drivers should call this routine after
     263:  * handling ioctls (if any) particular to themselves.
     264: */
     265:
     266: ioctldisklabel(dev, cmd, data, flag, disk, strat)
     267:     dev_t   dev;
     268:     int cmd;
     269:     register caddr_t    data;
     270:     int flag;
     271:     register struct dkdevice *disk;
     272:     int (*strat)();
     273:     {
     274:     struct  disklabel label;
     275:     register struct disklabel *lp = &label;
     276:     int error;
     277:     int flags;
     278:
     279: /*
     280:  * Copy in mapped out label to the local copy on the stack.  We're in the
     281:  * high kernel at this point so saving the mapping is not necessary.
     282: */
     283:     mapseg5(disk->dk_label, LABELDESC);
     284:     bcopy((struct disklabel *)SEG5, lp, sizeof (*lp));
     285:     normalseg5();
     286:
     287:     switch  (cmd)
     288:         {
     289:         case    DIOCGDINFO:
     290:             bcopy(lp, (struct disklabel *)data, sizeof (*lp));
     291:             return(0);
     292: /*
     293:  * Used internally by the kernel in init_main to verify that 'swapdev'
     294:  * is indeed a FS_SWAP partition.
     295:  *
     296:  * NOTE: the label address is the external click address!
     297: */
     298:         case    DIOCGPART:
     299:             ((struct partinfo *)data)->disklab =
     300:                     (struct disklabel *)disk->dk_label;
     301:             ((struct partinfo *)data)->part =
     302:                         &disk->dk_parts[dkpart(dev)];
     303:             return(0);
     304:         case    DIOCWLABEL:
     305:             if  ((flag & FWRITE) == 0)
     306:                 return(EBADF);
     307:             if  (*(int *)data)
     308:                 disk->dk_flags |= DKF_WLABEL;
     309:             else
     310:                 disk->dk_flags &= ~DKF_WLABEL;
     311:             return(0);
     312:         case    DIOCSDINFO:
     313:             if  ((flag & FWRITE) == 0)
     314:                 return(EBADF);
     315:             error = setdisklabel(lp, (struct disklabel *)data,
     316:                     disk->dk_flags & DKF_WLABEL ? 0
     317:                     : disk->dk_openmask);
     318: /*
     319:  * If no error was encountered setting the disklabel then we must copy
     320:  * out the new label from the local copy to the mapped out label.   Also
     321:  * update the partition tables (which are resident in the kernel).
     322: */
     323:             if  (error == 0)
     324:                 {
     325:                 mapseg5(disk->dk_label, LABELDESC);
     326:                 bcopy(lp,(struct disklabel *)SEG5,sizeof (*lp));
     327:                 normalseg5();
     328:                 bcopy(&lp->d_partitions, &disk->dk_parts,
     329:                     sizeof (lp->d_partitions));
     330:                 }
     331:             return(error);
     332:         case    DIOCWDINFO:
     333:             if  ((flag & FWRITE) == 0)
     334:                 return(EBADF);
     335:             error = setdisklabel(lp, (struct disklabel *)data,
     336:                     disk->dk_flags & DKF_WLABEL ? 0
     337:                     : disk->dk_openmask);
     338:             if  (error)
     339:                 return(error);
     340: /*
     341:  * Copy to external label.  Ah - need to also update the kernel resident
     342:  * partition tables!
     343: */
     344:             mapseg5(disk->dk_label, LABELDESC);
     345:             bcopy(lp,(struct disklabel *)SEG5,sizeof (*lp));
     346:             normalseg5();
     347:             bcopy(&lp->d_partitions, &disk->dk_parts,
     348:                 sizeof (lp->d_partitions));
     349:
     350: /*
     351:  * We use the 'a' partition to write the label.  This probably shouldn't
     352:  * be wired in here but it's not worth creating another macro for.  Is it?
     353:  * The flags are faked to write enable the label area and that the drive is
     354:  * alive - it better be at this point or there is a problem in the open routine.
     355: */
     356:             flags = disk->dk_flags;
     357:             disk->dk_flags |= (DKF_ALIVE | DKF_WLABEL);
     358:             error = writedisklabel(dev & ~7, strat, lp);
     359:             disk->dk_flags = flags;
     360:             return(error);
     361:         }
     362:     return(EINVAL);
     363:     }
     364:
     365:
     366: /*
     367:  * This was extracted from the MSCP driver so it could be shared between
     368:  * all disk drivers which implement disk labels.
     369: */
     370:
     371: partition_check(bp, dk)
     372:     struct  buf *bp;
     373:     struct  dkdevice *dk;
     374:     {
     375:     struct  partition *pi;
     376:     daddr_t sz;
     377:
     378:     pi = &dk->dk_parts[dkpart(bp->b_dev)];
     379:
     380:     /* Valid block in device partition */
     381:     sz = (bp->b_bcount + 511) >> 9;
     382:     if  (bp->b_blkno < 0 || bp->b_blkno + sz > pi->p_size)
     383:         {
     384:         sz = pi->p_size - bp->b_blkno;
     385:         /* if exactly at end of disk, return an EOF */
     386:         if  (sz == 0)
     387:             {
     388:             bp->b_resid = bp->b_bcount;
     389:             goto done;
     390:             }
     391:         /* or truncate if part of it fits */
     392:         if  (sz < 0)
     393:             {
     394:             bp->b_error = EINVAL;
     395:             goto bad;
     396:             }
     397:         bp->b_bcount = dbtob(sz);   /* compute byte count */
     398:         }
     399: /*
     400:  * Check for write to write-protected label area.  This does not include
     401:  * sector 0 which is the boot block.
     402: */
     403:     if  (bp->b_blkno + pi->p_offset <= LABELSECTOR &&
     404:          bp->b_blkno + pi->p_offset + sz > LABELSECTOR &&
     405:          !(bp->b_flags & B_READ) && !(dk->dk_flags & DKF_WLABEL))
     406:         {
     407:         bp->b_error = EROFS;
     408:         goto bad;
     409:         }
     410:     return(1);      /* success */
     411: bad:
     412:     return(-1);
     413: done:
     414:     return(0);
     415:     }

#### Defined functions

dkcksum defined in line 200; used 4 times

- in line 96, 123, 145, 181

dkoverlapchk defined in line 224; used 4 times

- in /usr/src/sys/pdpuba/hk.c line 198
- in /usr/src/sys/pdpuba/ra.c line 474
- in /usr/src/sys/pdpuba/rl.c line 197
- in /usr/src/sys/pdpuba/xp.c line 258

ioctldisklabel defined in line 266; used 3 times

- in /usr/src/sys/pdpuba/ra.c line 1213
- in /usr/src/sys/pdpuba/rl.c line 593
- in /usr/src/sys/pdpuba/xp.c line 942

partition_check defined in line 371; used 4 times

- in /usr/src/sys/pdpuba/hk.c line 341
- in /usr/src/sys/pdpuba/ra.c line 652
- in /usr/src/sys/pdpuba/rl.c line 335
- in /usr/src/sys/pdpuba/xp.c line 402

readdisklabel defined in line 60; used 5 times

- in /usr/src/sys/h/disk.h line 114
- in /usr/src/sys/pdpuba/hk.c line 313
- in /usr/src/sys/pdpuba/ra.c line 581
- in /usr/src/sys/pdpuba/rl.c line 307
- in /usr/src/sys/pdpuba/xp.c line 366

setdisklabel defined in line 113; used 3 times

- in line 315, 335
- in /usr/src/sys/h/disk.h line 115

writedisklabel defined in line 153; used 2 times

- in line 358
- in /usr/src/sys/h/disk.h line 116

#### Defined macros

RAWPART defined in line 222; used 2 times

- in line 238, 248

Last modified: 1998-04-04 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1105 |