diff options
author | Dave Chinner <dchinner@redhat.com> | 2022-07-18 18:20:37 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2022-07-20 16:40:39 -0700 |
commit | 231f91ab504ecebcb88e942341b3d7dd91de45f1 (patch) | |
tree | 65c1e9844a43b5c0ebacacc45678bfcc9be2ee08 /fs/xfs/xfs_buf.h | |
parent | 3f52e016af600982989b5dee958d313c52483c92 (diff) |
xfs: xfs_buf cache destroy isn't RCU safe
Darrick and Sachin Sant reported that xfs/435 and xfs/436 would
report an non-empty xfs_buf slab on module remove. This isn't easily
to reproduce, but is clearly a side effect of converting the buffer
caceh to RUC freeing and lockless lookups. Sachin bisected and
Darrick hit it when testing the patchset directly.
Turns out that the xfs_buf slab is not destroyed when all the other
XFS slab caches are destroyed. Instead, it's got it's own little
wrapper function that gets called separately, and so it doesn't have
an rcu_barrier() call in it that is needed to drain all the rcu
callbacks before the slab is destroyed.
Fix it by removing the xfs_buf_init/terminate wrappers that just
allocate and destroy the xfs_buf slab, and move them to the same
place that all the other slab caches are set up and destroyed.
Reported-and-tested-by: Sachin Sant <sachinp@linux.ibm.com>
Fixes: 298f34224506 ("xfs: lockless buffer lookup")
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/xfs/xfs_buf.h')
-rw-r--r-- | fs/xfs/xfs_buf.h | 6 |
1 files changed, 2 insertions, 4 deletions
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h index 02b3c1635ec3..549c60942208 100644 --- a/fs/xfs/xfs_buf.h +++ b/fs/xfs/xfs_buf.h @@ -15,6 +15,8 @@ #include <linux/uio.h> #include <linux/list_lru.h> +extern struct kmem_cache *xfs_buf_cache; + /* * Base types */ @@ -307,10 +309,6 @@ extern int xfs_buf_delwri_submit(struct list_head *); extern int xfs_buf_delwri_submit_nowait(struct list_head *); extern int xfs_buf_delwri_pushbuf(struct xfs_buf *, struct list_head *); -/* Buffer Daemon Setup Routines */ -extern int xfs_buf_init(void); -extern void xfs_buf_terminate(void); - static inline xfs_daddr_t xfs_buf_daddr(struct xfs_buf *bp) { return bp->b_maps[0].bm_bn; |