Fri Apr 17 09:42:27 2020 UTC ()
align buffers used for I/O to DEV_BSIZE so it's executed more optimally
when run for xbd(4) raw (character) device


(jdolecek)
diff -r1.72 -r1.73 src/sbin/fsck_ffs/inode.c
diff -r1.102 -r1.103 src/sbin/fsck_ffs/setup.c
diff -r1.65 -r1.66 src/sbin/fsck_ffs/utilities.c

cvs diff -r1.72 -r1.73 src/sbin/fsck_ffs/inode.c (switch to unified diff)

--- src/sbin/fsck_ffs/inode.c 2017/02/08 16:11:40 1.72
+++ src/sbin/fsck_ffs/inode.c 2020/04/17 09:42:27 1.73
@@ -1,1051 +1,1051 @@ @@ -1,1051 +1,1051 @@
1/* $NetBSD: inode.c,v 1.72 2017/02/08 16:11:40 rin Exp $ */ 1/* $NetBSD: inode.c,v 1.73 2020/04/17 09:42:27 jdolecek Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1980, 1986, 1993 4 * Copyright (c) 1980, 1986, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors 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 16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission. 17 * without specific prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 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 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33#ifndef lint 33#ifndef lint
34#if 0 34#if 0
35static char sccsid[] = "@(#)inode.c 8.8 (Berkeley) 4/28/95"; 35static char sccsid[] = "@(#)inode.c 8.8 (Berkeley) 4/28/95";
36#else 36#else
37__RCSID("$NetBSD: inode.c,v 1.72 2017/02/08 16:11:40 rin Exp $"); 37__RCSID("$NetBSD: inode.c,v 1.73 2020/04/17 09:42:27 jdolecek Exp $");
38#endif 38#endif
39#endif /* not lint */ 39#endif /* not lint */
40 40
41#include <sys/param.h> 41#include <sys/param.h>
42#include <sys/time.h> 42#include <sys/time.h>
43#include <sys/stat.h> 43#include <sys/stat.h>
44 44
45#include <ufs/ufs/dinode.h> 45#include <ufs/ufs/dinode.h>
46#include <ufs/ufs/dir.h> 46#include <ufs/ufs/dir.h>
47#include <ufs/ffs/fs.h> 47#include <ufs/ffs/fs.h>
48#include <ufs/ffs/ffs_extern.h> 48#include <ufs/ffs/ffs_extern.h>
49#include <ufs/ufs/ufs_bswap.h> 49#include <ufs/ufs/ufs_bswap.h>
50 50
51#ifndef SMALL 51#ifndef SMALL
52#include <err.h> 52#include <err.h>
53#include <pwd.h> 53#include <pwd.h>
54#endif 54#endif
55#include <stdio.h> 55#include <stdio.h>
56#include <stdlib.h> 56#include <stdlib.h>
57#include <string.h> 57#include <string.h>
58#include <time.h> 58#include <time.h>
59 59
60#include "fsck.h" 60#include "fsck.h"
61#include "fsutil.h" 61#include "fsutil.h"
62#include "extern.h" 62#include "extern.h"
63 63
64static ino_t startinum; 64static ino_t startinum;
65 65
66static int iblock(struct inodesc *, long, u_int64_t); 66static int iblock(struct inodesc *, long, u_int64_t);
67#ifndef NO_FFS_EI 67#ifndef NO_FFS_EI
68static void swap_dinode1(union dinode *, int); 68static void swap_dinode1(union dinode *, int);
69static void swap_dinode2(union dinode *, int); 69static void swap_dinode2(union dinode *, int);
70#endif 70#endif
71 71
72int 72int
73ckinode(union dinode *dp, struct inodesc *idesc) 73ckinode(union dinode *dp, struct inodesc *idesc)
74{ 74{
75 int ret, offset, i; 75 int ret, offset, i;
76 union dinode dino; 76 union dinode dino;
77 u_int64_t sizepb; 77 u_int64_t sizepb;
78 int64_t remsize; 78 int64_t remsize;
79 daddr_t ndb; 79 daddr_t ndb;
80 mode_t mode; 80 mode_t mode;
81 char pathbuf[MAXPATHLEN + 1]; 81 char pathbuf[MAXPATHLEN + 1];
82 82
83 if (idesc->id_fix != IGNORE) 83 if (idesc->id_fix != IGNORE)
84 idesc->id_fix = DONTKNOW; 84 idesc->id_fix = DONTKNOW;
85 idesc->id_entryno = 0; 85 idesc->id_entryno = 0;
86 idesc->id_filesize = iswap64(DIP(dp, size)); 86 idesc->id_filesize = iswap64(DIP(dp, size));
87 mode = iswap16(DIP(dp, mode)) & IFMT; 87 mode = iswap16(DIP(dp, mode)) & IFMT;
88 if (mode == IFBLK || mode == IFCHR || (mode == IFLNK && 88 if (mode == IFBLK || mode == IFCHR || (mode == IFLNK &&
89 (idesc->id_filesize < sblock->fs_maxsymlinklen || 89 (idesc->id_filesize < sblock->fs_maxsymlinklen ||
90 (isappleufs && (idesc->id_filesize < APPLEUFS_MAXSYMLINKLEN)) || 90 (isappleufs && (idesc->id_filesize < APPLEUFS_MAXSYMLINKLEN)) ||
91 (sblock->fs_maxsymlinklen == 0 && DIP(dp, blocks) == 0)))) 91 (sblock->fs_maxsymlinklen == 0 && DIP(dp, blocks) == 0))))
92 return (KEEPON); 92 return (KEEPON);
93 if (is_ufs2) 93 if (is_ufs2)
94 dino.dp2 = dp->dp2; 94 dino.dp2 = dp->dp2;
95 else 95 else
96 dino.dp1 = dp->dp1; 96 dino.dp1 = dp->dp1;
97 ndb = howmany(iswap64(DIP(&dino, size)), sblock->fs_bsize); 97 ndb = howmany(iswap64(DIP(&dino, size)), sblock->fs_bsize);
98 for (i = 0; i < UFS_NDADDR; i++) { 98 for (i = 0; i < UFS_NDADDR; i++) {
99 if (--ndb == 0 && 99 if (--ndb == 0 &&
100 (offset = ffs_blkoff(sblock, iswap64(DIP(&dino, size)))) != 0) 100 (offset = ffs_blkoff(sblock, iswap64(DIP(&dino, size)))) != 0)
101 idesc->id_numfrags = 101 idesc->id_numfrags =
102 ffs_numfrags(sblock, ffs_fragroundup(sblock, offset)); 102 ffs_numfrags(sblock, ffs_fragroundup(sblock, offset));
103 else 103 else
104 idesc->id_numfrags = sblock->fs_frag; 104 idesc->id_numfrags = sblock->fs_frag;
105 if (DIP(&dino, db[i]) == 0) { 105 if (DIP(&dino, db[i]) == 0) {
106 if (idesc->id_type == DATA && ndb >= 0) { 106 if (idesc->id_type == DATA && ndb >= 0) {
107 /* An empty block in a directory XXX */ 107 /* An empty block in a directory XXX */
108 markclean = 0; 108 markclean = 0;
109 getpathname(pathbuf, sizeof(pathbuf), 109 getpathname(pathbuf, sizeof(pathbuf),
110 idesc->id_number, idesc->id_number); 110 idesc->id_number, idesc->id_number);
111 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 111 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS",
112 pathbuf); 112 pathbuf);
113 if (reply("ADJUST LENGTH") == 1) { 113 if (reply("ADJUST LENGTH") == 1) {
114 dp = ginode(idesc->id_number); 114 dp = ginode(idesc->id_number);
115 DIP_SET(dp, size, iswap64(i * 115 DIP_SET(dp, size, iswap64(i *
116 sblock->fs_bsize)); 116 sblock->fs_bsize));
117 printf( 117 printf(
118 "YOU MUST RERUN FSCK AFTERWARDS\n"); 118 "YOU MUST RERUN FSCK AFTERWARDS\n");
119 rerun = 1; 119 rerun = 1;
120 inodirty(); 120 inodirty();
121 } 121 }
122 } 122 }
123 continue; 123 continue;
124 } 124 }
125 if (is_ufs2) 125 if (is_ufs2)
126 idesc->id_blkno = iswap64(dino.dp2.di_db[i]); 126 idesc->id_blkno = iswap64(dino.dp2.di_db[i]);
127 else 127 else
128 idesc->id_blkno = iswap32(dino.dp1.di_db[i]); 128 idesc->id_blkno = iswap32(dino.dp1.di_db[i]);
129 if (idesc->id_type != DATA) 129 if (idesc->id_type != DATA)
130 ret = (*idesc->id_func)(idesc); 130 ret = (*idesc->id_func)(idesc);
131 else 131 else
132 ret = dirscan(idesc); 132 ret = dirscan(idesc);
133 if (ret & STOP) 133 if (ret & STOP)
134 return (ret); 134 return (ret);
135 } 135 }
136 idesc->id_numfrags = sblock->fs_frag; 136 idesc->id_numfrags = sblock->fs_frag;
137 remsize = iswap64(DIP(&dino, size)) - sblock->fs_bsize * UFS_NDADDR; 137 remsize = iswap64(DIP(&dino, size)) - sblock->fs_bsize * UFS_NDADDR;
138 sizepb = sblock->fs_bsize; 138 sizepb = sblock->fs_bsize;
139 for (i = 0; i < UFS_NIADDR; i++) { 139 for (i = 0; i < UFS_NIADDR; i++) {
140 if (DIP(&dino, ib[i])) { 140 if (DIP(&dino, ib[i])) {
141 if (is_ufs2) 141 if (is_ufs2)
142 idesc->id_blkno = iswap64(dino.dp2.di_ib[i]); 142 idesc->id_blkno = iswap64(dino.dp2.di_ib[i]);
143 else 143 else
144 idesc->id_blkno = iswap32(dino.dp1.di_ib[i]); 144 idesc->id_blkno = iswap32(dino.dp1.di_ib[i]);
145 ret = iblock(idesc, i + 1, remsize); 145 ret = iblock(idesc, i + 1, remsize);
146 if (ret & STOP) 146 if (ret & STOP)
147 return (ret); 147 return (ret);
148 } else { 148 } else {
149 if (idesc->id_type == DATA && remsize > 0) { 149 if (idesc->id_type == DATA && remsize > 0) {
150 /* An empty block in a directory XXX */ 150 /* An empty block in a directory XXX */
151 markclean = 0; 151 markclean = 0;
152 getpathname(pathbuf, sizeof(pathbuf), 152 getpathname(pathbuf, sizeof(pathbuf),
153 idesc->id_number, idesc->id_number); 153 idesc->id_number, idesc->id_number);
154 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 154 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS",
155 pathbuf); 155 pathbuf);
156 if (reply("ADJUST LENGTH") == 1) { 156 if (reply("ADJUST LENGTH") == 1) {
157 dp = ginode(idesc->id_number); 157 dp = ginode(idesc->id_number);
158 DIP_SET(dp, size, 158 DIP_SET(dp, size,
159 iswap64(iswap64(DIP(dp, size)) 159 iswap64(iswap64(DIP(dp, size))
160 - remsize)); 160 - remsize));
161 remsize = 0; 161 remsize = 0;
162 printf( 162 printf(
163 "YOU MUST RERUN FSCK AFTERWARDS\n"); 163 "YOU MUST RERUN FSCK AFTERWARDS\n");
164 rerun = 1; 164 rerun = 1;
165 inodirty(); 165 inodirty();
166 break; 166 break;
167 } 167 }
168 } 168 }
169 } 169 }
170 sizepb *= FFS_NINDIR(sblock); 170 sizepb *= FFS_NINDIR(sblock);
171 remsize -= sizepb; 171 remsize -= sizepb;
172 } 172 }
173 return (KEEPON); 173 return (KEEPON);
174} 174}
175 175
176static int 176static int
177iblock(struct inodesc *idesc, long ilevel, u_int64_t isize) 177iblock(struct inodesc *idesc, long ilevel, u_int64_t isize)
178{ 178{
179 struct bufarea *bp; 179 struct bufarea *bp;
180 int i, n, (*func) (struct inodesc *), nif; 180 int i, n, (*func) (struct inodesc *), nif;
181 u_int64_t sizepb; 181 u_int64_t sizepb;
182 char buf[BUFSIZ]; 182 char buf[BUFSIZ];
183 char pathbuf[MAXPATHLEN + 1]; 183 char pathbuf[MAXPATHLEN + 1];
184 union dinode *dp; 184 union dinode *dp;
185 185
186 if (idesc->id_type != DATA) { 186 if (idesc->id_type != DATA) {
187 func = idesc->id_func; 187 func = idesc->id_func;
188 if (((n = (*func)(idesc)) & KEEPON) == 0) 188 if (((n = (*func)(idesc)) & KEEPON) == 0)
189 return (n); 189 return (n);
190 } else 190 } else
191 func = dirscan; 191 func = dirscan;
192 if (chkrange(idesc->id_blkno, idesc->id_numfrags)) 192 if (chkrange(idesc->id_blkno, idesc->id_numfrags))
193 return (SKIP); 193 return (SKIP);
194 bp = getdatablk(idesc->id_blkno, sblock->fs_bsize); 194 bp = getdatablk(idesc->id_blkno, sblock->fs_bsize);
195 ilevel--; 195 ilevel--;
196 for (sizepb = sblock->fs_bsize, i = 0; i < ilevel; i++) 196 for (sizepb = sblock->fs_bsize, i = 0; i < ilevel; i++)
197 sizepb *= FFS_NINDIR(sblock); 197 sizepb *= FFS_NINDIR(sblock);
198 if (howmany(isize, sizepb) > (size_t)FFS_NINDIR(sblock)) 198 if (howmany(isize, sizepb) > (size_t)FFS_NINDIR(sblock))
199 nif = FFS_NINDIR(sblock); 199 nif = FFS_NINDIR(sblock);
200 else 200 else
201 nif = howmany(isize, sizepb); 201 nif = howmany(isize, sizepb);
202 if (do_blkswap) { /* swap byte order of the whole blk */ 202 if (do_blkswap) { /* swap byte order of the whole blk */
203 if (is_ufs2) { 203 if (is_ufs2) {
204 for (i = 0; i < nif; i++) 204 for (i = 0; i < nif; i++)
205 bp->b_un.b_indir2[i] = 205 bp->b_un.b_indir2[i] =
206 bswap64(bp->b_un.b_indir2[i]); 206 bswap64(bp->b_un.b_indir2[i]);
207 } else { 207 } else {
208 for (i = 0; i < nif; i++) 208 for (i = 0; i < nif; i++)
209 bp->b_un.b_indir1[i] = 209 bp->b_un.b_indir1[i] =
210 bswap32(bp->b_un.b_indir1[i]); 210 bswap32(bp->b_un.b_indir1[i]);
211 } 211 }
212 dirty(bp); 212 dirty(bp);
213 flush(fswritefd, bp); 213 flush(fswritefd, bp);
214 } 214 }
215 if (idesc->id_func == pass1check && nif < FFS_NINDIR(sblock)) { 215 if (idesc->id_func == pass1check && nif < FFS_NINDIR(sblock)) {
216 for (i = nif; i < FFS_NINDIR(sblock); i++) { 216 for (i = nif; i < FFS_NINDIR(sblock); i++) {
217 if (IBLK(bp, i) == 0) 217 if (IBLK(bp, i) == 0)
218 continue; 218 continue;
219 (void)snprintf(buf, sizeof(buf), 219 (void)snprintf(buf, sizeof(buf),
220 "PARTIALLY TRUNCATED INODE I=%llu", 220 "PARTIALLY TRUNCATED INODE I=%llu",
221 (unsigned long long)idesc->id_number); 221 (unsigned long long)idesc->id_number);
222 if (dofix(idesc, buf)) { 222 if (dofix(idesc, buf)) {
223 IBLK_SET(bp, i, 0); 223 IBLK_SET(bp, i, 0);
224 dirty(bp); 224 dirty(bp);
225 } else 225 } else
226 markclean = 0; 226 markclean = 0;
227 } 227 }
228 flush(fswritefd, bp); 228 flush(fswritefd, bp);
229 } 229 }
230 for (i = 0; i < nif; i++) { 230 for (i = 0; i < nif; i++) {
231 if (IBLK(bp, i)) { 231 if (IBLK(bp, i)) {
232 if (is_ufs2) 232 if (is_ufs2)
233 idesc->id_blkno = iswap64(bp->b_un.b_indir2[i]); 233 idesc->id_blkno = iswap64(bp->b_un.b_indir2[i]);
234 else 234 else
235 idesc->id_blkno = iswap32(bp->b_un.b_indir1[i]); 235 idesc->id_blkno = iswap32(bp->b_un.b_indir1[i]);
236 if (ilevel == 0) 236 if (ilevel == 0)
237 n = (*func)(idesc); 237 n = (*func)(idesc);
238 else 238 else
239 n = iblock(idesc, ilevel, isize); 239 n = iblock(idesc, ilevel, isize);
240 if (n & STOP) { 240 if (n & STOP) {
241 bp->b_flags &= ~B_INUSE; 241 bp->b_flags &= ~B_INUSE;
242 return (n); 242 return (n);
243 } 243 }
244 } else { 244 } else {
245 if (idesc->id_type == DATA && isize > 0) { 245 if (idesc->id_type == DATA && isize > 0) {
246 /* An empty block in a directory XXX */ 246 /* An empty block in a directory XXX */
247 markclean = 0; 247 markclean = 0;
248 getpathname(pathbuf, sizeof(pathbuf), 248 getpathname(pathbuf, sizeof(pathbuf),
249 idesc->id_number, idesc->id_number); 249 idesc->id_number, idesc->id_number);
250 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 250 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS",
251 pathbuf); 251 pathbuf);
252 if (reply("ADJUST LENGTH") == 1) { 252 if (reply("ADJUST LENGTH") == 1) {
253 dp = ginode(idesc->id_number); 253 dp = ginode(idesc->id_number);
254 DIP_SET(dp, size,  254 DIP_SET(dp, size,
255 iswap64(iswap64(DIP(dp, size)) 255 iswap64(iswap64(DIP(dp, size))
256 - isize)); 256 - isize));
257 isize = 0; 257 isize = 0;
258 printf( 258 printf(
259 "YOU MUST RERUN FSCK AFTERWARDS\n"); 259 "YOU MUST RERUN FSCK AFTERWARDS\n");
260 rerun = 1; 260 rerun = 1;
261 inodirty(); 261 inodirty();
262 bp->b_flags &= ~B_INUSE; 262 bp->b_flags &= ~B_INUSE;
263 return(STOP); 263 return(STOP);
264 } 264 }
265 } 265 }
266 } 266 }
267 isize -= sizepb; 267 isize -= sizepb;
268 } 268 }
269 bp->b_flags &= ~B_INUSE; 269 bp->b_flags &= ~B_INUSE;
270 return (KEEPON); 270 return (KEEPON);
271} 271}
272 272
273/* 273/*
274 * Check that a block in a legal block number. 274 * Check that a block in a legal block number.
275 * Return 0 if in range, 1 if out of range. 275 * Return 0 if in range, 1 if out of range.
276 */ 276 */
277int 277int
278chkrange(daddr_t blk, int cnt) 278chkrange(daddr_t blk, int cnt)
279{ 279{
280 int c; 280 int c;
281 281
282 if (cnt <= 0 || blk <= 0 || blk > maxfsblock || 282 if (cnt <= 0 || blk <= 0 || blk > maxfsblock ||
283 cnt - 1 > maxfsblock - blk) 283 cnt - 1 > maxfsblock - blk)
284 return (1); 284 return (1);
285 if (cnt > sblock->fs_frag || 285 if (cnt > sblock->fs_frag ||
286 ffs_fragnum(sblock, blk) + cnt > sblock->fs_frag) { 286 ffs_fragnum(sblock, blk) + cnt > sblock->fs_frag) {
287 if (debug) 287 if (debug)
288 printf("bad size: blk %lld, offset %d, size %d\n", 288 printf("bad size: blk %lld, offset %d, size %d\n",
289 (long long)blk, (int)ffs_fragnum(sblock, blk), cnt); 289 (long long)blk, (int)ffs_fragnum(sblock, blk), cnt);
290 } 290 }
291 c = dtog(sblock, blk); 291 c = dtog(sblock, blk);
292 if (blk < cgdmin(sblock, c)) { 292 if (blk < cgdmin(sblock, c)) {
293 if ((blk + cnt) > cgsblock(sblock, c)) { 293 if ((blk + cnt) > cgsblock(sblock, c)) {
294 if (debug) { 294 if (debug) {
295 printf("blk %lld < cgdmin %lld;", 295 printf("blk %lld < cgdmin %lld;",
296 (long long)blk, 296 (long long)blk,
297 (long long)cgdmin(sblock, c)); 297 (long long)cgdmin(sblock, c));
298 printf(" blk + cnt %lld > cgsbase %lld\n", 298 printf(" blk + cnt %lld > cgsbase %lld\n",
299 (long long)(blk + cnt), 299 (long long)(blk + cnt),
300 (long long)cgsblock(sblock, c)); 300 (long long)cgsblock(sblock, c));
301 } 301 }
302 return (1); 302 return (1);
303 } 303 }
304 } else { 304 } else {
305 if ((blk + cnt) > cgbase(sblock, c+1)) { 305 if ((blk + cnt) > cgbase(sblock, c+1)) {
306 if (debug) { 306 if (debug) {
307 printf("blk %lld >= cgdmin %lld;", 307 printf("blk %lld >= cgdmin %lld;",
308 (long long)blk, 308 (long long)blk,
309 (long long)cgdmin(sblock, c)); 309 (long long)cgdmin(sblock, c));
310 printf(" blk + cnt %lld > sblock->fs_fpg %d\n", 310 printf(" blk + cnt %lld > sblock->fs_fpg %d\n",
311 (long long)(blk+cnt), sblock->fs_fpg); 311 (long long)(blk+cnt), sblock->fs_fpg);
312 } 312 }
313 return (1); 313 return (1);
314 } 314 }
315 } 315 }
316 return (0); 316 return (0);
317} 317}
318 318
319/* 319/*
320 * General purpose interface for reading inodes. 320 * General purpose interface for reading inodes.
321 */ 321 */
322union dinode * 322union dinode *
323ginode(ino_t inumber) 323ginode(ino_t inumber)
324{ 324{
325 daddr_t iblk; 325 daddr_t iblk;
326 int blkoff; 326 int blkoff;
327 327
328 if (inumber < UFS_ROOTINO || inumber > maxino) 328 if (inumber < UFS_ROOTINO || inumber > maxino)
329 errexit("bad inode number %llu to ginode", 329 errexit("bad inode number %llu to ginode",
330 (unsigned long long)inumber); 330 (unsigned long long)inumber);
331 if (startinum == 0 || 331 if (startinum == 0 ||
332 inumber < startinum || inumber >= startinum + FFS_INOPB(sblock)) { 332 inumber < startinum || inumber >= startinum + FFS_INOPB(sblock)) {
333 iblk = ino_to_fsba(sblock, inumber); 333 iblk = ino_to_fsba(sblock, inumber);
334 if (pbp != 0) 334 if (pbp != 0)
335 pbp->b_flags &= ~B_INUSE; 335 pbp->b_flags &= ~B_INUSE;
336 pbp = getdatablk(iblk, sblock->fs_bsize); 336 pbp = getdatablk(iblk, sblock->fs_bsize);
337 startinum = (inumber / FFS_INOPB(sblock)) * FFS_INOPB(sblock); 337 startinum = (inumber / FFS_INOPB(sblock)) * FFS_INOPB(sblock);
338 } 338 }
339 if (is_ufs2) { 339 if (is_ufs2) {
340 blkoff = (inumber % FFS_INOPB(sblock)) * DINODE2_SIZE; 340 blkoff = (inumber % FFS_INOPB(sblock)) * DINODE2_SIZE;
341 return ((union dinode *)((caddr_t)pbp->b_un.b_buf + blkoff)); 341 return ((union dinode *)((caddr_t)pbp->b_un.b_buf + blkoff));
342 } 342 }
343 blkoff = (inumber % FFS_INOPB(sblock)) * DINODE1_SIZE; 343 blkoff = (inumber % FFS_INOPB(sblock)) * DINODE1_SIZE;
344 return ((union dinode *)((caddr_t)pbp->b_un.b_buf + blkoff)); 344 return ((union dinode *)((caddr_t)pbp->b_un.b_buf + blkoff));
345} 345}
346 346
347#ifndef NO_FFS_EI 347#ifndef NO_FFS_EI
348static void 348static void
349swap_dinode1(union dinode *dp, int n) 349swap_dinode1(union dinode *dp, int n)
350{ 350{
351 int i, j; 351 int i, j;
352 struct ufs1_dinode *dp1; 352 struct ufs1_dinode *dp1;
353 int32_t maxsymlinklen = sblock->fs_maxsymlinklen; 353 int32_t maxsymlinklen = sblock->fs_maxsymlinklen;
354 if (isappleufs) 354 if (isappleufs)
355 maxsymlinklen = APPLEUFS_MAXSYMLINKLEN; 355 maxsymlinklen = APPLEUFS_MAXSYMLINKLEN;
356 356
357 dp1 = (struct ufs1_dinode *)&dp->dp1; 357 dp1 = (struct ufs1_dinode *)&dp->dp1;
358 for (i = 0; i < n; i++, dp1++) { 358 for (i = 0; i < n; i++, dp1++) {
359 ffs_dinode1_swap(dp1, dp1); 359 ffs_dinode1_swap(dp1, dp1);
360 if (((iswap16(dp1->di_mode) & IFMT) != IFLNK) || 360 if (((iswap16(dp1->di_mode) & IFMT) != IFLNK) ||
361 doinglevel2 || 361 doinglevel2 ||
362 (maxsymlinklen < 0) || 362 (maxsymlinklen < 0) ||
363 (iswap64(dp1->di_size) > (uint64_t)maxsymlinklen)) { 363 (iswap64(dp1->di_size) > (uint64_t)maxsymlinklen)) {
364 for (j = 0; j < UFS_NDADDR; j++) 364 for (j = 0; j < UFS_NDADDR; j++)
365 dp1->di_db[j] = bswap32(dp1->di_db[j]); 365 dp1->di_db[j] = bswap32(dp1->di_db[j]);
366 for (j = 0; j < UFS_NIADDR; j++) 366 for (j = 0; j < UFS_NIADDR; j++)
367 dp1->di_ib[j] = bswap32(dp1->di_ib[j]); 367 dp1->di_ib[j] = bswap32(dp1->di_ib[j]);
368 } 368 }
369 } 369 }
370} 370}
371 371
372static void 372static void
373swap_dinode2(union dinode *dp, int n) 373swap_dinode2(union dinode *dp, int n)
374{ 374{
375 int i, j; 375 int i, j;
376 struct ufs2_dinode *dp2; 376 struct ufs2_dinode *dp2;
377 377
378 dp2 = (struct ufs2_dinode *)&dp->dp2; 378 dp2 = (struct ufs2_dinode *)&dp->dp2;
379 for (i = 0; i < n; i++, dp2++) { 379 for (i = 0; i < n; i++, dp2++) {
380 ffs_dinode2_swap(dp2, dp2); 380 ffs_dinode2_swap(dp2, dp2);
381 if ((iswap16(dp2->di_mode) & IFMT) != IFLNK) { 381 if ((iswap16(dp2->di_mode) & IFMT) != IFLNK) {
382 for (j = 0; j < UFS_NXADDR; j++) 382 for (j = 0; j < UFS_NXADDR; j++)
383 dp2->di_extb[j] = bswap64(dp2->di_extb[j]); 383 dp2->di_extb[j] = bswap64(dp2->di_extb[j]);
384 for (j = 0; j < UFS_NDADDR; j++) 384 for (j = 0; j < UFS_NDADDR; j++)
385 dp2->di_db[j] = bswap64(dp2->di_db[j]); 385 dp2->di_db[j] = bswap64(dp2->di_db[j]);
386 for (j = 0; j < UFS_NIADDR; j++) 386 for (j = 0; j < UFS_NIADDR; j++)
387 dp2->di_ib[j] = bswap64(dp2->di_ib[j]); 387 dp2->di_ib[j] = bswap64(dp2->di_ib[j]);
388 } 388 }
389 } 389 }
390} 390}
391#endif /* !NO_FFS_EI */ 391#endif /* !NO_FFS_EI */
392 392
393/* 393/*
394 * Special purpose version of ginode used to optimize first pass 394 * Special purpose version of ginode used to optimize first pass
395 * over all the inodes in numerical order. 395 * over all the inodes in numerical order.
396 */ 396 */
397ino_t nextino, lastinum, lastvalidinum; 397ino_t nextino, lastinum, lastvalidinum;
398long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; 398long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
399union dinode *inodebuf; 399union dinode *inodebuf;
400 400
401union dinode * 401union dinode *
402getnextinode(ino_t inumber) 402getnextinode(ino_t inumber)
403{ 403{
404 long size; 404 long size;
405 daddr_t dblk; 405 daddr_t dblk;
406 static union dinode *dp; 406 static union dinode *dp;
407 union dinode *ret; 407 union dinode *ret;
408 408
409 if (inumber != nextino++ || inumber > lastvalidinum) 409 if (inumber != nextino++ || inumber > lastvalidinum)
410 errexit("bad inode number %llu to nextinode", 410 errexit("bad inode number %llu to nextinode",
411 (unsigned long long)inumber); 411 (unsigned long long)inumber);
412 412
413 if (inumber >= lastinum) { 413 if (inumber >= lastinum) {
414 readcnt++; 414 readcnt++;
415 dblk = FFS_FSBTODB(sblock, ino_to_fsba(sblock, lastinum)); 415 dblk = FFS_FSBTODB(sblock, ino_to_fsba(sblock, lastinum));
416 if (readcnt % readpercg == 0) { 416 if (readcnt % readpercg == 0) {
417 size = partialsize; 417 size = partialsize;
418 lastinum += partialcnt; 418 lastinum += partialcnt;
419 } else { 419 } else {
420 size = inobufsize; 420 size = inobufsize;
421 lastinum += fullcnt; 421 lastinum += fullcnt;
422 } 422 }
423 (void)bread(fsreadfd, (caddr_t)inodebuf, dblk, size); 423 (void)bread(fsreadfd, (caddr_t)inodebuf, dblk, size);
424 if (doswap) { 424 if (doswap) {
425 if (is_ufs2) 425 if (is_ufs2)
426 swap_dinode2(inodebuf, lastinum - inumber); 426 swap_dinode2(inodebuf, lastinum - inumber);
427 else 427 else
428 swap_dinode1(inodebuf, lastinum - inumber); 428 swap_dinode1(inodebuf, lastinum - inumber);
429 bwrite(fswritefd, (char *)inodebuf, dblk, size); 429 bwrite(fswritefd, (char *)inodebuf, dblk, size);
430 } 430 }
431 dp = (union dinode *)inodebuf; 431 dp = (union dinode *)inodebuf;
432 } 432 }
433 ret = dp; 433 ret = dp;
434 dp = (union dinode *) 434 dp = (union dinode *)
435 ((char *)dp + (is_ufs2 ? DINODE2_SIZE : DINODE1_SIZE)); 435 ((char *)dp + (is_ufs2 ? DINODE2_SIZE : DINODE1_SIZE));
436 return ret; 436 return ret;
437} 437}
438 438
439void 439void
440setinodebuf(ino_t inum) 440setinodebuf(ino_t inum)
441{ 441{
442 442
443 if (inum % sblock->fs_ipg != 0) 443 if (inum % sblock->fs_ipg != 0)
444 errexit("bad inode number %llu to setinodebuf", 444 errexit("bad inode number %llu to setinodebuf",
445 (unsigned long long)inum); 445 (unsigned long long)inum);
446 446
447 lastvalidinum = inum + sblock->fs_ipg - 1; 447 lastvalidinum = inum + sblock->fs_ipg - 1;
448 startinum = 0; 448 startinum = 0;
449 nextino = inum; 449 nextino = inum;
450 lastinum = inum; 450 lastinum = inum;
451 readcnt = 0; 451 readcnt = 0;
452 if (inodebuf != NULL) 452 if (inodebuf != NULL)
453 return; 453 return;
454 inobufsize = ffs_blkroundup(sblock, INOBUFSIZE); 454 inobufsize = ffs_blkroundup(sblock, INOBUFSIZE);
455 fullcnt = inobufsize / (is_ufs2 ? DINODE2_SIZE : DINODE1_SIZE); 455 fullcnt = inobufsize / (is_ufs2 ? DINODE2_SIZE : DINODE1_SIZE);
456 readpercg = sblock->fs_ipg / fullcnt; 456 readpercg = sblock->fs_ipg / fullcnt;
457 partialcnt = sblock->fs_ipg % fullcnt; 457 partialcnt = sblock->fs_ipg % fullcnt;
458 partialsize = partialcnt * (is_ufs2 ? DINODE2_SIZE : DINODE1_SIZE); 458 partialsize = partialcnt * (is_ufs2 ? DINODE2_SIZE : DINODE1_SIZE);
459 if (partialcnt != 0) { 459 if (partialcnt != 0) {
460 readpercg++; 460 readpercg++;
461 } else { 461 } else {
462 partialcnt = fullcnt; 462 partialcnt = fullcnt;
463 partialsize = inobufsize; 463 partialsize = inobufsize;
464 } 464 }
465 if (inodebuf == NULL && 465 if (inodebuf == NULL &&
466 (inodebuf = malloc((unsigned)inobufsize)) == NULL) 466 (inodebuf = aligned_alloc(DEV_BSIZE, (unsigned)inobufsize)) == NULL)
467 errexit("Cannot allocate space for inode buffer"); 467 errexit("Cannot allocate space for inode buffer");
468} 468}
469 469
470void 470void
471freeinodebuf(void) 471freeinodebuf(void)
472{ 472{
473 473
474 if (inodebuf != NULL) 474 if (inodebuf != NULL)
475 free((char *)inodebuf); 475 free((char *)inodebuf);
476 inodebuf = NULL; 476 inodebuf = NULL;
477} 477}
478 478
479/* 479/*
480 * Routines to maintain information about directory inodes. 480 * Routines to maintain information about directory inodes.
481 * This is built during the first pass and used during the 481 * This is built during the first pass and used during the
482 * second and third passes. 482 * second and third passes.
483 * 483 *
484 * Enter inodes into the cache. 484 * Enter inodes into the cache.
485 */ 485 */
486void 486void
487cacheino(union dinode *dp, ino_t inumber) 487cacheino(union dinode *dp, ino_t inumber)
488{ 488{
489 struct inoinfo *inp; 489 struct inoinfo *inp;
490 struct inoinfo **inpp, **ninpsort; 490 struct inoinfo **inpp, **ninpsort;
491 unsigned int i, blks, extra; 491 unsigned int i, blks, extra;
492 int64_t size; 492 int64_t size;
493 493
494 size = iswap64(DIP(dp, size)); 494 size = iswap64(DIP(dp, size));
495 blks = howmany(size, sblock->fs_bsize); 495 blks = howmany(size, sblock->fs_bsize);
496 if (blks > UFS_NDADDR) 496 if (blks > UFS_NDADDR)
497 blks = UFS_NDADDR + UFS_NIADDR; 497 blks = UFS_NDADDR + UFS_NIADDR;
498 if (blks > 0) 498 if (blks > 0)
499 extra = (blks - 1) * sizeof (int64_t); 499 extra = (blks - 1) * sizeof (int64_t);
500 else 500 else
501 extra = 0; 501 extra = 0;
502 inp = malloc(sizeof(*inp) + extra); 502 inp = malloc(sizeof(*inp) + extra);
503 if (inp == NULL) 503 if (inp == NULL)
504 return; 504 return;
505 inpp = &inphead[inumber % dirhash]; 505 inpp = &inphead[inumber % dirhash];
506 inp->i_nexthash = *inpp; 506 inp->i_nexthash = *inpp;
507 *inpp = inp; 507 *inpp = inp;
508 inp->i_child = inp->i_sibling = 0; 508 inp->i_child = inp->i_sibling = 0;
509 if (inumber == UFS_ROOTINO) 509 if (inumber == UFS_ROOTINO)
510 inp->i_parent = UFS_ROOTINO; 510 inp->i_parent = UFS_ROOTINO;
511 else 511 else
512 inp->i_parent = (ino_t)0; 512 inp->i_parent = (ino_t)0;
513 inp->i_dotdot = (ino_t)0; 513 inp->i_dotdot = (ino_t)0;
514 inp->i_number = inumber; 514 inp->i_number = inumber;
515 inp->i_isize = size; 515 inp->i_isize = size;
516 inp->i_numblks = blks; 516 inp->i_numblks = blks;
517 for (i = 0; i < (blks < UFS_NDADDR ? blks : UFS_NDADDR); i++) 517 for (i = 0; i < (blks < UFS_NDADDR ? blks : UFS_NDADDR); i++)
518 inp->i_blks[i] = DIP(dp, db[i]); 518 inp->i_blks[i] = DIP(dp, db[i]);
519 if (blks > UFS_NDADDR) 519 if (blks > UFS_NDADDR)
520 for (i = 0; i < UFS_NIADDR; i++) 520 for (i = 0; i < UFS_NIADDR; i++)
521 inp->i_blks[UFS_NDADDR + i] = DIP(dp, ib[i]); 521 inp->i_blks[UFS_NDADDR + i] = DIP(dp, ib[i]);
522 if (inplast == listmax) { 522 if (inplast == listmax) {
523 ninpsort = (struct inoinfo **)realloc((char *)inpsort, 523 ninpsort = (struct inoinfo **)realloc((char *)inpsort,
524 (unsigned)(listmax + 100) * sizeof(struct inoinfo *)); 524 (unsigned)(listmax + 100) * sizeof(struct inoinfo *));
525 if (inpsort == NULL) 525 if (inpsort == NULL)
526 errexit("cannot increase directory list"); 526 errexit("cannot increase directory list");
527 inpsort = ninpsort; 527 inpsort = ninpsort;
528 listmax += 100; 528 listmax += 100;
529 } 529 }
530 inpsort[inplast++] = inp; 530 inpsort[inplast++] = inp;
531} 531}
532 532
533/* 533/*
534 * Look up an inode cache structure. 534 * Look up an inode cache structure.
535 */ 535 */
536struct inoinfo * 536struct inoinfo *
537getinoinfo(ino_t inumber) 537getinoinfo(ino_t inumber)
538{ 538{
539 struct inoinfo *inp; 539 struct inoinfo *inp;
540 540
541 for (inp = inphead[inumber % dirhash]; inp; inp = inp->i_nexthash) { 541 for (inp = inphead[inumber % dirhash]; inp; inp = inp->i_nexthash) {
542 if (inp->i_number != inumber) 542 if (inp->i_number != inumber)
543 continue; 543 continue;
544 return (inp); 544 return (inp);
545 } 545 }
546 errexit("cannot find inode %llu", (unsigned long long)inumber); 546 errexit("cannot find inode %llu", (unsigned long long)inumber);
547 return ((struct inoinfo *)0); 547 return ((struct inoinfo *)0);
548} 548}
549 549
550/* 550/*
551 * Clean up all the inode cache structure. 551 * Clean up all the inode cache structure.
552 */ 552 */
553void 553void
554inocleanup(void) 554inocleanup(void)
555{ 555{
556 struct inoinfo **inpp; 556 struct inoinfo **inpp;
557 557
558 if (inphead == NULL) 558 if (inphead == NULL)
559 return; 559 return;
560 for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) 560 for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--)
561 free((char *)(*inpp)); 561 free((char *)(*inpp));
562 free((char *)inphead); 562 free((char *)inphead);
563 free((char *)inpsort); 563 free((char *)inpsort);
564 inphead = inpsort = NULL; 564 inphead = inpsort = NULL;
565} 565}
566  566
567void 567void
568inodirty(void) 568inodirty(void)
569{ 569{
570  570
571 dirty(pbp); 571 dirty(pbp);
572} 572}
573 573
574void 574void
575clri(struct inodesc *idesc, const char *type, int flag) 575clri(struct inodesc *idesc, const char *type, int flag)
576{ 576{
577 union dinode *dp; 577 union dinode *dp;
578 578
579 dp = ginode(idesc->id_number); 579 dp = ginode(idesc->id_number);
580 if (flag == 1) { 580 if (flag == 1) {
581 pwarn("%s %s", type, 581 pwarn("%s %s", type,
582 (iswap16(DIP(dp, mode)) & IFMT) == IFDIR ? "DIR" : "FILE"); 582 (iswap16(DIP(dp, mode)) & IFMT) == IFDIR ? "DIR" : "FILE");
583 pinode(idesc->id_number); 583 pinode(idesc->id_number);
584 } 584 }
585 if (preen || reply("CLEAR") == 1) { 585 if (preen || reply("CLEAR") == 1) {
586 if (preen) 586 if (preen)
587 printf(" (CLEARED)\n"); 587 printf(" (CLEARED)\n");
588 n_files--; 588 n_files--;
589 /* 589 /*
590 * ckinode will call id_func (actually always pass4check) 590 * ckinode will call id_func (actually always pass4check)
591 * which will update the block count 591 * which will update the block count
592 */ 592 */
593 if (idesc->id_type != SNAP) 593 if (idesc->id_type != SNAP)
594 update_uquot(idesc->id_number, 594 update_uquot(idesc->id_number,
595 idesc->id_uid, idesc->id_gid, 0, -1); 595 idesc->id_uid, idesc->id_gid, 0, -1);
596 (void)ckinode(dp, idesc); 596 (void)ckinode(dp, idesc);
597 clearinode(dp); 597 clearinode(dp);
598 inoinfo(idesc->id_number)->ino_state = USTATE; 598 inoinfo(idesc->id_number)->ino_state = USTATE;
599 inodirty(); 599 inodirty();
600 } else 600 } else
601 markclean = 0; 601 markclean = 0;
602} 602}
603 603
604int 604int
605findname(struct inodesc *idesc) 605findname(struct inodesc *idesc)
606{ 606{
607 struct direct *dirp = idesc->id_dirp; 607 struct direct *dirp = idesc->id_dirp;
608 size_t len; 608 size_t len;
609 char *buf; 609 char *buf;
610 610
611 if (iswap32(dirp->d_ino) != idesc->id_parent || idesc->id_entryno < 2) { 611 if (iswap32(dirp->d_ino) != idesc->id_parent || idesc->id_entryno < 2) {
612 idesc->id_entryno++; 612 idesc->id_entryno++;
613 return (KEEPON); 613 return (KEEPON);
614 } 614 }
615 if ((len = dirp->d_namlen + 1) > MAXPATHLEN) { 615 if ((len = dirp->d_namlen + 1) > MAXPATHLEN) {
616 /* XXX: We don't fix but we ignore */ 616 /* XXX: We don't fix but we ignore */
617 len = MAXPATHLEN; 617 len = MAXPATHLEN;
618 } 618 }
619 /* this is namebuf from utilities.c */ 619 /* this is namebuf from utilities.c */
620 buf = __UNCONST(idesc->id_name); 620 buf = __UNCONST(idesc->id_name);
621 (void)memcpy(buf, dirp->d_name, (size_t)dirp->d_namlen + 1); 621 (void)memcpy(buf, dirp->d_name, (size_t)dirp->d_namlen + 1);
622 return (STOP|FOUND); 622 return (STOP|FOUND);
623} 623}
624 624
625int 625int
626findino(struct inodesc *idesc) 626findino(struct inodesc *idesc)
627{ 627{
628 struct direct *dirp = idesc->id_dirp; 628 struct direct *dirp = idesc->id_dirp;
629 629
630 if (dirp->d_ino == 0) 630 if (dirp->d_ino == 0)
631 return (KEEPON); 631 return (KEEPON);
632 if (strcmp(dirp->d_name, idesc->id_name) == 0 && 632 if (strcmp(dirp->d_name, idesc->id_name) == 0 &&
633 iswap32(dirp->d_ino) >= UFS_ROOTINO && iswap32(dirp->d_ino) <= maxino) { 633 iswap32(dirp->d_ino) >= UFS_ROOTINO && iswap32(dirp->d_ino) <= maxino) {
634 idesc->id_parent = iswap32(dirp->d_ino); 634 idesc->id_parent = iswap32(dirp->d_ino);
635 return (STOP|FOUND); 635 return (STOP|FOUND);
636 } 636 }
637 return (KEEPON); 637 return (KEEPON);
638} 638}
639 639
640int 640int
641clearentry(struct inodesc *idesc) 641clearentry(struct inodesc *idesc)
642{ 642{
643 struct direct *dirp = idesc->id_dirp; 643 struct direct *dirp = idesc->id_dirp;
644 644
645 if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) { 645 if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) {
646 idesc->id_entryno++; 646 idesc->id_entryno++;
647 return (KEEPON); 647 return (KEEPON);
648 } 648 }
649 dirp->d_ino = 0; 649 dirp->d_ino = 0;
650 return (STOP|FOUND|ALTERED); 650 return (STOP|FOUND|ALTERED);
651} 651}
652 652
653void 653void
654pinode(ino_t ino) 654pinode(ino_t ino)
655{ 655{
656 union dinode *dp; 656 union dinode *dp;
657 struct passwd *pw; 657 struct passwd *pw;
658 658
659 printf(" I=%llu ", (unsigned long long)ino); 659 printf(" I=%llu ", (unsigned long long)ino);
660 if (ino < UFS_ROOTINO || ino > maxino) 660 if (ino < UFS_ROOTINO || ino > maxino)
661 return; 661 return;
662 dp = ginode(ino); 662 dp = ginode(ino);
663 printf(" OWNER="); 663 printf(" OWNER=");
664#ifndef SMALL 664#ifndef SMALL
665 if (Uflag && (pw = getpwuid((int)iswap32(DIP(dp, uid)))) != 0) 665 if (Uflag && (pw = getpwuid((int)iswap32(DIP(dp, uid)))) != 0)
666 printf("%s ", pw->pw_name); 666 printf("%s ", pw->pw_name);
667 else 667 else
668#endif 668#endif
669 printf("%u ", (unsigned)iswap32(DIP(dp, uid))); 669 printf("%u ", (unsigned)iswap32(DIP(dp, uid)));
670 printf("MODE=%o\n", iswap16(DIP(dp, mode))); 670 printf("MODE=%o\n", iswap16(DIP(dp, mode)));
671 if (preen) 671 if (preen)
672 printf("%s: ", cdevname()); 672 printf("%s: ", cdevname());
673 printf("SIZE=%llu ", (unsigned long long)iswap64(DIP(dp, size))); 673 printf("SIZE=%llu ", (unsigned long long)iswap64(DIP(dp, size)));
674 printf("MTIME=%s ", print_mtime(iswap32(DIP(dp, mtime)))); 674 printf("MTIME=%s ", print_mtime(iswap32(DIP(dp, mtime))));
675} 675}
676 676
677void 677void
678blkerror(ino_t ino, const char *type, daddr_t blk) 678blkerror(ino_t ino, const char *type, daddr_t blk)
679{ 679{
680 struct inostat *info; 680 struct inostat *info;
681 681
682 pfatal("%lld %s I=%llu", (long long)blk, type, (unsigned long long)ino); 682 pfatal("%lld %s I=%llu", (long long)blk, type, (unsigned long long)ino);
683 printf("\n"); 683 printf("\n");
684 info = inoinfo(ino); 684 info = inoinfo(ino);
685 switch (info->ino_state) { 685 switch (info->ino_state) {
686 686
687 case FSTATE: 687 case FSTATE:
688 info->ino_state = FCLEAR; 688 info->ino_state = FCLEAR;
689 return; 689 return;
690 690
691 case DSTATE: 691 case DSTATE:
692 info->ino_state = DCLEAR; 692 info->ino_state = DCLEAR;
693 return; 693 return;
694 694
695 case FCLEAR: 695 case FCLEAR:
696 case DCLEAR: 696 case DCLEAR:
697 return; 697 return;
698 698
699 default: 699 default:
700 errexit("BAD STATE %d TO BLKERR", info->ino_state); 700 errexit("BAD STATE %d TO BLKERR", info->ino_state);
701 /* NOTREACHED */ 701 /* NOTREACHED */
702 } 702 }
703} 703}
704 704
705/* 705/*
706 * allocate an unused inode 706 * allocate an unused inode
707 */ 707 */
708ino_t 708ino_t
709allocino(ino_t request, int type) 709allocino(ino_t request, int type)
710{ 710{
711 ino_t ino; 711 ino_t ino;
712 union dinode *dp; 712 union dinode *dp;
713 struct ufs1_dinode *dp1; 713 struct ufs1_dinode *dp1;
714 struct ufs2_dinode *dp2; 714 struct ufs2_dinode *dp2;
715 time_t t; 715 time_t t;
716 struct cg *cgp = cgrp; 716 struct cg *cgp = cgrp;
717 int cg; 717 int cg;
718 struct inostat *info = NULL; 718 struct inostat *info = NULL;
719 int nfrags; 719 int nfrags;
720 720
721 if (request == 0) 721 if (request == 0)
722 request = UFS_ROOTINO; 722 request = UFS_ROOTINO;
723 else if (inoinfo(request)->ino_state != USTATE) 723 else if (inoinfo(request)->ino_state != USTATE)
724 return (0); 724 return (0);
725 for (ino = request; ino < maxino; ino++) { 725 for (ino = request; ino < maxino; ino++) {
726 info = inoinfo(ino); 726 info = inoinfo(ino);
727 if (info->ino_state == USTATE) 727 if (info->ino_state == USTATE)
728 break; 728 break;
729 } 729 }
730 if (ino == maxino) 730 if (ino == maxino)
731 return (0); 731 return (0);
732 cg = ino_to_cg(sblock, ino); 732 cg = ino_to_cg(sblock, ino);
733 /* If necessary, extend the inoinfo array. grow exponentially */ 733 /* If necessary, extend the inoinfo array. grow exponentially */
734 if ((ino % sblock->fs_ipg) >= (uint64_t)inostathead[cg].il_numalloced) { 734 if ((ino % sblock->fs_ipg) >= (uint64_t)inostathead[cg].il_numalloced) {
735 unsigned long newalloced, i; 735 unsigned long newalloced, i;
736 newalloced = MIN(sblock->fs_ipg, 736 newalloced = MIN(sblock->fs_ipg,
737 MAX(2 * inostathead[cg].il_numalloced, 10)); 737 MAX(2 * inostathead[cg].il_numalloced, 10));
738 info = calloc(newalloced, sizeof(struct inostat)); 738 info = calloc(newalloced, sizeof(struct inostat));
739 if (info == NULL) { 739 if (info == NULL) {
740 pwarn("cannot alloc %lu bytes to extend inoinfo\n", 740 pwarn("cannot alloc %lu bytes to extend inoinfo\n",
741 sizeof(struct inostat) * newalloced); 741 sizeof(struct inostat) * newalloced);
742 return 0; 742 return 0;
743 } 743 }
744 memmove(info, inostathead[cg].il_stat, 744 memmove(info, inostathead[cg].il_stat,
745 inostathead[cg].il_numalloced * sizeof(*info)); 745 inostathead[cg].il_numalloced * sizeof(*info));
746 for (i = inostathead[cg].il_numalloced; i < newalloced; i++) { 746 for (i = inostathead[cg].il_numalloced; i < newalloced; i++) {
747 info[i].ino_state = USTATE; 747 info[i].ino_state = USTATE;
748 } 748 }
749 if (inostathead[cg].il_numalloced) 749 if (inostathead[cg].il_numalloced)
750 free(inostathead[cg].il_stat); 750 free(inostathead[cg].il_stat);
751 inostathead[cg].il_stat = info; 751 inostathead[cg].il_stat = info;
752 inostathead[cg].il_numalloced = newalloced; 752 inostathead[cg].il_numalloced = newalloced;
753 info = inoinfo(ino); 753 info = inoinfo(ino);
754 } 754 }
755 getblk(&cgblk, cgtod(sblock, cg), sblock->fs_cgsize); 755 getblk(&cgblk, cgtod(sblock, cg), sblock->fs_cgsize);
756 memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize); 756 memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize);
757 if ((doswap && !needswap) || (!doswap && needswap)) 757 if ((doswap && !needswap) || (!doswap && needswap))
758 ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock); 758 ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock);
759 if (!cg_chkmagic(cgp, 0)) 759 if (!cg_chkmagic(cgp, 0))
760 pfatal("CG %d: ALLOCINO: BAD MAGIC NUMBER\n", cg); 760 pfatal("CG %d: ALLOCINO: BAD MAGIC NUMBER\n", cg);
761 if (doswap) 761 if (doswap)
762 cgdirty(); 762 cgdirty();
763 setbit(cg_inosused(cgp, 0), ino % sblock->fs_ipg); 763 setbit(cg_inosused(cgp, 0), ino % sblock->fs_ipg);
764 cgp->cg_cs.cs_nifree--; 764 cgp->cg_cs.cs_nifree--;
765 sblock->fs_cstotal.cs_nifree--; 765 sblock->fs_cstotal.cs_nifree--;
766 sblock->fs_cs(fs, cg).cs_nifree--; 766 sblock->fs_cs(fs, cg).cs_nifree--;
767 sbdirty(); 767 sbdirty();
768 switch (type & IFMT) { 768 switch (type & IFMT) {
769 case IFDIR: 769 case IFDIR:
770 info->ino_state = DSTATE; 770 info->ino_state = DSTATE;
771 cgp->cg_cs.cs_ndir++; 771 cgp->cg_cs.cs_ndir++;
772 nfrags = 1; 772 nfrags = 1;
773 break; 773 break;
774 case IFREG: 774 case IFREG:
775 info->ino_state = FSTATE; 775 info->ino_state = FSTATE;
776 nfrags = sblock->fs_frag; 776 nfrags = sblock->fs_frag;
777 break; 777 break;
778 case IFLNK: 778 case IFLNK:
779 info->ino_state = FSTATE; 779 info->ino_state = FSTATE;
780 nfrags = 1; 780 nfrags = 1;
781 break; 781 break;
782 default: 782 default:
783 return (0); 783 return (0);
784 } 784 }
785 cgdirty(); 785 cgdirty();
786 dp = ginode(ino); 786 dp = ginode(ino);
787 if (is_ufs2) { 787 if (is_ufs2) {
788 dp2 = &dp->dp2; 788 dp2 = &dp->dp2;
789 dp2->di_db[0] = iswap64(allocblk(nfrags)); 789 dp2->di_db[0] = iswap64(allocblk(nfrags));
790 if (dp2->di_db[0] == 0) { 790 if (dp2->di_db[0] == 0) {
791 info->ino_state = USTATE; 791 info->ino_state = USTATE;
792 return (0); 792 return (0);
793 } 793 }
794 dp2->di_mode = iswap16(type); 794 dp2->di_mode = iswap16(type);
795 dp2->di_flags = 0; 795 dp2->di_flags = 0;
796 (void)time(&t); 796 (void)time(&t);
797 dp2->di_atime = iswap64(t); 797 dp2->di_atime = iswap64(t);
798 dp2->di_mtime = dp2->di_ctime = dp2->di_atime; 798 dp2->di_mtime = dp2->di_ctime = dp2->di_atime;
799 dp2->di_size = iswap64(ffs_lfragtosize(sblock, nfrags)); 799 dp2->di_size = iswap64(ffs_lfragtosize(sblock, nfrags));
800 dp2->di_blocks = iswap64(btodb(ffs_lfragtosize(sblock, nfrags))); 800 dp2->di_blocks = iswap64(btodb(ffs_lfragtosize(sblock, nfrags)));
801 } else { 801 } else {
802 dp1 = &dp->dp1; 802 dp1 = &dp->dp1;
803 dp1->di_db[0] = iswap32(allocblk(nfrags)); 803 dp1->di_db[0] = iswap32(allocblk(nfrags));
804 if (dp1->di_db[0] == 0) { 804 if (dp1->di_db[0] == 0) {
805 info->ino_state = USTATE; 805 info->ino_state = USTATE;
806 return (0); 806 return (0);
807 } 807 }
808 dp1->di_mode = iswap16(type); 808 dp1->di_mode = iswap16(type);
809 dp1->di_flags = 0; 809 dp1->di_flags = 0;
810 (void)time(&t); 810 (void)time(&t);
811 dp1->di_atime = iswap32(t); 811 dp1->di_atime = iswap32(t);
812 dp1->di_mtime = dp1->di_ctime = dp1->di_atime; 812 dp1->di_mtime = dp1->di_ctime = dp1->di_atime;
813 dp1->di_size = iswap64(ffs_lfragtosize(sblock, nfrags)); 813 dp1->di_size = iswap64(ffs_lfragtosize(sblock, nfrags));
814 dp1->di_blocks = iswap32(btodb(ffs_lfragtosize(sblock, nfrags))); 814 dp1->di_blocks = iswap32(btodb(ffs_lfragtosize(sblock, nfrags)));
815 } 815 }
816 n_files++; 816 n_files++;
817 inodirty(); 817 inodirty();
818 if (newinofmt) 818 if (newinofmt)
819 info->ino_type = IFTODT(type); 819 info->ino_type = IFTODT(type);
820 return (ino); 820 return (ino);
821} 821}
822 822
823/* 823/*
824 * deallocate an inode 824 * deallocate an inode
825 */ 825 */
826void 826void
827freeino(ino_t ino) 827freeino(ino_t ino)
828{ 828{
829 struct inodesc idesc; 829 struct inodesc idesc;
830 union dinode *dp; 830 union dinode *dp;
831 struct cg *cgp = cgrp; 831 struct cg *cgp = cgrp;
832 int cg; 832 int cg;
833 833
834 cg = ino_to_cg(sblock, ino); 834 cg = ino_to_cg(sblock, ino);
835 getblk(&cgblk, cgtod(sblock, cg), sblock->fs_cgsize); 835 getblk(&cgblk, cgtod(sblock, cg), sblock->fs_cgsize);
836 memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize); 836 memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize);
837 if ((doswap && !needswap) || (!doswap && needswap)) 837 if ((doswap && !needswap) || (!doswap && needswap))
838 ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock); 838 ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock);
839 if (!cg_chkmagic(cgp, 0)) { 839 if (!cg_chkmagic(cgp, 0)) {
840 pwarn("CG %d: FREEINO: BAD MAGIC NUMBER\n", cg); 840 pwarn("CG %d: FREEINO: BAD MAGIC NUMBER\n", cg);
841 cgp = NULL; 841 cgp = NULL;
842 } 842 }
843 843
844 memset(&idesc, 0, sizeof(struct inodesc)); 844 memset(&idesc, 0, sizeof(struct inodesc));
845 idesc.id_func = pass4check; 845 idesc.id_func = pass4check;
846 idesc.id_number = ino; 846 idesc.id_number = ino;
847 dp = ginode(ino); 847 dp = ginode(ino);
848 idesc.id_uid = iswap32(DIP(dp, uid)); 848 idesc.id_uid = iswap32(DIP(dp, uid));
849 idesc.id_gid = iswap32(DIP(dp, gid)); 849 idesc.id_gid = iswap32(DIP(dp, gid));
850 if (iswap32(DIP(dp, flags)) & SF_SNAPSHOT) 850 if (iswap32(DIP(dp, flags)) & SF_SNAPSHOT)
851 idesc.id_type = SNAP; 851 idesc.id_type = SNAP;
852 else 852 else
853 idesc.id_type = ADDR; 853 idesc.id_type = ADDR;
854 (void)ckinode(dp, &idesc); 854 (void)ckinode(dp, &idesc);
855 clearinode(dp); 855 clearinode(dp);
856 inodirty(); 856 inodirty();
857 inoinfo(ino)->ino_state = USTATE; 857 inoinfo(ino)->ino_state = USTATE;
858 if (idesc.id_type != SNAP) 858 if (idesc.id_type != SNAP)
859 update_uquot(idesc.id_number, 859 update_uquot(idesc.id_number,
860 idesc.id_uid, idesc.id_gid, 0, -1); 860 idesc.id_uid, idesc.id_gid, 0, -1);
861 n_files--; 861 n_files--;
862 if (cgp) { 862 if (cgp) {
863 clrbit(cg_inosused(cgp, 0), ino % sblock->fs_ipg); 863 clrbit(cg_inosused(cgp, 0), ino % sblock->fs_ipg);
864 cgp->cg_cs.cs_nifree++; 864 cgp->cg_cs.cs_nifree++;
865 sblock->fs_cstotal.cs_nifree++; 865 sblock->fs_cstotal.cs_nifree++;
866 sblock->fs_cs(fs, cg).cs_nifree++; 866 sblock->fs_cs(fs, cg).cs_nifree++;
867 sbdirty(); 867 sbdirty();
868 cgdirty(); 868 cgdirty();
869 } 869 }
870} 870}
871 871
872/* read a data block from inode */ 872/* read a data block from inode */
873ssize_t 873ssize_t
874readblk(union dinode *dp, off_t offset, struct bufarea **bp) 874readblk(union dinode *dp, off_t offset, struct bufarea **bp)
875{ 875{
876 daddr_t blkno = ffs_lblkno(sblock, offset); 876 daddr_t blkno = ffs_lblkno(sblock, offset);
877 daddr_t iblkno; 877 daddr_t iblkno;
878 int type = IFMT & iswap16(DIP(dp, mode)); 878 int type = IFMT & iswap16(DIP(dp, mode));
879 ssize_t filesize = iswap64(DIP(dp, size)); 879 ssize_t filesize = iswap64(DIP(dp, size));
880 int ilevel; 880 int ilevel;
881 daddr_t nblks; 881 daddr_t nblks;
882 const daddr_t naddrperblk = sblock->fs_bsize / 882 const daddr_t naddrperblk = sblock->fs_bsize /
883 (is_ufs2 ? sizeof(uint64_t) : sizeof(uint32_t)); 883 (is_ufs2 ? sizeof(uint64_t) : sizeof(uint32_t));
884 struct bufarea *ibp; 884 struct bufarea *ibp;
885 885
886 *bp = NULL; 886 *bp = NULL;
887 offset &= ~(sblock->fs_bsize - 1); 887 offset &= ~(sblock->fs_bsize - 1);
888 888
889 if (type != IFREG) 889 if (type != IFREG)
890 return 0; 890 return 0;
891 if (offset >= filesize) 891 if (offset >= filesize)
892 return 0; /* short read */ 892 return 0; /* short read */
893 if (blkno < UFS_NDADDR) { 893 if (blkno < UFS_NDADDR) {
894 blkno = is_ufs2 ? iswap64(dp->dp2.di_db[blkno]) : 894 blkno = is_ufs2 ? iswap64(dp->dp2.di_db[blkno]) :
895 iswap32(dp->dp1.di_db[blkno]); 895 iswap32(dp->dp1.di_db[blkno]);
896 if (blkno == 0) 896 if (blkno == 0)
897 return 0; 897 return 0;
898 *bp = getdatablk(blkno, sblock->fs_bsize); 898 *bp = getdatablk(blkno, sblock->fs_bsize);
899 return (bp != NULL) ? sblock->fs_bsize : 0; 899 return (bp != NULL) ? sblock->fs_bsize : 0;
900 } 900 }
901 blkno -= UFS_NDADDR; 901 blkno -= UFS_NDADDR;
902 /* find indir level */ 902 /* find indir level */
903 for (ilevel = 1, nblks = naddrperblk; 903 for (ilevel = 1, nblks = naddrperblk;
904 ilevel <= UFS_NIADDR; 904 ilevel <= UFS_NIADDR;
905 ilevel++, nblks *= naddrperblk) { 905 ilevel++, nblks *= naddrperblk) {
906 if (blkno < nblks) 906 if (blkno < nblks)
907 break; 907 break;
908 else 908 else
909 blkno -= nblks; 909 blkno -= nblks;
910 } 910 }
911 if (ilevel > UFS_NIADDR)  911 if (ilevel > UFS_NIADDR)
912 errexit("bad ofsset %" PRIu64 " to readblk", offset); 912 errexit("bad ofsset %" PRIu64 " to readblk", offset);
913 913
914 /* get the first indirect block */ 914 /* get the first indirect block */
915 iblkno = is_ufs2 ? iswap64(dp->dp2.di_ib[ilevel - 1]) : 915 iblkno = is_ufs2 ? iswap64(dp->dp2.di_ib[ilevel - 1]) :
916 iswap32(dp->dp1.di_ib[ilevel - 1]); 916 iswap32(dp->dp1.di_ib[ilevel - 1]);
917 if (iblkno == 0) 917 if (iblkno == 0)
918 return 0; 918 return 0;
919 ibp = getdatablk(iblkno, sblock->fs_bsize); 919 ibp = getdatablk(iblkno, sblock->fs_bsize);
920 /* walk indirect blocks up to the data block */ 920 /* walk indirect blocks up to the data block */
921 for (; ilevel >0 ; ilevel--) { 921 for (; ilevel >0 ; ilevel--) {
922 nblks = nblks / naddrperblk; 922 nblks = nblks / naddrperblk;
923 if (is_ufs2) 923 if (is_ufs2)
924 iblkno = iswap64(ibp->b_un.b_indir2[blkno / nblks]); 924 iblkno = iswap64(ibp->b_un.b_indir2[blkno / nblks]);
925 else 925 else
926 iblkno = iswap32(ibp->b_un.b_indir1[blkno / nblks]); 926 iblkno = iswap32(ibp->b_un.b_indir1[blkno / nblks]);
927 if (iblkno == 0) 927 if (iblkno == 0)
928 return 0; 928 return 0;
929 blkno = blkno % nblks; 929 blkno = blkno % nblks;
930 ibp->b_flags &= ~B_INUSE; 930 ibp->b_flags &= ~B_INUSE;
931 ibp = getdatablk(iblkno, sblock->fs_bsize); 931 ibp = getdatablk(iblkno, sblock->fs_bsize);
932 } 932 }
933 *bp = ibp; 933 *bp = ibp;
934 return sblock->fs_bsize; 934 return sblock->fs_bsize;
935} 935}
936 936
937static struct bufarea * getnewblk(daddr_t *); 937static struct bufarea * getnewblk(daddr_t *);
938static struct bufarea * 938static struct bufarea *
939getnewblk(daddr_t *blkno) 939getnewblk(daddr_t *blkno)
940{ 940{
941 struct bufarea *bp; 941 struct bufarea *bp;
942 *blkno = allocblk(sblock->fs_frag); 942 *blkno = allocblk(sblock->fs_frag);
943 if (*blkno == 0) 943 if (*blkno == 0)
944 return NULL; 944 return NULL;
945 bp = getdatablk(*blkno, sblock->fs_bsize); 945 bp = getdatablk(*blkno, sblock->fs_bsize);
946 memset(bp->b_un.b_buf, 0, sblock->fs_bsize); 946 memset(bp->b_un.b_buf, 0, sblock->fs_bsize);
947 return bp; 947 return bp;
948} 948}
949 949
950/* expand given inode by one full fs block */ 950/* expand given inode by one full fs block */
951struct bufarea * 951struct bufarea *
952expandfile(union dinode *dp) 952expandfile(union dinode *dp)
953{ 953{
954 uint64_t filesize = iswap64(DIP(dp, size)); 954 uint64_t filesize = iswap64(DIP(dp, size));
955 daddr_t newblk, blkno, iblkno, nblks; 955 daddr_t newblk, blkno, iblkno, nblks;
956 daddr_t di_blocks; 956 daddr_t di_blocks;
957 int ilevel; 957 int ilevel;
958 const daddr_t naddrperblk = sblock->fs_bsize / 958 const daddr_t naddrperblk = sblock->fs_bsize /
959 (is_ufs2 ? sizeof(uint64_t) : sizeof(uint32_t)); 959 (is_ufs2 ? sizeof(uint64_t) : sizeof(uint32_t));
960 struct bufarea *ibp, *bp = NULL; 960 struct bufarea *ibp, *bp = NULL;
961 961
962 di_blocks = is_ufs2 ? iswap64(dp->dp2.di_blocks) : 962 di_blocks = is_ufs2 ? iswap64(dp->dp2.di_blocks) :
963 iswap32(dp->dp1.di_blocks); 963 iswap32(dp->dp1.di_blocks);
964 /* compute location of new block */ 964 /* compute location of new block */
965 blkno = ffs_lblkno(sblock, filesize); 965 blkno = ffs_lblkno(sblock, filesize);
966 966
967 if (blkno < UFS_NDADDR) { 967 if (blkno < UFS_NDADDR) {
968 /* easy way: allocate a direct block */ 968 /* easy way: allocate a direct block */
969 if ((bp = getnewblk(&newblk)) == NULL) { 969 if ((bp = getnewblk(&newblk)) == NULL) {
970 return NULL; 970 return NULL;
971 } 971 }
972 di_blocks += btodb(sblock->fs_bsize); 972 di_blocks += btodb(sblock->fs_bsize);
973 973
974 if (is_ufs2) { 974 if (is_ufs2) {
975 dp->dp2.di_db[blkno] = iswap64(newblk); 975 dp->dp2.di_db[blkno] = iswap64(newblk);
976 } else { 976 } else {
977 dp->dp1.di_db[blkno] = iswap32(newblk); 977 dp->dp1.di_db[blkno] = iswap32(newblk);
978 } 978 }
979 goto out; 979 goto out;
980 } 980 }
981 blkno -= UFS_NDADDR; 981 blkno -= UFS_NDADDR;
982 /* find indir level */ 982 /* find indir level */
983 for (ilevel = 1, nblks = naddrperblk; 983 for (ilevel = 1, nblks = naddrperblk;
984 ilevel <= UFS_NIADDR; 984 ilevel <= UFS_NIADDR;
985 ilevel++, nblks *= naddrperblk) { 985 ilevel++, nblks *= naddrperblk) {
986 if (blkno < nblks) 986 if (blkno < nblks)
987 break; 987 break;
988 else 988 else
989 blkno -= nblks; 989 blkno -= nblks;
990 } 990 }
991 if (ilevel > UFS_NIADDR)  991 if (ilevel > UFS_NIADDR)
992 errexit("bad filesize %" PRIu64 " to expandfile", filesize); 992 errexit("bad filesize %" PRIu64 " to expandfile", filesize);
993 993
994 /* get the first indirect block, allocating if needed */ 994 /* get the first indirect block, allocating if needed */
995 if ((is_ufs2 ? iswap64(dp->dp2.di_ib[ilevel - 1]) : 995 if ((is_ufs2 ? iswap64(dp->dp2.di_ib[ilevel - 1]) :
996 iswap32(dp->dp1.di_ib[ilevel - 1])) == 0) { 996 iswap32(dp->dp1.di_ib[ilevel - 1])) == 0) {
997 if ((ibp = getnewblk(&newblk)) == NULL) 997 if ((ibp = getnewblk(&newblk)) == NULL)
998 return 0; 998 return 0;
999 di_blocks += btodb(sblock->fs_bsize); 999 di_blocks += btodb(sblock->fs_bsize);
1000 if (is_ufs2) 1000 if (is_ufs2)
1001 dp->dp2.di_ib[ilevel - 1] = iswap64(newblk); 1001 dp->dp2.di_ib[ilevel - 1] = iswap64(newblk);
1002 else 1002 else
1003 dp->dp1.di_ib[ilevel - 1] = iswap32(newblk); 1003 dp->dp1.di_ib[ilevel - 1] = iswap32(newblk);
1004 } else { 1004 } else {
1005 ibp = getdatablk(is_ufs2 ? iswap64(dp->dp2.di_ib[ilevel - 1]) : 1005 ibp = getdatablk(is_ufs2 ? iswap64(dp->dp2.di_ib[ilevel - 1]) :
1006 iswap32(dp->dp1.di_ib[ilevel - 1]), sblock->fs_bsize); 1006 iswap32(dp->dp1.di_ib[ilevel - 1]), sblock->fs_bsize);
1007 } 1007 }
1008 /* walk indirect blocks up to the data block */ 1008 /* walk indirect blocks up to the data block */
1009 for (; ilevel >0 ; ilevel--) { 1009 for (; ilevel >0 ; ilevel--) {
1010 nblks = nblks / naddrperblk; 1010 nblks = nblks / naddrperblk;
1011 if (is_ufs2) 1011 if (is_ufs2)
1012 iblkno = iswap64(ibp->b_un.b_indir2[blkno / nblks]); 1012 iblkno = iswap64(ibp->b_un.b_indir2[blkno / nblks]);
1013 else 1013 else
1014 iblkno = iswap32(ibp->b_un.b_indir1[blkno / nblks]); 1014 iblkno = iswap32(ibp->b_un.b_indir1[blkno / nblks]);
1015 if (iblkno == 0) { 1015 if (iblkno == 0) {
1016 if ((bp = getnewblk(&newblk)) == NULL) 1016 if ((bp = getnewblk(&newblk)) == NULL)
1017 return NULL; 1017 return NULL;
1018 di_blocks += btodb(sblock->fs_bsize); 1018 di_blocks += btodb(sblock->fs_bsize);
1019 if (is_ufs2) 1019 if (is_ufs2)
1020 ibp->b_un.b_indir2[blkno / nblks] = 1020 ibp->b_un.b_indir2[blkno / nblks] =
1021 iswap64(newblk); 1021 iswap64(newblk);
1022 else 1022 else
1023 ibp->b_un.b_indir1[blkno / nblks] = 1023 ibp->b_un.b_indir1[blkno / nblks] =
1024 iswap32(newblk); 1024 iswap32(newblk);
1025 dirty(ibp); 1025 dirty(ibp);
1026 ibp->b_flags &= ~B_INUSE; 1026 ibp->b_flags &= ~B_INUSE;
1027 ibp = bp; 1027 ibp = bp;
1028 } else { 1028 } else {
1029 ibp->b_flags &= ~B_INUSE; 1029 ibp->b_flags &= ~B_INUSE;
1030 ibp = getdatablk(iblkno, sblock->fs_bsize); 1030 ibp = getdatablk(iblkno, sblock->fs_bsize);
1031 bp = NULL; 1031 bp = NULL;
1032 } 1032 }
1033 blkno = blkno % nblks; 1033 blkno = blkno % nblks;
1034 } 1034 }
1035 if (bp == NULL) { 1035 if (bp == NULL) {
1036 errexit("INTERNAL ERROR: " 1036 errexit("INTERNAL ERROR: "
1037 "expandfile() failed to allocate a new block\n"); 1037 "expandfile() failed to allocate a new block\n");
1038 } 1038 }
1039  1039
1040out: 1040out:
1041 filesize += sblock->fs_bsize; 1041 filesize += sblock->fs_bsize;
1042 if (is_ufs2) { 1042 if (is_ufs2) {
1043 dp->dp2.di_size = iswap64(filesize); 1043 dp->dp2.di_size = iswap64(filesize);
1044 dp->dp2.di_blocks = iswap64(di_blocks); 1044 dp->dp2.di_blocks = iswap64(di_blocks);
1045 } else { 1045 } else {
1046 dp->dp1.di_size = iswap64(filesize); 1046 dp->dp1.di_size = iswap64(filesize);
1047 dp->dp1.di_blocks = iswap32(di_blocks); 1047 dp->dp1.di_blocks = iswap32(di_blocks);
1048 } 1048 }
1049 inodirty(); 1049 inodirty();
1050 return bp; 1050 return bp;
1051} 1051}

cvs diff -r1.102 -r1.103 src/sbin/fsck_ffs/setup.c (switch to unified diff)

--- src/sbin/fsck_ffs/setup.c 2018/10/05 09:49:23 1.102
+++ src/sbin/fsck_ffs/setup.c 2020/04/17 09:42:27 1.103
@@ -1,1144 +1,1147 @@ @@ -1,1144 +1,1147 @@
1/* $NetBSD: setup.c,v 1.102 2018/10/05 09:49:23 hannken Exp $ */ 1/* $NetBSD: setup.c,v 1.103 2020/04/17 09:42:27 jdolecek Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1980, 1986, 1993 4 * Copyright (c) 1980, 1986, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors 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 16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission. 17 * without specific prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 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 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33#ifndef lint 33#ifndef lint
34#if 0 34#if 0
35static char sccsid[] = "@(#)setup.c 8.10 (Berkeley) 5/9/95"; 35static char sccsid[] = "@(#)setup.c 8.10 (Berkeley) 5/9/95";
36#else 36#else
37__RCSID("$NetBSD: setup.c,v 1.102 2018/10/05 09:49:23 hannken Exp $"); 37__RCSID("$NetBSD: setup.c,v 1.103 2020/04/17 09:42:27 jdolecek Exp $");
38#endif 38#endif
39#endif /* not lint */ 39#endif /* not lint */
40 40
41#include <sys/param.h> 41#include <sys/param.h>
42#include <sys/time.h> 42#include <sys/time.h>
43#include <sys/stat.h> 43#include <sys/stat.h>
44#include <sys/ioctl.h> 44#include <sys/ioctl.h>
45#include <sys/file.h> 45#include <sys/file.h>
46#include <sys/disk.h> 46#include <sys/disk.h>
47 47
48#include <ufs/ufs/dinode.h> 48#include <ufs/ufs/dinode.h>
49#include <ufs/ufs/dir.h> 49#include <ufs/ufs/dir.h>
50#include <ufs/ufs/ufs_bswap.h> 50#include <ufs/ufs/ufs_bswap.h>
51#include <ufs/ufs/quota2.h> 51#include <ufs/ufs/quota2.h>
52#include <ufs/ffs/fs.h> 52#include <ufs/ffs/fs.h>
53#include <ufs/ffs/ffs_extern.h> 53#include <ufs/ffs/ffs_extern.h>
54 54
55#include <ctype.h> 55#include <ctype.h>
56#include <err.h> 56#include <err.h>
57#include <errno.h> 57#include <errno.h>
58#include <stdio.h> 58#include <stdio.h>
59#include <stdlib.h> 59#include <stdlib.h>
60#include <string.h> 60#include <string.h>
61 61
62#include "fsck.h" 62#include "fsck.h"
63#include "extern.h" 63#include "extern.h"
64#include "fsutil.h" 64#include "fsutil.h"
65#include "partutil.h" 65#include "partutil.h"
66#include "exitvalues.h" 66#include "exitvalues.h"
67 67
68#define POWEROF2(num) (((num) & ((num) - 1)) == 0) 68#define POWEROF2(num) (((num) & ((num) - 1)) == 0)
69 69
70static void badsb(int, const char *); 70static void badsb(int, const char *);
71static int calcsb(const char *, int, struct fs *); 71static int calcsb(const char *, int, struct fs *);
72static int readsb(int); 72static int readsb(int);
73#ifndef NO_APPLE_UFS 73#ifndef NO_APPLE_UFS
74static int readappleufs(void); 74static int readappleufs(void);
75#endif 75#endif
76static int check_snapinum(void); 76static int check_snapinum(void);
77 77
78int16_t sblkpostbl[256]; 78int16_t sblkpostbl[256];
79 79
80/* 80/*
81 * Read in a superblock finding an alternate if necessary. 81 * Read in a superblock finding an alternate if necessary.
82 * Return 1 if successful, 0 if unsuccessful, -1 if filesystem 82 * Return 1 if successful, 0 if unsuccessful, -1 if filesystem
83 * is already clean (preen mode only). 83 * is already clean (preen mode only).
84 */ 84 */
85int 85int
86setup(const char *dev, const char *origdev) 86setup(const char *dev, const char *origdev)
87{ 87{
88 long cg, size, asked, i, j; 88 long cg, size, asked, i, j;
89 long bmapsize; 89 long bmapsize;
90 struct disk_geom geo; 90 struct disk_geom geo;
91 struct dkwedge_info dkw; 91 struct dkwedge_info dkw;
92 off_t sizepb; 92 off_t sizepb;
93 struct stat statb; 93 struct stat statb;
94 struct fs proto; 94 struct fs proto;
95 int doskipclean; 95 int doskipclean;
96 u_int64_t maxfilesize; 96 u_int64_t maxfilesize;
97 struct csum *ccsp; 97 struct csum *ccsp;
98 int fd; 98 int fd;
99 99
100 havesb = 0; 100 havesb = 0;
101 fswritefd = -1; 101 fswritefd = -1;
102 doskipclean = skipclean; 102 doskipclean = skipclean;
103 if (stat(dev, &statb) < 0) { 103 if (stat(dev, &statb) < 0) {
104 printf("Can't stat %s: %s\n", dev, strerror(errno)); 104 printf("Can't stat %s: %s\n", dev, strerror(errno));
105 return (0); 105 return (0);
106 } 106 }
107 if (!forceimage && !S_ISCHR(statb.st_mode)) { 107 if (!forceimage && !S_ISCHR(statb.st_mode)) {
108 pfatal("%s is not a character device", dev); 108 pfatal("%s is not a character device", dev);
109 if (reply("CONTINUE") == 0) 109 if (reply("CONTINUE") == 0)
110 return (0); 110 return (0);
111 } 111 }
112 if ((fsreadfd = open(dev, O_RDONLY)) < 0) { 112 if ((fsreadfd = open(dev, O_RDONLY)) < 0) {
113 printf("Can't open %s: %s\n", dev, strerror(errno)); 113 printf("Can't open %s: %s\n", dev, strerror(errno));
114 return (0); 114 return (0);
115 } 115 }
116 if (nflag || (fswritefd = open(dev, O_WRONLY)) < 0) { 116 if (nflag || (fswritefd = open(dev, O_WRONLY)) < 0) {
117 fswritefd = -1; 117 fswritefd = -1;
118 if (preen) 118 if (preen)
119 pfatal("NO WRITE ACCESS"); 119 pfatal("NO WRITE ACCESS");
120 printf("** %s (NO WRITE)\n", dev); 120 printf("** %s (NO WRITE)\n", dev);
121 quiet = 0; 121 quiet = 0;
122 } else 122 } else
123 if (!preen && !quiet) 123 if (!preen && !quiet)
124 printf("** %s\n", dev); 124 printf("** %s\n", dev);
125 fsmodified = 0; 125 fsmodified = 0;
126 lfdir = 0; 126 lfdir = 0;
127 initbarea(&sblk); 127 initbarea(&sblk);
128 initbarea(&asblk); 128 initbarea(&asblk);
129 sblk.b_un.b_buf = malloc(SBLOCKSIZE); 129 sblk.b_un.b_buf = aligned_alloc(DEV_BSIZE, SBLOCKSIZE);
130 sblock = malloc(SBLOCKSIZE); 130 sblock = aligned_alloc(DEV_BSIZE, SBLOCKSIZE);
131 asblk.b_un.b_buf = malloc(SBLOCKSIZE); 131 asblk.b_un.b_buf = aligned_alloc(DEV_BSIZE, SBLOCKSIZE);
132 altsblock = malloc(SBLOCKSIZE); 132 altsblock = aligned_alloc(DEV_BSIZE, SBLOCKSIZE);
133 if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL || 133 if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL ||
134 sblock == NULL || altsblock == NULL) 134 sblock == NULL || altsblock == NULL)
135 errexit("Cannot allocate space for superblock"); 135 errexit("Cannot allocate space for superblock");
136 if (strcmp(dev, origdev) && !forceimage) { 136 if (strcmp(dev, origdev) && !forceimage) {
137 /* 137 /*
138 * dev isn't the original fs (for example it's a snapshot) 138 * dev isn't the original fs (for example it's a snapshot)
139 * do getdiskinfo on the original device 139 * do getdiskinfo on the original device
140 */ 140 */
141 fd = open(origdev, O_RDONLY); 141 fd = open(origdev, O_RDONLY);
142 if (fd < 0) { 142 if (fd < 0) {
143 warn("Can't open %s", origdev); 143 warn("Can't open %s", origdev);
144 return (0); 144 return (0);
145 } 145 }
146 } else { 146 } else {
147 fd = fsreadfd; 147 fd = fsreadfd;
148 } 148 }
149 if (!forceimage && getdiskinfo(origdev, fd, NULL, &geo, &dkw) != -1) 149 if (!forceimage && getdiskinfo(origdev, fd, NULL, &geo, &dkw) != -1)
150 dev_bsize = secsize = geo.dg_secsize; 150 dev_bsize = secsize = geo.dg_secsize;
151 else 151 else
152 dev_bsize = secsize = DEV_BSIZE; 152 dev_bsize = secsize = DEV_BSIZE;
153 /* 153 /*
154 * Read in the superblock, looking for alternates if necessary 154 * Read in the superblock, looking for alternates if necessary
155 */ 155 */
156 if (readsb(1) == 0) { 156 if (readsb(1) == 0) {
157 if (bflag || preen || forceimage || 157 if (bflag || preen || forceimage ||
158 calcsb(dev, fsreadfd, &proto) == 0) 158 calcsb(dev, fsreadfd, &proto) == 0)
159 return(0); 159 return(0);
160 if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0) 160 if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0)
161 return (0); 161 return (0);
162 for (cg = 0; cg < proto.fs_ncg; cg++) { 162 for (cg = 0; cg < proto.fs_ncg; cg++) {
163 bflag = FFS_FSBTODB(&proto, cgsblock(&proto, cg)); 163 bflag = FFS_FSBTODB(&proto, cgsblock(&proto, cg));
164 if (readsb(0) != 0) 164 if (readsb(0) != 0)
165 break; 165 break;
166 } 166 }
167 if (cg >= proto.fs_ncg) { 167 if (cg >= proto.fs_ncg) {
168 printf("%s %s\n%s %s\n%s %s\n", 168 printf("%s %s\n%s %s\n%s %s\n",
169 "SEARCH FOR ALTERNATE SUPER-BLOCK", 169 "SEARCH FOR ALTERNATE SUPER-BLOCK",
170 "FAILED. YOU MUST USE THE", 170 "FAILED. YOU MUST USE THE",
171 "-b OPTION TO fsck_ffs TO SPECIFY THE", 171 "-b OPTION TO fsck_ffs TO SPECIFY THE",
172 "LOCATION OF AN ALTERNATE", 172 "LOCATION OF AN ALTERNATE",
173 "SUPER-BLOCK TO SUPPLY NEEDED", 173 "SUPER-BLOCK TO SUPPLY NEEDED",
174 "INFORMATION; SEE fsck_ffs(8)."); 174 "INFORMATION; SEE fsck_ffs(8).");
175 return(0); 175 return(0);
176 } 176 }
177 doskipclean = 0; 177 doskipclean = 0;
178 pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag); 178 pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag);
179 } 179 }
180 180
181 if (!quota2_check_doquota()) 181 if (!quota2_check_doquota())
182 doskipclean = 0; 182 doskipclean = 0;
183  183
184 /* ffs_superblock_layout() == 2 */ 184 /* ffs_superblock_layout() == 2 */
185 if (sblock->fs_magic != FS_UFS1_MAGIC || 185 if (sblock->fs_magic != FS_UFS1_MAGIC ||
186 (sblock->fs_old_flags & FS_FLAGS_UPDATED) != 0) { 186 (sblock->fs_old_flags & FS_FLAGS_UPDATED) != 0) {
187 /* can have WAPBL */ 187 /* can have WAPBL */
188 if (check_wapbl() != 0) { 188 if (check_wapbl() != 0) {
189 doskipclean = 0; 189 doskipclean = 0;
190 } 190 }
191 if (sblock->fs_flags & FS_DOWAPBL) { 191 if (sblock->fs_flags & FS_DOWAPBL) {
192 if (preen && doskipclean) { 192 if (preen && doskipclean) {
193 if (!quiet) 193 if (!quiet)
194 pwarn("file system is journaled; " 194 pwarn("file system is journaled; "
195 "not checking\n"); 195 "not checking\n");
196 return (-1); 196 return (-1);
197 } 197 }
198 if (!quiet) 198 if (!quiet)
199 pwarn("** File system is journaled; " 199 pwarn("** File system is journaled; "
200 "replaying journal\n"); 200 "replaying journal\n");
201 replay_wapbl(); 201 replay_wapbl();
202 doskipclean = 0; 202 doskipclean = 0;
203 sblock->fs_flags &= ~FS_DOWAPBL; 203 sblock->fs_flags &= ~FS_DOWAPBL;
204 sbdirty(); 204 sbdirty();
205 /* Although we may have updated the superblock from 205 /* Although we may have updated the superblock from
206 * the journal, we are still going to do a full check, 206 * the journal, we are still going to do a full check,
207 * so we don't bother to re-read the superblock from 207 * so we don't bother to re-read the superblock from
208 * the journal. 208 * the journal.
209 * XXX, instead we could re-read the superblock and 209 * XXX, instead we could re-read the superblock and
210 * then not force doskipclean = 0  210 * then not force doskipclean = 0
211 */ 211 */
212 } 212 }
213 } 213 }
214 if (debug) 214 if (debug)
215 printf("clean = %d\n", sblock->fs_clean); 215 printf("clean = %d\n", sblock->fs_clean);
216 216
217 if (doswap) 217 if (doswap)
218 doskipclean = 0; 218 doskipclean = 0;
219 219
220 if (sblock->fs_clean & FS_ISCLEAN) { 220 if (sblock->fs_clean & FS_ISCLEAN) {
221 if (doskipclean) { 221 if (doskipclean) {
222 if (!quiet) 222 if (!quiet)
223 pwarn("%sile system is clean; not checking\n", 223 pwarn("%sile system is clean; not checking\n",
224 preen ? "f" : "** F"); 224 preen ? "f" : "** F");
225 return (-1); 225 return (-1);
226 } 226 }
227 if (!preen && !doswap) 227 if (!preen && !doswap)
228 pwarn("** File system is already clean\n"); 228 pwarn("** File system is already clean\n");
229 } 229 }
230 maxfsblock = sblock->fs_size; 230 maxfsblock = sblock->fs_size;
231 maxino = sblock->fs_ncg * sblock->fs_ipg; 231 maxino = sblock->fs_ncg * sblock->fs_ipg;
232 sizepb = sblock->fs_bsize; 232 sizepb = sblock->fs_bsize;
233 maxfilesize = sblock->fs_bsize * UFS_NDADDR - 1; 233 maxfilesize = sblock->fs_bsize * UFS_NDADDR - 1;
234 for (i = 0; i < UFS_NIADDR; i++) { 234 for (i = 0; i < UFS_NIADDR; i++) {
235 sizepb *= FFS_NINDIR(sblock); 235 sizepb *= FFS_NINDIR(sblock);
236 maxfilesize += sizepb; 236 maxfilesize += sizepb;
237 } 237 }
238 if ((!is_ufs2 && cvtlevel >= 4) && 238 if ((!is_ufs2 && cvtlevel >= 4) &&
239 (sblock->fs_old_flags & FS_FLAGS_UPDATED) == 0) { 239 (sblock->fs_old_flags & FS_FLAGS_UPDATED) == 0) {
240 if (preen) 240 if (preen)
241 pwarn("CONVERTING TO NEW SUPERBLOCK LAYOUT\n"); 241 pwarn("CONVERTING TO NEW SUPERBLOCK LAYOUT\n");
242 else if (!reply("CONVERT TO NEW SUPERBLOCK LAYOUT")) 242 else if (!reply("CONVERT TO NEW SUPERBLOCK LAYOUT"))
243 return(0); 243 return(0);
244 sblock->fs_old_flags |= FS_FLAGS_UPDATED; 244 sblock->fs_old_flags |= FS_FLAGS_UPDATED;
245 /* Disable the postbl tables */ 245 /* Disable the postbl tables */
246 sblock->fs_old_cpc = 0; 246 sblock->fs_old_cpc = 0;
247 sblock->fs_old_nrpos = 1; 247 sblock->fs_old_nrpos = 1;
248 sblock->fs_old_trackskew = 0; 248 sblock->fs_old_trackskew = 0;
249 /* The other fields have already been updated by 249 /* The other fields have already been updated by
250 * sb_oldfscompat_read 250 * sb_oldfscompat_read
251 */ 251 */
252 sbdirty(); 252 sbdirty();
253 } 253 }
254 if (!is_ufs2 && cvtlevel == 3 && 254 if (!is_ufs2 && cvtlevel == 3 &&
255 (sblock->fs_old_flags & FS_FLAGS_UPDATED)) { 255 (sblock->fs_old_flags & FS_FLAGS_UPDATED)) {
256 if (preen) 256 if (preen)
257 pwarn("DOWNGRADING TO OLD SUPERBLOCK LAYOUT\n"); 257 pwarn("DOWNGRADING TO OLD SUPERBLOCK LAYOUT\n");
258 else if (!reply("DOWNGRADE TO OLD SUPERBLOCK LAYOUT")) 258 else if (!reply("DOWNGRADE TO OLD SUPERBLOCK LAYOUT"))
259 return(0); 259 return(0);
260 sblock->fs_old_flags &= ~FS_FLAGS_UPDATED; 260 sblock->fs_old_flags &= ~FS_FLAGS_UPDATED;
261 sb_oldfscompat_write(sblock, sblock); 261 sb_oldfscompat_write(sblock, sblock);
262 sblock->fs_old_flags &= ~FS_FLAGS_UPDATED; /* just in case */ 262 sblock->fs_old_flags &= ~FS_FLAGS_UPDATED; /* just in case */
263 /* Leave postbl tables disabled, but blank its superblock region anyway */ 263 /* Leave postbl tables disabled, but blank its superblock region anyway */
264 sblock->fs_old_postblformat = FS_DYNAMICPOSTBLFMT; 264 sblock->fs_old_postblformat = FS_DYNAMICPOSTBLFMT;
265 sblock->fs_old_cpc = 0; 265 sblock->fs_old_cpc = 0;
266 sblock->fs_old_nrpos = 1; 266 sblock->fs_old_nrpos = 1;
267 sblock->fs_old_trackskew = 0; 267 sblock->fs_old_trackskew = 0;
268 memset(&sblock->fs_old_postbl_start, 0xff, 256); 268 memset(&sblock->fs_old_postbl_start, 0xff, 256);
269 sb_oldfscompat_read(sblock, &sblocksave); 269 sb_oldfscompat_read(sblock, &sblocksave);
270 sbdirty(); 270 sbdirty();
271 } 271 }
272 /* 272 /*
273 * Check and potentially fix certain fields in the super block. 273 * Check and potentially fix certain fields in the super block.
274 */ 274 */
275 if (sblock->fs_flags & ~(FS_KNOWN_FLAGS)) { 275 if (sblock->fs_flags & ~(FS_KNOWN_FLAGS)) {
276 pfatal("UNKNOWN FLAGS=0x%08x IN SUPERBLOCK", sblock->fs_flags); 276 pfatal("UNKNOWN FLAGS=0x%08x IN SUPERBLOCK", sblock->fs_flags);
277 if (reply("CLEAR") == 1) { 277 if (reply("CLEAR") == 1) {
278 sblock->fs_flags &= FS_KNOWN_FLAGS; 278 sblock->fs_flags &= FS_KNOWN_FLAGS;
279 sbdirty(); 279 sbdirty();
280 } 280 }
281 } 281 }
282 if (sblock->fs_optim != FS_OPTTIME && sblock->fs_optim != FS_OPTSPACE) { 282 if (sblock->fs_optim != FS_OPTTIME && sblock->fs_optim != FS_OPTSPACE) {
283 pfatal("UNDEFINED OPTIMIZATION IN SUPERBLOCK"); 283 pfatal("UNDEFINED OPTIMIZATION IN SUPERBLOCK");
284 if (reply("SET TO DEFAULT") == 1) { 284 if (reply("SET TO DEFAULT") == 1) {
285 sblock->fs_optim = FS_OPTTIME; 285 sblock->fs_optim = FS_OPTTIME;
286 sbdirty(); 286 sbdirty();
287 } 287 }
288 } 288 }
289 if ((sblock->fs_minfree < 0 || sblock->fs_minfree > 99)) { 289 if ((sblock->fs_minfree < 0 || sblock->fs_minfree > 99)) {
290 pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK", 290 pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK",
291 sblock->fs_minfree); 291 sblock->fs_minfree);
292 if (reply("SET TO DEFAULT") == 1) { 292 if (reply("SET TO DEFAULT") == 1) {
293 sblock->fs_minfree = 10; 293 sblock->fs_minfree = 10;
294 sbdirty(); 294 sbdirty();
295 } 295 }
296 } 296 }
297 if (!is_ufs2 && sblock->fs_old_postblformat != FS_42POSTBLFMT && 297 if (!is_ufs2 && sblock->fs_old_postblformat != FS_42POSTBLFMT &&
298 (sblock->fs_old_interleave < 1 ||  298 (sblock->fs_old_interleave < 1 ||
299 sblock->fs_old_interleave > sblock->fs_old_nsect)) { 299 sblock->fs_old_interleave > sblock->fs_old_nsect)) {
300 pwarn("IMPOSSIBLE INTERLEAVE=%d IN SUPERBLOCK", 300 pwarn("IMPOSSIBLE INTERLEAVE=%d IN SUPERBLOCK",
301 sblock->fs_old_interleave); 301 sblock->fs_old_interleave);
302 sblock->fs_old_interleave = 1; 302 sblock->fs_old_interleave = 1;
303 if (preen) 303 if (preen)
304 printf(" (FIXED)\n"); 304 printf(" (FIXED)\n");
305 if (preen || reply("SET TO DEFAULT") == 1) { 305 if (preen || reply("SET TO DEFAULT") == 1) {
306 sbdirty(); 306 sbdirty();
307 dirty(&asblk); 307 dirty(&asblk);
308 } 308 }
309 } 309 }
310 if (!is_ufs2 && sblock->fs_old_postblformat != FS_42POSTBLFMT && 310 if (!is_ufs2 && sblock->fs_old_postblformat != FS_42POSTBLFMT &&
311 (sblock->fs_old_npsect < sblock->fs_old_nsect ||  311 (sblock->fs_old_npsect < sblock->fs_old_nsect ||
312 sblock->fs_old_npsect > sblock->fs_old_nsect*2)) { 312 sblock->fs_old_npsect > sblock->fs_old_nsect*2)) {
313 pwarn("IMPOSSIBLE NPSECT=%d IN SUPERBLOCK", 313 pwarn("IMPOSSIBLE NPSECT=%d IN SUPERBLOCK",
314 sblock->fs_old_npsect); 314 sblock->fs_old_npsect);
315 sblock->fs_old_npsect = sblock->fs_old_nsect; 315 sblock->fs_old_npsect = sblock->fs_old_nsect;
316 if (preen) 316 if (preen)
317 printf(" (FIXED)\n"); 317 printf(" (FIXED)\n");
318 if (preen || reply("SET TO DEFAULT") == 1) { 318 if (preen || reply("SET TO DEFAULT") == 1) {
319 sbdirty(); 319 sbdirty();
320 dirty(&asblk); 320 dirty(&asblk);
321 } 321 }
322 } 322 }
323 if (sblock->fs_bmask != ~(sblock->fs_bsize - 1)) { 323 if (sblock->fs_bmask != ~(sblock->fs_bsize - 1)) {
324 pwarn("INCORRECT BMASK=0x%x IN SUPERBLOCK", 324 pwarn("INCORRECT BMASK=0x%x IN SUPERBLOCK",
325 sblock->fs_bmask); 325 sblock->fs_bmask);
326 sblock->fs_bmask = ~(sblock->fs_bsize - 1); 326 sblock->fs_bmask = ~(sblock->fs_bsize - 1);
327 if (preen) 327 if (preen)
328 printf(" (FIXED)\n"); 328 printf(" (FIXED)\n");
329 if (preen || reply("FIX") == 1) { 329 if (preen || reply("FIX") == 1) {
330 sbdirty(); 330 sbdirty();
331 dirty(&asblk); 331 dirty(&asblk);
332 } 332 }
333 } 333 }
334 if (sblock->fs_fmask != ~(sblock->fs_fsize - 1)) { 334 if (sblock->fs_fmask != ~(sblock->fs_fsize - 1)) {
335 pwarn("INCORRECT FMASK=0x%x IN SUPERBLOCK", 335 pwarn("INCORRECT FMASK=0x%x IN SUPERBLOCK",
336 sblock->fs_fmask); 336 sblock->fs_fmask);
337 sblock->fs_fmask = ~(sblock->fs_fsize - 1); 337 sblock->fs_fmask = ~(sblock->fs_fsize - 1);
338 if (preen) 338 if (preen)
339 printf(" (FIXED)\n"); 339 printf(" (FIXED)\n");
340 if (preen || reply("FIX") == 1) { 340 if (preen || reply("FIX") == 1) {
341 sbdirty(); 341 sbdirty();
342 dirty(&asblk); 342 dirty(&asblk);
343 } 343 }
344 } 344 }
345 if (check_snapinum()) { 345 if (check_snapinum()) {
346 if (preen) 346 if (preen)
347 printf(" (FIXED)\n"); 347 printf(" (FIXED)\n");
348 if (preen || reply("FIX") == 1) { 348 if (preen || reply("FIX") == 1) {
349 sbdirty(); 349 sbdirty();
350 dirty(&asblk); 350 dirty(&asblk);
351 } 351 }
352 } 352 }
353 if (is_ufs2 || sblock->fs_old_inodefmt >= FS_44INODEFMT) { 353 if (is_ufs2 || sblock->fs_old_inodefmt >= FS_44INODEFMT) {
354 if (sblock->fs_maxfilesize != maxfilesize) { 354 if (sblock->fs_maxfilesize != maxfilesize) {
355 pwarn("INCORRECT MAXFILESIZE=%lld IN SUPERBLOCK", 355 pwarn("INCORRECT MAXFILESIZE=%lld IN SUPERBLOCK",
356 (unsigned long long)sblock->fs_maxfilesize); 356 (unsigned long long)sblock->fs_maxfilesize);
357 sblock->fs_maxfilesize = maxfilesize; 357 sblock->fs_maxfilesize = maxfilesize;
358 if (preen) 358 if (preen)
359 printf(" (FIXED)\n"); 359 printf(" (FIXED)\n");
360 if (preen || reply("FIX") == 1) { 360 if (preen || reply("FIX") == 1) {
361 sbdirty(); 361 sbdirty();
362 dirty(&asblk); 362 dirty(&asblk);
363 } 363 }
364 } 364 }
365 if ((is_ufs2 && sblock->fs_maxsymlinklen != UFS2_MAXSYMLINKLEN) 365 if ((is_ufs2 && sblock->fs_maxsymlinklen != UFS2_MAXSYMLINKLEN)
366 || 366 ||
367 (!is_ufs2 && sblock->fs_maxsymlinklen != UFS1_MAXSYMLINKLEN)) 367 (!is_ufs2 && sblock->fs_maxsymlinklen != UFS1_MAXSYMLINKLEN))
368 { 368 {
369 pwarn("INCORRECT MAXSYMLINKLEN=%d IN SUPERBLOCK", 369 pwarn("INCORRECT MAXSYMLINKLEN=%d IN SUPERBLOCK",
370 sblock->fs_maxsymlinklen); 370 sblock->fs_maxsymlinklen);
371 sblock->fs_maxsymlinklen = is_ufs2 ? 371 sblock->fs_maxsymlinklen = is_ufs2 ?
372 UFS2_MAXSYMLINKLEN : UFS1_MAXSYMLINKLEN; 372 UFS2_MAXSYMLINKLEN : UFS1_MAXSYMLINKLEN;
373 if (preen) 373 if (preen)
374 printf(" (FIXED)\n"); 374 printf(" (FIXED)\n");
375 if (preen || reply("FIX") == 1) { 375 if (preen || reply("FIX") == 1) {
376 sbdirty(); 376 sbdirty();
377 dirty(&asblk); 377 dirty(&asblk);
378 } 378 }
379 } 379 }
380 if (sblock->fs_qbmask != ~sblock->fs_bmask) { 380 if (sblock->fs_qbmask != ~sblock->fs_bmask) {
381 pwarn("INCORRECT QBMASK=%#llx IN SUPERBLOCK", 381 pwarn("INCORRECT QBMASK=%#llx IN SUPERBLOCK",
382 (unsigned long long)sblock->fs_qbmask); 382 (unsigned long long)sblock->fs_qbmask);
383 sblock->fs_qbmask = ~sblock->fs_bmask; 383 sblock->fs_qbmask = ~sblock->fs_bmask;
384 if (preen) 384 if (preen)
385 printf(" (FIXED)\n"); 385 printf(" (FIXED)\n");
386 if (preen || reply("FIX") == 1) { 386 if (preen || reply("FIX") == 1) {
387 sbdirty(); 387 sbdirty();
388 dirty(&asblk); 388 dirty(&asblk);
389 } 389 }
390 } 390 }
391 if (sblock->fs_qfmask != ~sblock->fs_fmask) { 391 if (sblock->fs_qfmask != ~sblock->fs_fmask) {
392 pwarn("INCORRECT QFMASK=%#llx IN SUPERBLOCK", 392 pwarn("INCORRECT QFMASK=%#llx IN SUPERBLOCK",
393 (unsigned long long)sblock->fs_qfmask); 393 (unsigned long long)sblock->fs_qfmask);
394 sblock->fs_qfmask = ~sblock->fs_fmask; 394 sblock->fs_qfmask = ~sblock->fs_fmask;
395 if (preen) 395 if (preen)
396 printf(" (FIXED)\n"); 396 printf(" (FIXED)\n");
397 if (preen || reply("FIX") == 1) { 397 if (preen || reply("FIX") == 1) {
398 sbdirty(); 398 sbdirty();
399 dirty(&asblk); 399 dirty(&asblk);
400 } 400 }
401 } 401 }
402 newinofmt = 1; 402 newinofmt = 1;
403 } else { 403 } else {
404 sblock->fs_qbmask = ~sblock->fs_bmask; 404 sblock->fs_qbmask = ~sblock->fs_bmask;
405 sblock->fs_qfmask = ~sblock->fs_fmask; 405 sblock->fs_qfmask = ~sblock->fs_fmask;
406 newinofmt = 0; 406 newinofmt = 0;
407 } 407 }
408 /* 408 /*
409 * Convert to new inode format. 409 * Convert to new inode format.
410 */ 410 */
411 if (!is_ufs2 && cvtlevel >= 2 && 411 if (!is_ufs2 && cvtlevel >= 2 &&
412 sblock->fs_old_inodefmt < FS_44INODEFMT) { 412 sblock->fs_old_inodefmt < FS_44INODEFMT) {
413 if (preen) 413 if (preen)
414 pwarn("CONVERTING TO NEW INODE FORMAT\n"); 414 pwarn("CONVERTING TO NEW INODE FORMAT\n");
415 else if (!reply("CONVERT TO NEW INODE FORMAT")) 415 else if (!reply("CONVERT TO NEW INODE FORMAT"))
416 return(0); 416 return(0);
417 doinglevel2++; 417 doinglevel2++;
418 sblock->fs_old_inodefmt = FS_44INODEFMT; 418 sblock->fs_old_inodefmt = FS_44INODEFMT;
419 sblock->fs_maxfilesize = maxfilesize; 419 sblock->fs_maxfilesize = maxfilesize;
420 sblock->fs_maxsymlinklen = UFS1_MAXSYMLINKLEN; 420 sblock->fs_maxsymlinklen = UFS1_MAXSYMLINKLEN;
421 sblock->fs_qbmask = ~sblock->fs_bmask; 421 sblock->fs_qbmask = ~sblock->fs_bmask;
422 sblock->fs_qfmask = ~sblock->fs_fmask; 422 sblock->fs_qfmask = ~sblock->fs_fmask;
423 sbdirty(); 423 sbdirty();
424 dirty(&asblk); 424 dirty(&asblk);
425 } 425 }
426 /* 426 /*
427 * Convert to new cylinder group format. 427 * Convert to new cylinder group format.
428 */ 428 */
429 if (!is_ufs2 && cvtlevel >= 1 && 429 if (!is_ufs2 && cvtlevel >= 1 &&
430 sblock->fs_old_postblformat == FS_42POSTBLFMT) { 430 sblock->fs_old_postblformat == FS_42POSTBLFMT) {
431 if (preen) 431 if (preen)
432 pwarn("CONVERTING TO NEW CYLINDER GROUP FORMAT\n"); 432 pwarn("CONVERTING TO NEW CYLINDER GROUP FORMAT\n");
433 else if (!reply("CONVERT TO NEW CYLINDER GROUP FORMAT")) 433 else if (!reply("CONVERT TO NEW CYLINDER GROUP FORMAT"))
434 return(0); 434 return(0);
435 doinglevel1++; 435 doinglevel1++;
436 sblock->fs_old_postblformat = FS_DYNAMICPOSTBLFMT; 436 sblock->fs_old_postblformat = FS_DYNAMICPOSTBLFMT;
437 sblock->fs_old_nrpos = 8; 437 sblock->fs_old_nrpos = 8;
438 sblock->fs_old_postbloff = 438 sblock->fs_old_postbloff =
439 (char *)(&sblock->fs_old_postbl_start) - 439 (char *)(&sblock->fs_old_postbl_start) -
440 (char *)(&sblock->fs_firstfield); 440 (char *)(&sblock->fs_firstfield);
441 sblock->fs_old_rotbloff = 441 sblock->fs_old_rotbloff =
442 (char *)(&sblock->fs_magic+1) - 442 (char *)(&sblock->fs_magic+1) -
443 (char *)(&sblock->fs_firstfield); 443 (char *)(&sblock->fs_firstfield);
444 sblock->fs_cgsize = 444 sblock->fs_cgsize =
445 ffs_fragroundup(sblock, CGSIZE(sblock)); 445 ffs_fragroundup(sblock, CGSIZE(sblock));
446 sbdirty(); 446 sbdirty();
447 dirty(&asblk); 447 dirty(&asblk);
448 } 448 }
449 if (asblk.b_dirty && !bflag) { 449 if (asblk.b_dirty && !bflag) {
450 memmove(sblk.b_un.b_fs, sblock, SBLOCKSIZE); 450 memmove(sblk.b_un.b_fs, sblock, SBLOCKSIZE);
451 sb_oldfscompat_write(sblk.b_un.b_fs, sblocksave); 451 sb_oldfscompat_write(sblk.b_un.b_fs, sblocksave);
452 if (needswap) 452 if (needswap)
453 ffs_sb_swap(sblk.b_un.b_fs, sblk.b_un.b_fs); 453 ffs_sb_swap(sblk.b_un.b_fs, sblk.b_un.b_fs);
454 memmove(asblk.b_un.b_fs, sblk.b_un.b_fs, (size_t)sblock->fs_sbsize); 454 memmove(asblk.b_un.b_fs, sblk.b_un.b_fs, (size_t)sblock->fs_sbsize);
455 flush(fswritefd, &asblk); 455 flush(fswritefd, &asblk);
456 } 456 }
457 /* 457 /*
458 * read in the summary info. 458 * read in the summary info.
459 */ 459 */
460 asked = 0; 460 asked = 0;
461 sblock->fs_csp = (struct csum *)calloc(1, sblock->fs_cssize); 461 sblock->fs_csp = (struct csum *)aligned_alloc(DEV_BSIZE,
 462 sblock->fs_cssize);
462 if (sblock->fs_csp == NULL) { 463 if (sblock->fs_csp == NULL) {
463 pwarn("cannot alloc %u bytes for summary info\n", 464 pwarn("cannot alloc %u bytes for summary info\n",
464 sblock->fs_cssize);  465 sblock->fs_cssize);
465 goto badsblabel; 466 goto badsblabel;
466 } 467 }
 468 memset(sblock->fs_csp, 0, sblock->fs_cssize);
467 for (i = 0, j = 0; i < sblock->fs_cssize; i += sblock->fs_bsize, j++) { 469 for (i = 0, j = 0; i < sblock->fs_cssize; i += sblock->fs_bsize, j++) {
468 size = sblock->fs_cssize - i < sblock->fs_bsize ? 470 size = sblock->fs_cssize - i < sblock->fs_bsize ?
469 sblock->fs_cssize - i : sblock->fs_bsize; 471 sblock->fs_cssize - i : sblock->fs_bsize;
470 ccsp = (struct csum *)((char *)sblock->fs_csp + i); 472 ccsp = (struct csum *)((char *)sblock->fs_csp + i);
471 if (bread(fsreadfd, (char *)ccsp, 473 if (bread(fsreadfd, (char *)ccsp,
472 FFS_FSBTODB(sblock, sblock->fs_csaddr + j * sblock->fs_frag), 474 FFS_FSBTODB(sblock, sblock->fs_csaddr + j * sblock->fs_frag),
473 size) != 0 && !asked) { 475 size) != 0 && !asked) {
474 pfatal("BAD SUMMARY INFORMATION"); 476 pfatal("BAD SUMMARY INFORMATION");
475 if (reply("CONTINUE") == 0) { 477 if (reply("CONTINUE") == 0) {
476 markclean = 0; 478 markclean = 0;
477 exit(FSCK_EXIT_CHECK_FAILED); 479 exit(FSCK_EXIT_CHECK_FAILED);
478 } 480 }
479 asked++; 481 asked++;
480 } 482 }
481 if (doswap) { 483 if (doswap) {
482 ffs_csum_swap(ccsp, ccsp, size); 484 ffs_csum_swap(ccsp, ccsp, size);
483 bwrite(fswritefd, (char *)ccsp, 485 bwrite(fswritefd, (char *)ccsp,
484 FFS_FSBTODB(sblock, 486 FFS_FSBTODB(sblock,
485 sblock->fs_csaddr + j * sblock->fs_frag), 487 sblock->fs_csaddr + j * sblock->fs_frag),
486 size); 488 size);
487 } 489 }
488 if (needswap) 490 if (needswap)
489 ffs_csum_swap(ccsp, ccsp, size); 491 ffs_csum_swap(ccsp, ccsp, size);
490 } 492 }
491 /* 493 /*
492 * allocate and initialize the necessary maps 494 * allocate and initialize the necessary maps
493 */ 495 */
494 bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(int16_t)); 496 bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(int16_t));
495 blockmap = calloc((unsigned)bmapsize, sizeof (char)); 497 blockmap = aligned_alloc(DEV_BSIZE, (unsigned)bmapsize);
496 if (blockmap == NULL) { 498 if (blockmap == NULL) {
497 pwarn("cannot alloc %u bytes for blockmap\n", 499 pwarn("cannot alloc %u bytes for blockmap\n",
498 (unsigned)bmapsize); 500 (unsigned)bmapsize);
499 goto badsblabel; 501 goto badsblabel;
500 } 502 }
 503 memset(blockmap, 0, bmapsize);
501 inostathead = calloc((unsigned)(sblock->fs_ncg), 504 inostathead = calloc((unsigned)(sblock->fs_ncg),
502 sizeof(struct inostatlist)); 505 sizeof(struct inostatlist));
503 if (inostathead == NULL) { 506 if (inostathead == NULL) {
504 pwarn("cannot alloc %u bytes for inostathead\n", 507 pwarn("cannot alloc %u bytes for inostathead\n",
505 (unsigned)(sizeof(struct inostatlist) * (sblock->fs_ncg))); 508 (unsigned)(sizeof(struct inostatlist) * (sblock->fs_ncg)));
506 goto badsblabel; 509 goto badsblabel;
507 } 510 }
508 /* 511 /*
509 * cs_ndir may be inaccurate, particularly if we're using the -b 512 * cs_ndir may be inaccurate, particularly if we're using the -b
510 * option, so set a minimum to prevent bogus subdirectory reconnects 513 * option, so set a minimum to prevent bogus subdirectory reconnects
511 * and really inefficient directory scans. 514 * and really inefficient directory scans.
512 * Also set a maximum in case the value is too large. 515 * Also set a maximum in case the value is too large.
513 */ 516 */
514 numdirs = sblock->fs_cstotal.cs_ndir; 517 numdirs = sblock->fs_cstotal.cs_ndir;
515 if (numdirs < 1024) 518 if (numdirs < 1024)
516 numdirs = 1024; 519 numdirs = 1024;
517 if ((ino_t)numdirs > maxino + 1) 520 if ((ino_t)numdirs > maxino + 1)
518 numdirs = maxino + 1; 521 numdirs = maxino + 1;
519 dirhash = numdirs; 522 dirhash = numdirs;
520 inplast = 0; 523 inplast = 0;
521 listmax = numdirs + 10; 524 listmax = numdirs + 10;
522 inpsort = calloc((unsigned)listmax, sizeof(*inpsort)); 525 inpsort = calloc((unsigned)listmax, sizeof(*inpsort));
523 inphead = calloc((unsigned)numdirs, sizeof(*inphead)); 526 inphead = calloc((unsigned)numdirs, sizeof(*inphead));
524 if (inpsort == NULL || inphead == NULL) { 527 if (inpsort == NULL || inphead == NULL) {
525 pwarn("cannot alloc %u bytes for inphead\n",  528 pwarn("cannot alloc %u bytes for inphead\n",
526 (unsigned)(numdirs * sizeof(struct inoinfo *))); 529 (unsigned)(numdirs * sizeof(struct inoinfo *)));
527 goto badsblabel; 530 goto badsblabel;
528 } 531 }
529 cgrp = malloc(sblock->fs_cgsize); 532 cgrp = aligned_alloc(DEV_BSIZE, sblock->fs_cgsize);
530 if (cgrp == NULL) { 533 if (cgrp == NULL) {
531 pwarn("cannot alloc %u bytes for cylinder group\n", 534 pwarn("cannot alloc %u bytes for cylinder group\n",
532 sblock->fs_cgsize); 535 sblock->fs_cgsize);
533 goto badsblabel; 536 goto badsblabel;
534 } 537 }
535 bufinit(); 538 bufinit();
536 if (sblock->fs_flags & FS_DOSOFTDEP) 539 if (sblock->fs_flags & FS_DOSOFTDEP)
537 usedsoftdep = 1; 540 usedsoftdep = 1;
538 else 541 else
539 usedsoftdep = 0; 542 usedsoftdep = 0;
540 543
541#ifndef NO_APPLE_UFS 544#ifndef NO_APPLE_UFS
542 if (!forceimage && dkw.dkw_parent[0])  545 if (!forceimage && dkw.dkw_parent[0])
543 if (strcmp(dkw.dkw_ptype, DKW_PTYPE_APPLEUFS) == 0) 546 if (strcmp(dkw.dkw_ptype, DKW_PTYPE_APPLEUFS) == 0)
544 isappleufs = 1; 547 isappleufs = 1;
545 548
546 if (readappleufs()) 549 if (readappleufs())
547 isappleufs = 1; 550 isappleufs = 1;
548#endif 551#endif
549 552
550 if (isappleufs) 553 if (isappleufs)
551 dirblksiz = APPLEUFS_DIRBLKSIZ; 554 dirblksiz = APPLEUFS_DIRBLKSIZ;
552 else 555 else
553 dirblksiz = UFS_DIRBLKSIZ; 556 dirblksiz = UFS_DIRBLKSIZ;
554 557
555 if (debug) 558 if (debug)
556#ifndef NO_APPLE_UFS 559#ifndef NO_APPLE_UFS
557 printf("isappleufs = %d, dirblksiz = %d\n", isappleufs, dirblksiz); 560 printf("isappleufs = %d, dirblksiz = %d\n", isappleufs, dirblksiz);
558#else 561#else
559 printf("dirblksiz = %d\n", dirblksiz); 562 printf("dirblksiz = %d\n", dirblksiz);
560#endif 563#endif
561 564
562 if (sblock->fs_flags & FS_DOQUOTA2) { 565 if (sblock->fs_flags & FS_DOQUOTA2) {
563 /* allocate the quota hash table */ 566 /* allocate the quota hash table */
564 /* 567 /*
565 * first compute the size of the hash table 568 * first compute the size of the hash table
566 * We know the smallest block size is 4k, so we can use 2k 569 * We know the smallest block size is 4k, so we can use 2k
567 * for the hash table; as an entry is 8 bytes we can store 570 * for the hash table; as an entry is 8 bytes we can store
568 * 256 entries. So let start q2h_hash_shift at 8 571 * 256 entries. So let start q2h_hash_shift at 8
569 */ 572 */
570 for (q2h_hash_shift = 8; 573 for (q2h_hash_shift = 8;
571 q2h_hash_shift < 15; 574 q2h_hash_shift < 15;
572 q2h_hash_shift++) { 575 q2h_hash_shift++) {
573 if ((sizeof(uint64_t) << (q2h_hash_shift + 1)) + 576 if ((sizeof(uint64_t) << (q2h_hash_shift + 1)) +
574 sizeof(struct quota2_header) > 577 sizeof(struct quota2_header) >
575 (size_t)sblock->fs_bsize) 578 (size_t)sblock->fs_bsize)
576 break; 579 break;
577 } 580 }
578 q2h_hash_mask = (1 << q2h_hash_shift) - 1; 581 q2h_hash_mask = (1 << q2h_hash_shift) - 1;
579 if (debug) { 582 if (debug) {
580 printf("quota hash shift %d, %d entries, mask 0x%x\n", 583 printf("quota hash shift %d, %d entries, mask 0x%x\n",
581 q2h_hash_shift, (1 << q2h_hash_shift), 584 q2h_hash_shift, (1 << q2h_hash_shift),
582 q2h_hash_mask); 585 q2h_hash_mask);
583 } 586 }
584 uquot_user_hash = 587 uquot_user_hash =
585 calloc((1 << q2h_hash_shift), sizeof(struct uquot_hash)); 588 calloc((1 << q2h_hash_shift), sizeof(struct uquot_hash));
586 uquot_group_hash = 589 uquot_group_hash =
587 calloc((1 << q2h_hash_shift), sizeof(struct uquot_hash)); 590 calloc((1 << q2h_hash_shift), sizeof(struct uquot_hash));
588 if (uquot_user_hash == NULL || uquot_group_hash == NULL) 591 if (uquot_user_hash == NULL || uquot_group_hash == NULL)
589 errexit("Cannot allocate space for quotas hash\n"); 592 errexit("Cannot allocate space for quotas hash\n");
590 } else { 593 } else {
591 uquot_user_hash = uquot_group_hash = NULL; 594 uquot_user_hash = uquot_group_hash = NULL;
592 q2h_hash_shift = q2h_hash_mask = 0; 595 q2h_hash_shift = q2h_hash_mask = 0;
593 } 596 }
594 return (1); 597 return (1);
595badsblabel: 598badsblabel:
596 markclean=0; 599 markclean=0;
597 ckfini(1); 600 ckfini(1);
598 return (0); 601 return (0);
599} 602}
600 603
601#ifndef NO_APPLE_UFS 604#ifndef NO_APPLE_UFS
602static int 605static int
603readappleufs(void) 606readappleufs(void)
604{ 607{
605 daddr_t label = APPLEUFS_LABEL_OFFSET / dev_bsize; 608 daddr_t label = APPLEUFS_LABEL_OFFSET / dev_bsize;
606 struct appleufslabel *appleufs; 609 struct appleufslabel *appleufs;
607 int i; 610 int i;
608 611
609 /* XXX do we have to deal with APPLEUFS_LABEL_OFFSET not 612 /* XXX do we have to deal with APPLEUFS_LABEL_OFFSET not
610 * being block aligned (CD's?) 613 * being block aligned (CD's?)
611 */ 614 */
612 if (APPLEUFS_LABEL_SIZE % dev_bsize != 0) 615 if (APPLEUFS_LABEL_SIZE % dev_bsize != 0)
613 return 0; 616 return 0;
614 if (bread(fsreadfd, (char *)appleufsblk.b_un.b_fs, label, 617 if (bread(fsreadfd, (char *)appleufsblk.b_un.b_fs, label,
615 (long)APPLEUFS_LABEL_SIZE) != 0) 618 (long)APPLEUFS_LABEL_SIZE) != 0)
616 return 0; 619 return 0;
617 appleufsblk.b_bno = label; 620 appleufsblk.b_bno = label;
618 appleufsblk.b_size = APPLEUFS_LABEL_SIZE; 621 appleufsblk.b_size = APPLEUFS_LABEL_SIZE;
619 622
620 appleufs = appleufsblk.b_un.b_appleufs; 623 appleufs = appleufsblk.b_un.b_appleufs;
621 624
622 if (ntohl(appleufs->ul_magic) != APPLEUFS_LABEL_MAGIC) { 625 if (ntohl(appleufs->ul_magic) != APPLEUFS_LABEL_MAGIC) {
623 if (!isappleufs) { 626 if (!isappleufs) {
624 return 0; 627 return 0;
625 } else { 628 } else {
626 pfatal("MISSING APPLEUFS VOLUME LABEL\n"); 629 pfatal("MISSING APPLEUFS VOLUME LABEL\n");
627 if (reply("FIX") == 0) { 630 if (reply("FIX") == 0) {
628 return 1; 631 return 1;
629 } 632 }
630 ffs_appleufs_set(appleufs, NULL, -1, 0); 633 ffs_appleufs_set(appleufs, NULL, -1, 0);
631 appleufsdirty(); 634 appleufsdirty();
632 } 635 }
633 } 636 }
634 637
635 if (ntohl(appleufs->ul_version) != APPLEUFS_LABEL_VERSION) { 638 if (ntohl(appleufs->ul_version) != APPLEUFS_LABEL_VERSION) {
636 pwarn("INCORRECT APPLE UFS VERSION NUMBER (%d should be %d)", 639 pwarn("INCORRECT APPLE UFS VERSION NUMBER (%d should be %d)",
637 ntohl(appleufs->ul_version),APPLEUFS_LABEL_VERSION); 640 ntohl(appleufs->ul_version),APPLEUFS_LABEL_VERSION);
638 if (preen) { 641 if (preen) {
639 printf(" (CORRECTED)\n"); 642 printf(" (CORRECTED)\n");
640 } 643 }
641 if (preen || reply("CORRECT")) { 644 if (preen || reply("CORRECT")) {
642 appleufs->ul_version = htonl(APPLEUFS_LABEL_VERSION); 645 appleufs->ul_version = htonl(APPLEUFS_LABEL_VERSION);
643 appleufsdirty(); 646 appleufsdirty();
644 } 647 }
645 } 648 }
646 649
647 if (ntohs(appleufs->ul_namelen) > APPLEUFS_MAX_LABEL_NAME) { 650 if (ntohs(appleufs->ul_namelen) > APPLEUFS_MAX_LABEL_NAME) {
648 pwarn("APPLE UFS LABEL NAME TOO LONG"); 651 pwarn("APPLE UFS LABEL NAME TOO LONG");
649 if (preen) { 652 if (preen) {
650 printf(" (TRUNCATED)\n"); 653 printf(" (TRUNCATED)\n");
651 } 654 }
652 if (preen || reply("TRUNCATE")) { 655 if (preen || reply("TRUNCATE")) {
653 appleufs->ul_namelen = htons(APPLEUFS_MAX_LABEL_NAME); 656 appleufs->ul_namelen = htons(APPLEUFS_MAX_LABEL_NAME);
654 appleufsdirty(); 657 appleufsdirty();
655 } 658 }
656 } 659 }
657 660
658 if (ntohs(appleufs->ul_namelen) == 0) { 661 if (ntohs(appleufs->ul_namelen) == 0) {
659 pwarn("MISSING APPLE UFS LABEL NAME"); 662 pwarn("MISSING APPLE UFS LABEL NAME");
660 if (preen) { 663 if (preen) {
661 printf(" (FIXED)\n"); 664 printf(" (FIXED)\n");
662 } 665 }
663 if (preen || reply("FIX")) { 666 if (preen || reply("FIX")) {
664 ffs_appleufs_set(appleufs, NULL, -1, 0); 667 ffs_appleufs_set(appleufs, NULL, -1, 0);
665 appleufsdirty(); 668 appleufsdirty();
666 } 669 }
667 } 670 }
668 671
669 /* Scan name for first illegal character */ 672 /* Scan name for first illegal character */
670 for (i=0;i<ntohs(appleufs->ul_namelen);i++) { 673 for (i=0;i<ntohs(appleufs->ul_namelen);i++) {
671 if ((appleufs->ul_name[i] == '\0') || 674 if ((appleufs->ul_name[i] == '\0') ||
672 (appleufs->ul_name[i] == ':') || 675 (appleufs->ul_name[i] == ':') ||
673 (appleufs->ul_name[i] == '/')) { 676 (appleufs->ul_name[i] == '/')) {
674 pwarn("APPLE UFS LABEL NAME CONTAINS ILLEGAL CHARACTER"); 677 pwarn("APPLE UFS LABEL NAME CONTAINS ILLEGAL CHARACTER");
675 if (preen) { 678 if (preen) {
676 printf(" (TRUNCATED)\n"); 679 printf(" (TRUNCATED)\n");
677 } 680 }
678 if (preen || reply("TRUNCATE")) { 681 if (preen || reply("TRUNCATE")) {
679 appleufs->ul_namelen = i+1; 682 appleufs->ul_namelen = i+1;
680 appleufsdirty(); 683 appleufsdirty();
681 } 684 }
682 break; 685 break;
683 } 686 }
684 } 687 }
685 688
686 /* Check the checksum last, because if anything else was wrong, 689 /* Check the checksum last, because if anything else was wrong,
687 * then the checksum gets reset anyway. 690 * then the checksum gets reset anyway.
688 */ 691 */
689 appleufs->ul_checksum = 0; 692 appleufs->ul_checksum = 0;
690 appleufs->ul_checksum = ffs_appleufs_cksum(appleufs); 693 appleufs->ul_checksum = ffs_appleufs_cksum(appleufs);
691 if (appleufsblk.b_un.b_appleufs->ul_checksum != appleufs->ul_checksum) { 694 if (appleufsblk.b_un.b_appleufs->ul_checksum != appleufs->ul_checksum) {
692 pwarn("INVALID APPLE UFS CHECKSUM (%#04x should be %#04x)", 695 pwarn("INVALID APPLE UFS CHECKSUM (%#04x should be %#04x)",
693 appleufsblk.b_un.b_appleufs->ul_checksum, appleufs->ul_checksum); 696 appleufsblk.b_un.b_appleufs->ul_checksum, appleufs->ul_checksum);
694 if (preen) { 697 if (preen) {
695 printf(" (CORRECTED)\n"); 698 printf(" (CORRECTED)\n");
696 } 699 }
697 if (preen || reply("CORRECT")) { 700 if (preen || reply("CORRECT")) {
698 appleufsdirty(); 701 appleufsdirty();
699 } else { 702 } else {
700 /* put the incorrect checksum back in place */ 703 /* put the incorrect checksum back in place */
701 appleufs->ul_checksum = appleufsblk.b_un.b_appleufs->ul_checksum; 704 appleufs->ul_checksum = appleufsblk.b_un.b_appleufs->ul_checksum;
702 } 705 }
703 } 706 }
704 return 1; 707 return 1;
705} 708}
706#endif /* !NO_APPLE_UFS */ 709#endif /* !NO_APPLE_UFS */
707 710
708/* 711/*
709 * Detect byte order. Return 0 if valid magic found, -1 otherwise. 712 * Detect byte order. Return 0 if valid magic found, -1 otherwise.
710 */ 713 */
711static int 714static int
712detect_byteorder(struct fs *fs, int sblockoff) 715detect_byteorder(struct fs *fs, int sblockoff)
713{ 716{
714 if (sblockoff == SBLOCK_UFS2 && (fs->fs_magic == FS_UFS1_MAGIC || 717 if (sblockoff == SBLOCK_UFS2 && (fs->fs_magic == FS_UFS1_MAGIC ||
715 fs->fs_magic == FS_UFS1_MAGIC_SWAPPED)) 718 fs->fs_magic == FS_UFS1_MAGIC_SWAPPED))
716 /* Likely to be the first alternate of a fs with 64k blocks */ 719 /* Likely to be the first alternate of a fs with 64k blocks */
717 return -1; 720 return -1;
718 if (fs->fs_magic == FS_UFS1_MAGIC || fs->fs_magic == FS_UFS2_MAGIC) { 721 if (fs->fs_magic == FS_UFS1_MAGIC || fs->fs_magic == FS_UFS2_MAGIC) {
719#ifndef NO_FFS_EI 722#ifndef NO_FFS_EI
720 if (endian == 0 || BYTE_ORDER == endian) { 723 if (endian == 0 || BYTE_ORDER == endian) {
721 needswap = 0; 724 needswap = 0;
722 doswap = do_blkswap = do_dirswap = 0; 725 doswap = do_blkswap = do_dirswap = 0;
723 } else { 726 } else {
724 needswap = 1; 727 needswap = 1;
725 doswap = do_blkswap = do_dirswap = 1; 728 doswap = do_blkswap = do_dirswap = 1;
726 } 729 }
727#endif 730#endif
728 return 0; 731 return 0;
729 } 732 }
730#ifndef NO_FFS_EI 733#ifndef NO_FFS_EI
731 else if (fs->fs_magic == FS_UFS1_MAGIC_SWAPPED || 734 else if (fs->fs_magic == FS_UFS1_MAGIC_SWAPPED ||
732 fs->fs_magic == FS_UFS2_MAGIC_SWAPPED) { 735 fs->fs_magic == FS_UFS2_MAGIC_SWAPPED) {
733 if (endian == 0 || BYTE_ORDER != endian) { 736 if (endian == 0 || BYTE_ORDER != endian) {
734 needswap = 1; 737 needswap = 1;
735 doswap = do_blkswap = do_dirswap = 0; 738 doswap = do_blkswap = do_dirswap = 0;
736 } else { 739 } else {
737 needswap = 0; 740 needswap = 0;
738 doswap = do_blkswap = do_dirswap = 1; 741 doswap = do_blkswap = do_dirswap = 1;
739 } 742 }
740 return 0; 743 return 0;
741 } 744 }
742#endif 745#endif
743 return -1; 746 return -1;
744} 747}
745 748
746/* 749/*
747 * Possible superblock locations ordered from most to least likely. 750 * Possible superblock locations ordered from most to least likely.
748 */ 751 */
749static off_t sblock_try[] = SBLOCKSEARCH; 752static off_t sblock_try[] = SBLOCKSEARCH;
750 753
751/* 754/*
752 * Read in the super block and its summary info. 755 * Read in the super block and its summary info.
753 */ 756 */
754static int 757static int
755readsb(int listerr) 758readsb(int listerr)
756{ 759{
757 daddr_t super = 0; 760 daddr_t super = 0;
758 struct fs *fs; 761 struct fs *fs;
759 int i; 762 int i;
760 763
761 if (bflag) { 764 if (bflag) {
762 super = bflag; 765 super = bflag;
763 if (bread(fsreadfd, (char *)sblk.b_un.b_fs, super, 766 if (bread(fsreadfd, (char *)sblk.b_un.b_fs, super,
764 (long)SBLOCKSIZE) != 0) 767 (long)SBLOCKSIZE) != 0)
765 return (0); 768 return (0);
766 fs = sblk.b_un.b_fs; 769 fs = sblk.b_un.b_fs;
767 if (detect_byteorder(fs, -1) < 0) { 770 if (detect_byteorder(fs, -1) < 0) {
768 badsb(listerr, "MAGIC NUMBER WRONG"); 771 badsb(listerr, "MAGIC NUMBER WRONG");
769 return (0); 772 return (0);
770 } 773 }
771 } else { 774 } else {
772 for (i = 0; sblock_try[i] != -1; i++) { 775 for (i = 0; sblock_try[i] != -1; i++) {
773 super = sblock_try[i] / dev_bsize; 776 super = sblock_try[i] / dev_bsize;
774 if (bread(fsreadfd, (char *)sblk.b_un.b_fs, 777 if (bread(fsreadfd, (char *)sblk.b_un.b_fs,
775 super, (long)SBLOCKSIZE) != 0) 778 super, (long)SBLOCKSIZE) != 0)
776 continue; 779 continue;
777 fs = sblk.b_un.b_fs; 780 fs = sblk.b_un.b_fs;
778 if (detect_byteorder(fs, sblock_try[i]) == 0) 781 if (detect_byteorder(fs, sblock_try[i]) == 0)
779 break; 782 break;
780 } 783 }
781 if (sblock_try[i] == -1) { 784 if (sblock_try[i] == -1) {
782 badsb(listerr, "CAN'T FIND SUPERBLOCK"); 785 badsb(listerr, "CAN'T FIND SUPERBLOCK");
783 return (0); 786 return (0);
784 } 787 }
785 } 788 }
786 if (doswap) { 789 if (doswap) {
787 if (preen) 790 if (preen)
788 errx(FSCK_EXIT_USAGE, 791 errx(FSCK_EXIT_USAGE,
789 "Incompatible options -B and -p"); 792 "Incompatible options -B and -p");
790 if (nflag) 793 if (nflag)
791 errx(FSCK_EXIT_USAGE, 794 errx(FSCK_EXIT_USAGE,
792 "Incompatible options -B and -n"); 795 "Incompatible options -B and -n");
793 if (endian == LITTLE_ENDIAN) { 796 if (endian == LITTLE_ENDIAN) {
794 if (!reply("CONVERT TO LITTLE ENDIAN")) 797 if (!reply("CONVERT TO LITTLE ENDIAN"))
795 return 0; 798 return 0;
796 } else if (endian == BIG_ENDIAN) { 799 } else if (endian == BIG_ENDIAN) {
797 if (!reply("CONVERT TO BIG ENDIAN")) 800 if (!reply("CONVERT TO BIG ENDIAN"))
798 return 0; 801 return 0;
799 } else 802 } else
800 pfatal("INTERNAL ERROR: unknown endian"); 803 pfatal("INTERNAL ERROR: unknown endian");
801 } 804 }
802 if (needswap) 805 if (needswap)
803 pwarn("** Swapped byte order\n"); 806 pwarn("** Swapped byte order\n");
804 /* swap SB byte order if asked */ 807 /* swap SB byte order if asked */
805 if (doswap) 808 if (doswap)
806 ffs_sb_swap(sblk.b_un.b_fs, sblk.b_un.b_fs); 809 ffs_sb_swap(sblk.b_un.b_fs, sblk.b_un.b_fs);
807 810
808 memmove(sblock, sblk.b_un.b_fs, SBLOCKSIZE); 811 memmove(sblock, sblk.b_un.b_fs, SBLOCKSIZE);
809 if (needswap) 812 if (needswap)
810 ffs_sb_swap(sblk.b_un.b_fs, sblock); 813 ffs_sb_swap(sblk.b_un.b_fs, sblock);
811 814
812 is_ufs2 = sblock->fs_magic == FS_UFS2_MAGIC; 815 is_ufs2 = sblock->fs_magic == FS_UFS2_MAGIC;
813 816
814 /* 817 /*
815 * run a few consistency checks of the super block 818 * run a few consistency checks of the super block
816 */ 819 */
817 if (sblock->fs_sbsize > SBLOCKSIZE) 820 if (sblock->fs_sbsize > SBLOCKSIZE)
818 { badsb(listerr, "SIZE PREPOSTEROUSLY LARGE"); return (0); } 821 { badsb(listerr, "SIZE PREPOSTEROUSLY LARGE"); return (0); }
819 /* 822 /*
820 * Compute block size that the filesystem is based on, 823 * Compute block size that the filesystem is based on,
821 * according to FFS_FSBTODB, and adjust superblock block number 824 * according to FFS_FSBTODB, and adjust superblock block number
822 * so we can tell if this is an alternate later. 825 * so we can tell if this is an alternate later.
823 */ 826 */
824 super *= dev_bsize; 827 super *= dev_bsize;
825 dev_bsize = sblock->fs_fsize / FFS_FSBTODB(sblock, 1); 828 dev_bsize = sblock->fs_fsize / FFS_FSBTODB(sblock, 1);
826 sblk.b_bno = super / dev_bsize; 829 sblk.b_bno = super / dev_bsize;
827 sblk.b_size = SBLOCKSIZE; 830 sblk.b_size = SBLOCKSIZE;
828 if (bflag) 831 if (bflag)
829 goto out; 832 goto out;
830 /* 833 /*
831 * Set all possible fields that could differ, then do check 834 * Set all possible fields that could differ, then do check
832 * of whole super block against an alternate super block-> 835 * of whole super block against an alternate super block->
833 * When an alternate super-block is specified this check is skipped. 836 * When an alternate super-block is specified this check is skipped.
834 */ 837 */
835 getblk(&asblk, cgsblock(sblock, sblock->fs_ncg - 1), sblock->fs_sbsize); 838 getblk(&asblk, cgsblock(sblock, sblock->fs_ncg - 1), sblock->fs_sbsize);
836 if (asblk.b_errs) 839 if (asblk.b_errs)
837 return (0); 840 return (0);
838 /* swap SB byte order if asked */ 841 /* swap SB byte order if asked */
839 if (doswap) 842 if (doswap)
840 ffs_sb_swap(asblk.b_un.b_fs, asblk.b_un.b_fs); 843 ffs_sb_swap(asblk.b_un.b_fs, asblk.b_un.b_fs);
841 844
842 memmove(altsblock, asblk.b_un.b_fs, sblock->fs_sbsize); 845 memmove(altsblock, asblk.b_un.b_fs, sblock->fs_sbsize);
843 if (needswap) 846 if (needswap)
844 ffs_sb_swap(asblk.b_un.b_fs, altsblock); 847 ffs_sb_swap(asblk.b_un.b_fs, altsblock);
845 if (cmpsblks(sblock, altsblock)) { 848 if (cmpsblks(sblock, altsblock)) {
846 if (debug) { 849 if (debug) {
847 uint32_t *nlp, *olp, *endlp; 850 uint32_t *nlp, *olp, *endlp;
848 851
849 printf("superblock mismatches\n"); 852 printf("superblock mismatches\n");
850 nlp = (uint32_t *)altsblock; 853 nlp = (uint32_t *)altsblock;
851 olp = (uint32_t *)sblock; 854 olp = (uint32_t *)sblock;
852 endlp = olp + (sblock->fs_sbsize / sizeof *olp); 855 endlp = olp + (sblock->fs_sbsize / sizeof *olp);
853 for ( ; olp < endlp; olp++, nlp++) { 856 for ( ; olp < endlp; olp++, nlp++) {
854 if (*olp == *nlp) 857 if (*olp == *nlp)
855 continue; 858 continue;
856 printf("offset %#x, original 0x%08x, alternate " 859 printf("offset %#x, original 0x%08x, alternate "
857 "0x%08x\n", 860 "0x%08x\n",
858 (int)((uint8_t *)olp-(uint8_t *)sblock), 861 (int)((uint8_t *)olp-(uint8_t *)sblock),
859 *olp, *nlp); 862 *olp, *nlp);
860 } 863 }
861 } 864 }
862 badsb(listerr, 865 badsb(listerr,
863 "VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE"); 866 "VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE");
864/* 867/*
865 return (0); 868 return (0);
866*/ 869*/
867 } 870 }
868out: 871out:
869 872
870 sb_oldfscompat_read(sblock, &sblocksave); 873 sb_oldfscompat_read(sblock, &sblocksave);
871 874
872 /* Now we know the SB is valid, we can write it back if needed */ 875 /* Now we know the SB is valid, we can write it back if needed */
873 if (doswap) { 876 if (doswap) {
874 sbdirty(); 877 sbdirty();
875 dirty(&asblk); 878 dirty(&asblk);
876 } 879 }
877 havesb = 1; 880 havesb = 1;
878 return (1); 881 return (1);
879} 882}
880 883
881int 884int
882cmpsblks(const struct fs *sb, struct fs *asb) 885cmpsblks(const struct fs *sb, struct fs *asb)
883{ 886{
884 if (!is_ufs2 && ((sb->fs_old_flags & FS_FLAGS_UPDATED) == 0)) { 887 if (!is_ufs2 && ((sb->fs_old_flags & FS_FLAGS_UPDATED) == 0)) {
885 if (sb->fs_old_postblformat < FS_DYNAMICPOSTBLFMT) 888 if (sb->fs_old_postblformat < FS_DYNAMICPOSTBLFMT)
886 return cmpsblks42(sb, asb); 889 return cmpsblks42(sb, asb);
887 else 890 else
888 return cmpsblks44(sb, asb); 891 return cmpsblks44(sb, asb);
889 } 892 }
890 if (asb->fs_sblkno != sb->fs_sblkno || 893 if (asb->fs_sblkno != sb->fs_sblkno ||
891 asb->fs_cblkno != sb->fs_cblkno || 894 asb->fs_cblkno != sb->fs_cblkno ||
892 asb->fs_iblkno != sb->fs_iblkno || 895 asb->fs_iblkno != sb->fs_iblkno ||
893 asb->fs_dblkno != sb->fs_dblkno || 896 asb->fs_dblkno != sb->fs_dblkno ||
894 asb->fs_ncg != sb->fs_ncg || 897 asb->fs_ncg != sb->fs_ncg ||
895 asb->fs_bsize != sb->fs_bsize || 898 asb->fs_bsize != sb->fs_bsize ||
896 asb->fs_fsize != sb->fs_fsize || 899 asb->fs_fsize != sb->fs_fsize ||
897 asb->fs_frag != sb->fs_frag || 900 asb->fs_frag != sb->fs_frag ||
898 asb->fs_bmask != sb->fs_bmask || 901 asb->fs_bmask != sb->fs_bmask ||
899 asb->fs_fmask != sb->fs_fmask || 902 asb->fs_fmask != sb->fs_fmask ||
900 asb->fs_bshift != sb->fs_bshift || 903 asb->fs_bshift != sb->fs_bshift ||
901 asb->fs_fshift != sb->fs_fshift || 904 asb->fs_fshift != sb->fs_fshift ||
902 asb->fs_fragshift != sb->fs_fragshift || 905 asb->fs_fragshift != sb->fs_fragshift ||
903 asb->fs_fsbtodb != sb->fs_fsbtodb || 906 asb->fs_fsbtodb != sb->fs_fsbtodb ||
904 asb->fs_sbsize != sb->fs_sbsize || 907 asb->fs_sbsize != sb->fs_sbsize ||
905 asb->fs_nindir != sb->fs_nindir || 908 asb->fs_nindir != sb->fs_nindir ||
906 asb->fs_inopb != sb->fs_inopb || 909 asb->fs_inopb != sb->fs_inopb ||
907 asb->fs_cssize != sb->fs_cssize || 910 asb->fs_cssize != sb->fs_cssize ||
908 asb->fs_ipg != sb->fs_ipg || 911 asb->fs_ipg != sb->fs_ipg ||
909 asb->fs_fpg != sb->fs_fpg || 912 asb->fs_fpg != sb->fs_fpg ||
910 asb->fs_magic != sb->fs_magic) 913 asb->fs_magic != sb->fs_magic)
911 return 1; 914 return 1;
912 return 0; 915 return 0;
913} 916}
914 917
915/* BSD 4.2 performed the following superblock comparison 918/* BSD 4.2 performed the following superblock comparison
916 * It should correspond to FS_42POSTBLFMT 919 * It should correspond to FS_42POSTBLFMT
917 * (although note that in 4.2, the fs_old_postblformat 920 * (although note that in 4.2, the fs_old_postblformat
918 * field didn't exist and the corresponding bits are 921 * field didn't exist and the corresponding bits are
919 * located near the end of the postbl itself, where they 922 * located near the end of the postbl itself, where they
920 * are not likely to be used.) 923 * are not likely to be used.)
921 */ 924 */
922int 925int
923cmpsblks42(const struct fs *sb, struct fs *asb) 926cmpsblks42(const struct fs *sb, struct fs *asb)
924{ 927{
925 asb->fs_firstfield = sb->fs_firstfield; /* fs_link */ 928 asb->fs_firstfield = sb->fs_firstfield; /* fs_link */
926 asb->fs_unused_1 = sb->fs_unused_1; /* fs_rlink */ 929 asb->fs_unused_1 = sb->fs_unused_1; /* fs_rlink */
927 asb->fs_old_time = sb->fs_old_time; /* fs_time */ 930 asb->fs_old_time = sb->fs_old_time; /* fs_time */
928 asb->fs_old_cstotal = sb->fs_old_cstotal; /* fs_cstotal */ 931 asb->fs_old_cstotal = sb->fs_old_cstotal; /* fs_cstotal */
929 asb->fs_cgrotor = sb->fs_cgrotor; 932 asb->fs_cgrotor = sb->fs_cgrotor;
930 asb->fs_fmod = sb->fs_fmod; 933 asb->fs_fmod = sb->fs_fmod;
931 asb->fs_clean = sb->fs_clean; 934 asb->fs_clean = sb->fs_clean;
932 asb->fs_ronly = sb->fs_ronly; 935 asb->fs_ronly = sb->fs_ronly;
933 asb->fs_old_flags = sb->fs_old_flags; 936 asb->fs_old_flags = sb->fs_old_flags;
934 asb->fs_maxcontig = sb->fs_maxcontig; 937 asb->fs_maxcontig = sb->fs_maxcontig;
935 asb->fs_minfree = sb->fs_minfree; 938 asb->fs_minfree = sb->fs_minfree;
936 asb->fs_old_rotdelay = sb->fs_old_rotdelay; 939 asb->fs_old_rotdelay = sb->fs_old_rotdelay;
937 asb->fs_maxbpg = sb->fs_maxbpg; 940 asb->fs_maxbpg = sb->fs_maxbpg;
938 941
939 /* The former fs_csp, totaling 128 bytes */ 942 /* The former fs_csp, totaling 128 bytes */
940 memmove(asb->fs_ocsp, sb->fs_ocsp, sizeof sb->fs_ocsp); 943 memmove(asb->fs_ocsp, sb->fs_ocsp, sizeof sb->fs_ocsp);
941 asb->fs_contigdirs = sb->fs_contigdirs; 944 asb->fs_contigdirs = sb->fs_contigdirs;
942 asb->fs_csp = sb->fs_csp; 945 asb->fs_csp = sb->fs_csp;
943 asb->fs_maxcluster = sb->fs_maxcluster; 946 asb->fs_maxcluster = sb->fs_maxcluster;
944 asb->fs_active = sb->fs_active; 947 asb->fs_active = sb->fs_active;
945 948
946 /* The former fs_fsmnt, totaling 512 bytes */ 949 /* The former fs_fsmnt, totaling 512 bytes */
947 memmove(asb->fs_fsmnt, sb->fs_fsmnt, sizeof sb->fs_fsmnt); 950 memmove(asb->fs_fsmnt, sb->fs_fsmnt, sizeof sb->fs_fsmnt);
948 memmove(asb->fs_volname, sb->fs_volname, sizeof sb->fs_volname); 951 memmove(asb->fs_volname, sb->fs_volname, sizeof sb->fs_volname);
949 952
950 return memcmp(sb, asb, sb->fs_sbsize); 953 return memcmp(sb, asb, sb->fs_sbsize);
951} 954}
952 955
953/* BSD 4.4 performed the following superblock comparison 956/* BSD 4.4 performed the following superblock comparison
954 * This was used in NetBSD through 1.6.1 957 * This was used in NetBSD through 1.6.1
955 * 958 *
956 * Note that this implementation is destructive to asb. 959 * Note that this implementation is destructive to asb.
957 */ 960 */
958int 961int
959cmpsblks44(const struct fs *sb, struct fs *asb) 962cmpsblks44(const struct fs *sb, struct fs *asb)
960{ 963{
961 /* 964 /*
962 * "Copy fields which we don't care if they're different in the 965 * "Copy fields which we don't care if they're different in the
963 * alternate superblocks, as they're either likely to be 966 * alternate superblocks, as they're either likely to be
964 * different because they're per-cylinder-group specific, or 967 * different because they're per-cylinder-group specific, or
965 * because they're transient details which are only maintained 968 * because they're transient details which are only maintained
966 * in the primary superblock." 969 * in the primary superblock."
967 */ 970 */
968 asb->fs_firstfield = sb->fs_firstfield; 971 asb->fs_firstfield = sb->fs_firstfield;
969 asb->fs_unused_1 = sb->fs_unused_1; 972 asb->fs_unused_1 = sb->fs_unused_1;
970 asb->fs_old_time = sb->fs_old_time; 973 asb->fs_old_time = sb->fs_old_time;
971 asb->fs_old_cstotal = sb->fs_old_cstotal; 974 asb->fs_old_cstotal = sb->fs_old_cstotal;
972 asb->fs_cgrotor = sb->fs_cgrotor; 975 asb->fs_cgrotor = sb->fs_cgrotor;
973 asb->fs_fmod = sb->fs_fmod; 976 asb->fs_fmod = sb->fs_fmod;
974 asb->fs_clean = sb->fs_clean; 977 asb->fs_clean = sb->fs_clean;
975 asb->fs_ronly = sb->fs_ronly; 978 asb->fs_ronly = sb->fs_ronly;
976 asb->fs_old_flags = sb->fs_old_flags; 979 asb->fs_old_flags = sb->fs_old_flags;
977 asb->fs_maxcontig = sb->fs_maxcontig; 980 asb->fs_maxcontig = sb->fs_maxcontig;
978 asb->fs_minfree = sb->fs_minfree; 981 asb->fs_minfree = sb->fs_minfree;
979 asb->fs_optim = sb->fs_optim; 982 asb->fs_optim = sb->fs_optim;
980 asb->fs_old_rotdelay = sb->fs_old_rotdelay; 983 asb->fs_old_rotdelay = sb->fs_old_rotdelay;
981 asb->fs_maxbpg = sb->fs_maxbpg; 984 asb->fs_maxbpg = sb->fs_maxbpg;
982 985
983 /* The former fs_csp and fs_maxcluster, totaling 128 bytes */ 986 /* The former fs_csp and fs_maxcluster, totaling 128 bytes */
984 memmove(asb->fs_ocsp, sb->fs_ocsp, sizeof sb->fs_ocsp); 987 memmove(asb->fs_ocsp, sb->fs_ocsp, sizeof sb->fs_ocsp);
985 asb->fs_contigdirs = sb->fs_contigdirs; 988 asb->fs_contigdirs = sb->fs_contigdirs;
986 asb->fs_csp = sb->fs_csp; 989 asb->fs_csp = sb->fs_csp;
987 asb->fs_maxcluster = sb->fs_maxcluster; 990 asb->fs_maxcluster = sb->fs_maxcluster;
988 asb->fs_active = sb->fs_active; 991 asb->fs_active = sb->fs_active;
989 992
990 /* The former fs_fsmnt, totaling 512 bytes */ 993 /* The former fs_fsmnt, totaling 512 bytes */
991 memmove(asb->fs_fsmnt, sb->fs_fsmnt, sizeof sb->fs_fsmnt); 994 memmove(asb->fs_fsmnt, sb->fs_fsmnt, sizeof sb->fs_fsmnt);
992 memmove(asb->fs_volname, sb->fs_volname, sizeof sb->fs_volname); 995 memmove(asb->fs_volname, sb->fs_volname, sizeof sb->fs_volname);
993 996
994 /* The former fs_sparecon, totaling 200 bytes */ 997 /* The former fs_sparecon, totaling 200 bytes */
995 memmove(asb->fs_snapinum, 998 memmove(asb->fs_snapinum,
996 sb->fs_snapinum, sizeof sb->fs_snapinum); 999 sb->fs_snapinum, sizeof sb->fs_snapinum);
997 asb->fs_avgfilesize = sb->fs_avgfilesize; 1000 asb->fs_avgfilesize = sb->fs_avgfilesize;
998 asb->fs_avgfpdir = sb->fs_avgfpdir; 1001 asb->fs_avgfpdir = sb->fs_avgfpdir;
999 asb->fs_save_cgsize = sb->fs_save_cgsize; 1002 asb->fs_save_cgsize = sb->fs_save_cgsize;
1000 memmove(asb->fs_sparecon32, 1003 memmove(asb->fs_sparecon32,
1001 sb->fs_sparecon32, sizeof sb->fs_sparecon32); 1004 sb->fs_sparecon32, sizeof sb->fs_sparecon32);
1002 asb->fs_flags = sb->fs_flags; 1005 asb->fs_flags = sb->fs_flags;
1003 1006
1004 /* Original comment: 1007 /* Original comment:
1005 * "The following should not have to be copied, but need to be." 1008 * "The following should not have to be copied, but need to be."
1006 */ 1009 */
1007 asb->fs_fsbtodb = sb->fs_fsbtodb; 1010 asb->fs_fsbtodb = sb->fs_fsbtodb;
1008 asb->fs_old_interleave = sb->fs_old_interleave; 1011 asb->fs_old_interleave = sb->fs_old_interleave;
1009 asb->fs_old_npsect = sb->fs_old_npsect; 1012 asb->fs_old_npsect = sb->fs_old_npsect;
1010 asb->fs_old_nrpos = sb->fs_old_nrpos; 1013 asb->fs_old_nrpos = sb->fs_old_nrpos;
1011 asb->fs_state = sb->fs_state; 1014 asb->fs_state = sb->fs_state;
1012 asb->fs_qbmask = sb->fs_qbmask; 1015 asb->fs_qbmask = sb->fs_qbmask;
1013 asb->fs_qfmask = sb->fs_qfmask; 1016 asb->fs_qfmask = sb->fs_qfmask;
1014 asb->fs_state = sb->fs_state; 1017 asb->fs_state = sb->fs_state;
1015 asb->fs_maxfilesize = sb->fs_maxfilesize; 1018 asb->fs_maxfilesize = sb->fs_maxfilesize;
1016 1019
1017 /* 1020 /*
1018 * "Compare the superblocks, effectively checking every other 1021 * "Compare the superblocks, effectively checking every other
1019 * field to see if they differ." 1022 * field to see if they differ."
1020 */ 1023 */
1021 return memcmp(sb, asb, sb->fs_sbsize); 1024 return memcmp(sb, asb, sb->fs_sbsize);
1022} 1025}
1023 1026
1024 1027
1025static void 1028static void
1026badsb(int listerr, const char *s) 1029badsb(int listerr, const char *s)
1027{ 1030{
1028 1031
1029 if (!listerr) 1032 if (!listerr)
1030 return; 1033 return;
1031 if (preen) 1034 if (preen)
1032 printf("%s: ", cdevname()); 1035 printf("%s: ", cdevname());
1033 pfatal("BAD SUPER BLOCK: %s\n", s); 1036 pfatal("BAD SUPER BLOCK: %s\n", s);
1034} 1037}
1035 1038
1036/* 1039/*
1037 * Calculate a prototype superblock based on information in the disk label. 1040 * Calculate a prototype superblock based on information in the disk label.
1038 * When done the cgsblock macro can be calculated and the fs_ncg field 1041 * When done the cgsblock macro can be calculated and the fs_ncg field
1039 * can be used. Do NOT attempt to use other macros without verifying that 1042 * can be used. Do NOT attempt to use other macros without verifying that
1040 * their needed information is available! 1043 * their needed information is available!
1041 */ 1044 */
1042static int 1045static int
1043calcsb(const char *dev, int devfd, struct fs *fs) 1046calcsb(const char *dev, int devfd, struct fs *fs)
1044{ 1047{
1045 struct dkwedge_info dkw; 1048 struct dkwedge_info dkw;
1046 struct disk_geom geo; 1049 struct disk_geom geo;
1047 int i, nspf; 1050 int i, nspf;
1048 1051
1049 if (getdiskinfo(dev, fsreadfd, NULL, &geo, &dkw) == -1) 1052 if (getdiskinfo(dev, fsreadfd, NULL, &geo, &dkw) == -1)
1050 pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev); 1053 pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev);
1051 if (dkw.dkw_parent[0] == '\0') { 1054 if (dkw.dkw_parent[0] == '\0') {
1052 pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev); 1055 pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev);
1053 return (0); 1056 return (0);
1054 } 1057 }
1055 if (strcmp(dkw.dkw_ptype, DKW_PTYPE_FFS) 1058 if (strcmp(dkw.dkw_ptype, DKW_PTYPE_FFS)
1056#ifndef NO_APPLE_UFS 1059#ifndef NO_APPLE_UFS
1057 && strcmp(dkw.dkw_ptype, DKW_PTYPE_APPLEUFS) 1060 && strcmp(dkw.dkw_ptype, DKW_PTYPE_APPLEUFS)
1058#endif 1061#endif
1059 ) { 1062 ) {
1060 pfatal("%s: NOT LABELED AS A BSD FILE SYSTEM (%s)\n", 1063 pfatal("%s: NOT LABELED AS A BSD FILE SYSTEM (%s)\n",
1061 dev, dkw.dkw_ptype); 1064 dev, dkw.dkw_ptype);
1062 return (0); 1065 return (0);
1063 } 1066 }
1064 if (geo.dg_secsize == 0) { 1067 if (geo.dg_secsize == 0) {
1065 pfatal("%s: CANNOT FIGURE OUT SECTOR SIZE\n", dev); 1068 pfatal("%s: CANNOT FIGURE OUT SECTOR SIZE\n", dev);
1066 return 0; 1069 return 0;
1067 } 1070 }
1068 if (geo.dg_secpercyl == 0) { 1071 if (geo.dg_secpercyl == 0) {
1069 pfatal("%s: CANNOT FIGURE OUT SECTORS PER CYLINDER\n", dev); 1072 pfatal("%s: CANNOT FIGURE OUT SECTORS PER CYLINDER\n", dev);
1070 return 0; 1073 return 0;
1071 } 1074 }
1072 if (sblk.b_un.b_fs->fs_fsize == 0) { 1075 if (sblk.b_un.b_fs->fs_fsize == 0) {
1073 pfatal("%s: CANNOT FIGURE OUT FRAG BLOCK SIZE\n", dev); 1076 pfatal("%s: CANNOT FIGURE OUT FRAG BLOCK SIZE\n", dev);
1074 return 0; 1077 return 0;
1075 } 1078 }
1076 if (sblk.b_un.b_fs->fs_fpg == 0) { 1079 if (sblk.b_un.b_fs->fs_fpg == 0) {
1077 pfatal("%s: CANNOT FIGURE OUT FRAGS PER GROUP\n", dev); 1080 pfatal("%s: CANNOT FIGURE OUT FRAGS PER GROUP\n", dev);
1078 return 0; 1081 return 0;
1079 } 1082 }
1080 if (sblk.b_un.b_fs->fs_old_cpg == 0) { 1083 if (sblk.b_un.b_fs->fs_old_cpg == 0) {
1081 pfatal("%s: CANNOT FIGURE OUT OLD CYLINDERS PER GROUP\n", dev); 1084 pfatal("%s: CANNOT FIGURE OUT OLD CYLINDERS PER GROUP\n", dev);
1082 return 0; 1085 return 0;
1083 } 1086 }
1084 memcpy(fs, sblk.b_un.b_fs, sizeof(struct fs)); 1087 memcpy(fs, sblk.b_un.b_fs, sizeof(struct fs));
1085 nspf = fs->fs_fsize / geo.dg_secsize; 1088 nspf = fs->fs_fsize / geo.dg_secsize;
1086 fs->fs_old_nspf = nspf; 1089 fs->fs_old_nspf = nspf;
1087 for (fs->fs_fsbtodb = 0, i = nspf; i > 1; i >>= 1) 1090 for (fs->fs_fsbtodb = 0, i = nspf; i > 1; i >>= 1)
1088 fs->fs_fsbtodb++; 1091 fs->fs_fsbtodb++;
1089 dev_bsize = geo.dg_secsize; 1092 dev_bsize = geo.dg_secsize;
1090 if (fs->fs_magic == FS_UFS2_MAGIC) { 1093 if (fs->fs_magic == FS_UFS2_MAGIC) {
1091 fs->fs_ncg = howmany(fs->fs_size, fs->fs_fpg); 1094 fs->fs_ncg = howmany(fs->fs_size, fs->fs_fpg);
1092 } else /* if (fs->fs_magic == FS_UFS1_MAGIC) */ { 1095 } else /* if (fs->fs_magic == FS_UFS1_MAGIC) */ {
1093 fs->fs_old_cgmask = 0xffffffff; 1096 fs->fs_old_cgmask = 0xffffffff;
1094 for (i = geo.dg_ntracks; i > 1; i >>= 1) 1097 for (i = geo.dg_ntracks; i > 1; i >>= 1)
1095 fs->fs_old_cgmask <<= 1; 1098 fs->fs_old_cgmask <<= 1;
1096 if (!POWEROF2(geo.dg_ntracks)) 1099 if (!POWEROF2(geo.dg_ntracks))
1097 fs->fs_old_cgmask <<= 1; 1100 fs->fs_old_cgmask <<= 1;
1098 fs->fs_old_cgoffset = roundup( 1101 fs->fs_old_cgoffset = roundup(
1099 howmany(geo.dg_nsectors, nspf), fs->fs_frag); 1102 howmany(geo.dg_nsectors, nspf), fs->fs_frag);
1100 fs->fs_fpg = (fs->fs_old_cpg * geo.dg_secpercyl) / nspf; 1103 fs->fs_fpg = (fs->fs_old_cpg * geo.dg_secpercyl) / nspf;
1101 fs->fs_ncg = howmany(fs->fs_size / geo.dg_secpercyl, 1104 fs->fs_ncg = howmany(fs->fs_size / geo.dg_secpercyl,
1102 fs->fs_old_cpg); 1105 fs->fs_old_cpg);
1103 } 1106 }
1104 return (1); 1107 return (1);
1105} 1108}
1106 1109
1107/* 1110/*
1108 * Test the list of snapshot inode numbers for duplicates and repair. 1111 * Test the list of snapshot inode numbers for duplicates and repair.
1109 */ 1112 */
1110static int 1113static int
1111check_snapinum(void) 1114check_snapinum(void)
1112{ 1115{
1113 int loc, loc2, res; 1116 int loc, loc2, res;
1114 int *snapinum = &sblock->fs_snapinum[0]; 1117 int *snapinum = &sblock->fs_snapinum[0];
1115 1118
1116 res = 0; 1119 res = 0;
1117  1120
1118 if (isappleufs) 1121 if (isappleufs)
1119 return 0; 1122 return 0;
1120 1123
1121 for (loc = 0; loc < FSMAXSNAP; loc++) { 1124 for (loc = 0; loc < FSMAXSNAP; loc++) {
1122 if (snapinum[loc] == 0) 1125 if (snapinum[loc] == 0)
1123 break; 1126 break;
1124 for (loc2 = loc + 1; loc2 < FSMAXSNAP; loc2++) { 1127 for (loc2 = loc + 1; loc2 < FSMAXSNAP; loc2++) {
1125 if (snapinum[loc2] == 0 || 1128 if (snapinum[loc2] == 0 ||
1126 snapinum[loc2] == snapinum[loc]) 1129 snapinum[loc2] == snapinum[loc])
1127 break; 1130 break;
1128 } 1131 }
1129 if (loc2 >= FSMAXSNAP || snapinum[loc2] == 0) 1132 if (loc2 >= FSMAXSNAP || snapinum[loc2] == 0)
1130 continue; 1133 continue;
1131 pwarn("SNAPSHOT INODE %u ALREADY ON LIST%s", snapinum[loc2], 1134 pwarn("SNAPSHOT INODE %u ALREADY ON LIST%s", snapinum[loc2],
1132 (res ? "" : "\n")); 1135 (res ? "" : "\n"));
1133 res = 1; 1136 res = 1;
1134 for (loc2 = loc + 1; loc2 < FSMAXSNAP; loc2++) { 1137 for (loc2 = loc + 1; loc2 < FSMAXSNAP; loc2++) {
1135 if (snapinum[loc2] == 0) 1138 if (snapinum[loc2] == 0)
1136 break; 1139 break;
1137 snapinum[loc2 - 1] = snapinum[loc2]; 1140 snapinum[loc2 - 1] = snapinum[loc2];
1138 } 1141 }
1139 snapinum[loc2 - 1] = 0; 1142 snapinum[loc2 - 1] = 0;
1140 loc--; 1143 loc--;
1141 } 1144 }
1142 1145
1143 return res; 1146 return res;
1144} 1147}

cvs diff -r1.65 -r1.66 src/sbin/fsck_ffs/utilities.c (switch to unified diff)

--- src/sbin/fsck_ffs/utilities.c 2017/02/08 16:11:40 1.65
+++ src/sbin/fsck_ffs/utilities.c 2020/04/17 09:42:27 1.66
@@ -1,773 +1,773 @@ @@ -1,773 +1,773 @@
1/* $NetBSD: utilities.c,v 1.65 2017/02/08 16:11:40 rin Exp $ */ 1/* $NetBSD: utilities.c,v 1.66 2020/04/17 09:42:27 jdolecek Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1980, 1986, 1993 4 * Copyright (c) 1980, 1986, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors 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 16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission. 17 * without specific prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 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 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33#ifndef lint 33#ifndef lint
34#if 0 34#if 0
35static char sccsid[] = "@(#)utilities.c 8.6 (Berkeley) 5/19/95"; 35static char sccsid[] = "@(#)utilities.c 8.6 (Berkeley) 5/19/95";
36#else 36#else
37__RCSID("$NetBSD: utilities.c,v 1.65 2017/02/08 16:11:40 rin Exp $"); 37__RCSID("$NetBSD: utilities.c,v 1.66 2020/04/17 09:42:27 jdolecek Exp $");
38#endif 38#endif
39#endif /* not lint */ 39#endif /* not lint */
40 40
41#include <sys/param.h> 41#include <sys/param.h>
42#include <sys/time.h> 42#include <sys/time.h>
43 43
44#include <ufs/ufs/dinode.h> 44#include <ufs/ufs/dinode.h>
45#include <ufs/ufs/dir.h> 45#include <ufs/ufs/dir.h>
46#include <ufs/ffs/fs.h> 46#include <ufs/ffs/fs.h>
47#include <ufs/ffs/ffs_extern.h> 47#include <ufs/ffs/ffs_extern.h>
48#include <ufs/ufs/ufs_bswap.h> 48#include <ufs/ufs/ufs_bswap.h>
49#include <ufs/ufs/quota2.h> 49#include <ufs/ufs/quota2.h>
50 50
51#include <ctype.h> 51#include <ctype.h>
52#include <err.h> 52#include <err.h>
53#include <errno.h> 53#include <errno.h>
54#include <stdio.h> 54#include <stdio.h>
55#include <stdlib.h> 55#include <stdlib.h>
56#include <string.h> 56#include <string.h>
57#include <unistd.h> 57#include <unistd.h>
58#include <signal.h> 58#include <signal.h>
59 59
60#include "fsutil.h" 60#include "fsutil.h"
61#include "fsck.h" 61#include "fsck.h"
62#include "extern.h" 62#include "extern.h"
63#include "exitvalues.h" 63#include "exitvalues.h"
64 64
65long diskreads, totalreads; /* Disk cache statistics */ 65long diskreads, totalreads; /* Disk cache statistics */
66 66
67static void rwerror(const char *, daddr_t); 67static void rwerror(const char *, daddr_t);
68 68
69int 69int
70ftypeok(union dinode *dp) 70ftypeok(union dinode *dp)
71{ 71{
72 switch (iswap16(DIP(dp, mode)) & IFMT) { 72 switch (iswap16(DIP(dp, mode)) & IFMT) {
73 73
74 case IFDIR: 74 case IFDIR:
75 case IFREG: 75 case IFREG:
76 case IFBLK: 76 case IFBLK:
77 case IFCHR: 77 case IFCHR:
78 case IFLNK: 78 case IFLNK:
79 case IFSOCK: 79 case IFSOCK:
80 case IFIFO: 80 case IFIFO:
81 return (1); 81 return (1);
82 82
83 default: 83 default:
84 if (debug) 84 if (debug)
85 printf("bad file type 0%o\n", iswap16(DIP(dp, mode))); 85 printf("bad file type 0%o\n", iswap16(DIP(dp, mode)));
86 return (0); 86 return (0);
87 } 87 }
88} 88}
89 89
90int 90int
91reply(const char *question) 91reply(const char *question)
92{ 92{
93 int persevere; 93 int persevere;
94 char c; 94 char c;
95 95
96 if (preen) 96 if (preen)
97 pfatal("INTERNAL ERROR: GOT TO reply()"); 97 pfatal("INTERNAL ERROR: GOT TO reply()");
98 persevere = !strcmp(question, "CONTINUE"); 98 persevere = !strcmp(question, "CONTINUE");
99 printf("\n"); 99 printf("\n");
100 if (!persevere && (nflag || fswritefd < 0)) { 100 if (!persevere && (nflag || fswritefd < 0)) {
101 printf("%s? no\n\n", question); 101 printf("%s? no\n\n", question);
102 resolved = 0; 102 resolved = 0;
103 return (0); 103 return (0);
104 } 104 }
105 if (yflag || (persevere && nflag)) { 105 if (yflag || (persevere && nflag)) {
106 printf("%s? yes\n\n", question); 106 printf("%s? yes\n\n", question);
107 return (1); 107 return (1);
108 } 108 }
109 do { 109 do {
110 printf("%s? [yn] ", question); 110 printf("%s? [yn] ", question);
111 (void) fflush(stdout); 111 (void) fflush(stdout);
112 c = getc(stdin); 112 c = getc(stdin);
113 while (c != '\n' && getc(stdin) != '\n') { 113 while (c != '\n' && getc(stdin) != '\n') {
114 if (feof(stdin)) { 114 if (feof(stdin)) {
115 resolved = 0; 115 resolved = 0;
116 return (0); 116 return (0);
117 } 117 }
118 } 118 }
119 } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); 119 } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
120 printf("\n"); 120 printf("\n");
121 if (c == 'y' || c == 'Y') 121 if (c == 'y' || c == 'Y')
122 return (1); 122 return (1);
123 resolved = 0; 123 resolved = 0;
124 return (0); 124 return (0);
125} 125}
126 126
127/* 127/*
128 * Malloc buffers and set up cache. 128 * Malloc buffers and set up cache.
129 */ 129 */
130void 130void
131bufinit(void) 131bufinit(void)
132{ 132{
133 struct bufarea *bp; 133 struct bufarea *bp;
134 long bufcnt, i; 134 long bufcnt, i;
135 char *bufp; 135 char *bufp;
136 136
137 pbp = pdirbp = (struct bufarea *)0; 137 pbp = pdirbp = (struct bufarea *)0;
138 bufp = malloc((unsigned int)sblock->fs_bsize); 138 bufp = aligned_alloc(DEV_BSIZE, (unsigned int)sblock->fs_bsize);
139 if (bufp == 0) 139 if (bufp == 0)
140 errexit("cannot allocate buffer pool"); 140 errexit("cannot allocate buffer pool");
141 cgblk.b_un.b_buf = bufp; 141 cgblk.b_un.b_buf = bufp;
142 initbarea(&cgblk); 142 initbarea(&cgblk);
143#ifndef NO_APPLE_UFS 143#ifndef NO_APPLE_UFS
144 bufp = malloc((unsigned int)APPLEUFS_LABEL_SIZE); 144 bufp = aligned_alloc(DEV_BSIZE, (unsigned int)APPLEUFS_LABEL_SIZE);
145 if (bufp == 0) 145 if (bufp == 0)
146 errexit("cannot allocate buffer pool"); 146 errexit("cannot allocate buffer pool");
147 appleufsblk.b_un.b_buf = bufp; 147 appleufsblk.b_un.b_buf = bufp;
148 initbarea(&appleufsblk); 148 initbarea(&appleufsblk);
149#endif 149#endif
150 bufhead.b_next = bufhead.b_prev = &bufhead; 150 bufhead.b_next = bufhead.b_prev = &bufhead;
151 bufcnt = MAXBUFSPACE / sblock->fs_bsize; 151 bufcnt = MAXBUFSPACE / sblock->fs_bsize;
152 if (bufcnt < MINBUFS) 152 if (bufcnt < MINBUFS)
153 bufcnt = MINBUFS; 153 bufcnt = MINBUFS;
154 for (i = 0; i < bufcnt; i++) { 154 for (i = 0; i < bufcnt; i++) {
155 bp = malloc(sizeof(struct bufarea)); 155 bp = malloc(sizeof(struct bufarea));
156 bufp = malloc((unsigned int)sblock->fs_bsize); 156 bufp = aligned_alloc(DEV_BSIZE, (unsigned int)sblock->fs_bsize);
157 if (bp == NULL || bufp == NULL) { 157 if (bp == NULL || bufp == NULL) {
158 if (i >= MINBUFS) { 158 if (i >= MINBUFS) {
159 if (bp) 159 if (bp)
160 free(bp); 160 free(bp);
161 if (bufp) 161 if (bufp)
162 free(bufp); 162 free(bufp);
163 break; 163 break;
164 } 164 }
165 errexit("cannot allocate buffer pool"); 165 errexit("cannot allocate buffer pool");
166 } 166 }
167 bp->b_un.b_buf = bufp; 167 bp->b_un.b_buf = bufp;
168 bp->b_prev = &bufhead; 168 bp->b_prev = &bufhead;
169 bp->b_next = bufhead.b_next; 169 bp->b_next = bufhead.b_next;
170 bufhead.b_next->b_prev = bp; 170 bufhead.b_next->b_prev = bp;
171 bufhead.b_next = bp; 171 bufhead.b_next = bp;
172 initbarea(bp); 172 initbarea(bp);
173 } 173 }
174 bufhead.b_size = i; /* save number of buffers */ 174 bufhead.b_size = i; /* save number of buffers */
175} 175}
176 176
177/* 177/*
178 * Manage a cache of directory blocks. 178 * Manage a cache of directory blocks.
179 */ 179 */
180struct bufarea * 180struct bufarea *
181getdatablk(daddr_t blkno, long size) 181getdatablk(daddr_t blkno, long size)
182{ 182{
183 struct bufarea *bp; 183 struct bufarea *bp;
184 184
185 for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next) 185 for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next)
186 if (bp->b_bno == FFS_FSBTODB(sblock, blkno)) 186 if (bp->b_bno == FFS_FSBTODB(sblock, blkno))
187 goto foundit; 187 goto foundit;
188 for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev) 188 for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev)
189 if ((bp->b_flags & B_INUSE) == 0) 189 if ((bp->b_flags & B_INUSE) == 0)
190 break; 190 break;
191 if (bp == &bufhead) 191 if (bp == &bufhead)
192 errexit("deadlocked buffer pool"); 192 errexit("deadlocked buffer pool");
193 /* fall through */ 193 /* fall through */
194foundit: 194foundit:
195 getblk(bp, blkno, size); 195 getblk(bp, blkno, size);
196 bp->b_prev->b_next = bp->b_next; 196 bp->b_prev->b_next = bp->b_next;
197 bp->b_next->b_prev = bp->b_prev; 197 bp->b_next->b_prev = bp->b_prev;
198 bp->b_prev = &bufhead; 198 bp->b_prev = &bufhead;
199 bp->b_next = bufhead.b_next; 199 bp->b_next = bufhead.b_next;
200 bufhead.b_next->b_prev = bp; 200 bufhead.b_next->b_prev = bp;
201 bufhead.b_next = bp; 201 bufhead.b_next = bp;
202 bp->b_flags |= B_INUSE; 202 bp->b_flags |= B_INUSE;
203 return (bp); 203 return (bp);
204} 204}
205 205
206void 206void
207getblk(struct bufarea *bp, daddr_t blk, long size) 207getblk(struct bufarea *bp, daddr_t blk, long size)
208{ 208{
209 daddr_t dblk; 209 daddr_t dblk;
210 210
211 dblk = FFS_FSBTODB(sblock, blk); 211 dblk = FFS_FSBTODB(sblock, blk);
212 totalreads++; 212 totalreads++;
213 if (bp->b_bno != dblk) { 213 if (bp->b_bno != dblk) {
214 flush(fswritefd, bp); 214 flush(fswritefd, bp);
215 diskreads++; 215 diskreads++;
216 bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, size); 216 bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, size);
217 bp->b_bno = dblk; 217 bp->b_bno = dblk;
218 bp->b_size = size; 218 bp->b_size = size;
219 } 219 }
220} 220}
221 221
222void 222void
223flush(int fd, struct bufarea *bp) 223flush(int fd, struct bufarea *bp)
224{ 224{
225 int i, j; 225 int i, j;
226 struct csum *ccsp; 226 struct csum *ccsp;
227 227
228 if (!bp->b_dirty) 228 if (!bp->b_dirty)
229 return; 229 return;
230 if (bp->b_errs != 0) 230 if (bp->b_errs != 0)
231 pfatal("WRITING %sZERO'ED BLOCK %lld TO DISK\n", 231 pfatal("WRITING %sZERO'ED BLOCK %lld TO DISK\n",
232 (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ", 232 (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ",
233 (long long)bp->b_bno); 233 (long long)bp->b_bno);
234 bp->b_dirty = 0; 234 bp->b_dirty = 0;
235 bp->b_errs = 0; 235 bp->b_errs = 0;
236 bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size); 236 bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size);
237 if (bp != &sblk) 237 if (bp != &sblk)
238 return; 238 return;
239 for (i = 0, j = 0; i < sblock->fs_cssize; i += sblock->fs_bsize, j++) { 239 for (i = 0, j = 0; i < sblock->fs_cssize; i += sblock->fs_bsize, j++) {
240 int size = sblock->fs_cssize - i < sblock->fs_bsize ? 240 int size = sblock->fs_cssize - i < sblock->fs_bsize ?
241 sblock->fs_cssize - i : sblock->fs_bsize; 241 sblock->fs_cssize - i : sblock->fs_bsize;
242 ccsp = (struct csum *)((char *)sblock->fs_csp + i); 242 ccsp = (struct csum *)((char *)sblock->fs_csp + i);
243 if (needswap) 243 if (needswap)
244 ffs_csum_swap(ccsp, ccsp, size); 244 ffs_csum_swap(ccsp, ccsp, size);
245 bwrite(fswritefd, (char *)ccsp, 245 bwrite(fswritefd, (char *)ccsp,
246 FFS_FSBTODB(sblock, sblock->fs_csaddr + j * sblock->fs_frag), 246 FFS_FSBTODB(sblock, sblock->fs_csaddr + j * sblock->fs_frag),
247 size); 247 size);
248 if (needswap) 248 if (needswap)
249 ffs_csum_swap(ccsp, ccsp, size); 249 ffs_csum_swap(ccsp, ccsp, size);
250 } 250 }
251} 251}
252 252
253static void 253static void
254rwerror(const char *mesg, daddr_t blk) 254rwerror(const char *mesg, daddr_t blk)
255{ 255{
256 256
257 if (preen == 0) 257 if (preen == 0)
258 printf("\n"); 258 printf("\n");
259 pfatal("CANNOT %s: BLK %lld", mesg, (long long)blk); 259 pfatal("CANNOT %s: BLK %lld", mesg, (long long)blk);
260 if (reply("CONTINUE") == 0) 260 if (reply("CONTINUE") == 0)
261 exit(FSCK_EXIT_CHECK_FAILED); 261 exit(FSCK_EXIT_CHECK_FAILED);
262} 262}
263 263
264void 264void
265ckfini(int noint) 265ckfini(int noint)
266{ 266{
267 struct bufarea *bp, *nbp; 267 struct bufarea *bp, *nbp;
268 int cnt = 0; 268 int cnt = 0;
269 269
270 if (!noint) { 270 if (!noint) {
271 if (doinglevel2) 271 if (doinglevel2)
272 return; 272 return;
273 markclean = 0; 273 markclean = 0;
274 } 274 }
275 275
276 if (fswritefd < 0) { 276 if (fswritefd < 0) {
277 (void)close(fsreadfd); 277 (void)close(fsreadfd);
278 return; 278 return;
279 } 279 }
280 flush(fswritefd, &sblk); 280 flush(fswritefd, &sblk);
281 if (havesb && bflag != 0 && 281 if (havesb && bflag != 0 &&
282 (preen || reply("UPDATE STANDARD SUPERBLOCK"))) { 282 (preen || reply("UPDATE STANDARD SUPERBLOCK"))) {
283 if (preen) 283 if (preen)
284 pwarn("UPDATING STANDARD SUPERBLOCK\n"); 284 pwarn("UPDATING STANDARD SUPERBLOCK\n");
285 if (!is_ufs2 && (sblock->fs_old_flags & FS_FLAGS_UPDATED) == 0) 285 if (!is_ufs2 && (sblock->fs_old_flags & FS_FLAGS_UPDATED) == 0)
286 sblk.b_bno = SBLOCK_UFS1 / dev_bsize; 286 sblk.b_bno = SBLOCK_UFS1 / dev_bsize;
287 else 287 else
288 sblk.b_bno = sblock->fs_sblockloc / dev_bsize; 288 sblk.b_bno = sblock->fs_sblockloc / dev_bsize;
289 sbdirty(); 289 sbdirty();
290 flush(fswritefd, &sblk); 290 flush(fswritefd, &sblk);
291 } 291 }
292#ifndef NO_APPLE_UFS 292#ifndef NO_APPLE_UFS
293 flush(fswritefd, &appleufsblk); 293 flush(fswritefd, &appleufsblk);
294 free(appleufsblk.b_un.b_buf); 294 free(appleufsblk.b_un.b_buf);
295#endif 295#endif
296 flush(fswritefd, &cgblk); 296 flush(fswritefd, &cgblk);
297 free(cgblk.b_un.b_buf); 297 free(cgblk.b_un.b_buf);
298 for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) { 298 for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) {
299 cnt++; 299 cnt++;
300 flush(fswritefd, bp); 300 flush(fswritefd, bp);
301 nbp = bp->b_prev; 301 nbp = bp->b_prev;
302 free(bp->b_un.b_buf); 302 free(bp->b_un.b_buf);
303 free((char *)bp); 303 free((char *)bp);
304 } 304 }
305 if (bufhead.b_size != cnt) 305 if (bufhead.b_size != cnt)
306 errexit("Panic: lost %d buffers", bufhead.b_size - cnt); 306 errexit("Panic: lost %d buffers", bufhead.b_size - cnt);
307 pbp = pdirbp = (struct bufarea *)0; 307 pbp = pdirbp = (struct bufarea *)0;
308 if (markclean && (sblock->fs_clean & FS_ISCLEAN) == 0) { 308 if (markclean && (sblock->fs_clean & FS_ISCLEAN) == 0) {
309 /* 309 /*
310 * Mark the file system as clean, and sync the superblock. 310 * Mark the file system as clean, and sync the superblock.
311 */ 311 */
312 if (preen) 312 if (preen)
313 pwarn("MARKING FILE SYSTEM CLEAN\n"); 313 pwarn("MARKING FILE SYSTEM CLEAN\n");
314 else if (!reply("MARK FILE SYSTEM CLEAN")) 314 else if (!reply("MARK FILE SYSTEM CLEAN"))
315 markclean = 0; 315 markclean = 0;
316 if (markclean) { 316 if (markclean) {
317 sblock->fs_clean = FS_ISCLEAN; 317 sblock->fs_clean = FS_ISCLEAN;
318 sblock->fs_pendingblocks = 0; 318 sblock->fs_pendingblocks = 0;
319 sblock->fs_pendinginodes = 0; 319 sblock->fs_pendinginodes = 0;
320 sbdirty(); 320 sbdirty();
321 flush(fswritefd, &sblk); 321 flush(fswritefd, &sblk);
322 if (!preen) 322 if (!preen)
323 printf( 323 printf(
324 "\n***** FILE SYSTEM MARKED CLEAN *****\n"); 324 "\n***** FILE SYSTEM MARKED CLEAN *****\n");
325 } 325 }
326 } 326 }
327 if (debug) 327 if (debug)
328 printf("cache missed %ld of %ld (%d%%)\n", diskreads, 328 printf("cache missed %ld of %ld (%d%%)\n", diskreads,
329 totalreads, (int)(diskreads * 100 / totalreads)); 329 totalreads, (int)(diskreads * 100 / totalreads));
330 cleanup_wapbl(); 330 cleanup_wapbl();
331 (void)close(fsreadfd); 331 (void)close(fsreadfd);
332 (void)close(fswritefd); 332 (void)close(fswritefd);
333} 333}
334 334
335int 335int
336bread(int fd, char *buf, daddr_t blk, long size) 336bread(int fd, char *buf, daddr_t blk, long size)
337{ 337{
338 char *cp; 338 char *cp;
339 int i, errs; 339 int i, errs;
340 off_t offset; 340 off_t offset;
341 341
342 offset = blk; 342 offset = blk;
343 offset *= dev_bsize; 343 offset *= dev_bsize;
344 if ((pread(fd, buf, (int)size, offset) == size) && 344 if ((pread(fd, buf, (int)size, offset) == size) &&
345 read_wapbl(buf, size, blk) == 0) 345 read_wapbl(buf, size, blk) == 0)
346 return (0); 346 return (0);
347 rwerror("READ", blk); 347 rwerror("READ", blk);
348 errs = 0; 348 errs = 0;
349 memset(buf, 0, (size_t)size); 349 memset(buf, 0, (size_t)size);
350 printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:"); 350 printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:");
351 for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) { 351 for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) {
352 if (pread(fd, cp, (int)secsize, offset + i) != secsize) { 352 if (pread(fd, cp, (int)secsize, offset + i) != secsize) {
353 if (secsize != dev_bsize && dev_bsize != 1) 353 if (secsize != dev_bsize && dev_bsize != 1)
354 printf(" %lld (%lld),", 354 printf(" %lld (%lld),",
355 (long long)((blk*dev_bsize + i) / secsize), 355 (long long)((blk*dev_bsize + i) / secsize),
356 (long long)(blk + i / dev_bsize)); 356 (long long)(blk + i / dev_bsize));
357 else 357 else
358 printf(" %lld,", 358 printf(" %lld,",
359 (long long)(blk + i / dev_bsize)); 359 (long long)(blk + i / dev_bsize));
360 errs++; 360 errs++;
361 } 361 }
362 } 362 }
363 printf("\n"); 363 printf("\n");
364 return (errs); 364 return (errs);
365} 365}
366 366
367void 367void
368bwrite(int fd, char *buf, daddr_t blk, long size) 368bwrite(int fd, char *buf, daddr_t blk, long size)
369{ 369{
370 int i; 370 int i;
371 char *cp; 371 char *cp;
372 off_t offset; 372 off_t offset;
373 373
374 if (fd < 0) 374 if (fd < 0)
375 return; 375 return;
376 offset = blk; 376 offset = blk;
377 offset *= dev_bsize; 377 offset *= dev_bsize;
378 if (pwrite(fd, buf, (int)size, offset) == size) { 378 if (pwrite(fd, buf, (int)size, offset) == size) {
379 fsmodified = 1; 379 fsmodified = 1;
380 return; 380 return;
381 } 381 }
382 rwerror("WRITE", blk); 382 rwerror("WRITE", blk);
383 printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:"); 383 printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:");
384 for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize) 384 for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize)
385 if (pwrite(fd, cp, (int)dev_bsize, offset + i) != dev_bsize) 385 if (pwrite(fd, cp, (int)dev_bsize, offset + i) != dev_bsize)
386 printf(" %lld,", (long long)(blk + i / dev_bsize)); 386 printf(" %lld,", (long long)(blk + i / dev_bsize));
387 printf("\n"); 387 printf("\n");
388 return; 388 return;
389} 389}
390 390
391/* 391/*
392 * allocate a data block with the specified number of fragments 392 * allocate a data block with the specified number of fragments
393 */ 393 */
394daddr_t 394daddr_t
395allocblk(long frags) 395allocblk(long frags)
396{ 396{
397 int i, j, k, cg, baseblk; 397 int i, j, k, cg, baseblk;
398 struct cg *cgp = cgrp; 398 struct cg *cgp = cgrp;
399 399
400 if (frags <= 0 || frags > sblock->fs_frag) 400 if (frags <= 0 || frags > sblock->fs_frag)
401 return (0); 401 return (0);
402 for (i = 0; i < maxfsblock - sblock->fs_frag; i += sblock->fs_frag) { 402 for (i = 0; i < maxfsblock - sblock->fs_frag; i += sblock->fs_frag) {
403 for (j = 0; j <= sblock->fs_frag - frags; j++) { 403 for (j = 0; j <= sblock->fs_frag - frags; j++) {
404 if (testbmap(i + j)) 404 if (testbmap(i + j))
405 continue; 405 continue;
406 for (k = 1; k < frags; k++) 406 for (k = 1; k < frags; k++)
407 if (testbmap(i + j + k)) 407 if (testbmap(i + j + k))
408 break; 408 break;
409 if (k < frags) { 409 if (k < frags) {
410 j += k; 410 j += k;
411 continue; 411 continue;
412 } 412 }
413 cg = dtog(sblock, i + j); 413 cg = dtog(sblock, i + j);
414 getblk(&cgblk, cgtod(sblock, cg), sblock->fs_cgsize); 414 getblk(&cgblk, cgtod(sblock, cg), sblock->fs_cgsize);
415 memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize); 415 memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize);
416 if ((doswap && !needswap) || (!doswap && needswap)) 416 if ((doswap && !needswap) || (!doswap && needswap))
417 ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock); 417 ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock);
418 if (!cg_chkmagic(cgp, 0)) 418 if (!cg_chkmagic(cgp, 0))
419 pfatal("CG %d: ALLOCBLK: BAD MAGIC NUMBER\n", 419 pfatal("CG %d: ALLOCBLK: BAD MAGIC NUMBER\n",
420 cg); 420 cg);
421 baseblk = dtogd(sblock, i + j); 421 baseblk = dtogd(sblock, i + j);
422 for (k = 0; k < frags; k++) { 422 for (k = 0; k < frags; k++) {
423 setbmap(i + j + k); 423 setbmap(i + j + k);
424 clrbit(cg_blksfree(cgp, 0), baseblk + k); 424 clrbit(cg_blksfree(cgp, 0), baseblk + k);
425 } 425 }
426 n_blks += frags; 426 n_blks += frags;
427 if (frags == sblock->fs_frag) { 427 if (frags == sblock->fs_frag) {
428 cgp->cg_cs.cs_nbfree--; 428 cgp->cg_cs.cs_nbfree--;
429 sblock->fs_cstotal.cs_nbfree--; 429 sblock->fs_cstotal.cs_nbfree--;
430 sblock->fs_cs(fs, cg).cs_nbfree--; 430 sblock->fs_cs(fs, cg).cs_nbfree--;
431 ffs_clusteracct(sblock, cgp, 431 ffs_clusteracct(sblock, cgp,
432 ffs_fragstoblks(sblock, baseblk), -1); 432 ffs_fragstoblks(sblock, baseblk), -1);
433 } else { 433 } else {
434 cgp->cg_cs.cs_nffree -= frags; 434 cgp->cg_cs.cs_nffree -= frags;
435 sblock->fs_cstotal.cs_nffree -= frags; 435 sblock->fs_cstotal.cs_nffree -= frags;
436 sblock->fs_cs(fs, cg).cs_nffree -= frags; 436 sblock->fs_cs(fs, cg).cs_nffree -= frags;
437 } 437 }
438 sbdirty(); 438 sbdirty();
439 cgdirty(); 439 cgdirty();
440 return (i + j); 440 return (i + j);
441 } 441 }
442 } 442 }
443 return (0); 443 return (0);
444} 444}
445 445
446/* 446/*
447 * Free a previously allocated block 447 * Free a previously allocated block
448 */ 448 */
449void 449void
450freeblk(daddr_t blkno, long frags) 450freeblk(daddr_t blkno, long frags)
451{ 451{
452 struct inodesc idesc; 452 struct inodesc idesc;
453 453
454 memset(&idesc, 0, sizeof(idesc)); 454 memset(&idesc, 0, sizeof(idesc));
455 idesc.id_blkno = blkno; 455 idesc.id_blkno = blkno;
456 idesc.id_numfrags = frags; 456 idesc.id_numfrags = frags;
457 (void)pass4check(&idesc); 457 (void)pass4check(&idesc);
458} 458}
459 459
460/* 460/*
461 * Find a pathname 461 * Find a pathname
462 */ 462 */
463void 463void
464getpathname(char *namebuf, size_t namebuflen, ino_t curdir, ino_t ino) 464getpathname(char *namebuf, size_t namebuflen, ino_t curdir, ino_t ino)
465{ 465{
466 int len; 466 int len;
467 char *cp; 467 char *cp;
468 struct inodesc idesc; 468 struct inodesc idesc;
469 static int busy = 0; 469 static int busy = 0;
470 struct inostat *info; 470 struct inostat *info;
471 471
472 if (curdir == ino && ino == UFS_ROOTINO) { 472 if (curdir == ino && ino == UFS_ROOTINO) {
473 (void)strlcpy(namebuf, "/", namebuflen); 473 (void)strlcpy(namebuf, "/", namebuflen);
474 return; 474 return;
475 } 475 }
476 info = inoinfo(curdir); 476 info = inoinfo(curdir);
477 if (busy || (info->ino_state != DSTATE && info->ino_state != DFOUND)) { 477 if (busy || (info->ino_state != DSTATE && info->ino_state != DFOUND)) {
478 (void)strlcpy(namebuf, "?", namebuflen); 478 (void)strlcpy(namebuf, "?", namebuflen);
479 return; 479 return;
480 } 480 }
481 busy = 1; 481 busy = 1;
482 memset(&idesc, 0, sizeof(struct inodesc)); 482 memset(&idesc, 0, sizeof(struct inodesc));
483 idesc.id_type = DATA; 483 idesc.id_type = DATA;
484 idesc.id_fix = IGNORE; 484 idesc.id_fix = IGNORE;
485 cp = &namebuf[MAXPATHLEN - 1]; 485 cp = &namebuf[MAXPATHLEN - 1];
486 *cp = '\0'; 486 *cp = '\0';
487 if (curdir != ino) { 487 if (curdir != ino) {
488 idesc.id_parent = curdir; 488 idesc.id_parent = curdir;
489 goto namelookup; 489 goto namelookup;
490 } 490 }
491 while (ino != UFS_ROOTINO) { 491 while (ino != UFS_ROOTINO) {
492 idesc.id_number = ino; 492 idesc.id_number = ino;
493 idesc.id_func = findino; 493 idesc.id_func = findino;
494 idesc.id_name = ".."; 494 idesc.id_name = "..";
495 if ((ckinode(ginode(ino), &idesc) & FOUND) == 0) 495 if ((ckinode(ginode(ino), &idesc) & FOUND) == 0)
496 break; 496 break;
497 namelookup: 497 namelookup:
498 idesc.id_number = idesc.id_parent; 498 idesc.id_number = idesc.id_parent;
499 idesc.id_parent = ino; 499 idesc.id_parent = ino;
500 idesc.id_func = findname; 500 idesc.id_func = findname;
501 idesc.id_name = namebuf; 501 idesc.id_name = namebuf;
502 if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0) 502 if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0)
503 break; 503 break;
504 len = strlen(namebuf); 504 len = strlen(namebuf);
505 cp -= len; 505 cp -= len;
506 memmove(cp, namebuf, (size_t)len); 506 memmove(cp, namebuf, (size_t)len);
507 *--cp = '/'; 507 *--cp = '/';
508 if (cp < &namebuf[FFS_MAXNAMLEN]) 508 if (cp < &namebuf[FFS_MAXNAMLEN])
509 break; 509 break;
510 ino = idesc.id_number; 510 ino = idesc.id_number;
511 } 511 }
512 busy = 0; 512 busy = 0;
513 if (ino != UFS_ROOTINO) 513 if (ino != UFS_ROOTINO)
514 *--cp = '?'; 514 *--cp = '?';
515 memmove(namebuf, cp, (size_t)(&namebuf[MAXPATHLEN] - cp)); 515 memmove(namebuf, cp, (size_t)(&namebuf[MAXPATHLEN] - cp));
516} 516}
517 517
518/* 518/*
519 * determine whether an inode should be fixed. 519 * determine whether an inode should be fixed.
520 */ 520 */
521int 521int
522dofix(struct inodesc *idesc, const char *msg) 522dofix(struct inodesc *idesc, const char *msg)
523{ 523{
524 524
525 switch (idesc->id_fix) { 525 switch (idesc->id_fix) {
526 526
527 case DONTKNOW: 527 case DONTKNOW:
528 if (idesc->id_type == DATA) 528 if (idesc->id_type == DATA)
529 direrror(idesc->id_number, msg); 529 direrror(idesc->id_number, msg);
530 else 530 else
531 pwarn("%s", msg); 531 pwarn("%s", msg);
532 if (preen) { 532 if (preen) {
533 printf(" (SALVAGED)\n"); 533 printf(" (SALVAGED)\n");
534 idesc->id_fix = FIX; 534 idesc->id_fix = FIX;
535 return (ALTERED); 535 return (ALTERED);
536 } 536 }
537 if (reply("SALVAGE") == 0) { 537 if (reply("SALVAGE") == 0) {
538 idesc->id_fix = NOFIX; 538 idesc->id_fix = NOFIX;
539 return (0); 539 return (0);
540 } 540 }
541 idesc->id_fix = FIX; 541 idesc->id_fix = FIX;
542 return (ALTERED); 542 return (ALTERED);
543 543
544 case FIX: 544 case FIX:
545 return (ALTERED); 545 return (ALTERED);
546 546
547 case NOFIX: 547 case NOFIX:
548 case IGNORE: 548 case IGNORE:
549 return (0); 549 return (0);
550 550
551 default: 551 default:
552 errexit("UNKNOWN INODESC FIX MODE %d", idesc->id_fix); 552 errexit("UNKNOWN INODESC FIX MODE %d", idesc->id_fix);
553 } 553 }
554 /* NOTREACHED */ 554 /* NOTREACHED */
555 return (0); 555 return (0);
556} 556}
557 557
558void 558void
559copyback_cg(struct bufarea *blk) 559copyback_cg(struct bufarea *blk)
560{ 560{
561 561
562 memcpy(blk->b_un.b_cg, cgrp, sblock->fs_cgsize); 562 memcpy(blk->b_un.b_cg, cgrp, sblock->fs_cgsize);
563 if (needswap) 563 if (needswap)
564 ffs_cg_swap(cgrp, blk->b_un.b_cg, sblock); 564 ffs_cg_swap(cgrp, blk->b_un.b_cg, sblock);
565} 565}
566 566
567void 567void
568infohandler(int sig) 568infohandler(int sig)
569{ 569{
570 got_siginfo = 1; 570 got_siginfo = 1;
571} 571}
572 572
573/* 573/*
574 * Look up state information for an inode. 574 * Look up state information for an inode.
575 */ 575 */
576struct inostat * 576struct inostat *
577inoinfo(ino_t inum) 577inoinfo(ino_t inum)
578{ 578{
579 static struct inostat unallocated = { USTATE, 0, 0 }; 579 static struct inostat unallocated = { USTATE, 0, 0 };
580 struct inostatlist *ilp; 580 struct inostatlist *ilp;
581 int iloff; 581 int iloff;
582 582
583 if (inum > maxino) 583 if (inum > maxino)
584 errexit("inoinfo: inumber %llu out of range", 584 errexit("inoinfo: inumber %llu out of range",
585 (unsigned long long)inum); 585 (unsigned long long)inum);
586 ilp = &inostathead[inum / sblock->fs_ipg]; 586 ilp = &inostathead[inum / sblock->fs_ipg];
587 iloff = inum % sblock->fs_ipg; 587 iloff = inum % sblock->fs_ipg;
588 if (iloff >= ilp->il_numalloced) 588 if (iloff >= ilp->il_numalloced)
589 return (&unallocated); 589 return (&unallocated);
590 return (&ilp->il_stat[iloff]); 590 return (&ilp->il_stat[iloff]);
591} 591}
592 592
593void 593void
594sb_oldfscompat_read(struct fs *fs, struct fs **fssave) 594sb_oldfscompat_read(struct fs *fs, struct fs **fssave)
595{ 595{
596 if ((fs->fs_magic != FS_UFS1_MAGIC) || 596 if ((fs->fs_magic != FS_UFS1_MAGIC) ||
597 (fs->fs_old_flags & FS_FLAGS_UPDATED)) 597 (fs->fs_old_flags & FS_FLAGS_UPDATED))
598 return; 598 return;
599 599
600 /* Save a copy of fields that may be modified for compatibility */ 600 /* Save a copy of fields that may be modified for compatibility */
601 if (fssave) { 601 if (fssave) {
602 if (!*fssave) 602 if (!*fssave)
603 *fssave = malloc(sizeof(struct fs)); 603 *fssave = malloc(sizeof(struct fs));
604 if (!*fssave) 604 if (!*fssave)
605 errexit("cannot allocate space for compat store"); 605 errexit("cannot allocate space for compat store");
606 memmove(*fssave, fs, sizeof(struct fs)); 606 memmove(*fssave, fs, sizeof(struct fs));
607 607
608 if (debug) 608 if (debug)
609 printf("detected ufs1 superblock not yet updated for ufs2 kernels\n"); 609 printf("detected ufs1 superblock not yet updated for ufs2 kernels\n");
610 610
611 if (doswap) { 611 if (doswap) {
612 uint16_t postbl[256]; 612 uint16_t postbl[256];
613 int i, n; 613 int i, n;
614 614
615 if (fs->fs_old_postblformat == FS_42POSTBLFMT) 615 if (fs->fs_old_postblformat == FS_42POSTBLFMT)
616 n = 256; 616 n = 256;
617 else 617 else
618 n = 128; 618 n = 128;
619 619
620 /* extract the postbl from the unswapped superblock */ 620 /* extract the postbl from the unswapped superblock */
621 if (!needswap) 621 if (!needswap)
622 ffs_sb_swap(*fssave, *fssave); 622 ffs_sb_swap(*fssave, *fssave);
623 memmove(postbl, (&(*fssave)->fs_old_postbl_start), 623 memmove(postbl, (&(*fssave)->fs_old_postbl_start),
624 n * sizeof(postbl[0])); 624 n * sizeof(postbl[0]));
625 if (!needswap) 625 if (!needswap)
626 ffs_sb_swap(*fssave, *fssave); 626 ffs_sb_swap(*fssave, *fssave);
627 627
628 /* Now swap it */ 628 /* Now swap it */
629 for (i=0; i < n; i++) 629 for (i=0; i < n; i++)
630 postbl[i] = bswap16(postbl[i]); 630 postbl[i] = bswap16(postbl[i]);
631 631
632 /* And put it back such that it will get correctly 632 /* And put it back such that it will get correctly
633 * unscrambled if it is swapped again on the way out 633 * unscrambled if it is swapped again on the way out
634 */ 634 */
635 if (needswap) 635 if (needswap)
636 ffs_sb_swap(*fssave, *fssave); 636 ffs_sb_swap(*fssave, *fssave);
637 memmove((&(*fssave)->fs_old_postbl_start), postbl, 637 memmove((&(*fssave)->fs_old_postbl_start), postbl,
638 n * sizeof(postbl[0])); 638 n * sizeof(postbl[0]));
639 if (needswap) 639 if (needswap)
640 ffs_sb_swap(*fssave, *fssave); 640 ffs_sb_swap(*fssave, *fssave);
641 } 641 }
642 642
643 } 643 }
644 644
645 /* These fields will be overwritten by their 645 /* These fields will be overwritten by their
646 * original values in fs_oldfscompat_write, so it is harmless 646 * original values in fs_oldfscompat_write, so it is harmless
647 * to modify them here. 647 * to modify them here.
648 */ 648 */
649 fs->fs_cstotal.cs_ndir = 649 fs->fs_cstotal.cs_ndir =
650 fs->fs_old_cstotal.cs_ndir; 650 fs->fs_old_cstotal.cs_ndir;
651 fs->fs_cstotal.cs_nbfree = 651 fs->fs_cstotal.cs_nbfree =
652 fs->fs_old_cstotal.cs_nbfree; 652 fs->fs_old_cstotal.cs_nbfree;
653 fs->fs_cstotal.cs_nifree = 653 fs->fs_cstotal.cs_nifree =
654 fs->fs_old_cstotal.cs_nifree; 654 fs->fs_old_cstotal.cs_nifree;
655 fs->fs_cstotal.cs_nffree = 655 fs->fs_cstotal.cs_nffree =
656 fs->fs_old_cstotal.cs_nffree; 656 fs->fs_old_cstotal.cs_nffree;
657  657
658 fs->fs_maxbsize = fs->fs_bsize; 658 fs->fs_maxbsize = fs->fs_bsize;
659 fs->fs_time = fs->fs_old_time; 659 fs->fs_time = fs->fs_old_time;
660 fs->fs_size = fs->fs_old_size; 660 fs->fs_size = fs->fs_old_size;
661 fs->fs_dsize = fs->fs_old_dsize; 661 fs->fs_dsize = fs->fs_old_dsize;
662 fs->fs_csaddr = fs->fs_old_csaddr; 662 fs->fs_csaddr = fs->fs_old_csaddr;
663 fs->fs_sblockloc = SBLOCK_UFS1; 663 fs->fs_sblockloc = SBLOCK_UFS1;
664 664
665 fs->fs_flags = fs->fs_old_flags; 665 fs->fs_flags = fs->fs_old_flags;
666 666
667 if (fs->fs_old_postblformat == FS_42POSTBLFMT) { 667 if (fs->fs_old_postblformat == FS_42POSTBLFMT) {
668 fs->fs_old_nrpos = 8; 668 fs->fs_old_nrpos = 8;
669 fs->fs_old_npsect = fs->fs_old_nsect; 669 fs->fs_old_npsect = fs->fs_old_nsect;
670 fs->fs_old_interleave = 1; 670 fs->fs_old_interleave = 1;
671 fs->fs_old_trackskew = 0; 671 fs->fs_old_trackskew = 0;
672 } 672 }
673} 673}
674 674
675void 675void
676sb_oldfscompat_write(struct fs *fs, struct fs *fssave) 676sb_oldfscompat_write(struct fs *fs, struct fs *fssave)
677{ 677{
678 if ((fs->fs_magic != FS_UFS1_MAGIC) || 678 if ((fs->fs_magic != FS_UFS1_MAGIC) ||
679 (fs->fs_old_flags & FS_FLAGS_UPDATED)) 679 (fs->fs_old_flags & FS_FLAGS_UPDATED))
680 return; 680 return;
681 681
682 fs->fs_old_flags = fs->fs_flags; 682 fs->fs_old_flags = fs->fs_flags;
683 fs->fs_old_time = fs->fs_time; 683 fs->fs_old_time = fs->fs_time;
684 fs->fs_old_cstotal.cs_ndir = fs->fs_cstotal.cs_ndir; 684 fs->fs_old_cstotal.cs_ndir = fs->fs_cstotal.cs_ndir;
685 fs->fs_old_cstotal.cs_nbfree = fs->fs_cstotal.cs_nbfree; 685 fs->fs_old_cstotal.cs_nbfree = fs->fs_cstotal.cs_nbfree;
686 fs->fs_old_cstotal.cs_nifree = fs->fs_cstotal.cs_nifree; 686 fs->fs_old_cstotal.cs_nifree = fs->fs_cstotal.cs_nifree;
687 fs->fs_old_cstotal.cs_nffree = fs->fs_cstotal.cs_nffree; 687 fs->fs_old_cstotal.cs_nffree = fs->fs_cstotal.cs_nffree;
688 688
689 fs->fs_flags = fssave->fs_flags; 689 fs->fs_flags = fssave->fs_flags;
690 690
691 if (fs->fs_old_postblformat == FS_42POSTBLFMT) { 691 if (fs->fs_old_postblformat == FS_42POSTBLFMT) {
692 fs->fs_old_nrpos = fssave->fs_old_nrpos; 692 fs->fs_old_nrpos = fssave->fs_old_nrpos;
693 fs->fs_old_npsect = fssave->fs_old_npsect; 693 fs->fs_old_npsect = fssave->fs_old_npsect;
694 fs->fs_old_interleave = fssave->fs_old_interleave; 694 fs->fs_old_interleave = fssave->fs_old_interleave;
695 fs->fs_old_trackskew = fssave->fs_old_trackskew; 695 fs->fs_old_trackskew = fssave->fs_old_trackskew;
696 } 696 }
697 697
698 memmove(&fs->fs_old_postbl_start, &fssave->fs_old_postbl_start, 698 memmove(&fs->fs_old_postbl_start, &fssave->fs_old_postbl_start,
699 ((fs->fs_old_postblformat == FS_42POSTBLFMT) ? 699 ((fs->fs_old_postblformat == FS_42POSTBLFMT) ?
700 512 : 256)); 700 512 : 256));
701} 701}
702 702
703struct uquot * 703struct uquot *
704find_uquot(struct uquot_hash *uq_hash, uint32_t uid, int alloc) 704find_uquot(struct uquot_hash *uq_hash, uint32_t uid, int alloc)
705{ 705{
706 struct uquot *uq; 706 struct uquot *uq;
707 SLIST_FOREACH(uq, &uq_hash[uid & q2h_hash_mask], uq_entries) { 707 SLIST_FOREACH(uq, &uq_hash[uid & q2h_hash_mask], uq_entries) {
708 if (uq->uq_uid == uid) 708 if (uq->uq_uid == uid)
709 return uq; 709 return uq;
710 } 710 }
711 if (!alloc) 711 if (!alloc)
712 return NULL; 712 return NULL;
713 uq = malloc(sizeof(struct uquot)); 713 uq = malloc(sizeof(struct uquot));
714 if (uq == NULL) 714 if (uq == NULL)
715 errexit("cannot allocate quota entry"); 715 errexit("cannot allocate quota entry");
716 memset(uq, 0, sizeof(struct uquot)); 716 memset(uq, 0, sizeof(struct uquot));
717 uq->uq_uid = uid; 717 uq->uq_uid = uid;
718 SLIST_INSERT_HEAD(&uq_hash[uid & q2h_hash_mask], uq, uq_entries); 718 SLIST_INSERT_HEAD(&uq_hash[uid & q2h_hash_mask], uq, uq_entries);
719 return uq; 719 return uq;
720} 720}
721 721
722void 722void
723remove_uquot(struct uquot_hash *uq_hash, struct uquot *uq) 723remove_uquot(struct uquot_hash *uq_hash, struct uquot *uq)
724{ 724{
725 SLIST_REMOVE(&uq_hash[uq->uq_uid & q2h_hash_mask], 725 SLIST_REMOVE(&uq_hash[uq->uq_uid & q2h_hash_mask],
726 uq, uquot, uq_entries); 726 uq, uquot, uq_entries);
727} 727}
728 728
729void 729void
730update_uquot(ino_t inum, uid_t uid, gid_t gid, int64_t bchange, int64_t ichange) 730update_uquot(ino_t inum, uid_t uid, gid_t gid, int64_t bchange, int64_t ichange)
731{ 731{
732 /* simple uquot cache: remember the last used */ 732 /* simple uquot cache: remember the last used */
733 static struct uquot *uq_u = NULL; 733 static struct uquot *uq_u = NULL;
734 static struct uquot *uq_g = NULL; 734 static struct uquot *uq_g = NULL;
735 735
736 if (inum < UFS_ROOTINO) 736 if (inum < UFS_ROOTINO)
737 return; 737 return;
738 if (is_journal_inode(inum)) 738 if (is_journal_inode(inum))
739 return; 739 return;
740 if (is_quota_inode(inum)) 740 if (is_quota_inode(inum))
741 return; 741 return;
742  742
743 if (uquot_user_hash == NULL) 743 if (uquot_user_hash == NULL)
744 return; 744 return;
745  745
746 if (uq_u == NULL || uq_u->uq_uid != uid) 746 if (uq_u == NULL || uq_u->uq_uid != uid)
747 uq_u = find_uquot(uquot_user_hash, uid, 1); 747 uq_u = find_uquot(uquot_user_hash, uid, 1);
748 uq_u->uq_b += bchange; 748 uq_u->uq_b += bchange;
749 uq_u->uq_i += ichange; 749 uq_u->uq_i += ichange;
750 if (uq_g == NULL || uq_g->uq_uid != gid) 750 if (uq_g == NULL || uq_g->uq_uid != gid)
751 uq_g = find_uquot(uquot_group_hash, gid, 1); 751 uq_g = find_uquot(uquot_group_hash, gid, 1);
752 uq_g->uq_b += bchange;  752 uq_g->uq_b += bchange;
753 uq_g->uq_i += ichange; 753 uq_g->uq_i += ichange;
754} 754}
755 755
756int 756int
757is_quota_inode(ino_t inum) 757is_quota_inode(ino_t inum)
758{ 758{
759 759
760 if ((sblock->fs_flags & FS_DOQUOTA2) == 0) 760 if ((sblock->fs_flags & FS_DOQUOTA2) == 0)
761 return 0; 761 return 0;
762 762
763 if (sblock->fs_quota_magic != Q2_HEAD_MAGIC) 763 if (sblock->fs_quota_magic != Q2_HEAD_MAGIC)
764 return 0; 764 return 0;
765  765
766 if (sblock->fs_quotafile[USRQUOTA] == inum) 766 if (sblock->fs_quotafile[USRQUOTA] == inum)
767 return 1; 767 return 1;
768 768
769 if (sblock->fs_quotafile[GRPQUOTA] == inum)  769 if (sblock->fs_quotafile[GRPQUOTA] == inum)
770 return 1; 770 return 1;
771 771
772 return 0; 772 return 0;
773} 773}