Home | History | Annotate | Line # | Download | only in newsmips
      1 /*	$NetBSD: disksubr.c,v 1.29 2019/04/03 22:10:51 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. Neither the name of the University nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this software
     17  *    without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  *
     31  *	@(#)ufs_disksubr.c	7.16 (Berkeley) 5/4/91
     32  */
     33 
     34 #include <sys/cdefs.h>
     35 __KERNEL_RCSID(0, "$NetBSD: disksubr.c,v 1.29 2019/04/03 22:10:51 christos Exp $");
     36 
     37 #include <sys/param.h>
     38 #include <sys/systm.h>
     39 #include <sys/buf.h>
     40 #include <sys/device.h>
     41 #include <sys/disk.h>
     42 #include <sys/disklabel.h>
     43 #include <sys/kauth.h>
     44 #include <sys/proc.h>
     45 
     46 /*
     47  * Attempt to read a disk label from a device
     48  * using the indicated strategy routine.
     49  * The label must be partly set up before this:
     50  * secpercyl and anything required in the strategy routine
     51  * (e.g., sector size) must be filled in before calling us.
     52  * Returns null on success and an error string on failure.
     53  */
     54 const char *
     55 readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp,
     56     struct cpu_disklabel *osdep)
     57 {
     58 	struct buf *bp;
     59 	struct disklabel *dlp;
     60 	const char *msg = NULL;
     61 	int i;
     62 
     63 	if (lp->d_secsize == 0)
     64 		lp->d_secsize = DEV_BSIZE;
     65 	if (lp->d_secperunit == 0)
     66 		lp->d_secperunit = 0x1fffffff;
     67 	if (lp->d_npartitions < RAW_PART + 1)
     68 		lp->d_npartitions = RAW_PART + 1;
     69 	for (i = 0; i < RAW_PART; i++) {
     70 		lp->d_partitions[i].p_size = 0;
     71 		lp->d_partitions[i].p_offset = 0;
     72 	}
     73 	if (lp->d_partitions[RAW_PART].p_size == 0)
     74 		lp->d_partitions[RAW_PART].p_size = lp->d_secperunit;
     75 	lp->d_partitions[RAW_PART].p_offset = 0;
     76 
     77 	lp->d_partitions[0].p_size = lp->d_partitions[RAW_PART].p_size;
     78 	lp->d_partitions[0].p_fstype = FS_BSDFFS;
     79 
     80 	bp = geteblk((int)lp->d_secsize);
     81 	bp->b_dev = dev;
     82 	bp->b_blkno = LABELSECTOR;
     83 	bp->b_bcount = lp->d_secsize;
     84 	bp->b_flags |= B_READ;
     85 	bp->b_cylinder = LABELSECTOR / lp->d_secpercyl;
     86 	(*strat)(bp);
     87 	if (biowait(bp))
     88 		msg = "I/O error";
     89 	else for (dlp = (struct disklabel *)bp->b_data;
     90 	    dlp <= (struct disklabel *)((char *)bp->b_data + DEV_BSIZE -
     91 		sizeof(*dlp));
     92 	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
     93 		if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
     94 			if (msg == NULL)
     95 				msg = "no disk label";
     96 		} else if (dlp->d_npartitions > MAXPARTITIONS ||
     97 			   dkcksum(dlp) != 0)
     98 			msg = "disk label corrupted";
     99 		else {
    100 			*lp = *dlp;
    101 			msg = NULL;
    102 			break;
    103 		}
    104 	}
    105 	brelse(bp, 0);
    106 	return msg;
    107 }
    108 
    109 /*
    110  * Write disk label back to device after modification.
    111  */
    112 int
    113 writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp,
    114     struct cpu_disklabel *osdep)
    115 {
    116 	struct buf *bp;
    117 	struct disklabel *dlp;
    118 	int labelpart;
    119 	int error = 0;
    120 
    121 	labelpart = DISKPART(dev);
    122 	if (lp->d_partitions[labelpart].p_offset != 0) {
    123 		if (lp->d_partitions[0].p_offset != 0)
    124 			return EXDEV;			/* not quite right */
    125 		labelpart = 0;
    126 	}
    127 	bp = geteblk((int)lp->d_secsize);
    128 	bp->b_dev = MAKEDISKDEV(major(dev), DISKUNIT(dev), labelpart);
    129 	bp->b_blkno = LABELSECTOR;
    130 	bp->b_bcount = lp->d_secsize;
    131 	bp->b_flags |= B_READ;
    132 	(*strat)(bp);
    133 	if ((error = biowait(bp)) != 0)
    134 		goto done;
    135 	for (dlp = (struct disklabel *)bp->b_data;
    136 	    dlp <= (struct disklabel *)
    137 	      ((char *)bp->b_data + lp->d_secsize - sizeof(*dlp));
    138 	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
    139 		if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
    140 		    dkcksum(dlp) == 0) {
    141 			*dlp = *lp;
    142 			bp->b_flags &= ~(B_READ);
    143 			bp->b_oflags &= ~(BO_DONE);
    144 			bp->b_flags |= B_WRITE;
    145 			(*strat)(bp);
    146 			error = biowait(bp);
    147 			goto done;
    148 		}
    149 	}
    150 	error = ESRCH;
    151  done:
    152 	brelse(bp, 0);
    153 	return error;
    154 }
    155