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