]> www.infradead.org Git - users/hch/xfsprogs.git/commit
libxfs: dirty buffers should be marked uptodate too
authorDarrick J. Wong <djwong@kernel.org>
Mon, 16 Sep 2024 07:10:02 +0000 (09:10 +0200)
committerCarlos Maiolino <cem@kernel.org>
Mon, 16 Sep 2024 07:10:02 +0000 (09:10 +0200)
commit71d2969be616e79bcfaa2d27414337afde40cdfc
tree53fdec1ceb18646cde67fa262825d111552c22a0
parentfde42a497dba52bcf1faaf0f6ae50707a3d06b29
libxfs: dirty buffers should be marked uptodate too

I started fuzz-testing the realtime rmap feature with a very large
number of realtime allocation groups.  There were so many rt groups that
repair had to rebuild /realtime in the metadata directory tree, and that
directory was big enough to spur the creation of a block format
directory.

Unfortunately, repair then walks both directory trees to look for
unconnceted files.  This part of phase 6 emits CRC errors on the newly
created buffers for the /realtime directory, declares the directory to
be garbage, and moves all the rt rmap inodes to /lost+found, resulting
in a corrupt fs.

Poking around in gdb, I noticed that the buffer contents were indeed
zero, and that UPTODATE was not set.  This was very strange, until I
added a watch on bp->b_flags to watch for accesses.  It turns out that
xfs_repair's prefetch code will _get a buffer and zero the contents if
UPTODATE is not set.

The directory tree code in libxfs will also _get a buffer, initialize
it, and log it to the coordinating transaction, which in this case is
the transactions used to reconnect the rmap btree inodes to /realtime.
At no point does any of that code ever set UPTODATE on the buffer, which
is why prefetch zaps the contents.

Hence change both buffer dirtying functions to set UPTODATE, since a
dirty buffer is by definition at least as recent as whatever's on disk.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
libxfs/rdwr.c
libxfs/trans.c