1 /* $NetBSD: pass6.c,v 1.21 2008/04/28 20:23:08 martin Exp $ */
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Konrad E. Schroder <perseant@hhhh.org>.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/types.h>
33 #include <sys/param.h>
36 #include <sys/mount.h>
38 #include <ufs/ufs/ufsmount.h>
39 #include <ufs/ufs/inode.h>
40 #include <ufs/ufs/dir.h>
42 #include <ufs/lfs/lfs.h>
62 extern u_int32_t
cksum(void *, size_t);
63 extern u_int32_t
lfs_sb_cksum(struct dlfs
*);
65 extern ufs_daddr_t badblk
;
66 extern SEGUSE
*seg_table
;
68 static int nnewblocks
;
71 * Our own copy of lfs_update_single so we can account in seg_table
72 * as well as the Ifile; and so we can add the blocks to their new
75 * Change the given block's address to ndaddr, finding its previous
76 * location using ufs_bmaparray().
78 * Account for this change in the segment table.
81 rfw_update_single(struct uvnode
*vp
, daddr_t lbn
, ufs_daddr_t ndaddr
, int size
)
85 struct indir a
[NIADDR
+ 2], *ap
;
89 int i
, bb
, osize
= 0, obb
= 0;
93 ip
->i_flag
|= IN_MODIFIED
;
95 error
= ufs_bmaparray(fs
, vp
, lbn
, &daddr
, a
, &num
);
97 errx(1, "lfs_updatemeta: ufs_bmaparray returned %d"
98 " looking up lbn %" PRId64
"\n", error
, lbn
);
100 daddr
= dbtofsb(fs
, daddr
);
102 bb
= fragstofsb(fs
, numfrags(fs
, size
));
105 ooff
= ip
->i_ffs1_db
[lbn
];
107 ip
->i_ffs1_blocks
+= bb
;
109 /* possible fragment truncation or extension */
110 obb
= btofsb(fs
, ip
->i_lfs_fragsize
[lbn
]);
111 ip
->i_ffs1_blocks
+= (bb
- obb
);
113 ip
->i_ffs1_db
[lbn
] = ndaddr
;
116 ooff
= ip
->i_ffs1_ib
[a
[0].in_off
];
118 ip
->i_ffs1_blocks
+= bb
;
119 ip
->i_ffs1_ib
[a
[0].in_off
] = ndaddr
;
123 if (bread(vp
, ap
->in_lbn
, fs
->lfs_bsize
, NULL
, 0, &bp
))
124 errx(1, "lfs_updatemeta: bread bno %" PRId64
,
127 ooff
= ((ufs_daddr_t
*) bp
->b_data
)[ap
->in_off
];
129 ip
->i_ffs1_blocks
+= bb
;
130 ((ufs_daddr_t
*) bp
->b_data
)[ap
->in_off
] = ndaddr
;
131 (void) VOP_BWRITE(bp
);
135 * Update segment usage information, based on old size
139 oldsn
= dtosn(fs
, daddr
);
140 if (lbn
>= 0 && lbn
< NDADDR
)
141 osize
= ip
->i_lfs_fragsize
[lbn
];
143 osize
= fs
->lfs_bsize
;
144 LFS_SEGENTRY(sup
, fs
, oldsn
, bp
);
145 seg_table
[oldsn
].su_nbytes
-= osize
;
146 sup
->su_nbytes
-= osize
;
147 if (!(bp
->b_flags
& B_GATHERED
))
148 fs
->lfs_flags
|= LFS_IFDIRTY
;
149 LFS_WRITESEGENTRY(sup
, fs
, oldsn
, bp
);
150 for (i
= 0; i
< btofsb(fs
, osize
); i
++)
154 /* If block is beyond EOF, update size */
155 if (lbn
>= 0 && ip
->i_ffs1_size
<= (lbn
<< fs
->lfs_bshift
)) {
156 ip
->i_ffs1_size
= (lbn
<< fs
->lfs_bshift
) + 1;
159 /* If block frag size is too large for old EOF, update size */
163 minsize
= (lbn
<< fs
->lfs_bshift
);
164 minsize
+= (size
- fs
->lfs_fsize
) + 1;
165 if (ip
->i_ffs1_size
< minsize
)
166 ip
->i_ffs1_size
= minsize
;
169 /* Count for the user */
172 /* Add block to its new segment */
173 sn
= dtosn(fs
, ndaddr
);
174 LFS_SEGENTRY(sup
, fs
, sn
, bp
);
175 seg_table
[sn
].su_nbytes
+= size
;
176 sup
->su_nbytes
+= size
;
177 if (!(bp
->b_flags
& B_GATHERED
))
178 fs
->lfs_flags
|= LFS_IFDIRTY
;
179 LFS_WRITESEGENTRY(sup
, fs
, sn
, bp
);
180 for (i
= 0; i
< btofsb(fs
, size
); i
++)
181 #ifndef VERBOSE_BLOCKMAP
184 setbmap(daddr
+ i
, ip
->i_number
);
187 /* Check bfree accounting as well */
189 fs
->lfs_bfree
-= btofsb(fs
, size
);
190 } else if (size
!= osize
) {
191 fs
->lfs_bfree
-= (bb
- obb
);
195 * Now that this block has a new address, and its old
196 * segment no longer owns it, we can forget about its
199 if (lbn
>= 0 && lbn
< NDADDR
)
200 ip
->i_lfs_fragsize
[lbn
] = size
;
204 * Remove the vnode from the cache, including any blocks it
205 * may hold. Account the blocks. Finally account the removal
206 * of the inode from its segment.
209 remove_ino(struct uvnode
*vp
, ino_t ino
)
214 struct ubuf
*bp
, *sbp
, *cbp
;
215 struct inodesc idesc
;
220 pwarn("remove ino %d\n", (int)ino
);
222 obfree
= fs
->lfs_bfree
;
223 LFS_IENTRY(ifp
, fs
, ino
, bp
);
224 daddr
= ifp
->if_daddr
;
228 LFS_GET_HEADFREE(fs
, cip
, cbp
, &(ifp
->if_nextfree
));
230 LFS_PUT_HEADFREE(fs
, cip
, cbp
, ino
);
234 vp
= lfs_raw_vget(fs
, ino
, fs
->lfs_ivnode
->v_fd
, daddr
);
236 LFS_SEGENTRY(sup
, fs
, dtosn(fs
, daddr
), sbp
);
237 sup
->su_nbytes
-= DINODE1_SIZE
;
239 seg_table
[dtosn(fs
, daddr
)].su_nbytes
-= DINODE1_SIZE
;
243 /* Do on-disk accounting */
245 idesc
.id_number
= ino
;
246 idesc
.id_func
= pass4check
; /* Delete dinode and blocks */
247 idesc
.id_type
= ADDR
;
249 clri(&idesc
, "unknown", 2); /* XXX magic number 2 */
250 /* vp has been destroyed */
255 * Use FIP records to update blocks, if the generation number matches.
258 pass6harvest(ufs_daddr_t daddr
, FINFO
*fip
)
264 vp
= vget(fs
, fip
->fi_ino
);
265 if (vp
&& vp
!= fs
->lfs_ivnode
&&
266 VTOI(vp
)->i_ffs1_gen
== fip
->fi_version
) {
267 for (i
= 0; i
< fip
->fi_nblocks
; i
++) {
268 size
= (i
== fip
->fi_nblocks
- 1 ?
269 fip
->fi_lastlength
: fs
->lfs_bsize
);
271 pwarn("ino %lld lbn %lld -> 0x%lx\n",
272 (long long)fip
->fi_ino
,
273 (long long)fip
->fi_blocks
[i
],
275 rfw_update_single(vp
, fip
->fi_blocks
[i
], daddr
, size
);
276 daddr
+= btofsb(fs
, size
);
282 * Check validity of blocks on roll-forward inodes.
285 pass6check(struct inodesc
* idesc
)
287 int i
, sn
, anyout
, anynew
;
289 /* Brand new blocks are always OK */
290 if (idesc
->id_blkno
== UNWRITTEN
)
293 /* Check that the blocks do not lie within clean segments. */
295 for (i
= 0; i
< fragstofsb(fs
, idesc
->id_numfrags
); i
++) {
296 sn
= dtosn(fs
, idesc
->id_blkno
+ i
);
297 if (sn
< 0 || sn
>= fs
->lfs_nseg
||
298 (seg_table
[sn
].su_flags
& SEGUSE_DIRTY
) == 0) {
302 if (seg_table
[sn
].su_flags
& SEGUSE_ACTIVE
) {
303 if (sn
!= dtosn(fs
, fs
->lfs_offset
) ||
304 idesc
->id_blkno
> fs
->lfs_offset
) {
309 /* Clear so pass1check won't be surprised */
310 clrbmap(idesc
->id_blkno
+ i
);
311 seg_table
[sn
].su_nbytes
-= fsbtob(fs
, 1);
315 blkerror(idesc
->id_number
, "BAD", idesc
->id_blkno
);
316 if (badblk
++ >= MAXBAD
) {
317 pwarn("EXCESSIVE BAD BLKS I=%llu",
318 (unsigned long long)idesc
->id_number
);
320 pwarn(" (SKIPPING)\n");
321 else if (reply("CONTINUE") == 0)
322 err(EEXIT
, "%s", "");
327 return pass1check(idesc
);
331 account_indir(struct uvnode
*vp
, struct ufs1_dinode
*dp
, daddr_t ilbn
, daddr_t daddr
, int lvl
)
334 int32_t *dap
, *odap
, *buf
, *obuf
;
341 bread(fs
->lfs_devvp
, fsbtodb(fs
, daddr
), fs
->lfs_bsize
, NULL
, 0, &bp
);
342 buf
= emalloc(fs
->lfs_bsize
);
343 memcpy(buf
, bp
->b_data
, fs
->lfs_bsize
);
346 obuf
= emalloc(fs
->lfs_bsize
);
348 bread(vp
, ilbn
, fs
->lfs_bsize
, NULL
, 0, &bp
);
349 memcpy(obuf
, bp
->b_data
, fs
->lfs_bsize
);
352 memset(obuf
, 0, fs
->lfs_bsize
);
354 for (dap
= buf
, odap
= obuf
;
355 dap
< (int32_t *)((char *)buf
+ fs
->lfs_bsize
);
357 if (*dap
> 0 && *dap
!= *odap
) {
358 rfw_update_single(vp
, lbn
, *dap
, dblksize(fs
, dp
, lbn
));
360 account_indir(vp
, dp
, lbn
, *dap
, lvl
- 1);
367 lbn
-= NINDIR(fs
) * NINDIR(fs
);
375 * Account block changes between new found inode and existing inode.
378 account_block_changes(struct ufs1_dinode
*dp
)
381 daddr_t lbn
, off
, odaddr
;
385 vp
= vget(fs
, dp
->di_inumber
);
386 ip
= (vp
? VTOI(vp
) : NULL
);
388 /* Check direct block holdings between existing and new */
389 for (i
= 0; i
< NDADDR
; i
++) {
390 odaddr
= (ip
? ip
->i_ffs1_db
[i
] : 0x0);
391 if (dp
->di_db
[i
] > 0 && dp
->di_db
[i
] != odaddr
)
392 rfw_update_single(vp
, i
, dp
->di_db
[i
],
393 dblksize(fs
, dp
, i
));
396 /* Check indirect block holdings between existing and new */
398 for (i
= 0; i
< NIADDR
; i
++) {
399 odaddr
= (ip
? ip
->i_ffs1_ib
[i
] : 0x0);
400 if (dp
->di_ib
[i
] > 0 && dp
->di_ib
[i
] != odaddr
) {
401 lbn
= -(NDADDR
+ off
+ i
);
402 rfw_update_single(vp
, i
, dp
->di_ib
[i
], fs
->lfs_bsize
);
403 account_indir(vp
, dp
, lbn
, dp
->di_ib
[i
], i
);
413 * Give a previously allocated inode a new address; do segment
414 * accounting if necessary.
416 * Caller has ensured that this inode is not on the free list, so no
417 * free list accounting is done.
420 readdress_inode(struct ufs1_dinode
*dp
, ufs_daddr_t daddr
)
427 ino_t thisino
= dp
->di_inumber
;
430 /* Recursively check all block holdings, account changes */
431 account_block_changes(dp
);
433 /* Move ifile pointer to this location */
434 LFS_IENTRY(ifp
, fs
, thisino
, bp
);
435 odaddr
= ifp
->if_daddr
;
437 ifp
->if_daddr
= daddr
;
441 pwarn("readdress ino %d from 0x%x to 0x%x mode %o nlink %d\n",
445 (int)dp
->di_mode
, (int)dp
->di_nlink
);
447 /* Copy over preexisting in-core inode, if any */
448 vp
= vget(fs
, thisino
);
449 memcpy(VTOI(vp
)->i_din
.ffs1_din
, dp
, sizeof(*dp
));
451 /* Finally account the inode itself */
452 sn
= dtosn(fs
, odaddr
);
453 LFS_SEGENTRY(sup
, fs
, sn
, bp
);
454 sup
->su_nbytes
-= DINODE1_SIZE
;
456 seg_table
[sn
].su_nbytes
-= DINODE1_SIZE
;
458 sn
= dtosn(fs
, daddr
);
459 LFS_SEGENTRY(sup
, fs
, sn
, bp
);
460 sup
->su_nbytes
+= DINODE1_SIZE
;
462 seg_table
[sn
].su_nbytes
+= DINODE1_SIZE
;
466 * Allocate the given inode from the free list.
469 alloc_inode(ino_t thisino
, ufs_daddr_t daddr
)
471 ino_t ino
, nextfree
, oldhead
;
474 struct ubuf
*bp
, *cbp
;
478 pwarn("allocating ino %d at 0x%x\n", (int)thisino
,
480 while (thisino
>= maxino
) {
484 LFS_IENTRY(ifp
, fs
, thisino
, bp
);
485 if (ifp
->if_daddr
!= 0) {
486 pwarn("allocated inode %lld already allocated\n",
489 nextfree
= ifp
->if_nextfree
;
490 ifp
->if_nextfree
= 0;
491 ifp
->if_daddr
= daddr
;
494 LFS_GET_HEADFREE(fs
, cip
, cbp
, &oldhead
);
495 if (oldhead
== thisino
) {
496 LFS_PUT_HEADFREE(fs
, cip
, cbp
, nextfree
);
502 /* Search the free list for this inode */
505 LFS_IENTRY(ifp
, fs
, ino
, bp
);
506 assert(ifp
->if_nextfree
!= ino
);
507 if (ifp
->if_nextfree
== thisino
) {
508 ifp
->if_nextfree
= nextfree
;
511 LFS_PUT_TAILFREE(fs
, cip
, cbp
, ino
);
514 ino
= ifp
->if_nextfree
;
519 /* Account for new location */
520 LFS_SEGENTRY(sup
, fs
, dtosn(fs
, daddr
), bp
);
521 sup
->su_nbytes
+= DINODE1_SIZE
;
523 seg_table
[dtosn(fs
, daddr
)].su_nbytes
+= DINODE1_SIZE
;
527 * Roll forward from the last verified checkpoint.
531 * Run through the summaries finding the last valid partial segment.
532 * Note segment numbers as we go. For each inode that we find, compare
533 * its generation number; if newer than old inode's (or if old inode is
534 * USTATE), change to that inode. Recursively look at inode blocks that
535 * do not have their old disk addresses. These addresses must lie in
536 * segments we have seen already in our roll forward.
538 * A second pass through the past-checkpoint area verifies the validity
539 * of these new blocks, as well as updating other blocks that do not
540 * have corresponding new inodes (but their generation number must match
541 * the old generation number).
546 ufs_daddr_t daddr
, ibdaddr
, odaddr
, lastgood
, nextseg
, *idaddrp
;
547 struct uvnode
*vp
, *devvp
;
551 struct ubuf
*bp
, *ibp
, *sbp
, *cbp
;
552 struct ufs1_dinode
*dp
;
553 struct inodesc idesc
;
554 int i
, j
, bc
, hassuper
;
555 int nnewfiles
, ndelfiles
, nmvfiles
;
560 devvp
= fs
->lfs_devvp
;
562 /* If we can't roll forward because of created files, don't try */
563 if (no_roll_forward
) {
565 pwarn("not rolling forward due to possible allocation conflict\n");
569 /* Find last valid partial segment */
570 lastgood
= try_verify(fs
, devvp
, 0, debug
);
571 if (lastgood
== fs
->lfs_offset
) {
573 pwarn("not rolling forward, nothing to recover\n");
578 pwarn("could roll forward from 0x%" PRIx32
" to 0x%" PRIx32
"\n",
579 fs
->lfs_offset
, lastgood
);
581 if (!preen
&& reply("ROLL FORWARD") == 0)
584 * Pass 1: find inode blocks. We ignore the Ifile inode but accept
585 * changes to any other inode.
588 ibbuf
= emalloc(fs
->lfs_ibsize
);
589 nnewfiles
= ndelfiles
= nmvfiles
= nnewblocks
= 0;
590 daddr
= fs
->lfs_offset
;
591 nextseg
= fs
->lfs_nextseg
;
594 while (daddr
!= lastgood
) {
595 seg_table
[dtosn(fs
, daddr
)].su_flags
|= SEGUSE_DIRTY
| SEGUSE_ACTIVE
;
596 LFS_SEGENTRY(sup
, fs
, dtosn(fs
, daddr
), sbp
);
597 sup
->su_flags
|= SEGUSE_DIRTY
;
600 /* Could be a superblock */
601 if (sntod(fs
, dtosn(fs
, daddr
)) == daddr
) {
602 if (daddr
== fs
->lfs_start
) {
604 daddr
+= btofsb(fs
, LFS_LABELPAD
);
606 for (i
= 0; i
< LFS_MAXNUMSB
; i
++) {
607 if (daddr
== fs
->lfs_sboffs
[i
]) {
609 daddr
+= btofsb(fs
, LFS_SBPAD
);
611 if (daddr
< fs
->lfs_sboffs
[i
])
616 /* Read in summary block */
617 bread(devvp
, fsbtodb(fs
, daddr
), fs
->lfs_sumsize
, NULL
, 0, &bp
);
618 sp
= (SEGSUM
*)bp
->b_data
;
620 pwarn("sum at 0x%x: ninos=%d nfinfo=%d\n",
621 (unsigned)daddr
, (int)sp
->ss_ninos
,
624 /* We have verified that this is a good summary. */
625 LFS_SEGENTRY(sup
, fs
, dtosn(fs
, daddr
), sbp
);
628 fs
->lfs_bfree
-= btofsb(fs
, fs
->lfs_sumsize
);
629 fs
->lfs_dmeta
+= btofsb(fs
, fs
->lfs_sumsize
);
631 nextseg
= sp
->ss_next
;
632 if (sntod(fs
, dtosn(fs
, daddr
)) == daddr
+
633 hassuper
* btofsb(fs
, LFS_SBPAD
) &&
634 dtosn(fs
, daddr
) != dtosn(fs
, fs
->lfs_offset
)) {
639 /* Find inodes, look at generation number. */
641 LFS_SEGENTRY(sup
, fs
, dtosn(fs
, daddr
), sbp
);
642 sup
->su_ninos
+= howmany(sp
->ss_ninos
, INOPB(fs
));
644 fs
->lfs_dmeta
+= btofsb(fs
, howmany(sp
->ss_ninos
,
648 idaddrp
= ((ufs_daddr_t
*)((char *)bp
->b_data
+ fs
->lfs_sumsize
));
649 for (i
= 0; i
< howmany(sp
->ss_ninos
, INOPB(fs
)); i
++) {
652 inums
= ecalloc(INOPB(fs
) + 1, sizeof(*inums
));
653 ibdaddr
= *--idaddrp
;
654 fs
->lfs_bfree
-= btofsb(fs
, fs
->lfs_ibsize
);
656 bread(devvp
, fsbtodb(fs
, ibdaddr
), fs
->lfs_ibsize
,
658 memcpy(ibbuf
, ibp
->b_data
, fs
->lfs_ibsize
);
662 for (dp
= (struct ufs1_dinode
*)ibbuf
;
663 dp
< (struct ufs1_dinode
*)ibbuf
+ INOPB(fs
);
665 if (dp
->di_u
.inumber
== 0 ||
666 dp
->di_u
.inumber
== fs
->lfs_ifile
)
668 /* Basic sanity checks */
671 || dp
->di_u
.inumber
< 0
675 pwarn("BAD INODE AT 0x%" PRIx32
"\n",
682 vp
= vget(fs
, dp
->di_u
.inumber
);
686 * (1) Invalid inode (nlink == 0).
687 * If currently allocated, remove.
689 if (dp
->di_nlink
== 0) {
690 remove_ino(vp
, dp
->di_u
.inumber
);
695 * (2) New valid inode, previously free.
696 * Nothing to do except account
697 * the inode itself, done after the
701 if (!(sp
->ss_flags
& SS_DIROP
))
702 pfatal("NEW FILE IN NON-DIROP PARTIAL SEGMENT");
704 inums
[j
++] = dp
->di_u
.inumber
;
710 * (3) Valid new version of previously
711 * allocated inode. Delete old file
712 * and proceed as in (2).
714 if (vp
&& VTOI(vp
)->i_ffs1_gen
< dp
->di_gen
) {
715 remove_ino(vp
, dp
->di_u
.inumber
);
716 if (!(sp
->ss_flags
& SS_DIROP
))
717 pfatal("NEW FILE VERSION IN NON-DIROP PARTIAL SEGMENT");
719 inums
[j
++] = dp
->di_u
.inumber
;
726 * (4) Same version of previously
727 * allocated inode. Move inode to
728 * this location, account inode change
729 * only. We'll pick up any new
730 * blocks when we do the block pass.
732 if (vp
&& VTOI(vp
)->i_ffs1_gen
== dp
->di_gen
) {
734 readdress_inode(dp
, ibdaddr
);
736 /* Update with new info */
737 VTOD(vp
)->di_mode
= dp
->di_mode
;
738 VTOD(vp
)->di_nlink
= dp
->di_nlink
;
739 /* XXX size is important */
740 VTOD(vp
)->di_size
= dp
->di_size
;
741 VTOD(vp
)->di_atime
= dp
->di_atime
;
742 VTOD(vp
)->di_atimensec
= dp
->di_atimensec
;
743 VTOD(vp
)->di_mtime
= dp
->di_mtime
;
744 VTOD(vp
)->di_mtimensec
= dp
->di_mtimensec
;
745 VTOD(vp
)->di_ctime
= dp
->di_ctime
;
746 VTOD(vp
)->di_ctimensec
= dp
->di_ctimensec
;
747 VTOD(vp
)->di_flags
= dp
->di_flags
;
748 VTOD(vp
)->di_uid
= dp
->di_uid
;
749 VTOD(vp
)->di_gid
= dp
->di_gid
;
753 for (j
= 0; inums
[j
]; j
++) {
754 alloc_inode(inums
[j
], ibdaddr
);
755 vp
= lfs_raw_vget(fs
, inums
[j
],
756 devvp
->v_fd
, ibdaddr
);
757 /* We'll get the blocks later */
759 pwarn("alloc ino %d nlink %d\n",
760 (int)inums
[j
], VTOD(vp
)->di_nlink
);
761 memset(VTOD(vp
)->di_db
, 0, (NDADDR
+ NIADDR
) *
762 sizeof(ufs_daddr_t
));
763 VTOD(vp
)->di_blocks
= 0;
765 vp
->v_uflag
|= VU_DIROP
;
771 bc
= check_summary(fs
, sp
, daddr
, debug
, devvp
, NULL
);
773 pwarn("unexpected bad seg ptr at 0x%x with serial=%d\n",
774 (int)daddr
, (int)sp
->ss_serial
);
779 pwarn("good seg ptr at 0x%x with serial=%d\n",
780 (int)daddr
, (int)sp
->ss_serial
);
781 lastserial
= sp
->ss_serial
;
784 daddr
+= btofsb(fs
, fs
->lfs_sumsize
+ bc
);
785 if (dtosn(fs
, odaddr
) != dtosn(fs
, daddr
) ||
786 dtosn(fs
, daddr
) != dtosn(fs
, daddr
+
787 btofsb(fs
, fs
->lfs_sumsize
+ fs
->lfs_bsize
) - 1)) {
788 daddr
= ((SEGSUM
*)bp
->b_data
)->ss_next
;
796 /* Set serial here, just to be sure (XXX should be right already) */
797 fs
->lfs_serial
= lastserial
+ 1;
800 * Check our new vnodes. Any blocks must lie in segments that
801 * we've seen before (SEGUSE_DIRTY or SEGUSE_RFW); and the rest
802 * of the pass 1 checks as well.
804 memset(&idesc
, 0, sizeof(struct inodesc
));
805 idesc
.id_type
= ADDR
;
806 idesc
.id_func
= pass6check
;
808 LIST_FOREACH(vp
, &vnodelist
, v_mntvnodes
) {
809 if ((vp
->v_uflag
& VU_DIROP
) == 0)
810 --n_files
; /* Don't double count */
811 checkinode(VTOI(vp
)->i_number
, &idesc
);
815 * Second pass. Run through FINFO entries looking for blocks
816 * with the same generation number as files we've seen before.
817 * If they have it, pretend like we just wrote them. We don't
818 * do the pretend-write, though, if we've already seen them
819 * (the accounting would have been done for us already).
821 daddr
= fs
->lfs_offset
;
822 while (daddr
!= lastgood
) {
823 if (!(seg_table
[dtosn(fs
, daddr
)].su_flags
& SEGUSE_DIRTY
)) {
824 seg_table
[dtosn(fs
, daddr
)].su_flags
|= SEGUSE_DIRTY
;
825 LFS_SEGENTRY(sup
, fs
, dtosn(fs
, daddr
), sbp
);
826 sup
->su_flags
|= SEGUSE_DIRTY
;
830 /* Could be a superblock */
831 if (sntod(fs
, dtosn(fs
, daddr
)) == daddr
) {
832 if (daddr
== fs
->lfs_start
)
833 daddr
+= btofsb(fs
, LFS_LABELPAD
);
834 for (i
= 0; i
< LFS_MAXNUMSB
; i
++) {
835 if (daddr
== fs
->lfs_sboffs
[i
]) {
836 daddr
+= btofsb(fs
, LFS_SBPAD
);
838 if (daddr
< fs
->lfs_sboffs
[i
])
843 /* Read in summary block */
844 bread(devvp
, fsbtodb(fs
, daddr
), fs
->lfs_sumsize
, NULL
, 0, &bp
);
845 sp
= (SEGSUM
*)bp
->b_data
;
846 bc
= check_summary(fs
, sp
, daddr
, debug
, devvp
, pass6harvest
);
848 pwarn("unexpected bad seg ptr [2] at 0x%x with serial=%d\n",
849 (int)daddr
, (int)sp
->ss_serial
);
854 daddr
+= btofsb(fs
, fs
->lfs_sumsize
+ bc
);
855 fs
->lfs_avail
-= btofsb(fs
, fs
->lfs_sumsize
+ bc
);
856 if (dtosn(fs
, odaddr
) != dtosn(fs
, daddr
) ||
857 dtosn(fs
, daddr
) != dtosn(fs
, daddr
+
858 btofsb(fs
, fs
->lfs_sumsize
+ fs
->lfs_bsize
) - 1)) {
859 fs
->lfs_avail
-= sntod(fs
, dtosn(fs
, daddr
) + 1) - daddr
;
860 daddr
= ((SEGSUM
*)bp
->b_data
)->ss_next
;
862 LFS_CLEANERINFO(cip
, fs
, cbp
);
863 LFS_SYNC_CLEANERINFO(cip
, fs
, cbp
, 0);
864 bp
->b_flags
|= B_AGE
;
868 /* Final address could also be a superblock */
869 if (sntod(fs
, dtosn(fs
, lastgood
)) == lastgood
) {
870 if (lastgood
== fs
->lfs_start
)
871 lastgood
+= btofsb(fs
, LFS_LABELPAD
);
872 for (i
= 0; i
< LFS_MAXNUMSB
; i
++) {
873 if (lastgood
== fs
->lfs_sboffs
[i
])
874 lastgood
+= btofsb(fs
, LFS_SBPAD
);
875 if (lastgood
< fs
->lfs_sboffs
[i
])
880 /* Update offset to point at correct location */
881 fs
->lfs_offset
= lastgood
;
882 fs
->lfs_curseg
= sntod(fs
, dtosn(fs
, lastgood
));
883 for (sn
= curseg
= dtosn(fs
, fs
->lfs_curseg
);;) {
884 sn
= (sn
+ 1) % fs
->lfs_nseg
;
886 errx(1, "no clean segments");
887 LFS_SEGENTRY(sup
, fs
, sn
, bp
);
888 if ((sup
->su_flags
& SEGUSE_DIRTY
) == 0) {
889 sup
->su_flags
|= SEGUSE_DIRTY
| SEGUSE_ACTIVE
;
895 fs
->lfs_nextseg
= sntod(fs
, sn
);
899 pwarn("roll forward deleted %d file%s\n", ndelfiles
,
900 (ndelfiles
> 1 ? "s" : ""));
902 pwarn("roll forward added %d file%s\n", nnewfiles
,
903 (nnewfiles
> 1 ? "s" : ""));
905 pwarn("roll forward relocated %d inode%s\n", nmvfiles
,
906 (nmvfiles
> 1 ? "s" : ""));
908 pwarn("roll forward verified %d data block%s\n", nnewblocks
,
909 (nnewblocks
> 1 ? "s" : ""));
910 if (ndelfiles
== 0 && nnewfiles
== 0 && nmvfiles
== 0 &&
912 pwarn("roll forward produced nothing new\n");
916 /* Run pass 5 again (it's quick anyway). */
917 pwarn("** Phase 6b - Recheck Segment Block Accounting\n");
921 /* Likewise for pass 0 */
923 pwarn("** Phase 6c - Recheck Inode Free List\n");