Re: bin/56942 (fsck_ffs can't replay wapbl journals to memory)

[email protected]
Newsgroups gmane.os.netbsd.bugs
Message-ID <[email protected]>
Synopsis: fsck_ffs can't replay wapbl journals to memory

State-Changed-From-To: open->feedback
State-Changed-By: [email protected]
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?
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.