162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. 462306a36Sopenharmony_ci * All Rights Reserved. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#include "xfs.h" 762306a36Sopenharmony_ci#include "xfs_shared.h" 862306a36Sopenharmony_ci#include "xfs_format.h" 962306a36Sopenharmony_ci#include "xfs_fs.h" 1062306a36Sopenharmony_ci#include "xfs_log_format.h" 1162306a36Sopenharmony_ci#include "xfs_trans_resv.h" 1262306a36Sopenharmony_ci#include "xfs_mount.h" 1362306a36Sopenharmony_ci#include "xfs_errortag.h" 1462306a36Sopenharmony_ci#include "xfs_error.h" 1562306a36Sopenharmony_ci#include "xfs_sysfs.h" 1662306a36Sopenharmony_ci#include "xfs_inode.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#ifdef DEBUG 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic unsigned int xfs_errortag_random_default[] = { 2162306a36Sopenharmony_ci XFS_RANDOM_DEFAULT, 2262306a36Sopenharmony_ci XFS_RANDOM_IFLUSH_1, 2362306a36Sopenharmony_ci XFS_RANDOM_IFLUSH_2, 2462306a36Sopenharmony_ci XFS_RANDOM_IFLUSH_3, 2562306a36Sopenharmony_ci XFS_RANDOM_IFLUSH_4, 2662306a36Sopenharmony_ci XFS_RANDOM_IFLUSH_5, 2762306a36Sopenharmony_ci XFS_RANDOM_IFLUSH_6, 2862306a36Sopenharmony_ci XFS_RANDOM_DA_READ_BUF, 2962306a36Sopenharmony_ci XFS_RANDOM_BTREE_CHECK_LBLOCK, 3062306a36Sopenharmony_ci XFS_RANDOM_BTREE_CHECK_SBLOCK, 3162306a36Sopenharmony_ci XFS_RANDOM_ALLOC_READ_AGF, 3262306a36Sopenharmony_ci XFS_RANDOM_IALLOC_READ_AGI, 3362306a36Sopenharmony_ci XFS_RANDOM_ITOBP_INOTOBP, 3462306a36Sopenharmony_ci XFS_RANDOM_IUNLINK, 3562306a36Sopenharmony_ci XFS_RANDOM_IUNLINK_REMOVE, 3662306a36Sopenharmony_ci XFS_RANDOM_DIR_INO_VALIDATE, 3762306a36Sopenharmony_ci XFS_RANDOM_BULKSTAT_READ_CHUNK, 3862306a36Sopenharmony_ci XFS_RANDOM_IODONE_IOERR, 3962306a36Sopenharmony_ci XFS_RANDOM_STRATREAD_IOERR, 4062306a36Sopenharmony_ci XFS_RANDOM_STRATCMPL_IOERR, 4162306a36Sopenharmony_ci XFS_RANDOM_DIOWRITE_IOERR, 4262306a36Sopenharmony_ci XFS_RANDOM_BMAPIFORMAT, 4362306a36Sopenharmony_ci XFS_RANDOM_FREE_EXTENT, 4462306a36Sopenharmony_ci XFS_RANDOM_RMAP_FINISH_ONE, 4562306a36Sopenharmony_ci XFS_RANDOM_REFCOUNT_CONTINUE_UPDATE, 4662306a36Sopenharmony_ci XFS_RANDOM_REFCOUNT_FINISH_ONE, 4762306a36Sopenharmony_ci XFS_RANDOM_BMAP_FINISH_ONE, 4862306a36Sopenharmony_ci XFS_RANDOM_AG_RESV_CRITICAL, 4962306a36Sopenharmony_ci 0, /* XFS_RANDOM_DROP_WRITES has been removed */ 5062306a36Sopenharmony_ci XFS_RANDOM_LOG_BAD_CRC, 5162306a36Sopenharmony_ci XFS_RANDOM_LOG_ITEM_PIN, 5262306a36Sopenharmony_ci XFS_RANDOM_BUF_LRU_REF, 5362306a36Sopenharmony_ci XFS_RANDOM_FORCE_SCRUB_REPAIR, 5462306a36Sopenharmony_ci XFS_RANDOM_FORCE_SUMMARY_RECALC, 5562306a36Sopenharmony_ci XFS_RANDOM_IUNLINK_FALLBACK, 5662306a36Sopenharmony_ci XFS_RANDOM_BUF_IOERROR, 5762306a36Sopenharmony_ci XFS_RANDOM_REDUCE_MAX_IEXTENTS, 5862306a36Sopenharmony_ci XFS_RANDOM_BMAP_ALLOC_MINLEN_EXTENT, 5962306a36Sopenharmony_ci XFS_RANDOM_AG_RESV_FAIL, 6062306a36Sopenharmony_ci XFS_RANDOM_LARP, 6162306a36Sopenharmony_ci XFS_RANDOM_DA_LEAF_SPLIT, 6262306a36Sopenharmony_ci XFS_RANDOM_ATTR_LEAF_TO_NODE, 6362306a36Sopenharmony_ci XFS_RANDOM_WB_DELAY_MS, 6462306a36Sopenharmony_ci XFS_RANDOM_WRITE_DELAY_MS, 6562306a36Sopenharmony_ci}; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistruct xfs_errortag_attr { 6862306a36Sopenharmony_ci struct attribute attr; 6962306a36Sopenharmony_ci unsigned int tag; 7062306a36Sopenharmony_ci}; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cistatic inline struct xfs_errortag_attr * 7362306a36Sopenharmony_cito_attr(struct attribute *attr) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci return container_of(attr, struct xfs_errortag_attr, attr); 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistatic inline struct xfs_mount * 7962306a36Sopenharmony_cito_mp(struct kobject *kobject) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci struct xfs_kobj *kobj = to_kobj(kobject); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci return container_of(kobj, struct xfs_mount, m_errortag_kobj); 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ciSTATIC ssize_t 8762306a36Sopenharmony_cixfs_errortag_attr_store( 8862306a36Sopenharmony_ci struct kobject *kobject, 8962306a36Sopenharmony_ci struct attribute *attr, 9062306a36Sopenharmony_ci const char *buf, 9162306a36Sopenharmony_ci size_t count) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci struct xfs_mount *mp = to_mp(kobject); 9462306a36Sopenharmony_ci struct xfs_errortag_attr *xfs_attr = to_attr(attr); 9562306a36Sopenharmony_ci int ret; 9662306a36Sopenharmony_ci unsigned int val; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci if (strcmp(buf, "default") == 0) { 9962306a36Sopenharmony_ci val = xfs_errortag_random_default[xfs_attr->tag]; 10062306a36Sopenharmony_ci } else { 10162306a36Sopenharmony_ci ret = kstrtouint(buf, 0, &val); 10262306a36Sopenharmony_ci if (ret) 10362306a36Sopenharmony_ci return ret; 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci ret = xfs_errortag_set(mp, xfs_attr->tag, val); 10762306a36Sopenharmony_ci if (ret) 10862306a36Sopenharmony_ci return ret; 10962306a36Sopenharmony_ci return count; 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ciSTATIC ssize_t 11362306a36Sopenharmony_cixfs_errortag_attr_show( 11462306a36Sopenharmony_ci struct kobject *kobject, 11562306a36Sopenharmony_ci struct attribute *attr, 11662306a36Sopenharmony_ci char *buf) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci struct xfs_mount *mp = to_mp(kobject); 11962306a36Sopenharmony_ci struct xfs_errortag_attr *xfs_attr = to_attr(attr); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci return snprintf(buf, PAGE_SIZE, "%u\n", 12262306a36Sopenharmony_ci xfs_errortag_get(mp, xfs_attr->tag)); 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic const struct sysfs_ops xfs_errortag_sysfs_ops = { 12662306a36Sopenharmony_ci .show = xfs_errortag_attr_show, 12762306a36Sopenharmony_ci .store = xfs_errortag_attr_store, 12862306a36Sopenharmony_ci}; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci#define XFS_ERRORTAG_ATTR_RW(_name, _tag) \ 13162306a36Sopenharmony_cistatic struct xfs_errortag_attr xfs_errortag_attr_##_name = { \ 13262306a36Sopenharmony_ci .attr = {.name = __stringify(_name), \ 13362306a36Sopenharmony_ci .mode = VERIFY_OCTAL_PERMISSIONS(S_IWUSR | S_IRUGO) }, \ 13462306a36Sopenharmony_ci .tag = (_tag), \ 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci#define XFS_ERRORTAG_ATTR_LIST(_name) &xfs_errortag_attr_##_name.attr 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(noerror, XFS_ERRTAG_NOERROR); 14062306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(iflush1, XFS_ERRTAG_IFLUSH_1); 14162306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(iflush2, XFS_ERRTAG_IFLUSH_2); 14262306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(iflush3, XFS_ERRTAG_IFLUSH_3); 14362306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(iflush4, XFS_ERRTAG_IFLUSH_4); 14462306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(iflush5, XFS_ERRTAG_IFLUSH_5); 14562306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(iflush6, XFS_ERRTAG_IFLUSH_6); 14662306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(dareadbuf, XFS_ERRTAG_DA_READ_BUF); 14762306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(btree_chk_lblk, XFS_ERRTAG_BTREE_CHECK_LBLOCK); 14862306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(btree_chk_sblk, XFS_ERRTAG_BTREE_CHECK_SBLOCK); 14962306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(readagf, XFS_ERRTAG_ALLOC_READ_AGF); 15062306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(readagi, XFS_ERRTAG_IALLOC_READ_AGI); 15162306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(itobp, XFS_ERRTAG_ITOBP_INOTOBP); 15262306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(iunlink, XFS_ERRTAG_IUNLINK); 15362306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(iunlinkrm, XFS_ERRTAG_IUNLINK_REMOVE); 15462306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(dirinovalid, XFS_ERRTAG_DIR_INO_VALIDATE); 15562306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(bulkstat, XFS_ERRTAG_BULKSTAT_READ_CHUNK); 15662306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(logiodone, XFS_ERRTAG_IODONE_IOERR); 15762306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(stratread, XFS_ERRTAG_STRATREAD_IOERR); 15862306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(stratcmpl, XFS_ERRTAG_STRATCMPL_IOERR); 15962306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(diowrite, XFS_ERRTAG_DIOWRITE_IOERR); 16062306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(bmapifmt, XFS_ERRTAG_BMAPIFORMAT); 16162306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(free_extent, XFS_ERRTAG_FREE_EXTENT); 16262306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(rmap_finish_one, XFS_ERRTAG_RMAP_FINISH_ONE); 16362306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(refcount_continue_update, XFS_ERRTAG_REFCOUNT_CONTINUE_UPDATE); 16462306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(refcount_finish_one, XFS_ERRTAG_REFCOUNT_FINISH_ONE); 16562306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(bmap_finish_one, XFS_ERRTAG_BMAP_FINISH_ONE); 16662306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(ag_resv_critical, XFS_ERRTAG_AG_RESV_CRITICAL); 16762306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(log_bad_crc, XFS_ERRTAG_LOG_BAD_CRC); 16862306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(log_item_pin, XFS_ERRTAG_LOG_ITEM_PIN); 16962306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(buf_lru_ref, XFS_ERRTAG_BUF_LRU_REF); 17062306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(force_repair, XFS_ERRTAG_FORCE_SCRUB_REPAIR); 17162306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(bad_summary, XFS_ERRTAG_FORCE_SUMMARY_RECALC); 17262306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(iunlink_fallback, XFS_ERRTAG_IUNLINK_FALLBACK); 17362306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(buf_ioerror, XFS_ERRTAG_BUF_IOERROR); 17462306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(reduce_max_iextents, XFS_ERRTAG_REDUCE_MAX_IEXTENTS); 17562306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(bmap_alloc_minlen_extent, XFS_ERRTAG_BMAP_ALLOC_MINLEN_EXTENT); 17662306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(ag_resv_fail, XFS_ERRTAG_AG_RESV_FAIL); 17762306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(larp, XFS_ERRTAG_LARP); 17862306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(da_leaf_split, XFS_ERRTAG_DA_LEAF_SPLIT); 17962306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(attr_leaf_to_node, XFS_ERRTAG_ATTR_LEAF_TO_NODE); 18062306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(wb_delay_ms, XFS_ERRTAG_WB_DELAY_MS); 18162306a36Sopenharmony_ciXFS_ERRORTAG_ATTR_RW(write_delay_ms, XFS_ERRTAG_WRITE_DELAY_MS); 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic struct attribute *xfs_errortag_attrs[] = { 18462306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(noerror), 18562306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(iflush1), 18662306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(iflush2), 18762306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(iflush3), 18862306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(iflush4), 18962306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(iflush5), 19062306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(iflush6), 19162306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(dareadbuf), 19262306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(btree_chk_lblk), 19362306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(btree_chk_sblk), 19462306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(readagf), 19562306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(readagi), 19662306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(itobp), 19762306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(iunlink), 19862306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(iunlinkrm), 19962306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(dirinovalid), 20062306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(bulkstat), 20162306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(logiodone), 20262306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(stratread), 20362306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(stratcmpl), 20462306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(diowrite), 20562306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(bmapifmt), 20662306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(free_extent), 20762306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(rmap_finish_one), 20862306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(refcount_continue_update), 20962306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(refcount_finish_one), 21062306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(bmap_finish_one), 21162306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(ag_resv_critical), 21262306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(log_bad_crc), 21362306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(log_item_pin), 21462306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(buf_lru_ref), 21562306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(force_repair), 21662306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(bad_summary), 21762306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(iunlink_fallback), 21862306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(buf_ioerror), 21962306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(reduce_max_iextents), 22062306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(bmap_alloc_minlen_extent), 22162306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(ag_resv_fail), 22262306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(larp), 22362306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(da_leaf_split), 22462306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(attr_leaf_to_node), 22562306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(wb_delay_ms), 22662306a36Sopenharmony_ci XFS_ERRORTAG_ATTR_LIST(write_delay_ms), 22762306a36Sopenharmony_ci NULL, 22862306a36Sopenharmony_ci}; 22962306a36Sopenharmony_ciATTRIBUTE_GROUPS(xfs_errortag); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic const struct kobj_type xfs_errortag_ktype = { 23262306a36Sopenharmony_ci .release = xfs_sysfs_release, 23362306a36Sopenharmony_ci .sysfs_ops = &xfs_errortag_sysfs_ops, 23462306a36Sopenharmony_ci .default_groups = xfs_errortag_groups, 23562306a36Sopenharmony_ci}; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ciint 23862306a36Sopenharmony_cixfs_errortag_init( 23962306a36Sopenharmony_ci struct xfs_mount *mp) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci int ret; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci mp->m_errortag = kmem_zalloc(sizeof(unsigned int) * XFS_ERRTAG_MAX, 24462306a36Sopenharmony_ci KM_MAYFAIL); 24562306a36Sopenharmony_ci if (!mp->m_errortag) 24662306a36Sopenharmony_ci return -ENOMEM; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci ret = xfs_sysfs_init(&mp->m_errortag_kobj, &xfs_errortag_ktype, 24962306a36Sopenharmony_ci &mp->m_kobj, "errortag"); 25062306a36Sopenharmony_ci if (ret) 25162306a36Sopenharmony_ci kmem_free(mp->m_errortag); 25262306a36Sopenharmony_ci return ret; 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_civoid 25662306a36Sopenharmony_cixfs_errortag_del( 25762306a36Sopenharmony_ci struct xfs_mount *mp) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci xfs_sysfs_del(&mp->m_errortag_kobj); 26062306a36Sopenharmony_ci kmem_free(mp->m_errortag); 26162306a36Sopenharmony_ci} 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_cistatic bool 26462306a36Sopenharmony_cixfs_errortag_valid( 26562306a36Sopenharmony_ci unsigned int error_tag) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci if (error_tag >= XFS_ERRTAG_MAX) 26862306a36Sopenharmony_ci return false; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci /* Error out removed injection types */ 27162306a36Sopenharmony_ci if (error_tag == XFS_ERRTAG_DROP_WRITES) 27262306a36Sopenharmony_ci return false; 27362306a36Sopenharmony_ci return true; 27462306a36Sopenharmony_ci} 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_cibool 27762306a36Sopenharmony_cixfs_errortag_enabled( 27862306a36Sopenharmony_ci struct xfs_mount *mp, 27962306a36Sopenharmony_ci unsigned int tag) 28062306a36Sopenharmony_ci{ 28162306a36Sopenharmony_ci if (!mp->m_errortag) 28262306a36Sopenharmony_ci return false; 28362306a36Sopenharmony_ci if (!xfs_errortag_valid(tag)) 28462306a36Sopenharmony_ci return false; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci return mp->m_errortag[tag] != 0; 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cibool 29062306a36Sopenharmony_cixfs_errortag_test( 29162306a36Sopenharmony_ci struct xfs_mount *mp, 29262306a36Sopenharmony_ci const char *expression, 29362306a36Sopenharmony_ci const char *file, 29462306a36Sopenharmony_ci int line, 29562306a36Sopenharmony_ci unsigned int error_tag) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci unsigned int randfactor; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci /* 30062306a36Sopenharmony_ci * To be able to use error injection anywhere, we need to ensure error 30162306a36Sopenharmony_ci * injection mechanism is already initialized. 30262306a36Sopenharmony_ci * 30362306a36Sopenharmony_ci * Code paths like I/O completion can be called before the 30462306a36Sopenharmony_ci * initialization is complete, but be able to inject errors in such 30562306a36Sopenharmony_ci * places is still useful. 30662306a36Sopenharmony_ci */ 30762306a36Sopenharmony_ci if (!mp->m_errortag) 30862306a36Sopenharmony_ci return false; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci if (!xfs_errortag_valid(error_tag)) 31162306a36Sopenharmony_ci return false; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci randfactor = mp->m_errortag[error_tag]; 31462306a36Sopenharmony_ci if (!randfactor || get_random_u32_below(randfactor)) 31562306a36Sopenharmony_ci return false; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci xfs_warn_ratelimited(mp, 31862306a36Sopenharmony_ci"Injecting error (%s) at file %s, line %d, on filesystem \"%s\"", 31962306a36Sopenharmony_ci expression, file, line, mp->m_super->s_id); 32062306a36Sopenharmony_ci return true; 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ciint 32462306a36Sopenharmony_cixfs_errortag_get( 32562306a36Sopenharmony_ci struct xfs_mount *mp, 32662306a36Sopenharmony_ci unsigned int error_tag) 32762306a36Sopenharmony_ci{ 32862306a36Sopenharmony_ci if (!xfs_errortag_valid(error_tag)) 32962306a36Sopenharmony_ci return -EINVAL; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci return mp->m_errortag[error_tag]; 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ciint 33562306a36Sopenharmony_cixfs_errortag_set( 33662306a36Sopenharmony_ci struct xfs_mount *mp, 33762306a36Sopenharmony_ci unsigned int error_tag, 33862306a36Sopenharmony_ci unsigned int tag_value) 33962306a36Sopenharmony_ci{ 34062306a36Sopenharmony_ci if (!xfs_errortag_valid(error_tag)) 34162306a36Sopenharmony_ci return -EINVAL; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci mp->m_errortag[error_tag] = tag_value; 34462306a36Sopenharmony_ci return 0; 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ciint 34862306a36Sopenharmony_cixfs_errortag_add( 34962306a36Sopenharmony_ci struct xfs_mount *mp, 35062306a36Sopenharmony_ci unsigned int error_tag) 35162306a36Sopenharmony_ci{ 35262306a36Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(xfs_errortag_random_default) != XFS_ERRTAG_MAX); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci if (!xfs_errortag_valid(error_tag)) 35562306a36Sopenharmony_ci return -EINVAL; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci return xfs_errortag_set(mp, error_tag, 35862306a36Sopenharmony_ci xfs_errortag_random_default[error_tag]); 35962306a36Sopenharmony_ci} 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ciint 36262306a36Sopenharmony_cixfs_errortag_clearall( 36362306a36Sopenharmony_ci struct xfs_mount *mp) 36462306a36Sopenharmony_ci{ 36562306a36Sopenharmony_ci memset(mp->m_errortag, 0, sizeof(unsigned int) * XFS_ERRTAG_MAX); 36662306a36Sopenharmony_ci return 0; 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci#endif /* DEBUG */ 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_civoid 37162306a36Sopenharmony_cixfs_error_report( 37262306a36Sopenharmony_ci const char *tag, 37362306a36Sopenharmony_ci int level, 37462306a36Sopenharmony_ci struct xfs_mount *mp, 37562306a36Sopenharmony_ci const char *filename, 37662306a36Sopenharmony_ci int linenum, 37762306a36Sopenharmony_ci xfs_failaddr_t failaddr) 37862306a36Sopenharmony_ci{ 37962306a36Sopenharmony_ci if (level <= xfs_error_level) { 38062306a36Sopenharmony_ci xfs_alert_tag(mp, XFS_PTAG_ERROR_REPORT, 38162306a36Sopenharmony_ci "Internal error %s at line %d of file %s. Caller %pS", 38262306a36Sopenharmony_ci tag, linenum, filename, failaddr); 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci xfs_stack_trace(); 38562306a36Sopenharmony_ci } 38662306a36Sopenharmony_ci} 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_civoid 38962306a36Sopenharmony_cixfs_corruption_error( 39062306a36Sopenharmony_ci const char *tag, 39162306a36Sopenharmony_ci int level, 39262306a36Sopenharmony_ci struct xfs_mount *mp, 39362306a36Sopenharmony_ci const void *buf, 39462306a36Sopenharmony_ci size_t bufsize, 39562306a36Sopenharmony_ci const char *filename, 39662306a36Sopenharmony_ci int linenum, 39762306a36Sopenharmony_ci xfs_failaddr_t failaddr) 39862306a36Sopenharmony_ci{ 39962306a36Sopenharmony_ci if (buf && level <= xfs_error_level) 40062306a36Sopenharmony_ci xfs_hex_dump(buf, bufsize); 40162306a36Sopenharmony_ci xfs_error_report(tag, level, mp, filename, linenum, failaddr); 40262306a36Sopenharmony_ci xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair"); 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci/* 40662306a36Sopenharmony_ci * Complain about the kinds of metadata corruption that we can't detect from a 40762306a36Sopenharmony_ci * verifier, such as incorrect inter-block relationship data. Does not set 40862306a36Sopenharmony_ci * bp->b_error. 40962306a36Sopenharmony_ci * 41062306a36Sopenharmony_ci * Call xfs_buf_mark_corrupt, not this function. 41162306a36Sopenharmony_ci */ 41262306a36Sopenharmony_civoid 41362306a36Sopenharmony_cixfs_buf_corruption_error( 41462306a36Sopenharmony_ci struct xfs_buf *bp, 41562306a36Sopenharmony_ci xfs_failaddr_t fa) 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci struct xfs_mount *mp = bp->b_mount; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci xfs_alert_tag(mp, XFS_PTAG_VERIFIER_ERROR, 42062306a36Sopenharmony_ci "Metadata corruption detected at %pS, %s block 0x%llx", 42162306a36Sopenharmony_ci fa, bp->b_ops->name, xfs_buf_daddr(bp)); 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci xfs_alert(mp, "Unmount and run xfs_repair"); 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci if (xfs_error_level >= XFS_ERRLEVEL_HIGH) 42662306a36Sopenharmony_ci xfs_stack_trace(); 42762306a36Sopenharmony_ci} 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci/* 43062306a36Sopenharmony_ci * Warnings specifically for verifier errors. Differentiate CRC vs. invalid 43162306a36Sopenharmony_ci * values, and omit the stack trace unless the error level is tuned high. 43262306a36Sopenharmony_ci */ 43362306a36Sopenharmony_civoid 43462306a36Sopenharmony_cixfs_buf_verifier_error( 43562306a36Sopenharmony_ci struct xfs_buf *bp, 43662306a36Sopenharmony_ci int error, 43762306a36Sopenharmony_ci const char *name, 43862306a36Sopenharmony_ci const void *buf, 43962306a36Sopenharmony_ci size_t bufsz, 44062306a36Sopenharmony_ci xfs_failaddr_t failaddr) 44162306a36Sopenharmony_ci{ 44262306a36Sopenharmony_ci struct xfs_mount *mp = bp->b_mount; 44362306a36Sopenharmony_ci xfs_failaddr_t fa; 44462306a36Sopenharmony_ci int sz; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci fa = failaddr ? failaddr : __return_address; 44762306a36Sopenharmony_ci __xfs_buf_ioerror(bp, error, fa); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci xfs_alert_tag(mp, XFS_PTAG_VERIFIER_ERROR, 45062306a36Sopenharmony_ci "Metadata %s detected at %pS, %s block 0x%llx %s", 45162306a36Sopenharmony_ci bp->b_error == -EFSBADCRC ? "CRC error" : "corruption", 45262306a36Sopenharmony_ci fa, bp->b_ops->name, xfs_buf_daddr(bp), name); 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci xfs_alert(mp, "Unmount and run xfs_repair"); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci if (xfs_error_level >= XFS_ERRLEVEL_LOW) { 45762306a36Sopenharmony_ci sz = min_t(size_t, XFS_CORRUPTION_DUMP_LEN, bufsz); 45862306a36Sopenharmony_ci xfs_alert(mp, "First %d bytes of corrupted metadata buffer:", 45962306a36Sopenharmony_ci sz); 46062306a36Sopenharmony_ci xfs_hex_dump(buf, sz); 46162306a36Sopenharmony_ci } 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci if (xfs_error_level >= XFS_ERRLEVEL_HIGH) 46462306a36Sopenharmony_ci xfs_stack_trace(); 46562306a36Sopenharmony_ci} 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci/* 46862306a36Sopenharmony_ci * Warnings specifically for verifier errors. Differentiate CRC vs. invalid 46962306a36Sopenharmony_ci * values, and omit the stack trace unless the error level is tuned high. 47062306a36Sopenharmony_ci */ 47162306a36Sopenharmony_civoid 47262306a36Sopenharmony_cixfs_verifier_error( 47362306a36Sopenharmony_ci struct xfs_buf *bp, 47462306a36Sopenharmony_ci int error, 47562306a36Sopenharmony_ci xfs_failaddr_t failaddr) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci return xfs_buf_verifier_error(bp, error, "", xfs_buf_offset(bp, 0), 47862306a36Sopenharmony_ci XFS_CORRUPTION_DUMP_LEN, failaddr); 47962306a36Sopenharmony_ci} 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci/* 48262306a36Sopenharmony_ci * Warnings for inode corruption problems. Don't bother with the stack 48362306a36Sopenharmony_ci * trace unless the error level is turned up high. 48462306a36Sopenharmony_ci */ 48562306a36Sopenharmony_civoid 48662306a36Sopenharmony_cixfs_inode_verifier_error( 48762306a36Sopenharmony_ci struct xfs_inode *ip, 48862306a36Sopenharmony_ci int error, 48962306a36Sopenharmony_ci const char *name, 49062306a36Sopenharmony_ci const void *buf, 49162306a36Sopenharmony_ci size_t bufsz, 49262306a36Sopenharmony_ci xfs_failaddr_t failaddr) 49362306a36Sopenharmony_ci{ 49462306a36Sopenharmony_ci struct xfs_mount *mp = ip->i_mount; 49562306a36Sopenharmony_ci xfs_failaddr_t fa; 49662306a36Sopenharmony_ci int sz; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci fa = failaddr ? failaddr : __return_address; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci xfs_alert(mp, "Metadata %s detected at %pS, inode 0x%llx %s", 50162306a36Sopenharmony_ci error == -EFSBADCRC ? "CRC error" : "corruption", 50262306a36Sopenharmony_ci fa, ip->i_ino, name); 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci xfs_alert(mp, "Unmount and run xfs_repair"); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci if (buf && xfs_error_level >= XFS_ERRLEVEL_LOW) { 50762306a36Sopenharmony_ci sz = min_t(size_t, XFS_CORRUPTION_DUMP_LEN, bufsz); 50862306a36Sopenharmony_ci xfs_alert(mp, "First %d bytes of corrupted metadata buffer:", 50962306a36Sopenharmony_ci sz); 51062306a36Sopenharmony_ci xfs_hex_dump(buf, sz); 51162306a36Sopenharmony_ci } 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci if (xfs_error_level >= XFS_ERRLEVEL_HIGH) 51462306a36Sopenharmony_ci xfs_stack_trace(); 51562306a36Sopenharmony_ci} 516