brintos

brintos / linux-shallow public Read only

0
0
Text · 8.0 KiB · 15a362e Raw
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