dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / fs.d / ufs / fsck / inode.c
blob912c424a797a8a98eadac8e90298d5358f63dcee
1 /*
2 * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
3 */
5 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
6 /* All Rights Reserved */
8 /*
9 * Copyright (c) 1980, 1986, 1990 The Regents of the University of California.
10 * All rights reserved.
12 * Redistribution and use in source and binary forms are permitted
13 * provided that: (1) source distributions retain this entire copyright
14 * notice and comment, and (2) distributions including binaries display
15 * the following acknowledgement: ``This product includes software
16 * developed by the University of California, Berkeley and its contributors''
17 * in the documentation or other materials provided with the distribution
18 * and in all advertising materials mentioning features or use of this
19 * software. Neither the name of the University nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <time.h>
33 #include <limits.h>
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/sysmacros.h>
37 #include <sys/mntent.h>
38 #include <sys/vnode.h>
39 #include <sys/fs/ufs_inode.h>
40 #include <sys/fs/ufs_fs.h>
41 #define _KERNEL
42 #include <sys/fs/ufs_fsdir.h>
43 #undef _KERNEL
44 #include <pwd.h>
45 #include "fsck.h"
47 static int get_indir_offsets(int, daddr_t, int *, int *);
48 static int clearanentry(struct inodesc *);
49 static void pdinode(struct dinode *);
50 static void inoflush(void);
51 static void mark_delayed_inodes(fsck_ino_t, daddr32_t);
52 static int iblock(struct inodesc *, int, uoff_t, enum cki_action);
53 static struct inoinfo *search_cache(struct inoinfo *, fsck_ino_t);
54 static int ckinode_common(struct dinode *, struct inodesc *, enum cki_action);
55 static int lookup_dotdot_ino(fsck_ino_t);
58 * ckinode() essentially traverses the blocklist of the provided
59 * inode. For each block either the caller-supplied callback (id_func
60 * in the provided struct inodesc) or dirscan() is invoked. Which is
61 * chosen is controlled by what type of traversal was requested
62 * (id_type) - if it was for an ADDR or ACL, use the callback,
63 * otherwise it is assumed to be DATA (i.e., a directory) whose
64 * contents need to be scanned.
66 * Note that a directory inode can get passed in with a type of ADDR;
67 * the type field is orthogonal to the IFMT value. This is so that
68 * the file aspects (no duplicate blocks, etc) of a directory can be
69 * verified just like is done for any other file, or the actual
70 * contents can be scanned so that connectivity and such can be
71 * investigated.
73 * The traversal is controlled by flags in the return value of
74 * dirscan() or the callback. Five flags are defined, STOP, SKIP,
75 * KEEPON, ALTERED, and FOUND. Their semantics are:
77 * STOP - no further processing of this inode is desired/possible/
78 * feasible/etc. This can mean that whatever the scan
79 * was searching for was found, or a serious
80 * inconsistency was encountered, or anything else
81 * appropriate.
83 * SKIP - something that made it impossible to continue was
84 * encountered, and the caller should go on to the next
85 * inode. This is more for i/o failures than for
86 * logical inconsistencies. Nothing actually looks for
87 * this.
89 * KEEPON - no more blocks of this inode need to be scanned, but
90 * nothing's wrong, so keep on going with the next
91 * inode. It is similar to STOP, except that
92 * ckinode()'s caller will typically advance to the next
93 * inode for KEEPON, whereas it ceases scanning through
94 * the inodes completely for STOP.
96 * ALTERED - a change was made to the inode. If the caller sees
97 * this set, it should make sure to flush out the
98 * changes. Note that any data blocks read in by the
99 * function need to be marked dirty by it directly;
100 * flushing of those will happen automatically later.
102 * FOUND - whatever was being searched for was located.
103 * Typically combined with STOP to avoid wasting time
104 * doing additional looking.
106 * During a traversal, some state needs to be carried around. At the
107 * least, the callback functions need to know what inode they're
108 * working on, which logical block, and whether or not fixing problems
109 * when they're encountered is desired. Rather than try to guess what
110 * else might be needed (and thus end up passing way more arguments
111 * than is reasonable), all the possibilities have been bundled in
112 * struct inodesc. About half of the fields are specific to directory
113 * traversals, and the rest are pretty much generic to any traversal.
115 * The general fields are:
117 * id_fix What to do when an error is found. Generally, this
118 * is set to DONTKNOW before a traversal. If a
119 * problem is encountered, it is changed to either FIX
120 * or NOFIX by the dofix() query function. If id_fix
121 * has already been set to FIX when dofix() is called, then
122 * it includes the ALTERED flag (see above) in its return
123 * value; the net effect is that the inode's buffer
124 * will get marked dirty and written to disk at some
125 * point. If id_fix is DONTKNOW, then dofix() will
126 * query the user. If it is NOFIX, then dofix()
127 * essentially does nothing. A few routines set NOFIX
128 * as the initial value, as they are performing a best-
129 * effort informational task, rather than an actual
130 * repair operation.
132 * id_func This is the function that will be called for every
133 * logical block in the file (assuming id_type is not
134 * DATA). The logical block may represent a hole, so
135 * the callback needs to be prepared to handle that
136 * case. Its return value is a combination of the flags
137 * described above (SKIP, ALTERED, etc).
139 * id_number The inode number whose block list or data is being
140 * scanned.
142 * id_parent When id_type is DATA, this is the inode number for
143 * the parent of id_number. Otherwise, it is
144 * available for use as an extra parameter or return
145 * value between the callback and ckinode()'s caller.
146 * Which, if either, of those is left completely up to
147 * the two routines involved, so nothing can generally
148 * be assumed about the id_parent value for non-DATA
149 * traversals.
151 * id_lbn This is the current logical block (not fragment)
152 * number being visited by the traversal.
154 * id_blkno This is the physical block corresponding to id_lbn.
156 * id_numfrags This defines how large a block is being processed in
157 * this particular invocation of the callback.
158 * Usually, it will be the same as sblock.fs_frag.
159 * However, if a direct block is being processed and
160 * it is less than a full filesystem block,
161 * id_numfrags will indicate just how many fragments
162 * (starting from id_lbn) are actually part of the
163 * file.
165 * id_truncto The pass 4 callback is used in several places to
166 * free the blocks of a file (the `FILE HAS PROBLEM
167 * FOO; CLEAR?' scenario). This has been generalized
168 * to allow truncating a file to a particular length
169 * rather than always completely discarding it. If
170 * id_truncto is -1, then the entire file is released,
171 * otherwise it is logical block number to truncate
172 * to. This generalized interface was motivated by a
173 * desire to be able to discard everything after a
174 * hole in a directory, rather than the entire
175 * directory.
177 * id_type Selects the type of traversal. DATA for dirscan(),
178 * ADDR or ACL for using the provided callback.
180 * There are several more fields used just for dirscan() traversals:
182 * id_filesize The number of bytes in the overall directory left to
183 * process.
185 * id_loc Byte position within the directory block. Should always
186 * point to the start of a directory entry.
188 * id_entryno Which logical directory entry is being processed (0
189 * is `.', 1 is `..', 2 and on are normal entries).
190 * This field is primarily used to enable special
191 * checks when looking at the first two entries.
193 * The exception (there's always an exception in fsck)
194 * is that in pass 1, it tracks how many fragments are
195 * being used by a particular inode.
197 * id_firsthole The first logical block number that was found to
198 * be zero. As directories are not supposed to have
199 * holes, this marks where a directory should be
200 * truncated down to. A value of -1 indicates that
201 * no holes were found.
203 * id_dirp A pointer to the in-memory copy of the current
204 * directory entry (as identified by id_loc).
206 * id_name This is a directory entry name to either create
207 * (callback is mkentry) or locate (callback is
208 * chgino, findino, or findname).
211 ckinode(struct dinode *dp, struct inodesc *idesc, enum cki_action action)
213 struct inodesc cleardesc;
214 mode_t mode;
216 if (idesc->id_filesize == 0)
217 idesc->id_filesize = (offset_t)dp->di_size;
220 * Our caller should be filtering out completely-free inodes
221 * (mode == zero), so we'll work on the assumption that what
222 * we're given has some basic validity.
224 * The kernel is inconsistent about MAXPATHLEN including the
225 * trailing \0, so allow the more-generous length for symlinks.
227 mode = dp->di_mode & IFMT;
228 if (mode == IFBLK || mode == IFCHR)
229 return (KEEPON);
230 if (mode == IFLNK && dp->di_size > MAXPATHLEN) {
231 pwarn("I=%d Symlink longer than supported maximum\n",
232 idesc->id_number);
233 init_inodesc(&cleardesc);
234 cleardesc.id_type = ADDR;
235 cleardesc.id_number = idesc->id_number;
236 cleardesc.id_fix = DONTKNOW;
237 clri(&cleardesc, "BAD", CLRI_VERBOSE, CLRI_NOP_CORRUPT);
238 return (STOP);
240 return (ckinode_common(dp, idesc, action));
244 * This was split out from ckinode() to allow it to be used
245 * without having to pass in kludge flags to suppress the
246 * wrong-for-deletion initialization and irrelevant checks.
247 * This feature is no longer needed, but is being kept in case
248 * the need comes back.
250 static int
251 ckinode_common(struct dinode *dp, struct inodesc *idesc,
252 enum cki_action action)
254 offset_t offset;
255 struct dinode dino;
256 daddr_t ndb;
257 int indir_data_blks, last_indir_blk;
258 int ret, i, frags;
260 (void) memmove(&dino, dp, sizeof (struct dinode));
261 ndb = howmany(dino.di_size, (uoff_t)sblock.fs_bsize);
263 for (i = 0; i < NDADDR; i++) {
264 idesc->id_lbn++;
265 offset = blkoff(&sblock, dino.di_size);
266 if ((--ndb == 0) && (offset != 0)) {
267 idesc->id_numfrags =
268 numfrags(&sblock, fragroundup(&sblock, offset));
269 } else {
270 idesc->id_numfrags = sblock.fs_frag;
272 if (dino.di_db[i] == 0) {
273 if ((ndb > 0) && (idesc->id_firsthole < 0)) {
274 idesc->id_firsthole = i;
276 continue;
278 idesc->id_blkno = dino.di_db[i];
279 if (idesc->id_type == ADDR || idesc->id_type == ACL)
280 ret = (*idesc->id_func)(idesc);
281 else
282 ret = dirscan(idesc);
285 * Need to clear the entry, now that we're done with
286 * it. We depend on freeblk() ignoring a request to
287 * free already-free fragments to handle the problem of
288 * a partial block.
290 if ((action == CKI_TRUNCATE) &&
291 (idesc->id_truncto >= 0) &&
292 (idesc->id_lbn >= idesc->id_truncto)) {
293 dp = ginode(idesc->id_number);
295 * The (int) cast is safe, in that if di_size won't
296 * fit, it'll be a multiple of any legal fs_frag,
297 * thus giving a zero result. That value, in turn
298 * means we're doing an entire block.
300 frags = howmany((int)dp->di_size, sblock.fs_fsize) %
301 sblock.fs_frag;
302 if (frags == 0)
303 frags = sblock.fs_frag;
304 freeblk(idesc->id_number, dp->di_db[i],
305 frags);
306 dp = ginode(idesc->id_number);
307 dp->di_db[i] = 0;
308 inodirty();
309 ret |= ALTERED;
312 if (ret & STOP)
313 return (ret);
317 * indir_data_blks contains the number of data blocks in all
318 * the previous levels for this iteration. E.g., for the
319 * single indirect case (i = 0, di_ib[i] != 0), NDADDR's worth
320 * of blocks have already been covered by the direct blocks
321 * (di_db[]). At the triple indirect level (i = NIADDR - 1),
322 * it is all of the number of data blocks that were covered
323 * by the second indirect, single indirect, and direct block
324 * levels.
326 idesc->id_numfrags = sblock.fs_frag;
327 ndb = howmany(dino.di_size, (uoff_t)sblock.fs_bsize);
328 for (i = 0; i < NIADDR; i++) {
329 (void) get_indir_offsets(i, ndb, &indir_data_blks,
330 &last_indir_blk);
331 if (dino.di_ib[i] != 0) {
333 * We'll only clear di_ib[i] if the first entry (and
334 * therefore all of them) is to be cleared, since we
335 * only go through this code on the first entry of
336 * each level of indirection. The +1 is to account
337 * for the fact that we don't modify id_lbn until
338 * we actually start processing on a data block.
340 idesc->id_blkno = dino.di_ib[i];
341 ret = iblock(idesc, i + 1,
342 (uoff_t)howmany(dino.di_size,
343 (uoff_t)sblock.fs_bsize) - indir_data_blks,
344 action);
345 if ((action == CKI_TRUNCATE) &&
346 (idesc->id_truncto <= indir_data_blks) &&
347 ((idesc->id_lbn + 1) >= indir_data_blks) &&
348 ((idesc->id_lbn + 1) <= last_indir_blk)) {
349 dp = ginode(idesc->id_number);
350 if (dp->di_ib[i] != 0) {
351 freeblk(idesc->id_number, dp->di_ib[i],
352 sblock.fs_frag);
355 if (ret & STOP)
356 return (ret);
357 } else {
359 * Need to know which of the file's logical blocks
360 * reside in the missing indirect block. However, the
361 * precise location is only needed for truncating
362 * directories, and level-of-indirection precision is
363 * sufficient for that.
365 if ((indir_data_blks < ndb) &&
366 (idesc->id_firsthole < 0)) {
367 idesc->id_firsthole = indir_data_blks;
371 return (KEEPON);
374 static int
375 get_indir_offsets(int ilevel_wanted, daddr_t ndb, int *data_blks,
376 int *last_blk)
378 int ndb_ilevel = -1;
379 int ilevel;
380 int dblks, lblk;
382 for (ilevel = 0; ilevel < NIADDR; ilevel++) {
383 switch (ilevel) {
384 case 0: /* SINGLE */
385 dblks = NDADDR;
386 lblk = dblks + NINDIR(&sblock) - 1;
387 break;
388 case 1: /* DOUBLE */
389 dblks = NDADDR + NINDIR(&sblock);
390 lblk = dblks + (NINDIR(&sblock) * NINDIR(&sblock)) - 1;
391 break;
392 case 2: /* TRIPLE */
393 dblks = NDADDR + NINDIR(&sblock) +
394 (NINDIR(&sblock) * NINDIR(&sblock));
395 lblk = dblks + (NINDIR(&sblock) * NINDIR(&sblock) *
396 NINDIR(&sblock)) - 1;
397 break;
398 default:
399 exitstat = EXERRFATAL;
401 * Translate from zero-based array to
402 * one-based human-style counting.
404 errexit("panic: indirection level %d not 1, 2, or 3",
405 ilevel + 1);
406 /* NOTREACHED */
409 if (dblks < ndb && ndb <= lblk)
410 ndb_ilevel = ilevel;
412 if (ilevel == ilevel_wanted) {
413 if (data_blks != NULL)
414 *data_blks = dblks;
415 if (last_blk != NULL)
416 *last_blk = lblk;
420 return (ndb_ilevel);
423 static int
424 iblock(struct inodesc *idesc, int ilevel, uoff_t iblks,
425 enum cki_action action)
427 struct bufarea *bp;
428 int i, n;
429 int (*func)(struct inodesc *) = NULL;
430 uoff_t fsbperindirb;
431 daddr32_t last_lbn;
432 int nif;
433 char buf[BUFSIZ];
435 n = KEEPON;
437 switch (idesc->id_type) {
438 case ADDR:
439 func = idesc->id_func;
440 if (((n = (*func)(idesc)) & KEEPON) == 0)
441 return (n);
442 break;
443 case ACL:
444 func = idesc->id_func;
445 break;
446 case DATA:
447 func = dirscan;
448 break;
449 default:
450 errexit("unknown inodesc type %d in iblock()", idesc->id_type);
451 /* NOTREACHED */
453 if (chkrange(idesc->id_blkno, idesc->id_numfrags)) {
454 return ((idesc->id_type == ACL) ? STOP : SKIP);
457 bp = getdatablk(idesc->id_blkno, (size_t)sblock.fs_bsize);
458 if (bp->b_errs != 0) {
459 brelse(bp);
460 return (SKIP);
463 ilevel--;
465 * Trivia note: the BSD fsck has the number of bytes remaining
466 * as the third argument to iblock(), so the equivalent of
467 * fsbperindirb starts at fs_bsize instead of one. We're
468 * working in units of filesystem blocks here, not bytes or
469 * fragments.
471 for (fsbperindirb = 1, i = 0; i < ilevel; i++) {
472 fsbperindirb *= (uoff_t)NINDIR(&sblock);
475 * nif indicates the next "free" pointer (as an array index) in this
476 * indirect block, based on counting the blocks remaining in the
477 * file after subtracting all previously processed blocks.
478 * This figure is based on the size field of the inode.
480 * Note that in normal operation, nif may initially be calculated
481 * as larger than the number of pointers in this block (as when
482 * there are more indirect blocks following); if that is
483 * the case, nif is limited to the max number of pointers per
484 * indirect block.
486 * Also note that if an inode is inconsistent (has more blocks
487 * allocated to it than the size field would indicate), the sweep
488 * through any indirect blocks directly pointed at by the inode
489 * continues. Since the block offset of any data blocks referenced
490 * by these indirect blocks is greater than the size of the file,
491 * the index nif may be computed as a negative value.
492 * In this case, we reset nif to indicate that all pointers in
493 * this retrieval block should be zeroed and the resulting
494 * unreferenced data and/or retrieval blocks will be recovered
495 * through garbage collection later.
497 nif = (offset_t)howmany(iblks, fsbperindirb);
498 if (nif > NINDIR(&sblock))
499 nif = NINDIR(&sblock);
500 else if (nif < 0)
501 nif = 0;
503 * first pass: all "free" retrieval pointers (from [nif] thru
504 * the end of the indirect block) should be zero. (This
505 * assertion does not hold for directories, which may be
506 * truncated without releasing their allocated space)
508 if (nif < NINDIR(&sblock) && (idesc->id_func == pass1check ||
509 idesc->id_func == pass3bcheck)) {
510 for (i = nif; i < NINDIR(&sblock); i++) {
511 if (bp->b_un.b_indir[i] == 0)
512 continue;
513 (void) sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu",
514 (ulong_t)idesc->id_number);
515 if (preen) {
516 pfatal(buf);
517 } else if (dofix(idesc, buf)) {
518 freeblk(idesc->id_number,
519 bp->b_un.b_indir[i],
520 sblock.fs_frag);
521 bp->b_un.b_indir[i] = 0;
522 dirty(bp);
525 flush(fswritefd, bp);
528 * second pass: all retrieval pointers referring to blocks within
529 * a valid range [0..filesize] (both indirect and data blocks)
530 * are examined in the same manner as ckinode() checks the
531 * direct blocks in the inode. Sweep through from
532 * the first pointer in this retrieval block to [nif-1].
534 last_lbn = howmany(idesc->id_filesize, sblock.fs_bsize);
535 for (i = 0; i < nif; i++) {
536 if (ilevel == 0)
537 idesc->id_lbn++;
538 if (bp->b_un.b_indir[i] != 0) {
539 idesc->id_blkno = bp->b_un.b_indir[i];
540 if (ilevel > 0) {
541 n = iblock(idesc, ilevel, iblks, action);
543 * Each iteration decreases "remaining block
544 * count" by the number of blocks accessible
545 * by a pointer at this indirect block level.
547 iblks -= fsbperindirb;
548 } else {
550 * If we're truncating, func will discard
551 * the data block for us.
553 n = (*func)(idesc);
556 if ((action == CKI_TRUNCATE) &&
557 (idesc->id_truncto >= 0) &&
558 (idesc->id_lbn >= idesc->id_truncto)) {
559 freeblk(idesc->id_number, bp->b_un.b_indir[i],
560 sblock.fs_frag);
564 * Note that truncation never gets STOP back
565 * under normal circumstances. Abnormal would
566 * be a bad acl short-circuit in iblock() or
567 * an out-of-range failure in pass4check().
568 * We still want to keep going when truncating
569 * under those circumstances, since the whole
570 * point of truncating is to get rid of all
571 * that.
573 if ((n & STOP) && (action != CKI_TRUNCATE)) {
574 brelse(bp);
575 return (n);
577 } else {
578 if ((idesc->id_lbn < last_lbn) &&
579 (idesc->id_firsthole < 0)) {
580 idesc->id_firsthole = idesc->id_lbn;
582 if (idesc->id_type == DATA) {
584 * No point in continuing in the indirect
585 * blocks of a directory, since they'll just
586 * get freed anyway.
588 brelse(bp);
589 return ((n & ~KEEPON) | STOP);
594 brelse(bp);
595 return (KEEPON);
599 * Check that a block is a legal block number.
600 * Return 0 if in range, 1 if out of range.
603 chkrange(daddr32_t blk, int cnt)
605 int c;
607 if (cnt <= 0 || blk <= 0 || ((unsigned)blk >= (unsigned)maxfsblock) ||
608 ((cnt - 1) > (maxfsblock - blk))) {
609 if (debug)
610 (void) printf(
611 "Bad fragment range: should be 1 <= %d..%d < %d\n",
612 blk, blk + cnt, maxfsblock);
613 return (1);
615 if ((cnt > sblock.fs_frag) ||
616 ((fragnum(&sblock, blk) + cnt) > sblock.fs_frag)) {
617 if (debug)
618 (void) printf("Bad fragment size: size %d\n", cnt);
619 return (1);
621 c = dtog(&sblock, blk);
622 if (blk < cgdmin(&sblock, c)) {
623 if ((unsigned)(blk + cnt) > (unsigned)cgsblock(&sblock, c)) {
624 if (debug)
625 (void) printf(
626 "Bad fragment position: %d..%d spans start of cg metadata\n",
627 blk, blk + cnt);
628 return (1);
630 } else {
631 if ((unsigned)(blk + cnt) > (unsigned)cgbase(&sblock, c+1)) {
632 if (debug)
633 (void) printf(
634 "Bad frag pos: %d..%d crosses end of cg\n",
635 blk, blk + cnt);
636 return (1);
639 return (0);
643 * General purpose interface for reading inodes.
647 * Note that any call to ginode() can potentially invalidate any
648 * dinode pointers previously acquired from it. To avoid pain,
649 * make sure to always call inodirty() immediately after modifying
650 * an inode, if there's any chance of ginode() being called after
651 * that. Also, always call ginode() right before you need to access
652 * an inode, so that there won't be any surprises from functions
653 * called between the previous ginode() invocation and the dinode
654 * use.
656 * Despite all that, we aren't doing the amount of i/o that's implied,
657 * as we use the buffer cache that getdatablk() and friends maintain.
659 static fsck_ino_t startinum = -1;
661 struct dinode *
662 ginode(fsck_ino_t inum)
664 daddr32_t iblk;
665 struct dinode *dp;
667 if (inum < UFSROOTINO || inum > maxino) {
668 errexit("bad inode number %d to ginode\n", inum);
670 if (startinum == -1 ||
671 pbp == NULL ||
672 inum < startinum ||
673 inum >= (fsck_ino_t)(startinum + (fsck_ino_t)INOPB(&sblock))) {
674 iblk = itod(&sblock, inum);
675 if (pbp != NULL) {
676 brelse(pbp);
679 * We don't check for errors here, because we can't
680 * tell our caller about it, and the zeros that will
681 * be in the buffer are just as good as anything we
682 * could fake.
684 pbp = getdatablk(iblk, (size_t)sblock.fs_bsize);
685 startinum =
686 (fsck_ino_t)((inum / INOPB(&sblock)) * INOPB(&sblock));
688 dp = &pbp->b_un.b_dinode[inum % INOPB(&sblock)];
689 if (dp->di_suid != UID_LONG)
690 dp->di_uid = dp->di_suid;
691 if (dp->di_sgid != GID_LONG)
692 dp->di_gid = dp->di_sgid;
693 return (dp);
697 * Special purpose version of ginode used to optimize first pass
698 * over all the inodes in numerical order. It bypasses the buffer
699 * system used by ginode(), etc in favour of reading the bulk of a
700 * cg's inodes at one time.
702 static fsck_ino_t nextino, lastinum;
703 static int64_t readcnt, readpercg, fullcnt, inobufsize;
704 static int64_t partialcnt, partialsize;
705 static size_t lastsize;
706 static struct dinode *inodebuf;
707 static diskaddr_t currentdblk;
708 static struct dinode *currentinode;
710 struct dinode *
711 getnextinode(fsck_ino_t inum)
713 size_t size;
714 diskaddr_t dblk;
715 static struct dinode *dp;
717 if (inum != nextino++ || inum > maxino)
718 errexit("bad inode number %d to nextinode\n", inum);
721 * Will always go into the if() the first time we're called,
722 * so dp will always be valid.
724 if (inum >= lastinum) {
725 readcnt++;
726 dblk = fsbtodb(&sblock, itod(&sblock, lastinum));
727 currentdblk = dblk;
728 if (readcnt % readpercg == 0) {
729 if (partialsize > SIZE_MAX)
730 errexit(
731 "Internal error: partialsize overflow");
732 size = (size_t)partialsize;
733 lastinum += partialcnt;
734 } else {
735 if (inobufsize > SIZE_MAX)
736 errexit("Internal error: inobufsize overflow");
737 size = (size_t)inobufsize;
738 lastinum += fullcnt;
741 * If fsck_bread() returns an error, it will already have
742 * zeroed out the buffer, so we do not need to do so here.
744 (void) fsck_bread(fsreadfd, (caddr_t)inodebuf, dblk, size);
745 lastsize = size;
746 dp = inodebuf;
748 currentinode = dp;
749 return (dp++);
753 * Reread the current getnext() buffer. This allows for changing inodes
754 * other than the current one via ginode()/inodirty()/inoflush().
756 * Just reuses all the interesting variables that getnextinode() set up
757 * last time it was called. This shouldn't get called often, so we don't
758 * try to figure out if the caller's actually touched an inode in the
759 * range we have cached. There could have been an arbitrary number of
760 * them, after all.
762 struct dinode *
763 getnextrefresh(void)
765 if (inodebuf == NULL) {
766 return (NULL);
769 inoflush();
770 (void) fsck_bread(fsreadfd, (caddr_t)inodebuf, currentdblk, lastsize);
771 return (currentinode);
774 void
775 resetinodebuf(void)
777 startinum = 0;
778 nextino = 0;
779 lastinum = 0;
780 readcnt = 0;
781 inobufsize = blkroundup(&sblock, INOBUFSIZE);
782 fullcnt = inobufsize / sizeof (struct dinode);
783 readpercg = sblock.fs_ipg / fullcnt;
784 partialcnt = sblock.fs_ipg % fullcnt;
785 partialsize = partialcnt * sizeof (struct dinode);
786 if (partialcnt != 0) {
787 readpercg++;
788 } else {
789 partialcnt = fullcnt;
790 partialsize = inobufsize;
792 if (inodebuf == NULL &&
793 (inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL)
794 errexit("Cannot allocate space for inode buffer\n");
795 while (nextino < UFSROOTINO)
796 (void) getnextinode(nextino);
799 void
800 freeinodebuf(void)
802 if (inodebuf != NULL) {
803 free((void *)inodebuf);
805 inodebuf = NULL;
809 * Routines to maintain information about directory inodes.
810 * This is built during the first pass and used during the
811 * second and third passes.
813 * Enter inodes into the cache.
815 void
816 cacheino(struct dinode *dp, fsck_ino_t inum)
818 struct inoinfo *inp;
819 struct inoinfo **inpp;
820 uint_t blks;
822 blks = NDADDR + NIADDR;
823 inp = (struct inoinfo *)
824 malloc(sizeof (*inp) + (blks - 1) * sizeof (daddr32_t));
825 if (inp == NULL)
826 errexit("Cannot increase directory list\n");
827 init_inoinfo(inp, dp, inum); /* doesn't touch i_nextlist or i_number */
828 inpp = &inphead[inum % numdirs];
829 inp->i_nextlist = *inpp;
830 *inpp = inp;
831 inp->i_number = inum;
832 if (inplast == listmax) {
833 listmax += 100;
834 inpsort = reallocarray(inpsort, listmax,
835 sizeof (struct inoinfo *));
836 if (inpsort == NULL)
837 errexit("cannot increase directory list");
839 inpsort[inplast++] = inp;
843 * Look up an inode cache structure.
845 struct inoinfo *
846 getinoinfo(fsck_ino_t inum)
848 struct inoinfo *inp;
850 inp = search_cache(inphead[inum % numdirs], inum);
851 return (inp);
855 * Determine whether inode is in cache.
858 inocached(fsck_ino_t inum)
860 return (search_cache(inphead[inum % numdirs], inum) != NULL);
864 * Clean up all the inode cache structure.
866 void
867 inocleanup(void)
869 struct inoinfo **inpp;
871 if (inphead == NULL)
872 return;
873 for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) {
874 free((void *)(*inpp));
876 free((void *)inphead);
877 free((void *)inpsort);
878 inphead = inpsort = NULL;
882 * Routines to maintain information about acl inodes.
883 * This is built during the first pass and used during the
884 * second and third passes.
886 * Enter acl inodes into the cache.
888 void
889 cacheacl(struct dinode *dp, fsck_ino_t inum)
891 struct inoinfo *aclp;
892 struct inoinfo **aclpp;
893 uint_t blks;
895 blks = NDADDR + NIADDR;
896 aclp = (struct inoinfo *)
897 malloc(sizeof (*aclp) + (blks - 1) * sizeof (daddr32_t));
898 if (aclp == NULL)
899 return;
900 aclpp = &aclphead[inum % numacls];
901 aclp->i_nextlist = *aclpp;
902 *aclpp = aclp;
903 aclp->i_number = inum;
904 aclp->i_isize = (offset_t)dp->di_size;
905 aclp->i_blkssize = (size_t)(blks * sizeof (daddr32_t));
906 (void) memmove(&aclp->i_blks[0], &dp->di_db[0], aclp->i_blkssize);
907 if (aclplast == aclmax) {
908 aclmax += 100;
909 aclpsort = reallocarray(aclpsort, aclmax,
910 sizeof (struct inoinfo *));
911 if (aclpsort == NULL)
912 errexit("cannot increase acl list");
914 aclpsort[aclplast++] = aclp;
919 * Generic cache search function.
920 * ROOT is the first entry in a hash chain (the caller is expected
921 * to have done the initial bucket lookup). KEY is what's being
922 * searched for.
924 * Returns a pointer to the entry if it is found, NULL otherwise.
926 static struct inoinfo *
927 search_cache(struct inoinfo *element, fsck_ino_t key)
929 while (element != NULL) {
930 if (element->i_number == key)
931 break;
932 element = element->i_nextlist;
935 return (element);
938 void
939 inodirty(void)
941 dirty(pbp);
944 static void
945 inoflush(void)
947 if (pbp != NULL)
948 flush(fswritefd, pbp);
952 * Interactive wrapper for freeino(), for those times when we're
953 * not sure if we should throw something away.
955 void
956 clri(struct inodesc *idesc, char *type, int verbose, int corrupting)
958 int need_parent;
959 struct dinode *dp;
961 if (statemap[idesc->id_number] == USTATE)
962 return;
964 dp = ginode(idesc->id_number);
965 if (verbose == CLRI_VERBOSE) {
966 pwarn("%s %s", type, file_id(idesc->id_number, dp->di_mode));
967 pinode(idesc->id_number);
969 if (preen || (reply("CLEAR") == 1)) {
970 need_parent = (corrupting == CLRI_NOP_OK) ?
971 TI_NOPARENT : TI_PARENT;
972 freeino(idesc->id_number, need_parent);
973 if (preen)
974 (void) printf(" (CLEARED)\n");
975 remove_orphan_dir(idesc->id_number);
976 } else if (corrupting == CLRI_NOP_CORRUPT) {
977 iscorrupt = 1;
979 (void) printf("\n");
983 * Find the directory entry for the inode noted in id_parent (which is
984 * not necessarily the parent of anything, we're just using a convenient
985 * field.
988 findname(struct inodesc *idesc)
990 struct direct *dirp = idesc->id_dirp;
992 if (dirp->d_ino != idesc->id_parent)
993 return (KEEPON);
994 (void) memmove(idesc->id_name, dirp->d_name,
995 MIN(dirp->d_namlen, MAXNAMLEN) + 1);
996 return (STOP|FOUND);
1000 * Find the inode number associated with the given name.
1003 findino(struct inodesc *idesc)
1005 struct direct *dirp = idesc->id_dirp;
1007 if (dirp->d_ino == 0)
1008 return (KEEPON);
1009 if (strcmp(dirp->d_name, idesc->id_name) == 0 &&
1010 dirp->d_ino >= UFSROOTINO && dirp->d_ino <= maxino) {
1011 idesc->id_parent = dirp->d_ino;
1012 return (STOP|FOUND);
1014 return (KEEPON);
1018 cleardirentry(fsck_ino_t parentdir, fsck_ino_t target)
1020 struct inodesc idesc;
1021 struct dinode *dp;
1023 dp = ginode(parentdir);
1024 init_inodesc(&idesc);
1025 idesc.id_func = clearanentry;
1026 idesc.id_parent = target;
1027 idesc.id_type = DATA;
1028 idesc.id_fix = NOFIX;
1029 return (ckinode(dp, &idesc, CKI_TRAVERSE));
1032 static int
1033 clearanentry(struct inodesc *idesc)
1035 struct direct *dirp = idesc->id_dirp;
1037 if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) {
1038 idesc->id_entryno++;
1039 return (KEEPON);
1041 dirp->d_ino = 0;
1042 return (STOP|FOUND|ALTERED);
1045 void
1046 pinode(fsck_ino_t ino)
1048 struct dinode *dp;
1050 (void) printf(" I=%lu ", (ulong_t)ino);
1051 if (ino < UFSROOTINO || ino > maxino)
1052 return;
1053 dp = ginode(ino);
1054 pdinode(dp);
1057 static void
1058 pdinode(struct dinode *dp)
1060 char *p;
1061 struct passwd *pw;
1062 time_t t;
1064 (void) printf(" OWNER=");
1065 if ((pw = getpwuid((int)dp->di_uid)) != 0)
1066 (void) printf("%s ", pw->pw_name);
1067 else
1068 (void) printf("%lu ", (ulong_t)dp->di_uid);
1069 (void) printf("MODE=%o\n", dp->di_mode);
1070 if (preen)
1071 (void) printf("%s: ", devname);
1072 (void) printf("SIZE=%lld ", (longlong_t)dp->di_size);
1074 /* ctime() ignores LOCALE, so this is safe */
1075 t = (time_t)dp->di_mtime;
1076 p = ctime(&t);
1077 (void) printf("MTIME=%12.12s %4.4s ", p + 4, p + 20);
1080 void
1081 blkerror(fsck_ino_t ino, char *type, daddr32_t blk, daddr32_t lbn)
1083 pfatal("FRAGMENT %d %s I=%u LFN %d", blk, type, ino, lbn);
1084 (void) printf("\n");
1086 switch (statemap[ino] & ~INDELAYD) {
1088 case FSTATE:
1089 case FZLINK:
1090 statemap[ino] = FCLEAR;
1091 return;
1093 case DFOUND:
1094 case DSTATE:
1095 case DZLINK:
1096 statemap[ino] = DCLEAR;
1097 add_orphan_dir(ino);
1098 return;
1100 case SSTATE:
1101 statemap[ino] = SCLEAR;
1102 return;
1104 case FCLEAR:
1105 case DCLEAR:
1106 case SCLEAR:
1107 return;
1109 default:
1110 errexit("BAD STATE 0x%x TO BLKERR\n", statemap[ino]);
1111 /* NOTREACHED */
1116 * allocate an unused inode
1118 fsck_ino_t
1119 allocino(fsck_ino_t request, int type)
1121 fsck_ino_t ino;
1122 struct dinode *dp;
1123 struct cg *cgp = &cgrp;
1124 int cg;
1125 time_t t;
1126 caddr_t err;
1128 if (debug && (request != 0) && (request != UFSROOTINO))
1129 errexit("assertion failed: allocino() asked for "
1130 "inode %d instead of 0 or %d",
1131 (int)request, (int)UFSROOTINO);
1134 * We know that we're only going to get requests for UFSROOTINO
1135 * or 0. If UFSROOTINO is wanted, then it better be available
1136 * because our caller is trying to recreate the root directory.
1137 * If we're asked for 0, then which one we return doesn't matter.
1138 * We know that inodes 0 and 1 are never valid to return, so we
1139 * the start at the lowest-legal inode number.
1141 * If we got a request for UFSROOTINO, then request != 0, and
1142 * this pair of conditionals is the only place that treats
1143 * UFSROOTINO specially.
1145 if (request == 0)
1146 request = UFSROOTINO;
1147 else if (statemap[request] != USTATE)
1148 return (0);
1151 * Doesn't do wrapping, since we know we started at
1152 * the smallest inode.
1154 for (ino = request; ino < maxino; ino++)
1155 if (statemap[ino] == USTATE)
1156 break;
1157 if (ino == maxino)
1158 return (0);
1161 * In pass5, we'll calculate the bitmaps and counts all again from
1162 * scratch and do a comparison, but for that to work the cg has
1163 * to know what in-memory changes we've made to it. If we have
1164 * trouble reading the cg, cg_sanity() should kick it out so
1165 * we can skip explicit i/o error checking here.
1167 cg = itog(&sblock, ino);
1168 (void) getblk(&cgblk, cgtod(&sblock, cg), (size_t)sblock.fs_cgsize);
1169 err = cg_sanity(cgp, cg);
1170 if (err != NULL) {
1171 pfatal("CG %d: %s\n", cg, err);
1172 free((void *)err);
1173 if (reply("REPAIR") == 0)
1174 errexit("Program terminated.");
1175 fix_cg(cgp, cg);
1177 setbit(cg_inosused(cgp), ino % sblock.fs_ipg);
1178 cgp->cg_cs.cs_nifree--;
1179 cgdirty();
1181 if (lastino < ino)
1182 lastino = ino;
1185 * Don't currently support IFATTRDIR or any of the other
1186 * types, as they aren't needed.
1188 switch (type & IFMT) {
1189 case IFDIR:
1190 statemap[ino] = DSTATE;
1191 cgp->cg_cs.cs_ndir++;
1192 break;
1193 case IFREG:
1194 case IFLNK:
1195 statemap[ino] = FSTATE;
1196 break;
1197 default:
1199 * Pretend nothing ever happened. This clears the
1200 * dirty flag, among other things.
1202 initbarea(&cgblk);
1203 if (debug)
1204 (void) printf("allocino: unknown type 0%o\n",
1205 type & IFMT);
1206 return (0);
1210 * We're allocating what should be a completely-unused inode,
1211 * so make sure we don't inherit anything from any previous
1212 * incarnations.
1214 dp = ginode(ino);
1215 (void) memset(dp, 0, sizeof (struct dinode));
1216 dp->di_db[0] = allocblk(1);
1217 if (dp->di_db[0] == 0) {
1218 statemap[ino] = USTATE;
1219 return (0);
1221 dp->di_mode = (mode_t)type;
1222 (void) time(&t);
1223 dp->di_atime = (time32_t)t;
1224 dp->di_ctime = dp->di_atime;
1225 dp->di_mtime = dp->di_ctime;
1226 dp->di_size = (uoff_t)sblock.fs_fsize;
1227 dp->di_blocks = btodb(sblock.fs_fsize);
1228 n_files++;
1229 inodirty();
1230 return (ino);
1234 * Release some or all of the blocks of an inode.
1235 * Only truncates down. Assumes new_length is appropriately aligned
1236 * to a block boundary (or a directory block boundary, if it's a
1237 * directory).
1239 * If this is a directory, discard all of its contents first, so
1240 * we don't create a bunch of orphans that would need another fsck
1241 * run to clean up.
1243 * Even if truncating to zero length, the inode remains allocated.
1245 void
1246 truncino(fsck_ino_t ino, offset_t new_length, int update)
1248 struct inodesc idesc;
1249 struct inoinfo *iip;
1250 struct dinode *dp;
1251 fsck_ino_t parent;
1252 mode_t mode;
1253 caddr_t message;
1254 int isdir, islink;
1255 int ilevel, dblk;
1257 dp = ginode(ino);
1258 mode = (dp->di_mode & IFMT);
1259 isdir = (mode == IFDIR) || (mode == IFATTRDIR);
1260 islink = (mode == IFLNK);
1262 if (isdir) {
1264 * Go with the parent we found by chasing references,
1265 * if we've gotten that far. Otherwise, use what the
1266 * directory itself claims. If there's no ``..'' entry
1267 * in it, give up trying to get the link counts right.
1269 if (update == TI_NOPARENT) {
1270 parent = -1;
1271 } else {
1272 iip = getinoinfo(ino);
1273 if (iip != NULL) {
1274 parent = iip->i_parent;
1275 } else {
1276 parent = lookup_dotdot_ino(ino);
1277 if (parent != 0) {
1279 * Make sure that the claimed
1280 * parent actually has a
1281 * reference to us.
1283 dp = ginode(parent);
1284 idesc.id_name = lfname;
1285 idesc.id_type = DATA;
1286 idesc.id_func = findino;
1287 idesc.id_number = ino;
1288 idesc.id_fix = DONTKNOW;
1289 if ((ckinode(dp, &idesc,
1290 CKI_TRAVERSE) & FOUND) == 0)
1291 parent = 0;
1296 mark_delayed_inodes(ino, numfrags(&sblock, new_length));
1297 if (parent > 0) {
1298 dp = ginode(parent);
1299 LINK_RANGE(message, dp->di_nlink, -1);
1300 if (message != NULL) {
1301 LINK_CLEAR(message, parent, dp->di_mode,
1302 &idesc);
1303 if (statemap[parent] == USTATE)
1304 goto no_parent_update;
1306 TRACK_LNCNTP(parent, lncntp[parent]--);
1307 } else if ((mode == IFDIR) && (parent == 0)) {
1309 * Currently don't have a good way to
1310 * handle this, so throw up our hands.
1311 * However, we know that we can still
1312 * do some good if we continue, so
1313 * don't actually exit yet.
1315 * We don't do it for attrdirs,
1316 * because there aren't link counts
1317 * between them and their parents.
1319 pwarn("Could not determine former parent of "
1320 "inode %d, link counts are possibly\n"
1321 "incorrect. Please rerun fsck(1M) to "
1322 "correct this.\n",
1323 ino);
1324 iscorrupt = 1;
1327 * ...else if it's a directory with parent == -1, then
1328 * we've not gotten far enough to know connectivity,
1329 * and it'll get handled automatically later.
1333 no_parent_update:
1334 init_inodesc(&idesc);
1335 idesc.id_type = ADDR;
1336 idesc.id_func = pass4check;
1337 idesc.id_number = ino;
1338 idesc.id_fix = DONTKNOW;
1339 idesc.id_truncto = howmany(new_length, sblock.fs_bsize);
1340 dp = ginode(ino);
1341 if (!islink && ckinode(dp, &idesc, CKI_TRUNCATE) & ALTERED)
1342 inodirty();
1345 * This has to be done after ckinode(), so that all of
1346 * the fragments get visited. Note that we assume we're
1347 * always truncating to a block boundary, rather than a
1348 * fragment boundary.
1350 dp = ginode(ino);
1351 dp->di_size = new_length;
1354 * Clear now-obsolete pointers.
1356 for (dblk = idesc.id_truncto + 1; dblk < NDADDR; dblk++) {
1357 dp->di_db[dblk] = 0;
1360 ilevel = get_indir_offsets(-1, idesc.id_truncto, NULL, NULL);
1361 for (ilevel++; ilevel < NIADDR; ilevel++) {
1362 dp->di_ib[ilevel] = 0;
1365 inodirty();
1369 * Release an inode's resources, then release the inode itself.
1371 void
1372 freeino(fsck_ino_t ino, int update_parent)
1374 int cg;
1375 struct dinode *dp;
1376 struct cg *cgp;
1378 n_files--;
1379 dp = ginode(ino);
1381 * We need to make sure that the file is really a large file.
1382 * Everything bigger than UFS_MAXOFFSET_T is treated as a file with
1383 * negative size, which shall be cleared. (see verify_inode() in
1384 * pass1.c)
1386 if (dp->di_size > (uoff_t)MAXOFF_T &&
1387 dp->di_size <= (uoff_t)UFS_MAXOFFSET_T &&
1388 ftypeok(dp) &&
1389 (dp->di_mode & IFMT) != IFBLK &&
1390 (dp->di_mode & IFMT) != IFCHR) {
1391 largefile_count--;
1393 truncino(ino, 0, update_parent);
1395 dp = ginode(ino);
1396 if ((dp->di_mode & IFMT) == IFATTRDIR) {
1397 clearshadow(ino, &attrclientinfo);
1398 dp = ginode(ino);
1401 clearinode(dp);
1402 inodirty();
1403 statemap[ino] = USTATE;
1406 * Keep the disk in sync with us so that pass5 doesn't get
1407 * upset about spurious inconsistencies.
1409 cg = itog(&sblock, ino);
1410 (void) getblk(&cgblk, (diskaddr_t)cgtod(&sblock, cg),
1411 (size_t)sblock.fs_cgsize);
1412 cgp = cgblk.b_un.b_cg;
1413 clrbit(cg_inosused(cgp), ino % sblock.fs_ipg);
1414 cgp->cg_cs.cs_nifree += 1;
1415 cgdirty();
1416 sblock.fs_cstotal.cs_nifree += 1;
1417 sbdirty();
1420 void
1421 init_inoinfo(struct inoinfo *inp, struct dinode *dp, fsck_ino_t inum)
1423 inp->i_parent = ((inum == UFSROOTINO) ? UFSROOTINO : (fsck_ino_t)0);
1424 inp->i_dotdot = (fsck_ino_t)0;
1425 inp->i_isize = (offset_t)dp->di_size;
1426 inp->i_blkssize = (NDADDR + NIADDR) * sizeof (daddr32_t);
1427 inp->i_extattr = dp->di_oeftflag;
1428 (void) memmove((void *)&inp->i_blks[0], (void *)&dp->di_db[0],
1429 inp->i_blkssize);
1433 * Return the inode number in the ".." entry of the provided
1434 * directory inode.
1436 static int
1437 lookup_dotdot_ino(fsck_ino_t ino)
1439 struct inodesc idesc;
1441 init_inodesc(&idesc);
1442 idesc.id_type = DATA;
1443 idesc.id_func = findino;
1444 idesc.id_name = "..";
1445 idesc.id_number = ino;
1446 idesc.id_fix = NOFIX;
1448 if ((ckinode(ginode(ino), &idesc, CKI_TRAVERSE) & FOUND) != 0) {
1449 return (idesc.id_parent);
1452 return (0);
1456 * Convenience wrapper around ckinode(findino()).
1459 lookup_named_ino(fsck_ino_t dir, caddr_t name)
1461 struct inodesc idesc;
1463 init_inodesc(&idesc);
1464 idesc.id_type = DATA;
1465 idesc.id_func = findino;
1466 idesc.id_name = name;
1467 idesc.id_number = dir;
1468 idesc.id_fix = NOFIX;
1470 if ((ckinode(ginode(dir), &idesc, CKI_TRAVERSE) & FOUND) != 0) {
1471 return (idesc.id_parent);
1474 return (0);
1478 * Marks inodes that are being orphaned and might need to be reconnected
1479 * by pass4(). The inode we're traversing is the directory whose
1480 * contents will be reconnected later. id_parent is the lfn at which
1481 * to start looking at said contents.
1483 static int
1484 mark_a_delayed_inode(struct inodesc *idesc)
1486 struct direct *dirp = idesc->id_dirp;
1488 if (idesc->id_lbn < idesc->id_parent) {
1489 return (KEEPON);
1492 if (dirp->d_ino != 0 &&
1493 strcmp(dirp->d_name, ".") != 0 &&
1494 strcmp(dirp->d_name, "..") != 0) {
1495 statemap[dirp->d_ino] &= ~INFOUND;
1496 statemap[dirp->d_ino] |= INDELAYD;
1499 return (KEEPON);
1502 static void
1503 mark_delayed_inodes(fsck_ino_t ino, daddr32_t first_lfn)
1505 struct dinode *dp;
1506 struct inodesc idelayed;
1508 init_inodesc(&idelayed);
1509 idelayed.id_number = ino;
1510 idelayed.id_type = DATA;
1511 idelayed.id_fix = NOFIX;
1512 idelayed.id_func = mark_a_delayed_inode;
1513 idelayed.id_parent = first_lfn;
1514 idelayed.id_entryno = 2;
1516 dp = ginode(ino);
1517 (void) ckinode(dp, &idelayed, CKI_TRAVERSE);
1521 * Clear the i_oeftflag/extended attribute pointer from INO.
1523 void
1524 clearattrref(fsck_ino_t ino)
1526 struct dinode *dp;
1528 dp = ginode(ino);
1529 if (debug) {
1530 if (dp->di_oeftflag == 0)
1531 (void) printf("clearattref: no attr to clear on %d\n",
1532 ino);
1535 dp->di_oeftflag = 0;
1536 inodirty();