Message ID | 48ccb776f018f79730fb9b9139623960401f9505.1715951291.git.fdmanana@suse.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | btrfs: avoid data races when accessing an inode's delayed_node | expand |
在 2024/5/17 22:43, fdmanana@kernel.org 写道: > From: Filipe Manana <fdmanana@suse.com> > > When reading the delayed_node of an inode without taking the lock of the > root->delayed_nodes we are using READ_ONCE(), and when updating it we are > using WRITE_ONCE(). > > Add and use helpers that hide the usage of READ_ONCE() and WRITE_ONCE(), > like we do for other inode fields such as first_dir_index_to_log or the > log_transid field of struct btrfs_root for example. > > Also make use of the setter helper at btrfs_alloc_inode() for consistency > only - it shouldn't be needed since when allocating an inode no one else > can access it concurrently. > > Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: Qu Wenruo <wqu@suse.com> Thanks, Qu > --- > fs/btrfs/btrfs_inode.h | 12 ++++++++++++ > fs/btrfs/delayed-inode.c | 10 +++++----- > fs/btrfs/inode.c | 4 ++-- > 3 files changed, 19 insertions(+), 7 deletions(-) > > diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h > index 4d9299789a03..3c8bc7a8ebdd 100644 > --- a/fs/btrfs/btrfs_inode.h > +++ b/fs/btrfs/btrfs_inode.h > @@ -330,6 +330,18 @@ struct btrfs_inode { > struct inode vfs_inode; > }; > > +static inline struct btrfs_delayed_node *btrfs_get_inode_delayed_node( > + const struct btrfs_inode *inode) > +{ > + return READ_ONCE(inode->delayed_node); > +} > + > +static inline void btrfs_set_inode_delayed_node(struct btrfs_inode *inode, > + struct btrfs_delayed_node *node) > +{ > + WRITE_ONCE(inode->delayed_node, node); > +} > + > static inline u64 btrfs_get_first_dir_index_to_log(const struct btrfs_inode *inode) > { > return READ_ONCE(inode->first_dir_index_to_log); > diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c > index 6df7e44d9d31..f2fe488665e8 100644 > --- a/fs/btrfs/delayed-inode.c > +++ b/fs/btrfs/delayed-inode.c > @@ -71,7 +71,7 @@ static struct btrfs_delayed_node *btrfs_get_delayed_node( > u64 ino = btrfs_ino(btrfs_inode); > struct btrfs_delayed_node *node; > > - node = READ_ONCE(btrfs_inode->delayed_node); > + node = btrfs_get_inode_delayed_node(btrfs_inode); > if (node) { > refcount_inc(&node->refs); > return node; > @@ -106,7 +106,7 @@ static struct btrfs_delayed_node *btrfs_get_delayed_node( > */ > if (refcount_inc_not_zero(&node->refs)) { > refcount_inc(&node->refs); > - WRITE_ONCE(btrfs_inode->delayed_node, node); > + btrfs_set_inode_delayed_node(btrfs_inode, node); > } else { > node = NULL; > } > @@ -161,7 +161,7 @@ static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node( > ASSERT(xa_err(ptr) != -EINVAL); > ASSERT(xa_err(ptr) != -ENOMEM); > ASSERT(ptr == NULL); > - WRITE_ONCE(btrfs_inode->delayed_node, node); > + btrfs_set_inode_delayed_node(btrfs_inode, node); > xa_unlock(&root->delayed_nodes); > > return node; > @@ -1308,11 +1308,11 @@ void btrfs_remove_delayed_node(struct btrfs_inode *inode) > { > struct btrfs_delayed_node *delayed_node; > > - delayed_node = READ_ONCE(inode->delayed_node); > + delayed_node = btrfs_get_inode_delayed_node(inode); > if (!delayed_node) > return; > > - WRITE_ONCE(inode->delayed_node, NULL); > + btrfs_set_inode_delayed_node(inode, NULL); > btrfs_release_delayed_node(delayed_node); > } > > diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c > index 11cad22d7b4c..2f3129fe0e58 100644 > --- a/fs/btrfs/inode.c > +++ b/fs/btrfs/inode.c > @@ -6100,7 +6100,7 @@ static int btrfs_dirty_inode(struct btrfs_inode *inode) > ret = btrfs_update_inode(trans, inode); > } > btrfs_end_transaction(trans); > - if (READ_ONCE(inode->delayed_node)) > + if (btrfs_get_inode_delayed_node(inode)) > btrfs_balance_delayed_items(fs_info); > > return ret; > @@ -8475,7 +8475,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) > ei->prop_compress = BTRFS_COMPRESS_NONE; > ei->defrag_compress = BTRFS_COMPRESS_NONE; > > - ei->delayed_node = NULL; > + btrfs_set_inode_delayed_node(ei, NULL); > > ei->i_otime_sec = 0; > ei->i_otime_nsec = 0;
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index 4d9299789a03..3c8bc7a8ebdd 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h @@ -330,6 +330,18 @@ struct btrfs_inode { struct inode vfs_inode; }; +static inline struct btrfs_delayed_node *btrfs_get_inode_delayed_node( + const struct btrfs_inode *inode) +{ + return READ_ONCE(inode->delayed_node); +} + +static inline void btrfs_set_inode_delayed_node(struct btrfs_inode *inode, + struct btrfs_delayed_node *node) +{ + WRITE_ONCE(inode->delayed_node, node); +} + static inline u64 btrfs_get_first_dir_index_to_log(const struct btrfs_inode *inode) { return READ_ONCE(inode->first_dir_index_to_log); diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 6df7e44d9d31..f2fe488665e8 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -71,7 +71,7 @@ static struct btrfs_delayed_node *btrfs_get_delayed_node( u64 ino = btrfs_ino(btrfs_inode); struct btrfs_delayed_node *node; - node = READ_ONCE(btrfs_inode->delayed_node); + node = btrfs_get_inode_delayed_node(btrfs_inode); if (node) { refcount_inc(&node->refs); return node; @@ -106,7 +106,7 @@ static struct btrfs_delayed_node *btrfs_get_delayed_node( */ if (refcount_inc_not_zero(&node->refs)) { refcount_inc(&node->refs); - WRITE_ONCE(btrfs_inode->delayed_node, node); + btrfs_set_inode_delayed_node(btrfs_inode, node); } else { node = NULL; } @@ -161,7 +161,7 @@ static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node( ASSERT(xa_err(ptr) != -EINVAL); ASSERT(xa_err(ptr) != -ENOMEM); ASSERT(ptr == NULL); - WRITE_ONCE(btrfs_inode->delayed_node, node); + btrfs_set_inode_delayed_node(btrfs_inode, node); xa_unlock(&root->delayed_nodes); return node; @@ -1308,11 +1308,11 @@ void btrfs_remove_delayed_node(struct btrfs_inode *inode) { struct btrfs_delayed_node *delayed_node; - delayed_node = READ_ONCE(inode->delayed_node); + delayed_node = btrfs_get_inode_delayed_node(inode); if (!delayed_node) return; - WRITE_ONCE(inode->delayed_node, NULL); + btrfs_set_inode_delayed_node(inode, NULL); btrfs_release_delayed_node(delayed_node); } diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 11cad22d7b4c..2f3129fe0e58 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -6100,7 +6100,7 @@ static int btrfs_dirty_inode(struct btrfs_inode *inode) ret = btrfs_update_inode(trans, inode); } btrfs_end_transaction(trans); - if (READ_ONCE(inode->delayed_node)) + if (btrfs_get_inode_delayed_node(inode)) btrfs_balance_delayed_items(fs_info); return ret; @@ -8475,7 +8475,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) ei->prop_compress = BTRFS_COMPRESS_NONE; ei->defrag_compress = BTRFS_COMPRESS_NONE; - ei->delayed_node = NULL; + btrfs_set_inode_delayed_node(ei, NULL); ei->i_otime_sec = 0; ei->i_otime_nsec = 0;