]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
btrfs: expose per-inode stable writes flag
authorQu Wenruo <wqu@suse.com>
Mon, 27 Jan 2025 23:18:18 +0000 (09:48 +1030)
committerDavid Sterba <dsterba@suse.com>
Tue, 18 Mar 2025 19:35:41 +0000 (20:35 +0100)
The address space flag AS_STABLE_WRITES determine if FGP_STABLE for will
wait for the folio to finish its writeback.

For btrfs, due to the default data checksum behavior, if we modify the
folio while it's still under writeback, it will cause data checksum
mismatch.  Thus for quite some call sites we manually call
folio_wait_writeback() to prevent such problem from happening.

Currently there is only one call site inside btrfs really utilizing
FGP_STABLE, and in that case we also manually call folio_wait_writeback()
to do the waiting.

But it's better to properly expose the stable writes flag to a per-inode
basis, to allow call sites to fully benefit from FGP_STABLE flag.
E.g. for inodes with NODATASUM allowing beginning dirtying the page
without waiting for writeback.

This involves:

- Update the mapping's stable write flag when setting/clearing NODATASUM
  inode flag using ioctl
  This only works for empty files, so it should be fine.

- Update the mapping's stable write flag when reading an inode from disk

- Remove the explicit folio_wait_writeback() for FGP_BEGINWRITE call
  site

Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/btrfs_inode.h
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c

index b2fa33911c280a044a562e3b49f523323f9cb10a..029fba82b81dac069e188f36a6095380b9dbce22 100644 (file)
@@ -516,6 +516,14 @@ static inline void btrfs_assert_inode_locked(struct btrfs_inode *inode)
        lockdep_assert_held(&inode->vfs_inode.i_rwsem);
 }
 
+static inline void btrfs_update_inode_mapping_flags(struct btrfs_inode *inode)
+{
+       if (inode->flags & BTRFS_INODE_NODATASUM)
+               mapping_clear_stable_writes(inode->vfs_inode.i_mapping);
+       else
+               mapping_set_stable_writes(inode->vfs_inode.i_mapping);
+}
+
 /* Array of bytes with variable length, hexadecimal format 0x1234 */
 #define CSUM_FMT                               "0x%*phN"
 #define CSUM_FMT_VALUE(size, bytes)            size, bytes
index 0b568c8d24cbc5cadc5c852f56bef83d56111ae2..59af01d6cc56830c46790941647704bd12f3a6a5 100644 (file)
@@ -874,7 +874,6 @@ again:
                        ret = PTR_ERR(folio);
                return ret;
        }
-       folio_wait_writeback(folio);
        /* Only support page sized folio yet. */
        ASSERT(folio_order(folio) == 0);
        ret = set_folio_extent_mapped(folio);
index b32112c50707021a812f131f8563bc483aba0847..1964136dfdb4edb052562250a748e057f7edf33b 100644 (file)
@@ -3924,6 +3924,7 @@ static int btrfs_read_locked_inode(struct inode *inode, struct btrfs_path *path)
 
        btrfs_inode_split_flags(btrfs_inode_flags(leaf, inode_item),
                                &BTRFS_I(inode)->flags, &BTRFS_I(inode)->ro_flags);
+       btrfs_update_inode_mapping_flags(BTRFS_I(inode));
 
 cache_index:
        /*
@@ -6339,6 +6340,7 @@ int btrfs_create_new_inode(struct btrfs_trans_handle *trans,
                if (btrfs_test_opt(fs_info, NODATACOW))
                        BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW |
                                BTRFS_INODE_NODATASUM;
+               btrfs_update_inode_mapping_flags(BTRFS_I(inode));
        }
 
        ret = btrfs_insert_inode_locked(inode);
index 6c18bad53cd3eae9f5a42644f38abed42279aca6..8fff7ddf6409f7350d2c11da73af5576e67b472a 100644 (file)
@@ -393,6 +393,7 @@ int btrfs_fileattr_set(struct mnt_idmap *idmap,
 
 update_flags:
        binode->flags = binode_flags;
+       btrfs_update_inode_mapping_flags(binode);
        btrfs_sync_inode_flags_to_i_flags(inode);
        inode_inc_iversion(inode);
        inode_set_ctime_current(inode);