diff options
Diffstat (limited to 'fs/xfs/xfs_error.c')
-rw-r--r-- | fs/xfs/xfs_error.c | 154 |
1 files changed, 80 insertions, 74 deletions
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index ed7ee4e8af73..52f75bc1abac 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -25,100 +25,106 @@ #ifdef DEBUG -int xfs_etest[XFS_NUM_INJECT_ERROR]; -int64_t xfs_etest_fsid[XFS_NUM_INJECT_ERROR]; -char * xfs_etest_fsname[XFS_NUM_INJECT_ERROR]; -int xfs_error_test_active; +static unsigned int xfs_errortag_random_default[] = { + XFS_RANDOM_DEFAULT, + XFS_RANDOM_IFLUSH_1, + XFS_RANDOM_IFLUSH_2, + XFS_RANDOM_IFLUSH_3, + XFS_RANDOM_IFLUSH_4, + XFS_RANDOM_IFLUSH_5, + XFS_RANDOM_IFLUSH_6, + XFS_RANDOM_DA_READ_BUF, + XFS_RANDOM_BTREE_CHECK_LBLOCK, + XFS_RANDOM_BTREE_CHECK_SBLOCK, + XFS_RANDOM_ALLOC_READ_AGF, + XFS_RANDOM_IALLOC_READ_AGI, + XFS_RANDOM_ITOBP_INOTOBP, + XFS_RANDOM_IUNLINK, + XFS_RANDOM_IUNLINK_REMOVE, + XFS_RANDOM_DIR_INO_VALIDATE, + XFS_RANDOM_BULKSTAT_READ_CHUNK, + XFS_RANDOM_IODONE_IOERR, + XFS_RANDOM_STRATREAD_IOERR, + XFS_RANDOM_STRATCMPL_IOERR, + XFS_RANDOM_DIOWRITE_IOERR, + XFS_RANDOM_BMAPIFORMAT, + XFS_RANDOM_FREE_EXTENT, + XFS_RANDOM_RMAP_FINISH_ONE, + XFS_RANDOM_REFCOUNT_CONTINUE_UPDATE, + XFS_RANDOM_REFCOUNT_FINISH_ONE, + XFS_RANDOM_BMAP_FINISH_ONE, + XFS_RANDOM_AG_RESV_CRITICAL, +}; int -xfs_error_test(int error_tag, int *fsidp, char *expression, - int line, char *file, unsigned long randfactor) +xfs_errortag_init( + struct xfs_mount *mp) { - int i; - int64_t fsid; + mp->m_errortag = kmem_zalloc(sizeof(unsigned int) * XFS_ERRTAG_MAX, + KM_SLEEP | KM_MAYFAIL); + if (!mp->m_errortag) + return -ENOMEM; + return 0; +} - if (prandom_u32() % randfactor) - return 0; +void +xfs_errortag_del( + struct xfs_mount *mp) +{ + kmem_free(mp->m_errortag); +} - memcpy(&fsid, fsidp, sizeof(xfs_fsid_t)); +bool +xfs_errortag_test( + struct xfs_mount *mp, + const char *expression, + const char *file, + int line, + unsigned int error_tag) +{ + unsigned int randfactor; - for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { - if (xfs_etest[i] == error_tag && xfs_etest_fsid[i] == fsid) { - xfs_warn(NULL, - "Injecting error (%s) at file %s, line %d, on filesystem \"%s\"", - expression, file, line, xfs_etest_fsname[i]); - return 1; - } - } + ASSERT(error_tag < XFS_ERRTAG_MAX); + randfactor = mp->m_errortag[error_tag]; + if (!randfactor || prandom_u32() % randfactor) + return false; - return 0; + xfs_warn_ratelimited(mp, +"Injecting error (%s) at file %s, line %d, on filesystem \"%s\"", + expression, file, line, mp->m_fsname); + return true; } int -xfs_errortag_add(unsigned int error_tag, xfs_mount_t *mp) +xfs_errortag_set( + struct xfs_mount *mp, + unsigned int error_tag, + unsigned int tag_value) { - int i; - int len; - int64_t fsid; - if (error_tag >= XFS_ERRTAG_MAX) return -EINVAL; - memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t)); - - for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { - if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) { - xfs_warn(mp, "error tag #%d on", error_tag); - return 0; - } - } - - for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { - if (xfs_etest[i] == 0) { - xfs_warn(mp, "Turned on XFS error tag #%d", - error_tag); - xfs_etest[i] = error_tag; - xfs_etest_fsid[i] = fsid; - len = strlen(mp->m_fsname); - xfs_etest_fsname[i] = kmem_alloc(len + 1, KM_SLEEP); - strcpy(xfs_etest_fsname[i], mp->m_fsname); - xfs_error_test_active++; - return 0; - } - } - - xfs_warn(mp, "error tag overflow, too many turned on"); - - return 1; + mp->m_errortag[error_tag] = tag_value; + return 0; } int -xfs_errortag_clearall(xfs_mount_t *mp, int loud) +xfs_errortag_add( + struct xfs_mount *mp, + unsigned int error_tag) { - int64_t fsid; - int cleared = 0; - int i; - - memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t)); - - - for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { - if ((fsid == 0LL || xfs_etest_fsid[i] == fsid) && - xfs_etest[i] != 0) { - cleared = 1; - xfs_warn(mp, "Clearing XFS error tag #%d", - xfs_etest[i]); - xfs_etest[i] = 0; - xfs_etest_fsid[i] = 0LL; - kmem_free(xfs_etest_fsname[i]); - xfs_etest_fsname[i] = NULL; - xfs_error_test_active--; - } - } + if (error_tag >= XFS_ERRTAG_MAX) + return -EINVAL; - if (loud || cleared) - xfs_warn(mp, "Cleared all XFS error tags for filesystem"); + return xfs_errortag_set(mp, error_tag, + xfs_errortag_random_default[error_tag]); +} +int +xfs_errortag_clearall( + struct xfs_mount *mp) +{ + memset(mp->m_errortag, 0, sizeof(unsigned int) * XFS_ERRTAG_MAX); return 0; } #endif /* DEBUG */ |