NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: bin/56942 (fsck_ffs can't replay wapbl journals to memory)
Synopsis: fsck_ffs can't replay wapbl journals to memory
State-Changed-From-To: open->feedback
State-Changed-By: riastradh%NetBSD.org@localhost
State-Changed-When: Thu, 20 Aug 2026 14:05:04 +0000
State-Changed-Why:
> I discovered recently that although fsck_ffs -n claims it's replaying
> the journal, it actually doesn't, because fsck doesn't have the
> infrastructure necessary to support replaying the journal without
> writing to disk.
How did you conclude this?
When fsck_ffs starts, it checks for a journal and prepares it with
wapbl_replay_start:
186 /* ffs_superblock_layout() == 2 */
187 if (sblock->fs_magic != FS_UFS1_MAGIC ||
188 (sblock->fs_old_flags & FS_FLAGS_UPDATED) != 0) {
189 /* can have WAPBL */
190 if (check_wapbl() != 0) {
191 doskipclean = 0;
192 }
https://nxr.netbsd.org/xref/src/sbin/fsck_ffs/setup.c?r=1.112#186
162 int
163 check_wapbl(void)
164 {
...
218 if (sblock->fs_flags & FS_DOWAPBL) {
219 error = wapbl_replay_start(
220 &wapbl_replay, 0, addr, count, blksize);
wapbl_replay_start loads the journal into memory and sets up the hash
table of pending block writes:
2959 int
2960 wapbl_replay_start(struct wapbl_replay **wrp, struct vnode *vp,
2961 daddr_t off, size_t count, size_t blksize)
2962 {
...
3048 wapbl_blkhash_init(wr, (used >> wch->wc_fs_dev_bshift));
3049
3050 error = wapbl_replay_process(wr, wch->wc_head, wch->wc_tail);
...
3131 static void
3132 wapbl_replay_process_blocks(struct wapbl_replay *wr, off_t *offp)
3133 {
3134 struct wapbl_wc_blocklist *wc =
3135 (struct wapbl_wc_blocklist *)wr->wr_scratch;
3136 int fsblklen = 1 << wr->wr_fs_dev_bshift;
3137 int i, j, n;
3138
3139 for (i = 0; i < wc->wc_blkcount; i++) {
3140 /*
3141 * Enter each physical block into the hashtable independently.
3142 */
3143 n = wc->wc_blocks[i].wc_dlen >> wr->wr_fs_dev_bshift;
3144 for (j = 0; j < n; j++) {
3145 wapbl_blkhash_ins(wr,
3146 wapbl_block_daddr(wc, i, j, fsblklen),
3147 *offp);
3148 wapbl_circ_advance(wr, fsblklen, offp);
3149 }
3150 }
3151 }
...
3212 static int
3213 wapbl_replay_process(struct wapbl_replay *wr, off_t head, off_t tail)
3214 {
...
3231 case WAPBL_WC_BLOCKS:
3232 wapbl_replay_process_blocks(wr, &off);
https://nxr.netbsd.org/xref/src/sys/kern/vfs_wapbl.c?r=1.117#2959
This is used by wapbl_replay_read:
3435
3436 int
3437 wapbl_replay_read(struct wapbl_replay *wr, void *data, daddr_t blk, long len)
3438 {
...
3446 struct wapbl_blk *wb = wapbl_blkhash_get(wr, blk);
3447 if (wb) {
3448 off_t off = wb->wb_off;
3449 int error;
3450 error = wapbl_circ_read(wr, data, fsblklen, &off);
https://nxr.netbsd.org/xref/src/sys/kern/vfs_wapbl.c?r=1.117#3436
which in turn is used by fsck_ffs's bread when wapbl is enabled:
347 int
348 bread(int fd, char *buf, daddr_t blk, long size)
349 {
350 char *cp;
351 int i, errs;
352 off_t offset;
353
354 offset = blk;
355 offset *= dev_bsize;
356 if ((pread(fd, buf, (int)size, offset) == size) &&
357 read_wapbl(buf, size, blk) == 0)
358 return (0);
https://nxr.netbsd.org/xref/src/sbin/fsck_ffs/utilities.c?r=1.71#347
138 int
139 read_wapbl(char *buf, long size, daddr_t blk)
140 {
141
142 if (!wapbl_replay || !wapbl_replay_isopen(wapbl_replay))
143 return 0;
144 return wapbl_replay_read(wapbl_replay, buf, blk, size);
145 }
https://nxr.netbsd.org/xref/src/sbin/fsck_ffs/wapbl.c?r=1.6#138
So what's missing?
Home |
Main Index |
Thread Index |
Old Index