From: Christian Brauner <brauner@kernel.org>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Christian Brauner <brauner@kernel.org>,
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [GIT PULL 05/19 for v7.4] vfs bh
Date: Fri, 16 Oct 2026 12:16:30 +0200 [thread overview]
Message-ID: <20261016-vfs-7.4-rc1.bh-97cf6f68db3d@brauner> (raw)
In-Reply-To: <20261016-vfs-v74-41eaf6c4712c@brauner>
Hey Linus,
/* Summary */
This stops the buffer_head write completion handlers from clearing
BH_Uptodate when a write fails.
A buffer whose write failed still holds exactly the data the filesystem
asked to be written. It's the disk that is stale, not the buffer.
Claiming otherwise has consequences. mark_buffer_dirty() warns when a
filesystem redirties the buffer to retry the write, a buffer that isn't
up to date gets re-read from disk which silently replaces the data with
the stale on-disk copy, and the window between the write completing and
BH_Uptodate being cleared is visible to anyone holding the folio lock.
BH_Write_EIO already records that the last write failed. Every consumer
is moved over to buffer_write_io_error(): the two core helpers in
fs/buffer.c, adfs, ext2, omfs, exfat, fat, ext4, ocfs2, gfs2 and jbd2.
Then write completion stops touching BH_Uptodate in both directions and
BH_Write_EIO is cleared on successful completion instead of at
submission, so a resubmission no longer hides an error that hasn't been
fixed yet. bforget() and invalidation drop the flag so a reused block
doesn't inherit someone else's write error.
The groundwork for this removes b_page from struct buffer_head and lets
a buffer_head point at memory outside the page cache. jbd2's shadow
buffers sit on a slab folio today. A slab folio overloads ->mapping so
mark_buffer_write_io_error() couldn't be called on them at all. They
now point at the frozen data directly with b_folio NULL.
Also included are documentation updates from Matthew for sb_bread(),
sb_breadahead() and mmb_mark_buffer_dirty() and the removal of stale
references to unmap_buffer() and mark_buffer_dirty_inode().
/* Testing */
No build failures or warnings were observed.
/* Conflicts */
Merge conflicts with mainline
=============================
No known conflicts.
Merge conflicts with other trees
================================
This conflicts with the mm tree in include/linux/buffer_head.h between
commits effd0cf5f5261 ("md: remove the last use of page_buffers()") and
ebb7205efe614 ("md: use folio_alloc_buffers()") from the mm tree and
commits 1aeacc2cbf86e ("buffer_head: Remove b_page") and 3c9ab45852f63
("jbd2: point the shadow buffer at the frozen data directly") from this
tree. The mm tree removes the page_buffers() macro, this tree switches
bh_offset() to b_folio and adds kmap_local_bh() and kunmap_local_bh()
right above it:
diff --cc include/linux/buffer_head.h
index 4b0b7188472b,e7a701ce029d..f8782b719026
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@@ -172,10 -169,44 +169,39 @@@ static __always_inline int buffer_uptod
static inline unsigned long bh_offset(const struct buffer_head *bh)
{
- return (unsigned long)(bh)->b_data & (page_size(bh->b_page) - 1);
+ return (unsigned long)(bh)->b_data & (folio_size(bh->b_folio) - 1);
+ }
+
+ /**
+ * kmap_local_bh - Map the data of a buffer.
+ * @bh: The buffer.
+ *
+ * Buffers usually live in the page cache, but a few are built over memory
+ * which is not. Those carry no folio and b_data is already a kernel address
+ * which is always mapped, so there is nothing to do for them. Pair with
+ * kunmap_local_bh().
+ *
+ * Return: A pointer to the buffer's data.
+ */
+ static inline void *kmap_local_bh(const struct buffer_head *bh)
+ {
+ if (!bh->b_folio)
+ return bh->b_data;
+ return kmap_local_folio(bh->b_folio, bh_offset(bh));
+ }
+
+ /**
+ * kunmap_local_bh - Unmap the data of a buffer.
+ * @bh: The buffer.
+ * @addr: The address returned by kmap_local_bh().
+ */
+ static inline void kunmap_local_bh(const struct buffer_head *bh, void *addr)
+ {
+ if (bh->b_folio)
+ kunmap_local(addr);
}
-/* If we *know* page->private refers to buffer_heads */
-#define page_buffers(page) \
- ({ \
- BUG_ON(!PagePrivate(page)); \
- ((struct buffer_head *)page_private(page)); \
- })
+/* If we *know* folio->private refers to buffer_heads */
#define folio_buffers(folio) folio_get_private(folio)
void buffer_check_dirty_writeback(struct folio *folio,
The following changes since commit cee9395acd8043be0644b25c34bfa86623f2b935:
Linux 7.3-rc1 (2026-08-30 13:34:40 -0700)
are available in the Git repository at:
git@gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs tags/vfs-7.4-rc1.bh
for you to fetch changes up to 7c5bb35718a6ecc2001e2f8f6abc068ab926b583:
Merge patch series "Buffer head documentation updates" (2026-09-10 09:27:29 +0200)
----------------------------------------------------------------
vfs-7.4-rc1.bh
Please consider pulling these changes from the signed vfs-7.4-rc1.bh tag.
Thanks!
Christian
----------------------------------------------------------------
Chao Shi (20):
buffer: allow a buffer_head to point at memory outside the page cache
jbd2: point the shadow buffer at the frozen data directly
buffer: read the folio's mapping directly in buffer_set_crypto_ctx()
buffer: clear BH_Write_EIO when a buffer is forgotten
buffer: discard BH_Write_EIO along with the rest of the buffer state
buffer: detect metadata write errors with buffer_write_io_error()
adfs: check for a directory write error with buffer_write_io_error()
ext2: check for an xattr block write error with buffer_write_io_error()
omfs: check for an inode write error with buffer_write_io_error()
exfat: check for a directory write error with buffer_write_io_error()
fat: check for a metadata write error with buffer_write_io_error()
ext4: check for a metadata write error with buffer_write_io_error()
ocfs2: check for a metadata write error with buffer_write_io_error()
ocfs2: check for a stale write error before reusing a metadata buffer
gfs2: check for a metadata write error with buffer_write_io_error()
jbd2: report journal write errors with BH_Write_EIO
jbd2: say what jbd2_freeze_jh_data()'s assertion is actually checking
jbd2: check for a fast commit write error with buffer_write_io_error()
buffer: stop touching BH_Uptodate on write completion
buffer: clear BH_Write_EIO when a write succeeds, not when one starts
Christian Brauner (2):
Merge patch series "buffer: stop clearing BH_Uptodate when a write fails"
Merge patch series "Buffer head documentation updates"
Matthew Wilcox (Oracle) (7):
buffer_head: Remove b_page
buffer: Remove reference to unmap_buffer()
fs: Remove references to mark_buffer_dirty_inode()
buffer: Document sb_bread(), sb_bread_unmovable() and sb_breadahead()
buffer: Document mmb_mark_buffer_dirty()
buffer: Refer to folios in comments
buffer: Rename label
Documentation/filesystems/porting.rst | 2 +-
fs/adfs/dir.c | 2 +-
fs/buffer.c | 131 ++++++++++++++++++----------------
fs/exfat/misc.c | 2 +-
fs/ext2/xattr.c | 2 +-
fs/ext4/ext4_jbd2.c | 2 +-
fs/ext4/mmp.c | 2 +-
fs/fat/misc.c | 2 +-
fs/gfs2/log.c | 4 +-
fs/gfs2/lops.c | 4 +-
fs/jbd2/commit.c | 22 +++---
fs/jbd2/journal.c | 31 ++++----
fs/jbd2/transaction.c | 2 +-
fs/ocfs2/buffer_head_io.c | 12 ++--
fs/ocfs2/journal.c | 25 +++----
fs/omfs/inode.c | 4 +-
include/linux/buffer_head.h | 86 +++++++++++++++++++---
17 files changed, 209 insertions(+), 126 deletions(-)
next prev parent reply other threads:[~2026-10-16 10:16 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-16 10:13 [GIT PULL 00/19 for v7.4] v7.4 Christian Brauner
2026-10-16 10:14 ` [GIT PULL 01/19 for v7.4] ipc misc Christian Brauner
2026-10-16 10:15 ` [GIT PULL 02/19 for v7.4] kernel signal Christian Brauner
2026-10-16 10:15 ` [GIT PULL 03/19 for v7.4] namespace misc Christian Brauner
2026-10-16 10:16 ` [GIT PULL 04/19 for v7.4] vfs bfs Christian Brauner
2026-10-16 10:16 ` Christian Brauner [this message]
2026-10-16 10:16 ` [GIT PULL 06/19 for v7.4] vfs binfmt Christian Brauner
2026-10-16 10:17 ` [GIT PULL 07/19 for v7.4] vfs close_range Christian Brauner
2026-10-16 10:18 ` [GIT PULL 08/19 for v7.4] vfs coredump Christian Brauner
2026-10-16 10:18 ` [GIT PULL 09/19 for v7.4] vfs file Christian Brauner
2026-10-16 10:19 ` [GIT PULL 10/19 for v7.4] vfs idmap Christian Brauner
2026-10-16 10:21 ` [GIT PULL 11/19 for v7.4] vfs iomap Christian Brauner
2026-10-16 10:21 ` [GIT PULL 12/19 for v7.4] vfs kernfs Christian Brauner
2026-10-16 10:22 ` [GIT PULL 13/19 for v7.4] vfs lookup Christian Brauner
2026-10-16 10:23 ` [GIT PULL 14/19 for v7.4] vfs misc Christian Brauner
2026-10-16 10:24 ` [GIT PULL 15/19 for v7.4] vfs mount Christian Brauner
2026-10-16 10:25 ` [GIT PULL 16/19 for v7.4] vfs netfs Christian Brauner
2026-10-16 10:26 ` [GIT PULL 17/19 for v7.4] vfs shared net-next pidfd Christian Brauner
2026-10-16 10:26 ` [GIT PULL 18/19 for v7.4] vfs shared super Christian Brauner
2026-10-16 10:27 ` [GIT PULL 19/19 for v7.4] vfs sync_close Christian Brauner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261016-vfs-7.4-rc1.bh-97cf6f68db3d@brauner \
--to=brauner@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®