disksubr.c revision 1.4
1/*	$NetBSD: disksubr.c,v 1.4 1994/11/28 18:42:22 dean 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. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by the University of
18 *	California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 *	@(#)ufs_disksubr.c	7.16 (Berkeley) 5/4/91
36 */
37
38#include "param.h"
39#include "systm.h"
40#include "buf.h"
41#include "disklabel.h"
42#include "syslog.h"
43
44#define	b_cylin	b_resid
45
46#ifdef COMPAT_ULTRIX
47#include "../../stand/dec_boot.h"
48#endif
49
50
51/*
52 * Attempt to read a disk label from a device
53 * using the indicated stategy routine.
54 * The label must be partly set up before this:
55 * secpercyl and anything required in the strategy routine
56 * (e.g., sector size) must be filled in before calling us.
57 * Returns null on success and an error string on failure.
58 */
59char *
60readdisklabel(dev, strat, lp, osdep)
61	dev_t dev;
62	void (*strat)();
63	register struct disklabel *lp;
64	struct cpu_disklabel *osdep;
65{
66	register struct buf *bp;
67	struct disklabel *dlp;
68#ifdef COMPAT_ULTRIX
69	Dec_DiskLabel *Dec_dlp;
70#endif
71	char *msg = NULL;
72
73	if (lp->d_secperunit == 0)
74		lp->d_secperunit = 0x1fffffff;
75	lp->d_npartitions = 1;
76	if (lp->d_partitions[0].p_size == 0)
77		lp->d_partitions[0].p_size = 0x1fffffff;
78	lp->d_partitions[0].p_offset = 0;
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_BUSY | B_READ;
85	bp->b_cylin = LABELSECTOR / lp->d_secpercyl;
86	(*strat)(bp);
87	if (biowait(bp)) {
88		msg = "I/O error";
89	} else for (dlp = (struct disklabel *)bp->b_un.b_addr;
90	    dlp <= (struct disklabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*dlp));
91	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
92		if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
93			if (msg == NULL)
94				msg = "no disk label";
95		} else if (dlp->d_npartitions > MAXPARTITIONS ||
96			   dkcksum(dlp) != 0)
97			msg = "disk label corrupted";
98		else {
99			*lp = *dlp;
100			msg = NULL;
101			break;
102		}
103	}
104#ifdef COMPAT_ULTRIX	  /* look for ultrix disklabel
105			     gallatin@isds.duke.edu , 8/21/94 */
106	if(msg){
107	     msg = NULL;
108	     bp->b_dev = dev;
109	     bp->b_blkno = DEC_LABEL_SECTOR;
110	     bp->b_bcount = lp->d_secsize;
111	     bp->b_flags = B_BUSY | B_READ;
112	     bp->b_cylin = DEC_LABEL_SECTOR / lp->d_secpercyl;
113	     (*strat)(bp);
114	     if (biowait(bp)) {
115                msg = "I/O error";
116	     }  else for (Dec_dlp = (Dec_DiskLabel *)bp->b_un.b_addr;
117			  Dec_dlp <= (Dec_DiskLabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*Dec_dlp));
118			  Dec_dlp = (Dec_DiskLabel *)((char *)Dec_dlp + sizeof(long))) {
119	       if (Dec_dlp->magic != DEC_LABEL_MAGIC) {
120		 printf("label: %x\n",Dec_dlp->magic);
121		 if (msg == NULL)
122		   msg = "no disk label";
123	       }
124	       else {
125		 int i;
126		 lp->d_magic=DEC_LABEL_MAGIC;
127		 for(i=0;i<((MAXPARTITIONS<DEC_NUM_DISK_PARTS) ?
128			    MAXPARTITIONS : DEC_NUM_DISK_PARTS); i++) {
129		   lp->d_partitions[i].p_size = Dec_dlp->map[i].numBlocks;
130		   lp->d_partitions[i].p_offset = Dec_dlp->map[i].startBlock;
131		   lp->d_partitions[i].p_fsize = 1024;
132		   if(i==1)
133		     lp->d_partitions[i].p_fstype=FS_SWAP;
134		   else
135		     lp->d_partitions[i].p_fstype=FS_BSDFFS;
136		 }
137		 msg = "using ULTRIX partition information";
138		 break;
139	       }
140	     }
141	}
142#endif /* COMPAT_ULTRIX */
143	bp->b_flags = B_INVAL | B_AGE;
144	brelse(bp);
145	return (msg);
146}
147
148/*
149 * Check new disk label for sensibility
150 * before setting it.
151 */
152setdisklabel(olp, nlp, openmask, osdep)
153	register struct disklabel *olp, *nlp;
154	u_long openmask;
155	struct cpu_disklabel *osdep;
156{
157	register i;
158	register struct partition *opp, *npp;
159
160	if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC ||
161	    dkcksum(nlp) != 0)
162		return (EINVAL);
163	while ((i = ffs((long)openmask)) != 0) {
164		i--;
165		openmask &= ~(1 << i);
166		if (nlp->d_npartitions <= i)
167			return (EBUSY);
168		opp = &olp->d_partitions[i];
169		npp = &nlp->d_partitions[i];
170		if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size)
171			return (EBUSY);
172		/*
173		 * Copy internally-set partition information
174		 * if new label doesn't include it.		XXX
175		 */
176		if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) {
177			npp->p_fstype = opp->p_fstype;
178			npp->p_fsize = opp->p_fsize;
179			npp->p_frag = opp->p_frag;
180			npp->p_cpg = opp->p_cpg;
181		}
182	}
183 	nlp->d_checksum = 0;
184 	nlp->d_checksum = dkcksum(nlp);
185	*olp = *nlp;
186	return (0);
187}
188
189/* encoding of disk minor numbers, should be elsewhere... */
190#define dkunit(dev)		(minor(dev) >> 3)
191#define dkpart(dev)		(minor(dev) & 07)
192#define dkminor(unit, part)	(((unit) << 3) | (part))
193
194/*
195 * Write disk label back to device after modification.
196 */
197writedisklabel(dev, strat, lp, osdep)
198	dev_t dev;
199	void (*strat)();
200	register struct disklabel *lp;
201	struct cpu_disklabel *osdep;
202{
203	struct buf *bp;
204	struct disklabel *dlp;
205	int labelpart;
206	int error = 0;
207
208	labelpart = dkpart(dev);
209	if (lp->d_partitions[labelpart].p_offset != 0) {
210		if (lp->d_partitions[0].p_offset != 0)
211			return (EXDEV);			/* not quite right */
212		labelpart = 0;
213	}
214	bp = geteblk((int)lp->d_secsize);
215	bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), labelpart));
216	bp->b_blkno = LABELSECTOR;
217	bp->b_bcount = lp->d_secsize;
218	bp->b_flags = B_READ;
219	(*strat)(bp);
220	if (error = biowait(bp))
221		goto done;
222	for (dlp = (struct disklabel *)bp->b_un.b_addr;
223	    dlp <= (struct disklabel *)
224	      (bp->b_un.b_addr + lp->d_secsize - sizeof(*dlp));
225	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
226		if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
227		    dkcksum(dlp) == 0) {
228			*dlp = *lp;
229			bp->b_flags = B_WRITE;
230			(*strat)(bp);
231			error = biowait(bp);
232			goto done;
233		}
234	}
235	error = ESRCH;
236done:
237	brelse(bp);
238	return (error);
239}
240