writeback: don't kick a missing wb for dontcache writes

With CONFIG_CGROUP_WRITEBACK, inode->i_wb stays NULL until the inode is
dirtied for the first time (folio_account_dirtied(), __mark_inode_dirty()
or wbc_attach_fdatawrite_inode() attach it).  generic_write_sync() calls
filemap_dontcache_kick_writeback() for every IOCB_DONTCACHE write,
including O_DIRECT ones, which never dirty the page cache.  The function
then passes the NULL returned by unlocked_inode_to_wb_begin() to
wb_has_dirty_io():

  fd = open("/dev/ram0", O_WRONLY | O_DIRECT);
  pwritev2(fd, &iov, 1, 0, RWF_DONTCACHE);

  BUG: KASAN: null-ptr-deref in filemap_dontcache_kick_writeback+0xec
  Oops: general protection fault, probably for non-canonical address
  RIP: 0010:filemap_dontcache_kick_writeback+0xfd/0x7a0

The task dies inside rcu_read_lock().  blkdev_write_iter() gets there for
any block device whose page cache has not been dirtied yet.
nfs_file_direct_write() calls generic_write_sync() the same way.

An inode without a wb has never had dirty pages, so there is nothing to
flush: skip the kick.

Fixes: e1bf796284 ("mm: kick writeback flusher for IOCB_DONTCACHE with targeted dirty tracking")
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
This commit is contained in:
Josef Bacik 2026-10-04 20:33:45 +00:00 committed by Christian Brauner
parent b14fcabd34
commit aa6439028d
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2

View File

@ -2579,8 +2579,9 @@ void filemap_dontcache_kick_writeback(struct address_space *mapping)
struct wb_lock_cookie cookie = {};
bool need_wakeup = false;
/* An inode which was never dirtied has no wb and nothing to flush. */
wb = unlocked_inode_to_wb_begin(inode, &cookie);
if (wb_has_dirty_io(wb) &&
if (wb && wb_has_dirty_io(wb) &&
!test_bit(WB_start_dontcache, &wb->state) &&
!test_and_set_bit(WB_start_dontcache, &wb->state)) {
wb_get(wb);