162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2000-2006 Silicon Graphics, Inc. 462306a36Sopenharmony_ci * Copyright (c) 2013 Red Hat, Inc. 562306a36Sopenharmony_ci * All Rights Reserved. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#include "xfs.h" 862306a36Sopenharmony_ci#include "xfs_fs.h" 962306a36Sopenharmony_ci#include "xfs_shared.h" 1062306a36Sopenharmony_ci#include "xfs_format.h" 1162306a36Sopenharmony_ci#include "xfs_log_format.h" 1262306a36Sopenharmony_ci#include "xfs_trans_resv.h" 1362306a36Sopenharmony_ci#include "xfs_mount.h" 1462306a36Sopenharmony_ci#include "xfs_inode.h" 1562306a36Sopenharmony_ci#include "xfs_quota.h" 1662306a36Sopenharmony_ci#include "xfs_trans.h" 1762306a36Sopenharmony_ci#include "xfs_qm.h" 1862306a36Sopenharmony_ci#include "xfs_error.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ciint 2162306a36Sopenharmony_cixfs_calc_dquots_per_chunk( 2262306a36Sopenharmony_ci unsigned int nbblks) /* basic block units */ 2362306a36Sopenharmony_ci{ 2462306a36Sopenharmony_ci ASSERT(nbblks > 0); 2562306a36Sopenharmony_ci return BBTOB(nbblks) / sizeof(struct xfs_dqblk); 2662306a36Sopenharmony_ci} 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci/* 2962306a36Sopenharmony_ci * Do some primitive error checking on ondisk dquot data structures. 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * The xfs_dqblk structure /contains/ the xfs_disk_dquot structure; 3262306a36Sopenharmony_ci * we verify them separately because at some points we have only the 3362306a36Sopenharmony_ci * smaller xfs_disk_dquot structure available. 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cixfs_failaddr_t 3762306a36Sopenharmony_cixfs_dquot_verify( 3862306a36Sopenharmony_ci struct xfs_mount *mp, 3962306a36Sopenharmony_ci struct xfs_disk_dquot *ddq, 4062306a36Sopenharmony_ci xfs_dqid_t id) /* used only during quotacheck */ 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci __u8 ddq_type; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci /* 4562306a36Sopenharmony_ci * We can encounter an uninitialized dquot buffer for 2 reasons: 4662306a36Sopenharmony_ci * 1. If we crash while deleting the quotainode(s), and those blks got 4762306a36Sopenharmony_ci * used for user data. This is because we take the path of regular 4862306a36Sopenharmony_ci * file deletion; however, the size field of quotainodes is never 4962306a36Sopenharmony_ci * updated, so all the tricks that we play in itruncate_finish 5062306a36Sopenharmony_ci * don't quite matter. 5162306a36Sopenharmony_ci * 5262306a36Sopenharmony_ci * 2. We don't play the quota buffers when there's a quotaoff logitem. 5362306a36Sopenharmony_ci * But the allocation will be replayed so we'll end up with an 5462306a36Sopenharmony_ci * uninitialized quota block. 5562306a36Sopenharmony_ci * 5662306a36Sopenharmony_ci * This is all fine; things are still consistent, and we haven't lost 5762306a36Sopenharmony_ci * any quota information. Just don't complain about bad dquot blks. 5862306a36Sopenharmony_ci */ 5962306a36Sopenharmony_ci if (ddq->d_magic != cpu_to_be16(XFS_DQUOT_MAGIC)) 6062306a36Sopenharmony_ci return __this_address; 6162306a36Sopenharmony_ci if (ddq->d_version != XFS_DQUOT_VERSION) 6262306a36Sopenharmony_ci return __this_address; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci if (ddq->d_type & ~XFS_DQTYPE_ANY) 6562306a36Sopenharmony_ci return __this_address; 6662306a36Sopenharmony_ci ddq_type = ddq->d_type & XFS_DQTYPE_REC_MASK; 6762306a36Sopenharmony_ci if (ddq_type != XFS_DQTYPE_USER && 6862306a36Sopenharmony_ci ddq_type != XFS_DQTYPE_PROJ && 6962306a36Sopenharmony_ci ddq_type != XFS_DQTYPE_GROUP) 7062306a36Sopenharmony_ci return __this_address; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci if ((ddq->d_type & XFS_DQTYPE_BIGTIME) && 7362306a36Sopenharmony_ci !xfs_has_bigtime(mp)) 7462306a36Sopenharmony_ci return __this_address; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci if ((ddq->d_type & XFS_DQTYPE_BIGTIME) && !ddq->d_id) 7762306a36Sopenharmony_ci return __this_address; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (id != -1 && id != be32_to_cpu(ddq->d_id)) 8062306a36Sopenharmony_ci return __this_address; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci if (!ddq->d_id) 8362306a36Sopenharmony_ci return NULL; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci if (ddq->d_blk_softlimit && 8662306a36Sopenharmony_ci be64_to_cpu(ddq->d_bcount) > be64_to_cpu(ddq->d_blk_softlimit) && 8762306a36Sopenharmony_ci !ddq->d_btimer) 8862306a36Sopenharmony_ci return __this_address; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci if (ddq->d_ino_softlimit && 9162306a36Sopenharmony_ci be64_to_cpu(ddq->d_icount) > be64_to_cpu(ddq->d_ino_softlimit) && 9262306a36Sopenharmony_ci !ddq->d_itimer) 9362306a36Sopenharmony_ci return __this_address; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci if (ddq->d_rtb_softlimit && 9662306a36Sopenharmony_ci be64_to_cpu(ddq->d_rtbcount) > be64_to_cpu(ddq->d_rtb_softlimit) && 9762306a36Sopenharmony_ci !ddq->d_rtbtimer) 9862306a36Sopenharmony_ci return __this_address; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci return NULL; 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cixfs_failaddr_t 10462306a36Sopenharmony_cixfs_dqblk_verify( 10562306a36Sopenharmony_ci struct xfs_mount *mp, 10662306a36Sopenharmony_ci struct xfs_dqblk *dqb, 10762306a36Sopenharmony_ci xfs_dqid_t id) /* used only during quotacheck */ 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci if (xfs_has_crc(mp) && 11062306a36Sopenharmony_ci !uuid_equal(&dqb->dd_uuid, &mp->m_sb.sb_meta_uuid)) 11162306a36Sopenharmony_ci return __this_address; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci return xfs_dquot_verify(mp, &dqb->dd_diskdq, id); 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci/* 11762306a36Sopenharmony_ci * Do some primitive error checking on ondisk dquot data structures. 11862306a36Sopenharmony_ci */ 11962306a36Sopenharmony_civoid 12062306a36Sopenharmony_cixfs_dqblk_repair( 12162306a36Sopenharmony_ci struct xfs_mount *mp, 12262306a36Sopenharmony_ci struct xfs_dqblk *dqb, 12362306a36Sopenharmony_ci xfs_dqid_t id, 12462306a36Sopenharmony_ci xfs_dqtype_t type) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci /* 12762306a36Sopenharmony_ci * Typically, a repair is only requested by quotacheck. 12862306a36Sopenharmony_ci */ 12962306a36Sopenharmony_ci ASSERT(id != -1); 13062306a36Sopenharmony_ci memset(dqb, 0, sizeof(struct xfs_dqblk)); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci dqb->dd_diskdq.d_magic = cpu_to_be16(XFS_DQUOT_MAGIC); 13362306a36Sopenharmony_ci dqb->dd_diskdq.d_version = XFS_DQUOT_VERSION; 13462306a36Sopenharmony_ci dqb->dd_diskdq.d_type = type; 13562306a36Sopenharmony_ci dqb->dd_diskdq.d_id = cpu_to_be32(id); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci if (xfs_has_crc(mp)) { 13862306a36Sopenharmony_ci uuid_copy(&dqb->dd_uuid, &mp->m_sb.sb_meta_uuid); 13962306a36Sopenharmony_ci xfs_update_cksum((char *)dqb, sizeof(struct xfs_dqblk), 14062306a36Sopenharmony_ci XFS_DQUOT_CRC_OFF); 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ciSTATIC bool 14562306a36Sopenharmony_cixfs_dquot_buf_verify_crc( 14662306a36Sopenharmony_ci struct xfs_mount *mp, 14762306a36Sopenharmony_ci struct xfs_buf *bp, 14862306a36Sopenharmony_ci bool readahead) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr; 15162306a36Sopenharmony_ci int ndquots; 15262306a36Sopenharmony_ci int i; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci if (!xfs_has_crc(mp)) 15562306a36Sopenharmony_ci return true; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci /* 15862306a36Sopenharmony_ci * if we are in log recovery, the quota subsystem has not been 15962306a36Sopenharmony_ci * initialised so we have no quotainfo structure. In that case, we need 16062306a36Sopenharmony_ci * to manually calculate the number of dquots in the buffer. 16162306a36Sopenharmony_ci */ 16262306a36Sopenharmony_ci if (mp->m_quotainfo) 16362306a36Sopenharmony_ci ndquots = mp->m_quotainfo->qi_dqperchunk; 16462306a36Sopenharmony_ci else 16562306a36Sopenharmony_ci ndquots = xfs_calc_dquots_per_chunk(bp->b_length); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci for (i = 0; i < ndquots; i++, d++) { 16862306a36Sopenharmony_ci if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk), 16962306a36Sopenharmony_ci XFS_DQUOT_CRC_OFF)) { 17062306a36Sopenharmony_ci if (!readahead) 17162306a36Sopenharmony_ci xfs_buf_verifier_error(bp, -EFSBADCRC, __func__, 17262306a36Sopenharmony_ci d, sizeof(*d), __this_address); 17362306a36Sopenharmony_ci return false; 17462306a36Sopenharmony_ci } 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci return true; 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ciSTATIC xfs_failaddr_t 18062306a36Sopenharmony_cixfs_dquot_buf_verify( 18162306a36Sopenharmony_ci struct xfs_mount *mp, 18262306a36Sopenharmony_ci struct xfs_buf *bp, 18362306a36Sopenharmony_ci bool readahead) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci struct xfs_dqblk *dqb = bp->b_addr; 18662306a36Sopenharmony_ci xfs_failaddr_t fa; 18762306a36Sopenharmony_ci xfs_dqid_t id = 0; 18862306a36Sopenharmony_ci int ndquots; 18962306a36Sopenharmony_ci int i; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci /* 19262306a36Sopenharmony_ci * if we are in log recovery, the quota subsystem has not been 19362306a36Sopenharmony_ci * initialised so we have no quotainfo structure. In that case, we need 19462306a36Sopenharmony_ci * to manually calculate the number of dquots in the buffer. 19562306a36Sopenharmony_ci */ 19662306a36Sopenharmony_ci if (mp->m_quotainfo) 19762306a36Sopenharmony_ci ndquots = mp->m_quotainfo->qi_dqperchunk; 19862306a36Sopenharmony_ci else 19962306a36Sopenharmony_ci ndquots = xfs_calc_dquots_per_chunk(bp->b_length); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci /* 20262306a36Sopenharmony_ci * On the first read of the buffer, verify that each dquot is valid. 20362306a36Sopenharmony_ci * We don't know what the id of the dquot is supposed to be, just that 20462306a36Sopenharmony_ci * they should be increasing monotonically within the buffer. If the 20562306a36Sopenharmony_ci * first id is corrupt, then it will fail on the second dquot in the 20662306a36Sopenharmony_ci * buffer so corruptions could point to the wrong dquot in this case. 20762306a36Sopenharmony_ci */ 20862306a36Sopenharmony_ci for (i = 0; i < ndquots; i++) { 20962306a36Sopenharmony_ci struct xfs_disk_dquot *ddq; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci ddq = &dqb[i].dd_diskdq; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci if (i == 0) 21462306a36Sopenharmony_ci id = be32_to_cpu(ddq->d_id); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci fa = xfs_dqblk_verify(mp, &dqb[i], id + i); 21762306a36Sopenharmony_ci if (fa) { 21862306a36Sopenharmony_ci if (!readahead) 21962306a36Sopenharmony_ci xfs_buf_verifier_error(bp, -EFSCORRUPTED, 22062306a36Sopenharmony_ci __func__, &dqb[i], 22162306a36Sopenharmony_ci sizeof(struct xfs_dqblk), fa); 22262306a36Sopenharmony_ci return fa; 22362306a36Sopenharmony_ci } 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci return NULL; 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_cistatic xfs_failaddr_t 23062306a36Sopenharmony_cixfs_dquot_buf_verify_struct( 23162306a36Sopenharmony_ci struct xfs_buf *bp) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci struct xfs_mount *mp = bp->b_mount; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci return xfs_dquot_buf_verify(mp, bp, false); 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistatic void 23962306a36Sopenharmony_cixfs_dquot_buf_read_verify( 24062306a36Sopenharmony_ci struct xfs_buf *bp) 24162306a36Sopenharmony_ci{ 24262306a36Sopenharmony_ci struct xfs_mount *mp = bp->b_mount; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci if (!xfs_dquot_buf_verify_crc(mp, bp, false)) 24562306a36Sopenharmony_ci return; 24662306a36Sopenharmony_ci xfs_dquot_buf_verify(mp, bp, false); 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci/* 25062306a36Sopenharmony_ci * readahead errors are silent and simply leave the buffer as !done so a real 25162306a36Sopenharmony_ci * read will then be run with the xfs_dquot_buf_ops verifier. See 25262306a36Sopenharmony_ci * xfs_inode_buf_verify() for why we use EIO and ~XBF_DONE here rather than 25362306a36Sopenharmony_ci * reporting the failure. 25462306a36Sopenharmony_ci */ 25562306a36Sopenharmony_cistatic void 25662306a36Sopenharmony_cixfs_dquot_buf_readahead_verify( 25762306a36Sopenharmony_ci struct xfs_buf *bp) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci struct xfs_mount *mp = bp->b_mount; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci if (!xfs_dquot_buf_verify_crc(mp, bp, true) || 26262306a36Sopenharmony_ci xfs_dquot_buf_verify(mp, bp, true) != NULL) { 26362306a36Sopenharmony_ci xfs_buf_ioerror(bp, -EIO); 26462306a36Sopenharmony_ci bp->b_flags &= ~XBF_DONE; 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci} 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci/* 26962306a36Sopenharmony_ci * we don't calculate the CRC here as that is done when the dquot is flushed to 27062306a36Sopenharmony_ci * the buffer after the update is done. This ensures that the dquot in the 27162306a36Sopenharmony_ci * buffer always has an up-to-date CRC value. 27262306a36Sopenharmony_ci */ 27362306a36Sopenharmony_cistatic void 27462306a36Sopenharmony_cixfs_dquot_buf_write_verify( 27562306a36Sopenharmony_ci struct xfs_buf *bp) 27662306a36Sopenharmony_ci{ 27762306a36Sopenharmony_ci struct xfs_mount *mp = bp->b_mount; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci xfs_dquot_buf_verify(mp, bp, false); 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ciconst struct xfs_buf_ops xfs_dquot_buf_ops = { 28362306a36Sopenharmony_ci .name = "xfs_dquot", 28462306a36Sopenharmony_ci .magic16 = { cpu_to_be16(XFS_DQUOT_MAGIC), 28562306a36Sopenharmony_ci cpu_to_be16(XFS_DQUOT_MAGIC) }, 28662306a36Sopenharmony_ci .verify_read = xfs_dquot_buf_read_verify, 28762306a36Sopenharmony_ci .verify_write = xfs_dquot_buf_write_verify, 28862306a36Sopenharmony_ci .verify_struct = xfs_dquot_buf_verify_struct, 28962306a36Sopenharmony_ci}; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ciconst struct xfs_buf_ops xfs_dquot_buf_ra_ops = { 29262306a36Sopenharmony_ci .name = "xfs_dquot_ra", 29362306a36Sopenharmony_ci .magic16 = { cpu_to_be16(XFS_DQUOT_MAGIC), 29462306a36Sopenharmony_ci cpu_to_be16(XFS_DQUOT_MAGIC) }, 29562306a36Sopenharmony_ci .verify_read = xfs_dquot_buf_readahead_verify, 29662306a36Sopenharmony_ci .verify_write = xfs_dquot_buf_write_verify, 29762306a36Sopenharmony_ci}; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci/* Convert an on-disk timer value into an incore timer value. */ 30062306a36Sopenharmony_citime64_t 30162306a36Sopenharmony_cixfs_dquot_from_disk_ts( 30262306a36Sopenharmony_ci struct xfs_disk_dquot *ddq, 30362306a36Sopenharmony_ci __be32 dtimer) 30462306a36Sopenharmony_ci{ 30562306a36Sopenharmony_ci uint32_t t = be32_to_cpu(dtimer); 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci if (t != 0 && (ddq->d_type & XFS_DQTYPE_BIGTIME)) 30862306a36Sopenharmony_ci return xfs_dq_bigtime_to_unix(t); 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci return t; 31162306a36Sopenharmony_ci} 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci/* Convert an incore timer value into an on-disk timer value. */ 31462306a36Sopenharmony_ci__be32 31562306a36Sopenharmony_cixfs_dquot_to_disk_ts( 31662306a36Sopenharmony_ci struct xfs_dquot *dqp, 31762306a36Sopenharmony_ci time64_t timer) 31862306a36Sopenharmony_ci{ 31962306a36Sopenharmony_ci uint32_t t = timer; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci if (timer != 0 && (dqp->q_type & XFS_DQTYPE_BIGTIME)) 32262306a36Sopenharmony_ci t = xfs_dq_unix_to_bigtime(timer); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci return cpu_to_be32(t); 32562306a36Sopenharmony_ci} 326