]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
xfs: buffer lru reference count error injection tag
authorBrian Foster <bfoster@redhat.com>
Tue, 17 Oct 2017 21:16:29 +0000 (14:16 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Thu, 26 Oct 2017 22:38:23 +0000 (15:38 -0700)
XFS uses a fixed reference count for certain types of buffers in the
internal LRU cache. These reference counts dictate how aggressively
certain buffers are reclaimed vs. others. While the reference counts
implements priority across different buffer types, all buffers
(other than uncached buffers) are typically cached for at least one
reclaim cycle.

We've had at least one bug recently that has been hidden by a
released buffer sitting around in the LRU. Users hitting the problem
were able to reproduce under enough memory pressure to cause
aggressive reclaim in a particular window of time.

To support future xfstests cases, add an error injection tag to
hardcode the buffer reference count to zero. When enabled, this
bypasses caching of associated buffers and facilitates test cases
that depend on this behavior.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf.h
fs/xfs/xfs_error.c
fs/xfs/xfs_error.h

index 2f97c12ca75e4d5554b94b7a195b4dca53f90174..d481dd2b29a688db8475383b4e2d6a4cc6a45a65 100644 (file)
@@ -42,6 +42,7 @@
 #include "xfs_mount.h"
 #include "xfs_trace.h"
 #include "xfs_log.h"
+#include "xfs_error.h"
 
 static kmem_zone_t *xfs_buf_zone;
 
@@ -2129,3 +2130,18 @@ xfs_buf_terminate(void)
 {
        kmem_zone_destroy(xfs_buf_zone);
 }
+
+void xfs_buf_set_ref(struct xfs_buf *bp, int lru_ref)
+{
+       struct xfs_mount        *mp = bp->b_target->bt_mount;
+
+       /*
+        * Set the lru reference count to 0 based on the error injection tag.
+        * This allows userspace to disrupt buffer caching for debug/testing
+        * purposes.
+        */
+       if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BUF_LRU_REF))
+               lru_ref = 0;
+
+       atomic_set(&bp->b_lru_ref, lru_ref);
+}
index bf71507ddb1659ec6991d5ba0c721ee01da7b210..f873bb786824280f01eeb90bf6e891f5d5ae7165 100644 (file)
@@ -352,10 +352,7 @@ extern void xfs_buf_terminate(void);
 #define XFS_BUF_ADDR(bp)               ((bp)->b_maps[0].bm_bn)
 #define XFS_BUF_SET_ADDR(bp, bno)      ((bp)->b_maps[0].bm_bn = (xfs_daddr_t)(bno))
 
-static inline void xfs_buf_set_ref(struct xfs_buf *bp, int lru_ref)
-{
-       atomic_set(&bp->b_lru_ref, lru_ref);
-}
+void xfs_buf_set_ref(struct xfs_buf *bp, int lru_ref);
 
 static inline int xfs_buf_ispinned(struct xfs_buf *bp)
 {
index eaf86f55b7f2156c351aa26fd0190871ef1772bd..6732b0a0d8261b6bf0537d0e97d924900d258174 100644 (file)
@@ -58,6 +58,7 @@ static unsigned int xfs_errortag_random_default[] = {
        XFS_RANDOM_DROP_WRITES,
        XFS_RANDOM_LOG_BAD_CRC,
        XFS_RANDOM_LOG_ITEM_PIN,
+       XFS_RANDOM_BUF_LRU_REF,
 };
 
 struct xfs_errortag_attr {
@@ -163,6 +164,7 @@ XFS_ERRORTAG_ATTR_RW(ag_resv_critical,      XFS_ERRTAG_AG_RESV_CRITICAL);
 XFS_ERRORTAG_ATTR_RW(drop_writes,      XFS_ERRTAG_DROP_WRITES);
 XFS_ERRORTAG_ATTR_RW(log_bad_crc,      XFS_ERRTAG_LOG_BAD_CRC);
 XFS_ERRORTAG_ATTR_RW(log_item_pin,     XFS_ERRTAG_LOG_ITEM_PIN);
+XFS_ERRORTAG_ATTR_RW(buf_lru_ref,      XFS_ERRTAG_BUF_LRU_REF);
 
 static struct attribute *xfs_errortag_attrs[] = {
        XFS_ERRORTAG_ATTR_LIST(noerror),
@@ -196,6 +198,7 @@ static struct attribute *xfs_errortag_attrs[] = {
        XFS_ERRORTAG_ATTR_LIST(drop_writes),
        XFS_ERRORTAG_ATTR_LIST(log_bad_crc),
        XFS_ERRORTAG_ATTR_LIST(log_item_pin),
+       XFS_ERRORTAG_ATTR_LIST(buf_lru_ref),
        NULL,
 };
 
index 7c4bef3bddb7504d0c06dd27479fc5b6dfa9f1c5..78a7f43f8d018ede9d1851b2bc8f14c0fd63b8fd 100644 (file)
@@ -107,7 +107,8 @@ extern void xfs_verifier_error(struct xfs_buf *bp);
 #define XFS_ERRTAG_DROP_WRITES                         28
 #define XFS_ERRTAG_LOG_BAD_CRC                         29
 #define XFS_ERRTAG_LOG_ITEM_PIN                                30
-#define XFS_ERRTAG_MAX                                 31
+#define XFS_ERRTAG_BUF_LRU_REF                         31
+#define XFS_ERRTAG_MAX                                 32
 
 /*
  * Random factors for above tags, 1 means always, 2 means 1/2 time, etc.
@@ -143,6 +144,7 @@ extern void xfs_verifier_error(struct xfs_buf *bp);
 #define XFS_RANDOM_DROP_WRITES                         1
 #define XFS_RANDOM_LOG_BAD_CRC                         1
 #define XFS_RANDOM_LOG_ITEM_PIN                                1
+#define XFS_RANDOM_BUF_LRU_REF                         2
 
 #ifdef DEBUG
 extern int xfs_errortag_init(struct xfs_mount *mp);