326 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2000-2006 Silicon Graphics, Inc.4 * Copyright (c) 2013 Red Hat, Inc.5 * All Rights Reserved.6 */7#include "xfs.h"8#include "xfs_fs.h"9#include "xfs_shared.h"10#include "xfs_format.h"11#include "xfs_log_format.h"12#include "xfs_trans_resv.h"13#include "xfs_mount.h"14#include "xfs_inode.h"15#include "xfs_quota.h"16#include "xfs_trans.h"17#include "xfs_qm.h"18#include "xfs_error.h"19 20int21xfs_calc_dquots_per_chunk(22 unsigned int nbblks) /* basic block units */23{24 ASSERT(nbblks > 0);25 return BBTOB(nbblks) / sizeof(struct xfs_dqblk);26}27 28/*29 * Do some primitive error checking on ondisk dquot data structures.30 *31 * The xfs_dqblk structure /contains/ the xfs_disk_dquot structure;32 * we verify them separately because at some points we have only the33 * smaller xfs_disk_dquot structure available.34 */35 36xfs_failaddr_t37xfs_dquot_verify(38 struct xfs_mount *mp,39 struct xfs_disk_dquot *ddq,40 xfs_dqid_t id) /* used only during quotacheck */41{42 __u8 ddq_type;43 44 /*45 * We can encounter an uninitialized dquot buffer for 2 reasons:46 * 1. If we crash while deleting the quotainode(s), and those blks got47 * used for user data. This is because we take the path of regular48 * file deletion; however, the size field of quotainodes is never49 * updated, so all the tricks that we play in itruncate_finish50 * don't quite matter.51 *52 * 2. We don't play the quota buffers when there's a quotaoff logitem.53 * But the allocation will be replayed so we'll end up with an54 * uninitialized quota block.55 *56 * This is all fine; things are still consistent, and we haven't lost57 * any quota information. Just don't complain about bad dquot blks.58 */59 if (ddq->d_magic != cpu_to_be16(XFS_DQUOT_MAGIC))60 return __this_address;61 if (ddq->d_version != XFS_DQUOT_VERSION)62 return __this_address;63 64 if (ddq->d_type & ~XFS_DQTYPE_ANY)65 return __this_address;66 ddq_type = ddq->d_type & XFS_DQTYPE_REC_MASK;67 if (ddq_type != XFS_DQTYPE_USER &&68 ddq_type != XFS_DQTYPE_PROJ &&69 ddq_type != XFS_DQTYPE_GROUP)70 return __this_address;71 72 if ((ddq->d_type & XFS_DQTYPE_BIGTIME) &&73 !xfs_has_bigtime(mp))74 return __this_address;75 76 if ((ddq->d_type & XFS_DQTYPE_BIGTIME) && !ddq->d_id)77 return __this_address;78 79 if (id != -1 && id != be32_to_cpu(ddq->d_id))80 return __this_address;81 82 if (!ddq->d_id)83 return NULL;84 85 if (ddq->d_blk_softlimit &&86 be64_to_cpu(ddq->d_bcount) > be64_to_cpu(ddq->d_blk_softlimit) &&87 !ddq->d_btimer)88 return __this_address;89 90 if (ddq->d_ino_softlimit &&91 be64_to_cpu(ddq->d_icount) > be64_to_cpu(ddq->d_ino_softlimit) &&92 !ddq->d_itimer)93 return __this_address;94 95 if (ddq->d_rtb_softlimit &&96 be64_to_cpu(ddq->d_rtbcount) > be64_to_cpu(ddq->d_rtb_softlimit) &&97 !ddq->d_rtbtimer)98 return __this_address;99 100 return NULL;101}102 103xfs_failaddr_t104xfs_dqblk_verify(105 struct xfs_mount *mp,106 struct xfs_dqblk *dqb,107 xfs_dqid_t id) /* used only during quotacheck */108{109 if (xfs_has_crc(mp) &&110 !uuid_equal(&dqb->dd_uuid, &mp->m_sb.sb_meta_uuid))111 return __this_address;112 113 return xfs_dquot_verify(mp, &dqb->dd_diskdq, id);114}115 116/*117 * Do some primitive error checking on ondisk dquot data structures.118 */119void120xfs_dqblk_repair(121 struct xfs_mount *mp,122 struct xfs_dqblk *dqb,123 xfs_dqid_t id,124 xfs_dqtype_t type)125{126 /*127 * Typically, a repair is only requested by quotacheck.128 */129 ASSERT(id != -1);130 memset(dqb, 0, sizeof(struct xfs_dqblk));131 132 dqb->dd_diskdq.d_magic = cpu_to_be16(XFS_DQUOT_MAGIC);133 dqb->dd_diskdq.d_version = XFS_DQUOT_VERSION;134 dqb->dd_diskdq.d_type = type;135 dqb->dd_diskdq.d_id = cpu_to_be32(id);136 137 if (xfs_has_crc(mp)) {138 uuid_copy(&dqb->dd_uuid, &mp->m_sb.sb_meta_uuid);139 xfs_update_cksum((char *)dqb, sizeof(struct xfs_dqblk),140 XFS_DQUOT_CRC_OFF);141 }142}143 144STATIC bool145xfs_dquot_buf_verify_crc(146 struct xfs_mount *mp,147 struct xfs_buf *bp,148 bool readahead)149{150 struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr;151 int ndquots;152 int i;153 154 if (!xfs_has_crc(mp))155 return true;156 157 /*158 * if we are in log recovery, the quota subsystem has not been159 * initialised so we have no quotainfo structure. In that case, we need160 * to manually calculate the number of dquots in the buffer.161 */162 if (mp->m_quotainfo)163 ndquots = mp->m_quotainfo->qi_dqperchunk;164 else165 ndquots = xfs_calc_dquots_per_chunk(bp->b_length);166 167 for (i = 0; i < ndquots; i++, d++) {168 if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),169 XFS_DQUOT_CRC_OFF)) {170 if (!readahead)171 xfs_buf_verifier_error(bp, -EFSBADCRC, __func__,172 d, sizeof(*d), __this_address);173 return false;174 }175 }176 return true;177}178 179STATIC xfs_failaddr_t180xfs_dquot_buf_verify(181 struct xfs_mount *mp,182 struct xfs_buf *bp,183 bool readahead)184{185 struct xfs_dqblk *dqb = bp->b_addr;186 xfs_failaddr_t fa;187 xfs_dqid_t id = 0;188 int ndquots;189 int i;190 191 /*192 * if we are in log recovery, the quota subsystem has not been193 * initialised so we have no quotainfo structure. In that case, we need194 * to manually calculate the number of dquots in the buffer.195 */196 if (mp->m_quotainfo)197 ndquots = mp->m_quotainfo->qi_dqperchunk;198 else199 ndquots = xfs_calc_dquots_per_chunk(bp->b_length);200 201 /*202 * On the first read of the buffer, verify that each dquot is valid.203 * We don't know what the id of the dquot is supposed to be, just that204 * they should be increasing monotonically within the buffer. If the205 * first id is corrupt, then it will fail on the second dquot in the206 * buffer so corruptions could point to the wrong dquot in this case.207 */208 for (i = 0; i < ndquots; i++) {209 struct xfs_disk_dquot *ddq;210 211 ddq = &dqb[i].dd_diskdq;212 213 if (i == 0)214 id = be32_to_cpu(ddq->d_id);215 216 fa = xfs_dqblk_verify(mp, &dqb[i], id + i);217 if (fa) {218 if (!readahead)219 xfs_buf_verifier_error(bp, -EFSCORRUPTED,220 __func__, &dqb[i],221 sizeof(struct xfs_dqblk), fa);222 return fa;223 }224 }225 226 return NULL;227}228 229static xfs_failaddr_t230xfs_dquot_buf_verify_struct(231 struct xfs_buf *bp)232{233 struct xfs_mount *mp = bp->b_mount;234 235 return xfs_dquot_buf_verify(mp, bp, false);236}237 238static void239xfs_dquot_buf_read_verify(240 struct xfs_buf *bp)241{242 struct xfs_mount *mp = bp->b_mount;243 244 if (!xfs_dquot_buf_verify_crc(mp, bp, false))245 return;246 xfs_dquot_buf_verify(mp, bp, false);247}248 249/*250 * readahead errors are silent and simply leave the buffer as !done so a real251 * read will then be run with the xfs_dquot_buf_ops verifier. See252 * xfs_inode_buf_verify() for why we use EIO and ~XBF_DONE here rather than253 * reporting the failure.254 */255static void256xfs_dquot_buf_readahead_verify(257 struct xfs_buf *bp)258{259 struct xfs_mount *mp = bp->b_mount;260 261 if (!xfs_dquot_buf_verify_crc(mp, bp, true) ||262 xfs_dquot_buf_verify(mp, bp, true) != NULL) {263 xfs_buf_ioerror(bp, -EIO);264 bp->b_flags &= ~XBF_DONE;265 }266}267 268/*269 * we don't calculate the CRC here as that is done when the dquot is flushed to270 * the buffer after the update is done. This ensures that the dquot in the271 * buffer always has an up-to-date CRC value.272 */273static void274xfs_dquot_buf_write_verify(275 struct xfs_buf *bp)276{277 struct xfs_mount *mp = bp->b_mount;278 279 xfs_dquot_buf_verify(mp, bp, false);280}281 282const struct xfs_buf_ops xfs_dquot_buf_ops = {283 .name = "xfs_dquot",284 .magic16 = { cpu_to_be16(XFS_DQUOT_MAGIC),285 cpu_to_be16(XFS_DQUOT_MAGIC) },286 .verify_read = xfs_dquot_buf_read_verify,287 .verify_write = xfs_dquot_buf_write_verify,288 .verify_struct = xfs_dquot_buf_verify_struct,289};290 291const struct xfs_buf_ops xfs_dquot_buf_ra_ops = {292 .name = "xfs_dquot_ra",293 .magic16 = { cpu_to_be16(XFS_DQUOT_MAGIC),294 cpu_to_be16(XFS_DQUOT_MAGIC) },295 .verify_read = xfs_dquot_buf_readahead_verify,296 .verify_write = xfs_dquot_buf_write_verify,297};298 299/* Convert an on-disk timer value into an incore timer value. */300time64_t301xfs_dquot_from_disk_ts(302 struct xfs_disk_dquot *ddq,303 __be32 dtimer)304{305 uint32_t t = be32_to_cpu(dtimer);306 307 if (t != 0 && (ddq->d_type & XFS_DQTYPE_BIGTIME))308 return xfs_dq_bigtime_to_unix(t);309 310 return t;311}312 313/* Convert an incore timer value into an on-disk timer value. */314__be32315xfs_dquot_to_disk_ts(316 struct xfs_dquot *dqp,317 time64_t timer)318{319 uint32_t t = timer;320 321 if (timer != 0 && (dqp->q_type & XFS_DQTYPE_BIGTIME))322 t = xfs_dq_unix_to_bigtime(timer);323 324 return cpu_to_be32(t);325}326