1 |
/* Pass one of GNU fsck -- count blocks and verify inodes |
/* Pass one of GNU fsck -- count blocks and verify inodes |
2 |
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. |
Copyright (C) 1994,95,96,2002 Free Software Foundation, Inc. |
3 |
Written by Michael I. Bushnell. |
Written by Michael I. Bushnell. |
4 |
|
|
5 |
This file is part of the GNU Hurd. |
This file is part of the GNU Hurd. |
24 |
|
|
25 |
static struct dinode zino; |
static struct dinode zino; |
26 |
|
|
27 |
/* Find all the blocks in use by files and filesystem reserved blocks. |
/* Find all the blocks in use by files and filesystem reserved blocks. |
28 |
Set them in the global block map. For each file, if a block is found |
Set them in the global block map. For each file, if a block is found |
29 |
allocated twice, then record the block and inode in DUPLIST. |
allocated twice, then record the block and inode in DUPLIST. |
30 |
Initialize INODESTATE, LINKCOUNT, and TYPEMAP. */ |
Initialize INODESTATE, LINKCOUNT, and TYPEMAP. */ |
52 |
node. Increment NBLOCKS by the number of data blocks held. |
node. Increment NBLOCKS by the number of data blocks held. |
53 |
Set BLKERROR if this block is invalid. |
Set BLKERROR if this block is invalid. |
54 |
Return RET_GOOD, RET_BAD, RET_STOP if the block is good, |
Return RET_GOOD, RET_BAD, RET_STOP if the block is good, |
55 |
bad, or if we should entirely stop checking blocks in this |
bad, or if we should entirely stop checking blocks in this |
56 |
inode. */ |
inode. */ |
57 |
int |
int |
58 |
checkblock (daddr_t bno, int nfrags, off_t offset) |
checkblock (daddr_t bno, int nfrags, off_t offset) |
69 |
blkerror = 1; |
blkerror = 1; |
70 |
wasbad = 1; |
wasbad = 1; |
71 |
if (nblkrngerrors == 0) |
if (nblkrngerrors == 0) |
72 |
warning (0, "I=%d HAS BAD BLOCKS", number); |
warning (0, "I=%Ld HAS BAD BLOCKS", number); |
73 |
if (nblkrngerrors++ > MAXBAD) |
if (nblkrngerrors++ > MAXBAD) |
74 |
{ |
{ |
75 |
problem (0, "EXCESSIVE BAD BLKS I=%d", number); |
problem (0, "EXCESSIVE BAD BLKS I=%Ld", number); |
76 |
if (preen || reply ("SKIP")) |
if (preen || reply ("SKIP")) |
77 |
{ |
{ |
78 |
pfail ("SKIPPING"); |
pfail ("SKIPPING"); |
93 |
{ |
{ |
94 |
blkerror = 1; |
blkerror = 1; |
95 |
if (nblkduperrors == 0) |
if (nblkduperrors == 0) |
96 |
warning (0, "I=%d HAS DUPLICATE BLOCKS", number); |
warning (0, "I=%Ld HAS DUPLICATE BLOCKS", number); |
97 |
warning (0, "DUPLICATE BLOCK %ld", bno); |
warning (0, "DUPLICATE BLOCK %ld", bno); |
98 |
wasbad = 1; |
wasbad = 1; |
99 |
if (nblkduperrors++ > MAXBAD) |
if (nblkduperrors++ > MAXBAD) |
100 |
{ |
{ |
101 |
problem (0, "EXCESSIVE DUP BLKS I=%d", number); |
problem (0, "EXCESSIVE DUP BLKS I=%Ld", number); |
102 |
if (preen || reply ("SKIP")) |
if (preen || reply ("SKIP")) |
103 |
{ |
{ |
104 |
pfail ("SKIPPING"); |
pfail ("SKIPPING"); |
128 |
} |
} |
129 |
return wasbad ? RET_BAD : RET_GOOD; |
return wasbad ? RET_BAD : RET_GOOD; |
130 |
} |
} |
131 |
|
|
132 |
|
|
133 |
/* Account for blocks used by meta data */ |
/* Account for blocks used by meta data */ |
134 |
for (cg = 0; cg < sblock->fs_ncg; cg++) |
for (cg = 0; cg < sblock->fs_ncg; cg++) |
135 |
{ |
{ |
136 |
daddr_t firstdata, firstcgblock, bno; |
daddr_t firstdata, firstcgblock, bno; |
137 |
|
|
138 |
/* Each cylinder group past the first reserves data |
/* Each cylinder group past the first reserves data |
139 |
from its cylinder group copy to (but not including) |
from its cylinder group copy to (but not including) |
140 |
the first datablock. |
the first datablock. |
141 |
|
|
142 |
The first, however, reserves from the very front of the |
The first, however, reserves from the very front of the |
143 |
cylinder group (thus including the boot block), and it also |
cylinder group (thus including the boot block), and it also |
155 |
for (bno = firstcgblock; bno < firstdata; bno++) |
for (bno = firstcgblock; bno < firstdata; bno++) |
156 |
setbmap (bno); |
setbmap (bno); |
157 |
} |
} |
158 |
|
|
159 |
/* Loop through each inode, doing initial checks */ |
/* Loop through each inode, doing initial checks */ |
160 |
for (number = 0, cg = 0; cg < sblock->fs_ncg; cg++) |
for (number = 0, cg = 0; cg < sblock->fs_ncg; cg++) |
161 |
for (i = 0; i < sblock->fs_ipg; i++, number++) |
for (i = 0; i < sblock->fs_ipg; i++, number++) |
165 |
int dbwarn = 0, ibwarn = 0; |
int dbwarn = 0, ibwarn = 0; |
166 |
|
|
167 |
/* if (!preen && !(number % 10000)) |
/* if (!preen && !(number % 10000)) |
168 |
printf ("I=%d\n", number); */ |
printf ("I=%Ld\n", number); */ |
169 |
|
|
170 |
if (number < ROOTINO) |
if (number < ROOTINO) |
171 |
continue; |
continue; |
172 |
|
|
173 |
getinode (number, dp); |
getinode (number, dp); |
174 |
mode = DI_MODE (dp); |
mode = DI_MODE (dp); |
175 |
type = mode & IFMT; |
type = mode & IFMT; |
176 |
|
|
177 |
/* If the node is not allocated, then make sure it's |
/* If the node is not allocated, then make sure it's |
178 |
properly clear */ |
properly clear */ |
179 |
if (type == 0) |
if (type == 0) |
184 |
|| DI_MODE (dp) |
|| DI_MODE (dp) |
185 |
|| dp->di_size) |
|| dp->di_size) |
186 |
{ |
{ |
187 |
problem (0, "PARTIALLY ALLOCATED INODE I=%d", number); |
problem (0, "PARTIALLY ALLOCATED INODE I=%Ld", number); |
188 |
if (preen || reply ("CLEAR")) |
if (preen || reply ("CLEAR")) |
189 |
{ |
{ |
190 |
clear_inode (number, dp); |
clear_inode (number, dp); |
196 |
else |
else |
197 |
{ |
{ |
198 |
/* Node is allocated. */ |
/* Node is allocated. */ |
199 |
|
|
200 |
/* Check to see if we think the node should be cleared */ |
/* Check to see if we think the node should be cleared */ |
201 |
|
|
202 |
/* Verify size for basic validity */ |
/* Verify size for basic validity */ |
203 |
holdallblocks = 0; |
holdallblocks = 0; |
204 |
|
|
205 |
if (dp->di_size + sblock->fs_bsize - 1 < dp->di_size) |
if (dp->di_size + sblock->fs_bsize - 1 < dp->di_size) |
206 |
{ |
{ |
207 |
problem (1, "OVERFLOW IN FILE SIZE I=%d (SIZE == %lld)", number, |
problem (1, "OVERFLOW IN FILE SIZE I=%Ld (SIZE == %lld)", number, |
208 |
dp->di_size); |
dp->di_size); |
209 |
if (reply ("CLEAR")) |
if (reply ("CLEAR")) |
210 |
{ |
{ |
213 |
continue; |
continue; |
214 |
} |
} |
215 |
inodestate[number] = UNALLOC; |
inodestate[number] = UNALLOC; |
216 |
warning (0, "WILL TREAT ANY BLOCKS HELD BY I=%d AS ALLOCATED", |
warning (0, "WILL TREAT ANY BLOCKS HELD BY I=%Ld AS ALLOCATED", |
217 |
number); |
number); |
218 |
holdallblocks = 1; |
holdallblocks = 1; |
219 |
} |
} |
220 |
|
|
221 |
/* Decode type and set NDB |
/* Decode type and set NDB |
222 |
also set inodestate correctly. */ |
also set inodestate correctly. */ |
223 |
inodestate[number] = REG; |
inodestate[number] = REG; |
224 |
switch (type) |
switch (type) |
227 |
case IFCHR: |
case IFCHR: |
228 |
ndb = 1; |
ndb = 1; |
229 |
break; |
break; |
230 |
|
|
231 |
case IFIFO: |
case IFIFO: |
232 |
case IFSOCK: |
case IFSOCK: |
233 |
ndb = 0; |
ndb = 0; |
234 |
break; |
break; |
235 |
|
|
236 |
case IFLNK: |
case IFLNK: |
237 |
if (sblock->fs_maxsymlinklen != -1) |
if (sblock->fs_maxsymlinklen != -1) |
238 |
{ |
{ |
239 |
/* Check to see if this is a fastlink. The |
/* Check to see if this is a fastlink. The |
240 |
old fast link format has fs_maxsymlinklen |
old fast link format has fs_maxsymlinklen |
241 |
of zero and di_blocks zero; the new format has |
of zero and di_blocks zero; the new format has |
242 |
fs_maxsymlinklen set and we ignore di_blocks. |
fs_maxsymlinklen set and we ignore di_blocks. |
243 |
So check for either. */ |
So check for either. */ |
244 |
if ((sblock->fs_maxsymlinklen |
if ((sblock->fs_maxsymlinklen |
245 |
&& dp->di_size < sblock->fs_maxsymlinklen) |
&& dp->di_size < sblock->fs_maxsymlinklen) |
262 |
else |
else |
263 |
ndb = howmany (dp->di_size, sblock->fs_bsize); |
ndb = howmany (dp->di_size, sblock->fs_bsize); |
264 |
break; |
break; |
265 |
|
|
266 |
case IFDIR: |
case IFDIR: |
267 |
inodestate[number] = DIRECTORY; |
inodestate[number] = DIRECTORY; |
268 |
/* Fall through */ |
/* Fall through */ |
269 |
case IFREG: |
case IFREG: |
270 |
ndb = howmany (dp->di_size, sblock->fs_bsize); |
ndb = howmany (dp->di_size, sblock->fs_bsize); |
271 |
break; |
break; |
272 |
|
|
273 |
default: |
default: |
274 |
problem (1, "UNKNOWN FILE TYPE I=%d (MODE=%ol)", number, mode); |
problem (1, "UNKNOWN FILE TYPE I=%Ld (MODE=%ol)", number, mode); |
275 |
if (reply ("CLEAR")) |
if (reply ("CLEAR")) |
276 |
{ |
{ |
277 |
clear_inode (number, dp); |
clear_inode (number, dp); |
280 |
} |
} |
281 |
inodestate[number] = UNALLOC; |
inodestate[number] = UNALLOC; |
282 |
holdallblocks = 1; |
holdallblocks = 1; |
283 |
warning (0, "WILL TREAT ANY BLOCKS HELD BY I=%d " |
warning (0, "WILL TREAT ANY BLOCKS HELD BY I=%Ld " |
284 |
"AS ALLOCATED", number); |
"AS ALLOCATED", number); |
285 |
ndb = 0; |
ndb = 0; |
286 |
} |
} |
287 |
|
|
288 |
if (ndb < 0) |
if (ndb < 0) |
289 |
{ |
{ |
290 |
problem (1, "BAD FILE SIZE I= %d (SIZE == %lld)", number, |
problem (1, "BAD FILE SIZE I= %Ld (SIZE == %lld)", number, |
291 |
dp->di_size); |
dp->di_size); |
292 |
if (reply ("CLEAR")) |
if (reply ("CLEAR")) |
293 |
{ |
{ |
296 |
continue; |
continue; |
297 |
} |
} |
298 |
inodestate[number] = UNALLOC; |
inodestate[number] = UNALLOC; |
299 |
warning (0, "WILL TREAT ANY BLOCKS HELD BY I=%d AS ALLOCATED", |
warning (0, "WILL TREAT ANY BLOCKS HELD BY I=%Ld AS ALLOCATED", |
300 |
number); |
number); |
301 |
holdallblocks = 1; |
holdallblocks = 1; |
302 |
} |
} |
308 |
if (!holdallblocks) |
if (!holdallblocks) |
309 |
{ |
{ |
310 |
if (dp->di_size |
if (dp->di_size |
311 |
&& (type == IFBLK || type == IFCHR |
&& (type == IFBLK || type == IFCHR |
312 |
|| type == IFSOCK || type == IFIFO)) |
|| type == IFSOCK || type == IFIFO)) |
313 |
{ |
{ |
314 |
problem (1, "SPECIAL NODE I=%d (MODE=%ol) HAS SIZE %lld", |
problem (1, "SPECIAL NODE I=%Ld (MODE=%ol) HAS SIZE %lld", |
315 |
number, mode, dp->di_size); |
number, mode, dp->di_size); |
316 |
if (reply ("TRUNCATE")) |
if (reply ("TRUNCATE")) |
317 |
{ |
{ |
319 |
write_inode (number, dp); |
write_inode (number, dp); |
320 |
} |
} |
321 |
} |
} |
322 |
|
|
323 |
/* If we haven't set NDB speciall above, then it is set from |
/* If we haven't set NDB speciall above, then it is set from |
324 |
the file size correctly by the size check. */ |
the file size correctly by the size check. */ |
325 |
|
|
326 |
/* Check all the direct and indirect blocks that are past the |
/* Check all the direct and indirect blocks that are past the |
327 |
amount necessary to be zero. */ |
amount necessary to be zero. */ |
328 |
for (lbn = ndb; lbn < NDADDR; lbn++) |
for (lbn = ndb; lbn < NDADDR; lbn++) |
332 |
if (!dbwarn) |
if (!dbwarn) |
333 |
{ |
{ |
334 |
dbwarn = 1; |
dbwarn = 1; |
335 |
problem (0, "INODE I=%d HAS EXTRA DIRECT BLOCKS", |
problem (0, "INODE I=%Ld HAS EXTRA DIRECT BLOCKS", |
336 |
number); |
number); |
337 |
if (preen || reply ("DEALLOCATE")) |
if (preen || reply ("DEALLOCATE")) |
338 |
{ |
{ |
357 |
if (ibwarn) |
if (ibwarn) |
358 |
{ |
{ |
359 |
ibwarn = 1; |
ibwarn = 1; |
360 |
problem (0, "INODE I=%d HAS EXTRA INDIRECT BLOCKS", |
problem (0, "INODE I=%Ld HAS EXTRA INDIRECT BLOCKS", |
361 |
number); |
number); |
362 |
if (preen || reply ("DEALLOCATE")) |
if (preen || reply ("DEALLOCATE")) |
363 |
{ |
{ |
373 |
write_inode (number, dp); |
write_inode (number, dp); |
374 |
} |
} |
375 |
} |
} |
376 |
|
|
377 |
/* If this node is really allocated (as opposed to something |
/* If this node is really allocated (as opposed to something |
378 |
that we should clear but the user won't) then set LINKCOUNT |
that we should clear but the user won't) then set LINKCOUNT |
379 |
and TYPEMAP entries. */ |
and TYPEMAP entries. */ |
397 |
warning (1, "DUPLICATE or BAD BLOCKS"); |
warning (1, "DUPLICATE or BAD BLOCKS"); |
398 |
else |
else |
399 |
{ |
{ |
400 |
problem (0, "I=%d has ", number); |
problem (0, "I=%Ld has ", number); |
401 |
if (nblkduperrors) |
if (nblkduperrors) |
402 |
{ |
{ |
403 |
pextend ("%d DUPLICATE BLOCKS", nblkduperrors); |
pextend ("%d DUPLICATE BLOCKS", nblkduperrors); |
418 |
} |
} |
419 |
else if (dp->di_blocks != nblocks) |
else if (dp->di_blocks != nblocks) |
420 |
{ |
{ |
421 |
problem (0, "INCORRECT BLOCK COUNT I=%d (%ld should be %d)", |
problem (0, "INCORRECT BLOCK COUNT I=%Ld (%ld should be %d)", |
422 |
number, dp->di_blocks, nblocks); |
number, dp->di_blocks, nblocks); |
423 |
if (preen || reply ("CORRECT")) |
if (preen || reply ("CORRECT")) |
424 |
{ |
{ |
435 |
} |
} |
436 |
} |
} |
437 |
} |
} |
|
|
|
|
|
|