162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2000-2003 Silicon Graphics, Inc.
462306a36Sopenharmony_ci * All Rights Reserved.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci#include "xfs.h"
762306a36Sopenharmony_ci#include "xfs_fs.h"
862306a36Sopenharmony_ci#include "xfs_format.h"
962306a36Sopenharmony_ci#include "xfs_log_format.h"
1062306a36Sopenharmony_ci#include "xfs_shared.h"
1162306a36Sopenharmony_ci#include "xfs_trans_resv.h"
1262306a36Sopenharmony_ci#include "xfs_bit.h"
1362306a36Sopenharmony_ci#include "xfs_mount.h"
1462306a36Sopenharmony_ci#include "xfs_defer.h"
1562306a36Sopenharmony_ci#include "xfs_inode.h"
1662306a36Sopenharmony_ci#include "xfs_bmap.h"
1762306a36Sopenharmony_ci#include "xfs_quota.h"
1862306a36Sopenharmony_ci#include "xfs_trans.h"
1962306a36Sopenharmony_ci#include "xfs_buf_item.h"
2062306a36Sopenharmony_ci#include "xfs_trans_space.h"
2162306a36Sopenharmony_ci#include "xfs_trans_priv.h"
2262306a36Sopenharmony_ci#include "xfs_qm.h"
2362306a36Sopenharmony_ci#include "xfs_trace.h"
2462306a36Sopenharmony_ci#include "xfs_log.h"
2562306a36Sopenharmony_ci#include "xfs_bmap_btree.h"
2662306a36Sopenharmony_ci#include "xfs_error.h"
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/*
2962306a36Sopenharmony_ci * Lock order:
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci * ip->i_lock
3262306a36Sopenharmony_ci *   qi->qi_tree_lock
3362306a36Sopenharmony_ci *     dquot->q_qlock (xfs_dqlock() and friends)
3462306a36Sopenharmony_ci *       dquot->q_flush (xfs_dqflock() and friends)
3562306a36Sopenharmony_ci *       qi->qi_lru_lock
3662306a36Sopenharmony_ci *
3762306a36Sopenharmony_ci * If two dquots need to be locked the order is user before group/project,
3862306a36Sopenharmony_ci * otherwise by the lowest id first, see xfs_dqlock2.
3962306a36Sopenharmony_ci */
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistruct kmem_cache		*xfs_dqtrx_cache;
4262306a36Sopenharmony_cistatic struct kmem_cache	*xfs_dquot_cache;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic struct lock_class_key xfs_dquot_group_class;
4562306a36Sopenharmony_cistatic struct lock_class_key xfs_dquot_project_class;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/*
4862306a36Sopenharmony_ci * This is called to free all the memory associated with a dquot
4962306a36Sopenharmony_ci */
5062306a36Sopenharmony_civoid
5162306a36Sopenharmony_cixfs_qm_dqdestroy(
5262306a36Sopenharmony_ci	struct xfs_dquot	*dqp)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	ASSERT(list_empty(&dqp->q_lru));
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	kmem_free(dqp->q_logitem.qli_item.li_lv_shadow);
5762306a36Sopenharmony_ci	mutex_destroy(&dqp->q_qlock);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	XFS_STATS_DEC(dqp->q_mount, xs_qm_dquot);
6062306a36Sopenharmony_ci	kmem_cache_free(xfs_dquot_cache, dqp);
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci/*
6462306a36Sopenharmony_ci * If default limits are in force, push them into the dquot now.
6562306a36Sopenharmony_ci * We overwrite the dquot limits only if they are zero and this
6662306a36Sopenharmony_ci * is not the root dquot.
6762306a36Sopenharmony_ci */
6862306a36Sopenharmony_civoid
6962306a36Sopenharmony_cixfs_qm_adjust_dqlimits(
7062306a36Sopenharmony_ci	struct xfs_dquot	*dq)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	struct xfs_mount	*mp = dq->q_mount;
7362306a36Sopenharmony_ci	struct xfs_quotainfo	*q = mp->m_quotainfo;
7462306a36Sopenharmony_ci	struct xfs_def_quota	*defq;
7562306a36Sopenharmony_ci	int			prealloc = 0;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	ASSERT(dq->q_id);
7862306a36Sopenharmony_ci	defq = xfs_get_defquota(q, xfs_dquot_type(dq));
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	if (!dq->q_blk.softlimit) {
8162306a36Sopenharmony_ci		dq->q_blk.softlimit = defq->blk.soft;
8262306a36Sopenharmony_ci		prealloc = 1;
8362306a36Sopenharmony_ci	}
8462306a36Sopenharmony_ci	if (!dq->q_blk.hardlimit) {
8562306a36Sopenharmony_ci		dq->q_blk.hardlimit = defq->blk.hard;
8662306a36Sopenharmony_ci		prealloc = 1;
8762306a36Sopenharmony_ci	}
8862306a36Sopenharmony_ci	if (!dq->q_ino.softlimit)
8962306a36Sopenharmony_ci		dq->q_ino.softlimit = defq->ino.soft;
9062306a36Sopenharmony_ci	if (!dq->q_ino.hardlimit)
9162306a36Sopenharmony_ci		dq->q_ino.hardlimit = defq->ino.hard;
9262306a36Sopenharmony_ci	if (!dq->q_rtb.softlimit)
9362306a36Sopenharmony_ci		dq->q_rtb.softlimit = defq->rtb.soft;
9462306a36Sopenharmony_ci	if (!dq->q_rtb.hardlimit)
9562306a36Sopenharmony_ci		dq->q_rtb.hardlimit = defq->rtb.hard;
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	if (prealloc)
9862306a36Sopenharmony_ci		xfs_dquot_set_prealloc_limits(dq);
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci/* Set the expiration time of a quota's grace period. */
10262306a36Sopenharmony_citime64_t
10362306a36Sopenharmony_cixfs_dquot_set_timeout(
10462306a36Sopenharmony_ci	struct xfs_mount	*mp,
10562306a36Sopenharmony_ci	time64_t		timeout)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	struct xfs_quotainfo	*qi = mp->m_quotainfo;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	return clamp_t(time64_t, timeout, qi->qi_expiry_min,
11062306a36Sopenharmony_ci					  qi->qi_expiry_max);
11162306a36Sopenharmony_ci}
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci/* Set the length of the default grace period. */
11462306a36Sopenharmony_citime64_t
11562306a36Sopenharmony_cixfs_dquot_set_grace_period(
11662306a36Sopenharmony_ci	time64_t		grace)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	return clamp_t(time64_t, grace, XFS_DQ_GRACE_MIN, XFS_DQ_GRACE_MAX);
11962306a36Sopenharmony_ci}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci/*
12262306a36Sopenharmony_ci * Determine if this quota counter is over either limit and set the quota
12362306a36Sopenharmony_ci * timers as appropriate.
12462306a36Sopenharmony_ci */
12562306a36Sopenharmony_cistatic inline void
12662306a36Sopenharmony_cixfs_qm_adjust_res_timer(
12762306a36Sopenharmony_ci	struct xfs_mount	*mp,
12862306a36Sopenharmony_ci	struct xfs_dquot_res	*res,
12962306a36Sopenharmony_ci	struct xfs_quota_limits	*qlim)
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	ASSERT(res->hardlimit == 0 || res->softlimit <= res->hardlimit);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	if ((res->softlimit && res->count > res->softlimit) ||
13462306a36Sopenharmony_ci	    (res->hardlimit && res->count > res->hardlimit)) {
13562306a36Sopenharmony_ci		if (res->timer == 0)
13662306a36Sopenharmony_ci			res->timer = xfs_dquot_set_timeout(mp,
13762306a36Sopenharmony_ci					ktime_get_real_seconds() + qlim->time);
13862306a36Sopenharmony_ci	} else {
13962306a36Sopenharmony_ci		res->timer = 0;
14062306a36Sopenharmony_ci	}
14162306a36Sopenharmony_ci}
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci/*
14462306a36Sopenharmony_ci * Check the limits and timers of a dquot and start or reset timers
14562306a36Sopenharmony_ci * if necessary.
14662306a36Sopenharmony_ci * This gets called even when quota enforcement is OFF, which makes our
14762306a36Sopenharmony_ci * life a little less complicated. (We just don't reject any quota
14862306a36Sopenharmony_ci * reservations in that case, when enforcement is off).
14962306a36Sopenharmony_ci * We also return 0 as the values of the timers in Q_GETQUOTA calls, when
15062306a36Sopenharmony_ci * enforcement's off.
15162306a36Sopenharmony_ci * In contrast, warnings are a little different in that they don't
15262306a36Sopenharmony_ci * 'automatically' get started when limits get exceeded.  They do
15362306a36Sopenharmony_ci * get reset to zero, however, when we find the count to be under
15462306a36Sopenharmony_ci * the soft limit (they are only ever set non-zero via userspace).
15562306a36Sopenharmony_ci */
15662306a36Sopenharmony_civoid
15762306a36Sopenharmony_cixfs_qm_adjust_dqtimers(
15862306a36Sopenharmony_ci	struct xfs_dquot	*dq)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	struct xfs_mount	*mp = dq->q_mount;
16162306a36Sopenharmony_ci	struct xfs_quotainfo	*qi = mp->m_quotainfo;
16262306a36Sopenharmony_ci	struct xfs_def_quota	*defq;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	ASSERT(dq->q_id);
16562306a36Sopenharmony_ci	defq = xfs_get_defquota(qi, xfs_dquot_type(dq));
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	xfs_qm_adjust_res_timer(dq->q_mount, &dq->q_blk, &defq->blk);
16862306a36Sopenharmony_ci	xfs_qm_adjust_res_timer(dq->q_mount, &dq->q_ino, &defq->ino);
16962306a36Sopenharmony_ci	xfs_qm_adjust_res_timer(dq->q_mount, &dq->q_rtb, &defq->rtb);
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci/*
17362306a36Sopenharmony_ci * initialize a buffer full of dquots and log the whole thing
17462306a36Sopenharmony_ci */
17562306a36Sopenharmony_ciSTATIC void
17662306a36Sopenharmony_cixfs_qm_init_dquot_blk(
17762306a36Sopenharmony_ci	struct xfs_trans	*tp,
17862306a36Sopenharmony_ci	struct xfs_mount	*mp,
17962306a36Sopenharmony_ci	xfs_dqid_t		id,
18062306a36Sopenharmony_ci	xfs_dqtype_t		type,
18162306a36Sopenharmony_ci	struct xfs_buf		*bp)
18262306a36Sopenharmony_ci{
18362306a36Sopenharmony_ci	struct xfs_quotainfo	*q = mp->m_quotainfo;
18462306a36Sopenharmony_ci	struct xfs_dqblk	*d;
18562306a36Sopenharmony_ci	xfs_dqid_t		curid;
18662306a36Sopenharmony_ci	unsigned int		qflag;
18762306a36Sopenharmony_ci	unsigned int		blftype;
18862306a36Sopenharmony_ci	int			i;
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	ASSERT(tp);
19162306a36Sopenharmony_ci	ASSERT(xfs_buf_islocked(bp));
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	switch (type) {
19462306a36Sopenharmony_ci	case XFS_DQTYPE_USER:
19562306a36Sopenharmony_ci		qflag = XFS_UQUOTA_CHKD;
19662306a36Sopenharmony_ci		blftype = XFS_BLF_UDQUOT_BUF;
19762306a36Sopenharmony_ci		break;
19862306a36Sopenharmony_ci	case XFS_DQTYPE_PROJ:
19962306a36Sopenharmony_ci		qflag = XFS_PQUOTA_CHKD;
20062306a36Sopenharmony_ci		blftype = XFS_BLF_PDQUOT_BUF;
20162306a36Sopenharmony_ci		break;
20262306a36Sopenharmony_ci	case XFS_DQTYPE_GROUP:
20362306a36Sopenharmony_ci		qflag = XFS_GQUOTA_CHKD;
20462306a36Sopenharmony_ci		blftype = XFS_BLF_GDQUOT_BUF;
20562306a36Sopenharmony_ci		break;
20662306a36Sopenharmony_ci	default:
20762306a36Sopenharmony_ci		ASSERT(0);
20862306a36Sopenharmony_ci		return;
20962306a36Sopenharmony_ci	}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	d = bp->b_addr;
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	/*
21462306a36Sopenharmony_ci	 * ID of the first dquot in the block - id's are zero based.
21562306a36Sopenharmony_ci	 */
21662306a36Sopenharmony_ci	curid = id - (id % q->qi_dqperchunk);
21762306a36Sopenharmony_ci	memset(d, 0, BBTOB(q->qi_dqchunklen));
21862306a36Sopenharmony_ci	for (i = 0; i < q->qi_dqperchunk; i++, d++, curid++) {
21962306a36Sopenharmony_ci		d->dd_diskdq.d_magic = cpu_to_be16(XFS_DQUOT_MAGIC);
22062306a36Sopenharmony_ci		d->dd_diskdq.d_version = XFS_DQUOT_VERSION;
22162306a36Sopenharmony_ci		d->dd_diskdq.d_id = cpu_to_be32(curid);
22262306a36Sopenharmony_ci		d->dd_diskdq.d_type = type;
22362306a36Sopenharmony_ci		if (curid > 0 && xfs_has_bigtime(mp))
22462306a36Sopenharmony_ci			d->dd_diskdq.d_type |= XFS_DQTYPE_BIGTIME;
22562306a36Sopenharmony_ci		if (xfs_has_crc(mp)) {
22662306a36Sopenharmony_ci			uuid_copy(&d->dd_uuid, &mp->m_sb.sb_meta_uuid);
22762306a36Sopenharmony_ci			xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk),
22862306a36Sopenharmony_ci					 XFS_DQUOT_CRC_OFF);
22962306a36Sopenharmony_ci		}
23062306a36Sopenharmony_ci	}
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	xfs_trans_dquot_buf(tp, bp, blftype);
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	/*
23562306a36Sopenharmony_ci	 * quotacheck uses delayed writes to update all the dquots on disk in an
23662306a36Sopenharmony_ci	 * efficient manner instead of logging the individual dquot changes as
23762306a36Sopenharmony_ci	 * they are made. However if we log the buffer allocated here and crash
23862306a36Sopenharmony_ci	 * after quotacheck while the logged initialisation is still in the
23962306a36Sopenharmony_ci	 * active region of the log, log recovery can replay the dquot buffer
24062306a36Sopenharmony_ci	 * initialisation over the top of the checked dquots and corrupt quota
24162306a36Sopenharmony_ci	 * accounting.
24262306a36Sopenharmony_ci	 *
24362306a36Sopenharmony_ci	 * To avoid this problem, quotacheck cannot log the initialised buffer.
24462306a36Sopenharmony_ci	 * We must still dirty the buffer and write it back before the
24562306a36Sopenharmony_ci	 * allocation transaction clears the log. Therefore, mark the buffer as
24662306a36Sopenharmony_ci	 * ordered instead of logging it directly. This is safe for quotacheck
24762306a36Sopenharmony_ci	 * because it detects and repairs allocated but initialized dquot blocks
24862306a36Sopenharmony_ci	 * in the quota inodes.
24962306a36Sopenharmony_ci	 */
25062306a36Sopenharmony_ci	if (!(mp->m_qflags & qflag))
25162306a36Sopenharmony_ci		xfs_trans_ordered_buf(tp, bp);
25262306a36Sopenharmony_ci	else
25362306a36Sopenharmony_ci		xfs_trans_log_buf(tp, bp, 0, BBTOB(q->qi_dqchunklen) - 1);
25462306a36Sopenharmony_ci}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci/*
25762306a36Sopenharmony_ci * Initialize the dynamic speculative preallocation thresholds. The lo/hi
25862306a36Sopenharmony_ci * watermarks correspond to the soft and hard limits by default. If a soft limit
25962306a36Sopenharmony_ci * is not specified, we use 95% of the hard limit.
26062306a36Sopenharmony_ci */
26162306a36Sopenharmony_civoid
26262306a36Sopenharmony_cixfs_dquot_set_prealloc_limits(struct xfs_dquot *dqp)
26362306a36Sopenharmony_ci{
26462306a36Sopenharmony_ci	uint64_t space;
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	dqp->q_prealloc_hi_wmark = dqp->q_blk.hardlimit;
26762306a36Sopenharmony_ci	dqp->q_prealloc_lo_wmark = dqp->q_blk.softlimit;
26862306a36Sopenharmony_ci	if (!dqp->q_prealloc_lo_wmark) {
26962306a36Sopenharmony_ci		dqp->q_prealloc_lo_wmark = dqp->q_prealloc_hi_wmark;
27062306a36Sopenharmony_ci		do_div(dqp->q_prealloc_lo_wmark, 100);
27162306a36Sopenharmony_ci		dqp->q_prealloc_lo_wmark *= 95;
27262306a36Sopenharmony_ci	}
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	space = dqp->q_prealloc_hi_wmark;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	do_div(space, 100);
27762306a36Sopenharmony_ci	dqp->q_low_space[XFS_QLOWSP_1_PCNT] = space;
27862306a36Sopenharmony_ci	dqp->q_low_space[XFS_QLOWSP_3_PCNT] = space * 3;
27962306a36Sopenharmony_ci	dqp->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5;
28062306a36Sopenharmony_ci}
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci/*
28362306a36Sopenharmony_ci * Ensure that the given in-core dquot has a buffer on disk backing it, and
28462306a36Sopenharmony_ci * return the buffer locked and held. This is called when the bmapi finds a
28562306a36Sopenharmony_ci * hole.
28662306a36Sopenharmony_ci */
28762306a36Sopenharmony_ciSTATIC int
28862306a36Sopenharmony_cixfs_dquot_disk_alloc(
28962306a36Sopenharmony_ci	struct xfs_dquot	*dqp,
29062306a36Sopenharmony_ci	struct xfs_buf		**bpp)
29162306a36Sopenharmony_ci{
29262306a36Sopenharmony_ci	struct xfs_bmbt_irec	map;
29362306a36Sopenharmony_ci	struct xfs_trans	*tp;
29462306a36Sopenharmony_ci	struct xfs_mount	*mp = dqp->q_mount;
29562306a36Sopenharmony_ci	struct xfs_buf		*bp;
29662306a36Sopenharmony_ci	xfs_dqtype_t		qtype = xfs_dquot_type(dqp);
29762306a36Sopenharmony_ci	struct xfs_inode	*quotip = xfs_quota_inode(mp, qtype);
29862306a36Sopenharmony_ci	int			nmaps = 1;
29962306a36Sopenharmony_ci	int			error;
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	trace_xfs_dqalloc(dqp);
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_dqalloc,
30462306a36Sopenharmony_ci			XFS_QM_DQALLOC_SPACE_RES(mp), 0, 0, &tp);
30562306a36Sopenharmony_ci	if (error)
30662306a36Sopenharmony_ci		return error;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	xfs_ilock(quotip, XFS_ILOCK_EXCL);
30962306a36Sopenharmony_ci	xfs_trans_ijoin(tp, quotip, 0);
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	if (!xfs_this_quota_on(dqp->q_mount, qtype)) {
31262306a36Sopenharmony_ci		/*
31362306a36Sopenharmony_ci		 * Return if this type of quotas is turned off while we didn't
31462306a36Sopenharmony_ci		 * have an inode lock
31562306a36Sopenharmony_ci		 */
31662306a36Sopenharmony_ci		error = -ESRCH;
31762306a36Sopenharmony_ci		goto err_cancel;
31862306a36Sopenharmony_ci	}
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	error = xfs_iext_count_may_overflow(quotip, XFS_DATA_FORK,
32162306a36Sopenharmony_ci			XFS_IEXT_ADD_NOSPLIT_CNT);
32262306a36Sopenharmony_ci	if (error == -EFBIG)
32362306a36Sopenharmony_ci		error = xfs_iext_count_upgrade(tp, quotip,
32462306a36Sopenharmony_ci				XFS_IEXT_ADD_NOSPLIT_CNT);
32562306a36Sopenharmony_ci	if (error)
32662306a36Sopenharmony_ci		goto err_cancel;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	/* Create the block mapping. */
32962306a36Sopenharmony_ci	error = xfs_bmapi_write(tp, quotip, dqp->q_fileoffset,
33062306a36Sopenharmony_ci			XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA, 0, &map,
33162306a36Sopenharmony_ci			&nmaps);
33262306a36Sopenharmony_ci	if (error)
33362306a36Sopenharmony_ci		goto err_cancel;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB);
33662306a36Sopenharmony_ci	ASSERT(nmaps == 1);
33762306a36Sopenharmony_ci	ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
33862306a36Sopenharmony_ci	       (map.br_startblock != HOLESTARTBLOCK));
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	/*
34162306a36Sopenharmony_ci	 * Keep track of the blkno to save a lookup later
34262306a36Sopenharmony_ci	 */
34362306a36Sopenharmony_ci	dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock);
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	/* now we can just get the buffer (there's nothing to read yet) */
34662306a36Sopenharmony_ci	error = xfs_trans_get_buf(tp, mp->m_ddev_targp, dqp->q_blkno,
34762306a36Sopenharmony_ci			mp->m_quotainfo->qi_dqchunklen, 0, &bp);
34862306a36Sopenharmony_ci	if (error)
34962306a36Sopenharmony_ci		goto err_cancel;
35062306a36Sopenharmony_ci	bp->b_ops = &xfs_dquot_buf_ops;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	/*
35362306a36Sopenharmony_ci	 * Make a chunk of dquots out of this buffer and log
35462306a36Sopenharmony_ci	 * the entire thing.
35562306a36Sopenharmony_ci	 */
35662306a36Sopenharmony_ci	xfs_qm_init_dquot_blk(tp, mp, dqp->q_id, qtype, bp);
35762306a36Sopenharmony_ci	xfs_buf_set_ref(bp, XFS_DQUOT_REF);
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	/*
36062306a36Sopenharmony_ci	 * Hold the buffer and join it to the dfops so that we'll still own
36162306a36Sopenharmony_ci	 * the buffer when we return to the caller.  The buffer disposal on
36262306a36Sopenharmony_ci	 * error must be paid attention to very carefully, as it has been
36362306a36Sopenharmony_ci	 * broken since commit efa092f3d4c6 "[XFS] Fixes a bug in the quota
36462306a36Sopenharmony_ci	 * code when allocating a new dquot record" in 2005, and the later
36562306a36Sopenharmony_ci	 * conversion to xfs_defer_ops in commit 310a75a3c6c747 failed to keep
36662306a36Sopenharmony_ci	 * the buffer locked across the _defer_finish call.  We can now do
36762306a36Sopenharmony_ci	 * this correctly with xfs_defer_bjoin.
36862306a36Sopenharmony_ci	 *
36962306a36Sopenharmony_ci	 * Above, we allocated a disk block for the dquot information and used
37062306a36Sopenharmony_ci	 * get_buf to initialize the dquot. If the _defer_finish fails, the old
37162306a36Sopenharmony_ci	 * transaction is gone but the new buffer is not joined or held to any
37262306a36Sopenharmony_ci	 * transaction, so we must _buf_relse it.
37362306a36Sopenharmony_ci	 *
37462306a36Sopenharmony_ci	 * If everything succeeds, the caller of this function is returned a
37562306a36Sopenharmony_ci	 * buffer that is locked and held to the transaction.  The caller
37662306a36Sopenharmony_ci	 * is responsible for unlocking any buffer passed back, either
37762306a36Sopenharmony_ci	 * manually or by committing the transaction.  On error, the buffer is
37862306a36Sopenharmony_ci	 * released and not passed back.
37962306a36Sopenharmony_ci	 *
38062306a36Sopenharmony_ci	 * Keep the quota inode ILOCKed until after the transaction commit to
38162306a36Sopenharmony_ci	 * maintain the atomicity of bmap/rmap updates.
38262306a36Sopenharmony_ci	 */
38362306a36Sopenharmony_ci	xfs_trans_bhold(tp, bp);
38462306a36Sopenharmony_ci	error = xfs_trans_commit(tp);
38562306a36Sopenharmony_ci	xfs_iunlock(quotip, XFS_ILOCK_EXCL);
38662306a36Sopenharmony_ci	if (error) {
38762306a36Sopenharmony_ci		xfs_buf_relse(bp);
38862306a36Sopenharmony_ci		return error;
38962306a36Sopenharmony_ci	}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	*bpp = bp;
39262306a36Sopenharmony_ci	return 0;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_cierr_cancel:
39562306a36Sopenharmony_ci	xfs_trans_cancel(tp);
39662306a36Sopenharmony_ci	xfs_iunlock(quotip, XFS_ILOCK_EXCL);
39762306a36Sopenharmony_ci	return error;
39862306a36Sopenharmony_ci}
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci/*
40162306a36Sopenharmony_ci * Read in the in-core dquot's on-disk metadata and return the buffer.
40262306a36Sopenharmony_ci * Returns ENOENT to signal a hole.
40362306a36Sopenharmony_ci */
40462306a36Sopenharmony_ciSTATIC int
40562306a36Sopenharmony_cixfs_dquot_disk_read(
40662306a36Sopenharmony_ci	struct xfs_mount	*mp,
40762306a36Sopenharmony_ci	struct xfs_dquot	*dqp,
40862306a36Sopenharmony_ci	struct xfs_buf		**bpp)
40962306a36Sopenharmony_ci{
41062306a36Sopenharmony_ci	struct xfs_bmbt_irec	map;
41162306a36Sopenharmony_ci	struct xfs_buf		*bp;
41262306a36Sopenharmony_ci	xfs_dqtype_t		qtype = xfs_dquot_type(dqp);
41362306a36Sopenharmony_ci	struct xfs_inode	*quotip = xfs_quota_inode(mp, qtype);
41462306a36Sopenharmony_ci	uint			lock_mode;
41562306a36Sopenharmony_ci	int			nmaps = 1;
41662306a36Sopenharmony_ci	int			error;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	lock_mode = xfs_ilock_data_map_shared(quotip);
41962306a36Sopenharmony_ci	if (!xfs_this_quota_on(mp, qtype)) {
42062306a36Sopenharmony_ci		/*
42162306a36Sopenharmony_ci		 * Return if this type of quotas is turned off while we
42262306a36Sopenharmony_ci		 * didn't have the quota inode lock.
42362306a36Sopenharmony_ci		 */
42462306a36Sopenharmony_ci		xfs_iunlock(quotip, lock_mode);
42562306a36Sopenharmony_ci		return -ESRCH;
42662306a36Sopenharmony_ci	}
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	/*
42962306a36Sopenharmony_ci	 * Find the block map; no allocations yet
43062306a36Sopenharmony_ci	 */
43162306a36Sopenharmony_ci	error = xfs_bmapi_read(quotip, dqp->q_fileoffset,
43262306a36Sopenharmony_ci			XFS_DQUOT_CLUSTER_SIZE_FSB, &map, &nmaps, 0);
43362306a36Sopenharmony_ci	xfs_iunlock(quotip, lock_mode);
43462306a36Sopenharmony_ci	if (error)
43562306a36Sopenharmony_ci		return error;
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	ASSERT(nmaps == 1);
43862306a36Sopenharmony_ci	ASSERT(map.br_blockcount >= 1);
43962306a36Sopenharmony_ci	ASSERT(map.br_startblock != DELAYSTARTBLOCK);
44062306a36Sopenharmony_ci	if (map.br_startblock == HOLESTARTBLOCK)
44162306a36Sopenharmony_ci		return -ENOENT;
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci	trace_xfs_dqtobp_read(dqp);
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci	/*
44662306a36Sopenharmony_ci	 * store the blkno etc so that we don't have to do the
44762306a36Sopenharmony_ci	 * mapping all the time
44862306a36Sopenharmony_ci	 */
44962306a36Sopenharmony_ci	dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock);
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno,
45262306a36Sopenharmony_ci			mp->m_quotainfo->qi_dqchunklen, 0, &bp,
45362306a36Sopenharmony_ci			&xfs_dquot_buf_ops);
45462306a36Sopenharmony_ci	if (error) {
45562306a36Sopenharmony_ci		ASSERT(bp == NULL);
45662306a36Sopenharmony_ci		return error;
45762306a36Sopenharmony_ci	}
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	ASSERT(xfs_buf_islocked(bp));
46062306a36Sopenharmony_ci	xfs_buf_set_ref(bp, XFS_DQUOT_REF);
46162306a36Sopenharmony_ci	*bpp = bp;
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci	return 0;
46462306a36Sopenharmony_ci}
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci/* Allocate and initialize everything we need for an incore dquot. */
46762306a36Sopenharmony_ciSTATIC struct xfs_dquot *
46862306a36Sopenharmony_cixfs_dquot_alloc(
46962306a36Sopenharmony_ci	struct xfs_mount	*mp,
47062306a36Sopenharmony_ci	xfs_dqid_t		id,
47162306a36Sopenharmony_ci	xfs_dqtype_t		type)
47262306a36Sopenharmony_ci{
47362306a36Sopenharmony_ci	struct xfs_dquot	*dqp;
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	dqp = kmem_cache_zalloc(xfs_dquot_cache, GFP_KERNEL | __GFP_NOFAIL);
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	dqp->q_type = type;
47862306a36Sopenharmony_ci	dqp->q_id = id;
47962306a36Sopenharmony_ci	dqp->q_mount = mp;
48062306a36Sopenharmony_ci	INIT_LIST_HEAD(&dqp->q_lru);
48162306a36Sopenharmony_ci	mutex_init(&dqp->q_qlock);
48262306a36Sopenharmony_ci	init_waitqueue_head(&dqp->q_pinwait);
48362306a36Sopenharmony_ci	dqp->q_fileoffset = (xfs_fileoff_t)id / mp->m_quotainfo->qi_dqperchunk;
48462306a36Sopenharmony_ci	/*
48562306a36Sopenharmony_ci	 * Offset of dquot in the (fixed sized) dquot chunk.
48662306a36Sopenharmony_ci	 */
48762306a36Sopenharmony_ci	dqp->q_bufoffset = (id % mp->m_quotainfo->qi_dqperchunk) *
48862306a36Sopenharmony_ci			sizeof(struct xfs_dqblk);
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	/*
49162306a36Sopenharmony_ci	 * Because we want to use a counting completion, complete
49262306a36Sopenharmony_ci	 * the flush completion once to allow a single access to
49362306a36Sopenharmony_ci	 * the flush completion without blocking.
49462306a36Sopenharmony_ci	 */
49562306a36Sopenharmony_ci	init_completion(&dqp->q_flush);
49662306a36Sopenharmony_ci	complete(&dqp->q_flush);
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	/*
49962306a36Sopenharmony_ci	 * Make sure group quotas have a different lock class than user
50062306a36Sopenharmony_ci	 * quotas.
50162306a36Sopenharmony_ci	 */
50262306a36Sopenharmony_ci	switch (type) {
50362306a36Sopenharmony_ci	case XFS_DQTYPE_USER:
50462306a36Sopenharmony_ci		/* uses the default lock class */
50562306a36Sopenharmony_ci		break;
50662306a36Sopenharmony_ci	case XFS_DQTYPE_GROUP:
50762306a36Sopenharmony_ci		lockdep_set_class(&dqp->q_qlock, &xfs_dquot_group_class);
50862306a36Sopenharmony_ci		break;
50962306a36Sopenharmony_ci	case XFS_DQTYPE_PROJ:
51062306a36Sopenharmony_ci		lockdep_set_class(&dqp->q_qlock, &xfs_dquot_project_class);
51162306a36Sopenharmony_ci		break;
51262306a36Sopenharmony_ci	default:
51362306a36Sopenharmony_ci		ASSERT(0);
51462306a36Sopenharmony_ci		break;
51562306a36Sopenharmony_ci	}
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	xfs_qm_dquot_logitem_init(dqp);
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	XFS_STATS_INC(mp, xs_qm_dquot);
52062306a36Sopenharmony_ci	return dqp;
52162306a36Sopenharmony_ci}
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci/* Check the ondisk dquot's id and type match what the incore dquot expects. */
52462306a36Sopenharmony_cistatic bool
52562306a36Sopenharmony_cixfs_dquot_check_type(
52662306a36Sopenharmony_ci	struct xfs_dquot	*dqp,
52762306a36Sopenharmony_ci	struct xfs_disk_dquot	*ddqp)
52862306a36Sopenharmony_ci{
52962306a36Sopenharmony_ci	uint8_t			ddqp_type;
53062306a36Sopenharmony_ci	uint8_t			dqp_type;
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	ddqp_type = ddqp->d_type & XFS_DQTYPE_REC_MASK;
53362306a36Sopenharmony_ci	dqp_type = xfs_dquot_type(dqp);
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	if (be32_to_cpu(ddqp->d_id) != dqp->q_id)
53662306a36Sopenharmony_ci		return false;
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	/*
53962306a36Sopenharmony_ci	 * V5 filesystems always expect an exact type match.  V4 filesystems
54062306a36Sopenharmony_ci	 * expect an exact match for user dquots and for non-root group and
54162306a36Sopenharmony_ci	 * project dquots.
54262306a36Sopenharmony_ci	 */
54362306a36Sopenharmony_ci	if (xfs_has_crc(dqp->q_mount) ||
54462306a36Sopenharmony_ci	    dqp_type == XFS_DQTYPE_USER || dqp->q_id != 0)
54562306a36Sopenharmony_ci		return ddqp_type == dqp_type;
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci	/*
54862306a36Sopenharmony_ci	 * V4 filesystems support either group or project quotas, but not both
54962306a36Sopenharmony_ci	 * at the same time.  The non-user quota file can be switched between
55062306a36Sopenharmony_ci	 * group and project quota uses depending on the mount options, which
55162306a36Sopenharmony_ci	 * means that we can encounter the other type when we try to load quota
55262306a36Sopenharmony_ci	 * defaults.  Quotacheck will soon reset the entire quota file
55362306a36Sopenharmony_ci	 * (including the root dquot) anyway, but don't log scary corruption
55462306a36Sopenharmony_ci	 * reports to dmesg.
55562306a36Sopenharmony_ci	 */
55662306a36Sopenharmony_ci	return ddqp_type == XFS_DQTYPE_GROUP || ddqp_type == XFS_DQTYPE_PROJ;
55762306a36Sopenharmony_ci}
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci/* Copy the in-core quota fields in from the on-disk buffer. */
56062306a36Sopenharmony_ciSTATIC int
56162306a36Sopenharmony_cixfs_dquot_from_disk(
56262306a36Sopenharmony_ci	struct xfs_dquot	*dqp,
56362306a36Sopenharmony_ci	struct xfs_buf		*bp)
56462306a36Sopenharmony_ci{
56562306a36Sopenharmony_ci	struct xfs_dqblk	*dqb = xfs_buf_offset(bp, dqp->q_bufoffset);
56662306a36Sopenharmony_ci	struct xfs_disk_dquot	*ddqp = &dqb->dd_diskdq;
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	/*
56962306a36Sopenharmony_ci	 * Ensure that we got the type and ID we were looking for.
57062306a36Sopenharmony_ci	 * Everything else was checked by the dquot buffer verifier.
57162306a36Sopenharmony_ci	 */
57262306a36Sopenharmony_ci	if (!xfs_dquot_check_type(dqp, ddqp)) {
57362306a36Sopenharmony_ci		xfs_alert_tag(bp->b_mount, XFS_PTAG_VERIFIER_ERROR,
57462306a36Sopenharmony_ci			  "Metadata corruption detected at %pS, quota %u",
57562306a36Sopenharmony_ci			  __this_address, dqp->q_id);
57662306a36Sopenharmony_ci		xfs_alert(bp->b_mount, "Unmount and run xfs_repair");
57762306a36Sopenharmony_ci		return -EFSCORRUPTED;
57862306a36Sopenharmony_ci	}
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	/* copy everything from disk dquot to the incore dquot */
58162306a36Sopenharmony_ci	dqp->q_type = ddqp->d_type;
58262306a36Sopenharmony_ci	dqp->q_blk.hardlimit = be64_to_cpu(ddqp->d_blk_hardlimit);
58362306a36Sopenharmony_ci	dqp->q_blk.softlimit = be64_to_cpu(ddqp->d_blk_softlimit);
58462306a36Sopenharmony_ci	dqp->q_ino.hardlimit = be64_to_cpu(ddqp->d_ino_hardlimit);
58562306a36Sopenharmony_ci	dqp->q_ino.softlimit = be64_to_cpu(ddqp->d_ino_softlimit);
58662306a36Sopenharmony_ci	dqp->q_rtb.hardlimit = be64_to_cpu(ddqp->d_rtb_hardlimit);
58762306a36Sopenharmony_ci	dqp->q_rtb.softlimit = be64_to_cpu(ddqp->d_rtb_softlimit);
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	dqp->q_blk.count = be64_to_cpu(ddqp->d_bcount);
59062306a36Sopenharmony_ci	dqp->q_ino.count = be64_to_cpu(ddqp->d_icount);
59162306a36Sopenharmony_ci	dqp->q_rtb.count = be64_to_cpu(ddqp->d_rtbcount);
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci	dqp->q_blk.timer = xfs_dquot_from_disk_ts(ddqp, ddqp->d_btimer);
59462306a36Sopenharmony_ci	dqp->q_ino.timer = xfs_dquot_from_disk_ts(ddqp, ddqp->d_itimer);
59562306a36Sopenharmony_ci	dqp->q_rtb.timer = xfs_dquot_from_disk_ts(ddqp, ddqp->d_rtbtimer);
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	/*
59862306a36Sopenharmony_ci	 * Reservation counters are defined as reservation plus current usage
59962306a36Sopenharmony_ci	 * to avoid having to add every time.
60062306a36Sopenharmony_ci	 */
60162306a36Sopenharmony_ci	dqp->q_blk.reserved = dqp->q_blk.count;
60262306a36Sopenharmony_ci	dqp->q_ino.reserved = dqp->q_ino.count;
60362306a36Sopenharmony_ci	dqp->q_rtb.reserved = dqp->q_rtb.count;
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci	/* initialize the dquot speculative prealloc thresholds */
60662306a36Sopenharmony_ci	xfs_dquot_set_prealloc_limits(dqp);
60762306a36Sopenharmony_ci	return 0;
60862306a36Sopenharmony_ci}
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci/* Copy the in-core quota fields into the on-disk buffer. */
61162306a36Sopenharmony_civoid
61262306a36Sopenharmony_cixfs_dquot_to_disk(
61362306a36Sopenharmony_ci	struct xfs_disk_dquot	*ddqp,
61462306a36Sopenharmony_ci	struct xfs_dquot	*dqp)
61562306a36Sopenharmony_ci{
61662306a36Sopenharmony_ci	ddqp->d_magic = cpu_to_be16(XFS_DQUOT_MAGIC);
61762306a36Sopenharmony_ci	ddqp->d_version = XFS_DQUOT_VERSION;
61862306a36Sopenharmony_ci	ddqp->d_type = dqp->q_type;
61962306a36Sopenharmony_ci	ddqp->d_id = cpu_to_be32(dqp->q_id);
62062306a36Sopenharmony_ci	ddqp->d_pad0 = 0;
62162306a36Sopenharmony_ci	ddqp->d_pad = 0;
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	ddqp->d_blk_hardlimit = cpu_to_be64(dqp->q_blk.hardlimit);
62462306a36Sopenharmony_ci	ddqp->d_blk_softlimit = cpu_to_be64(dqp->q_blk.softlimit);
62562306a36Sopenharmony_ci	ddqp->d_ino_hardlimit = cpu_to_be64(dqp->q_ino.hardlimit);
62662306a36Sopenharmony_ci	ddqp->d_ino_softlimit = cpu_to_be64(dqp->q_ino.softlimit);
62762306a36Sopenharmony_ci	ddqp->d_rtb_hardlimit = cpu_to_be64(dqp->q_rtb.hardlimit);
62862306a36Sopenharmony_ci	ddqp->d_rtb_softlimit = cpu_to_be64(dqp->q_rtb.softlimit);
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci	ddqp->d_bcount = cpu_to_be64(dqp->q_blk.count);
63162306a36Sopenharmony_ci	ddqp->d_icount = cpu_to_be64(dqp->q_ino.count);
63262306a36Sopenharmony_ci	ddqp->d_rtbcount = cpu_to_be64(dqp->q_rtb.count);
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci	ddqp->d_bwarns = 0;
63562306a36Sopenharmony_ci	ddqp->d_iwarns = 0;
63662306a36Sopenharmony_ci	ddqp->d_rtbwarns = 0;
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci	ddqp->d_btimer = xfs_dquot_to_disk_ts(dqp, dqp->q_blk.timer);
63962306a36Sopenharmony_ci	ddqp->d_itimer = xfs_dquot_to_disk_ts(dqp, dqp->q_ino.timer);
64062306a36Sopenharmony_ci	ddqp->d_rtbtimer = xfs_dquot_to_disk_ts(dqp, dqp->q_rtb.timer);
64162306a36Sopenharmony_ci}
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci/*
64462306a36Sopenharmony_ci * Read in the ondisk dquot using dqtobp() then copy it to an incore version,
64562306a36Sopenharmony_ci * and release the buffer immediately.  If @can_alloc is true, fill any
64662306a36Sopenharmony_ci * holes in the on-disk metadata.
64762306a36Sopenharmony_ci */
64862306a36Sopenharmony_cistatic int
64962306a36Sopenharmony_cixfs_qm_dqread(
65062306a36Sopenharmony_ci	struct xfs_mount	*mp,
65162306a36Sopenharmony_ci	xfs_dqid_t		id,
65262306a36Sopenharmony_ci	xfs_dqtype_t		type,
65362306a36Sopenharmony_ci	bool			can_alloc,
65462306a36Sopenharmony_ci	struct xfs_dquot	**dqpp)
65562306a36Sopenharmony_ci{
65662306a36Sopenharmony_ci	struct xfs_dquot	*dqp;
65762306a36Sopenharmony_ci	struct xfs_buf		*bp;
65862306a36Sopenharmony_ci	int			error;
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	dqp = xfs_dquot_alloc(mp, id, type);
66162306a36Sopenharmony_ci	trace_xfs_dqread(dqp);
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	/* Try to read the buffer, allocating if necessary. */
66462306a36Sopenharmony_ci	error = xfs_dquot_disk_read(mp, dqp, &bp);
66562306a36Sopenharmony_ci	if (error == -ENOENT && can_alloc)
66662306a36Sopenharmony_ci		error = xfs_dquot_disk_alloc(dqp, &bp);
66762306a36Sopenharmony_ci	if (error)
66862306a36Sopenharmony_ci		goto err;
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	/*
67162306a36Sopenharmony_ci	 * At this point we should have a clean locked buffer.  Copy the data
67262306a36Sopenharmony_ci	 * to the incore dquot and release the buffer since the incore dquot
67362306a36Sopenharmony_ci	 * has its own locking protocol so we needn't tie up the buffer any
67462306a36Sopenharmony_ci	 * further.
67562306a36Sopenharmony_ci	 */
67662306a36Sopenharmony_ci	ASSERT(xfs_buf_islocked(bp));
67762306a36Sopenharmony_ci	error = xfs_dquot_from_disk(dqp, bp);
67862306a36Sopenharmony_ci	xfs_buf_relse(bp);
67962306a36Sopenharmony_ci	if (error)
68062306a36Sopenharmony_ci		goto err;
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	*dqpp = dqp;
68362306a36Sopenharmony_ci	return error;
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_cierr:
68662306a36Sopenharmony_ci	trace_xfs_dqread_fail(dqp);
68762306a36Sopenharmony_ci	xfs_qm_dqdestroy(dqp);
68862306a36Sopenharmony_ci	*dqpp = NULL;
68962306a36Sopenharmony_ci	return error;
69062306a36Sopenharmony_ci}
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_ci/*
69362306a36Sopenharmony_ci * Advance to the next id in the current chunk, or if at the
69462306a36Sopenharmony_ci * end of the chunk, skip ahead to first id in next allocated chunk
69562306a36Sopenharmony_ci * using the SEEK_DATA interface.
69662306a36Sopenharmony_ci */
69762306a36Sopenharmony_cistatic int
69862306a36Sopenharmony_cixfs_dq_get_next_id(
69962306a36Sopenharmony_ci	struct xfs_mount	*mp,
70062306a36Sopenharmony_ci	xfs_dqtype_t		type,
70162306a36Sopenharmony_ci	xfs_dqid_t		*id)
70262306a36Sopenharmony_ci{
70362306a36Sopenharmony_ci	struct xfs_inode	*quotip = xfs_quota_inode(mp, type);
70462306a36Sopenharmony_ci	xfs_dqid_t		next_id = *id + 1; /* simple advance */
70562306a36Sopenharmony_ci	uint			lock_flags;
70662306a36Sopenharmony_ci	struct xfs_bmbt_irec	got;
70762306a36Sopenharmony_ci	struct xfs_iext_cursor	cur;
70862306a36Sopenharmony_ci	xfs_fsblock_t		start;
70962306a36Sopenharmony_ci	int			error = 0;
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci	/* If we'd wrap past the max ID, stop */
71262306a36Sopenharmony_ci	if (next_id < *id)
71362306a36Sopenharmony_ci		return -ENOENT;
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci	/* If new ID is within the current chunk, advancing it sufficed */
71662306a36Sopenharmony_ci	if (next_id % mp->m_quotainfo->qi_dqperchunk) {
71762306a36Sopenharmony_ci		*id = next_id;
71862306a36Sopenharmony_ci		return 0;
71962306a36Sopenharmony_ci	}
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci	/* Nope, next_id is now past the current chunk, so find the next one */
72262306a36Sopenharmony_ci	start = (xfs_fsblock_t)next_id / mp->m_quotainfo->qi_dqperchunk;
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci	lock_flags = xfs_ilock_data_map_shared(quotip);
72562306a36Sopenharmony_ci	error = xfs_iread_extents(NULL, quotip, XFS_DATA_FORK);
72662306a36Sopenharmony_ci	if (error)
72762306a36Sopenharmony_ci		return error;
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci	if (xfs_iext_lookup_extent(quotip, &quotip->i_df, start, &cur, &got)) {
73062306a36Sopenharmony_ci		/* contiguous chunk, bump startoff for the id calculation */
73162306a36Sopenharmony_ci		if (got.br_startoff < start)
73262306a36Sopenharmony_ci			got.br_startoff = start;
73362306a36Sopenharmony_ci		*id = got.br_startoff * mp->m_quotainfo->qi_dqperchunk;
73462306a36Sopenharmony_ci	} else {
73562306a36Sopenharmony_ci		error = -ENOENT;
73662306a36Sopenharmony_ci	}
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	xfs_iunlock(quotip, lock_flags);
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	return error;
74162306a36Sopenharmony_ci}
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci/*
74462306a36Sopenharmony_ci * Look up the dquot in the in-core cache.  If found, the dquot is returned
74562306a36Sopenharmony_ci * locked and ready to go.
74662306a36Sopenharmony_ci */
74762306a36Sopenharmony_cistatic struct xfs_dquot *
74862306a36Sopenharmony_cixfs_qm_dqget_cache_lookup(
74962306a36Sopenharmony_ci	struct xfs_mount	*mp,
75062306a36Sopenharmony_ci	struct xfs_quotainfo	*qi,
75162306a36Sopenharmony_ci	struct radix_tree_root	*tree,
75262306a36Sopenharmony_ci	xfs_dqid_t		id)
75362306a36Sopenharmony_ci{
75462306a36Sopenharmony_ci	struct xfs_dquot	*dqp;
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_cirestart:
75762306a36Sopenharmony_ci	mutex_lock(&qi->qi_tree_lock);
75862306a36Sopenharmony_ci	dqp = radix_tree_lookup(tree, id);
75962306a36Sopenharmony_ci	if (!dqp) {
76062306a36Sopenharmony_ci		mutex_unlock(&qi->qi_tree_lock);
76162306a36Sopenharmony_ci		XFS_STATS_INC(mp, xs_qm_dqcachemisses);
76262306a36Sopenharmony_ci		return NULL;
76362306a36Sopenharmony_ci	}
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci	xfs_dqlock(dqp);
76662306a36Sopenharmony_ci	if (dqp->q_flags & XFS_DQFLAG_FREEING) {
76762306a36Sopenharmony_ci		xfs_dqunlock(dqp);
76862306a36Sopenharmony_ci		mutex_unlock(&qi->qi_tree_lock);
76962306a36Sopenharmony_ci		trace_xfs_dqget_freeing(dqp);
77062306a36Sopenharmony_ci		delay(1);
77162306a36Sopenharmony_ci		goto restart;
77262306a36Sopenharmony_ci	}
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci	dqp->q_nrefs++;
77562306a36Sopenharmony_ci	mutex_unlock(&qi->qi_tree_lock);
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	trace_xfs_dqget_hit(dqp);
77862306a36Sopenharmony_ci	XFS_STATS_INC(mp, xs_qm_dqcachehits);
77962306a36Sopenharmony_ci	return dqp;
78062306a36Sopenharmony_ci}
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci/*
78362306a36Sopenharmony_ci * Try to insert a new dquot into the in-core cache.  If an error occurs the
78462306a36Sopenharmony_ci * caller should throw away the dquot and start over.  Otherwise, the dquot
78562306a36Sopenharmony_ci * is returned locked (and held by the cache) as if there had been a cache
78662306a36Sopenharmony_ci * hit.
78762306a36Sopenharmony_ci */
78862306a36Sopenharmony_cistatic int
78962306a36Sopenharmony_cixfs_qm_dqget_cache_insert(
79062306a36Sopenharmony_ci	struct xfs_mount	*mp,
79162306a36Sopenharmony_ci	struct xfs_quotainfo	*qi,
79262306a36Sopenharmony_ci	struct radix_tree_root	*tree,
79362306a36Sopenharmony_ci	xfs_dqid_t		id,
79462306a36Sopenharmony_ci	struct xfs_dquot	*dqp)
79562306a36Sopenharmony_ci{
79662306a36Sopenharmony_ci	int			error;
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ci	mutex_lock(&qi->qi_tree_lock);
79962306a36Sopenharmony_ci	error = radix_tree_insert(tree, id, dqp);
80062306a36Sopenharmony_ci	if (unlikely(error)) {
80162306a36Sopenharmony_ci		/* Duplicate found!  Caller must try again. */
80262306a36Sopenharmony_ci		mutex_unlock(&qi->qi_tree_lock);
80362306a36Sopenharmony_ci		trace_xfs_dqget_dup(dqp);
80462306a36Sopenharmony_ci		return error;
80562306a36Sopenharmony_ci	}
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci	/* Return a locked dquot to the caller, with a reference taken. */
80862306a36Sopenharmony_ci	xfs_dqlock(dqp);
80962306a36Sopenharmony_ci	dqp->q_nrefs = 1;
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci	qi->qi_dquots++;
81262306a36Sopenharmony_ci	mutex_unlock(&qi->qi_tree_lock);
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci	return 0;
81562306a36Sopenharmony_ci}
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci/* Check our input parameters. */
81862306a36Sopenharmony_cistatic int
81962306a36Sopenharmony_cixfs_qm_dqget_checks(
82062306a36Sopenharmony_ci	struct xfs_mount	*mp,
82162306a36Sopenharmony_ci	xfs_dqtype_t		type)
82262306a36Sopenharmony_ci{
82362306a36Sopenharmony_ci	switch (type) {
82462306a36Sopenharmony_ci	case XFS_DQTYPE_USER:
82562306a36Sopenharmony_ci		if (!XFS_IS_UQUOTA_ON(mp))
82662306a36Sopenharmony_ci			return -ESRCH;
82762306a36Sopenharmony_ci		return 0;
82862306a36Sopenharmony_ci	case XFS_DQTYPE_GROUP:
82962306a36Sopenharmony_ci		if (!XFS_IS_GQUOTA_ON(mp))
83062306a36Sopenharmony_ci			return -ESRCH;
83162306a36Sopenharmony_ci		return 0;
83262306a36Sopenharmony_ci	case XFS_DQTYPE_PROJ:
83362306a36Sopenharmony_ci		if (!XFS_IS_PQUOTA_ON(mp))
83462306a36Sopenharmony_ci			return -ESRCH;
83562306a36Sopenharmony_ci		return 0;
83662306a36Sopenharmony_ci	default:
83762306a36Sopenharmony_ci		WARN_ON_ONCE(0);
83862306a36Sopenharmony_ci		return -EINVAL;
83962306a36Sopenharmony_ci	}
84062306a36Sopenharmony_ci}
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_ci/*
84362306a36Sopenharmony_ci * Given the file system, id, and type (UDQUOT/GDQUOT/PDQUOT), return a
84462306a36Sopenharmony_ci * locked dquot, doing an allocation (if requested) as needed.
84562306a36Sopenharmony_ci */
84662306a36Sopenharmony_ciint
84762306a36Sopenharmony_cixfs_qm_dqget(
84862306a36Sopenharmony_ci	struct xfs_mount	*mp,
84962306a36Sopenharmony_ci	xfs_dqid_t		id,
85062306a36Sopenharmony_ci	xfs_dqtype_t		type,
85162306a36Sopenharmony_ci	bool			can_alloc,
85262306a36Sopenharmony_ci	struct xfs_dquot	**O_dqpp)
85362306a36Sopenharmony_ci{
85462306a36Sopenharmony_ci	struct xfs_quotainfo	*qi = mp->m_quotainfo;
85562306a36Sopenharmony_ci	struct radix_tree_root	*tree = xfs_dquot_tree(qi, type);
85662306a36Sopenharmony_ci	struct xfs_dquot	*dqp;
85762306a36Sopenharmony_ci	int			error;
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci	error = xfs_qm_dqget_checks(mp, type);
86062306a36Sopenharmony_ci	if (error)
86162306a36Sopenharmony_ci		return error;
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_cirestart:
86462306a36Sopenharmony_ci	dqp = xfs_qm_dqget_cache_lookup(mp, qi, tree, id);
86562306a36Sopenharmony_ci	if (dqp) {
86662306a36Sopenharmony_ci		*O_dqpp = dqp;
86762306a36Sopenharmony_ci		return 0;
86862306a36Sopenharmony_ci	}
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci	error = xfs_qm_dqread(mp, id, type, can_alloc, &dqp);
87162306a36Sopenharmony_ci	if (error)
87262306a36Sopenharmony_ci		return error;
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci	error = xfs_qm_dqget_cache_insert(mp, qi, tree, id, dqp);
87562306a36Sopenharmony_ci	if (error) {
87662306a36Sopenharmony_ci		/*
87762306a36Sopenharmony_ci		 * Duplicate found. Just throw away the new dquot and start
87862306a36Sopenharmony_ci		 * over.
87962306a36Sopenharmony_ci		 */
88062306a36Sopenharmony_ci		xfs_qm_dqdestroy(dqp);
88162306a36Sopenharmony_ci		XFS_STATS_INC(mp, xs_qm_dquot_dups);
88262306a36Sopenharmony_ci		goto restart;
88362306a36Sopenharmony_ci	}
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_ci	trace_xfs_dqget_miss(dqp);
88662306a36Sopenharmony_ci	*O_dqpp = dqp;
88762306a36Sopenharmony_ci	return 0;
88862306a36Sopenharmony_ci}
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci/*
89162306a36Sopenharmony_ci * Given a dquot id and type, read and initialize a dquot from the on-disk
89262306a36Sopenharmony_ci * metadata.  This function is only for use during quota initialization so
89362306a36Sopenharmony_ci * it ignores the dquot cache assuming that the dquot shrinker isn't set up.
89462306a36Sopenharmony_ci * The caller is responsible for _qm_dqdestroy'ing the returned dquot.
89562306a36Sopenharmony_ci */
89662306a36Sopenharmony_ciint
89762306a36Sopenharmony_cixfs_qm_dqget_uncached(
89862306a36Sopenharmony_ci	struct xfs_mount	*mp,
89962306a36Sopenharmony_ci	xfs_dqid_t		id,
90062306a36Sopenharmony_ci	xfs_dqtype_t		type,
90162306a36Sopenharmony_ci	struct xfs_dquot	**dqpp)
90262306a36Sopenharmony_ci{
90362306a36Sopenharmony_ci	int			error;
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	error = xfs_qm_dqget_checks(mp, type);
90662306a36Sopenharmony_ci	if (error)
90762306a36Sopenharmony_ci		return error;
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci	return xfs_qm_dqread(mp, id, type, 0, dqpp);
91062306a36Sopenharmony_ci}
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci/* Return the quota id for a given inode and type. */
91362306a36Sopenharmony_cixfs_dqid_t
91462306a36Sopenharmony_cixfs_qm_id_for_quotatype(
91562306a36Sopenharmony_ci	struct xfs_inode	*ip,
91662306a36Sopenharmony_ci	xfs_dqtype_t		type)
91762306a36Sopenharmony_ci{
91862306a36Sopenharmony_ci	switch (type) {
91962306a36Sopenharmony_ci	case XFS_DQTYPE_USER:
92062306a36Sopenharmony_ci		return i_uid_read(VFS_I(ip));
92162306a36Sopenharmony_ci	case XFS_DQTYPE_GROUP:
92262306a36Sopenharmony_ci		return i_gid_read(VFS_I(ip));
92362306a36Sopenharmony_ci	case XFS_DQTYPE_PROJ:
92462306a36Sopenharmony_ci		return ip->i_projid;
92562306a36Sopenharmony_ci	}
92662306a36Sopenharmony_ci	ASSERT(0);
92762306a36Sopenharmony_ci	return 0;
92862306a36Sopenharmony_ci}
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ci/*
93162306a36Sopenharmony_ci * Return the dquot for a given inode and type.  If @can_alloc is true, then
93262306a36Sopenharmony_ci * allocate blocks if needed.  The inode's ILOCK must be held and it must not
93362306a36Sopenharmony_ci * have already had an inode attached.
93462306a36Sopenharmony_ci */
93562306a36Sopenharmony_ciint
93662306a36Sopenharmony_cixfs_qm_dqget_inode(
93762306a36Sopenharmony_ci	struct xfs_inode	*ip,
93862306a36Sopenharmony_ci	xfs_dqtype_t		type,
93962306a36Sopenharmony_ci	bool			can_alloc,
94062306a36Sopenharmony_ci	struct xfs_dquot	**O_dqpp)
94162306a36Sopenharmony_ci{
94262306a36Sopenharmony_ci	struct xfs_mount	*mp = ip->i_mount;
94362306a36Sopenharmony_ci	struct xfs_quotainfo	*qi = mp->m_quotainfo;
94462306a36Sopenharmony_ci	struct radix_tree_root	*tree = xfs_dquot_tree(qi, type);
94562306a36Sopenharmony_ci	struct xfs_dquot	*dqp;
94662306a36Sopenharmony_ci	xfs_dqid_t		id;
94762306a36Sopenharmony_ci	int			error;
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_ci	error = xfs_qm_dqget_checks(mp, type);
95062306a36Sopenharmony_ci	if (error)
95162306a36Sopenharmony_ci		return error;
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
95462306a36Sopenharmony_ci	ASSERT(xfs_inode_dquot(ip, type) == NULL);
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci	id = xfs_qm_id_for_quotatype(ip, type);
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_cirestart:
95962306a36Sopenharmony_ci	dqp = xfs_qm_dqget_cache_lookup(mp, qi, tree, id);
96062306a36Sopenharmony_ci	if (dqp) {
96162306a36Sopenharmony_ci		*O_dqpp = dqp;
96262306a36Sopenharmony_ci		return 0;
96362306a36Sopenharmony_ci	}
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	/*
96662306a36Sopenharmony_ci	 * Dquot cache miss. We don't want to keep the inode lock across
96762306a36Sopenharmony_ci	 * a (potential) disk read. Also we don't want to deal with the lock
96862306a36Sopenharmony_ci	 * ordering between quotainode and this inode. OTOH, dropping the inode
96962306a36Sopenharmony_ci	 * lock here means dealing with a chown that can happen before
97062306a36Sopenharmony_ci	 * we re-acquire the lock.
97162306a36Sopenharmony_ci	 */
97262306a36Sopenharmony_ci	xfs_iunlock(ip, XFS_ILOCK_EXCL);
97362306a36Sopenharmony_ci	error = xfs_qm_dqread(mp, id, type, can_alloc, &dqp);
97462306a36Sopenharmony_ci	xfs_ilock(ip, XFS_ILOCK_EXCL);
97562306a36Sopenharmony_ci	if (error)
97662306a36Sopenharmony_ci		return error;
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_ci	/*
97962306a36Sopenharmony_ci	 * A dquot could be attached to this inode by now, since we had
98062306a36Sopenharmony_ci	 * dropped the ilock.
98162306a36Sopenharmony_ci	 */
98262306a36Sopenharmony_ci	if (xfs_this_quota_on(mp, type)) {
98362306a36Sopenharmony_ci		struct xfs_dquot	*dqp1;
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci		dqp1 = xfs_inode_dquot(ip, type);
98662306a36Sopenharmony_ci		if (dqp1) {
98762306a36Sopenharmony_ci			xfs_qm_dqdestroy(dqp);
98862306a36Sopenharmony_ci			dqp = dqp1;
98962306a36Sopenharmony_ci			xfs_dqlock(dqp);
99062306a36Sopenharmony_ci			goto dqret;
99162306a36Sopenharmony_ci		}
99262306a36Sopenharmony_ci	} else {
99362306a36Sopenharmony_ci		/* inode stays locked on return */
99462306a36Sopenharmony_ci		xfs_qm_dqdestroy(dqp);
99562306a36Sopenharmony_ci		return -ESRCH;
99662306a36Sopenharmony_ci	}
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci	error = xfs_qm_dqget_cache_insert(mp, qi, tree, id, dqp);
99962306a36Sopenharmony_ci	if (error) {
100062306a36Sopenharmony_ci		/*
100162306a36Sopenharmony_ci		 * Duplicate found. Just throw away the new dquot and start
100262306a36Sopenharmony_ci		 * over.
100362306a36Sopenharmony_ci		 */
100462306a36Sopenharmony_ci		xfs_qm_dqdestroy(dqp);
100562306a36Sopenharmony_ci		XFS_STATS_INC(mp, xs_qm_dquot_dups);
100662306a36Sopenharmony_ci		goto restart;
100762306a36Sopenharmony_ci	}
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_cidqret:
101062306a36Sopenharmony_ci	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
101162306a36Sopenharmony_ci	trace_xfs_dqget_miss(dqp);
101262306a36Sopenharmony_ci	*O_dqpp = dqp;
101362306a36Sopenharmony_ci	return 0;
101462306a36Sopenharmony_ci}
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ci/*
101762306a36Sopenharmony_ci * Starting at @id and progressing upwards, look for an initialized incore
101862306a36Sopenharmony_ci * dquot, lock it, and return it.
101962306a36Sopenharmony_ci */
102062306a36Sopenharmony_ciint
102162306a36Sopenharmony_cixfs_qm_dqget_next(
102262306a36Sopenharmony_ci	struct xfs_mount	*mp,
102362306a36Sopenharmony_ci	xfs_dqid_t		id,
102462306a36Sopenharmony_ci	xfs_dqtype_t		type,
102562306a36Sopenharmony_ci	struct xfs_dquot	**dqpp)
102662306a36Sopenharmony_ci{
102762306a36Sopenharmony_ci	struct xfs_dquot	*dqp;
102862306a36Sopenharmony_ci	int			error = 0;
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_ci	*dqpp = NULL;
103162306a36Sopenharmony_ci	for (; !error; error = xfs_dq_get_next_id(mp, type, &id)) {
103262306a36Sopenharmony_ci		error = xfs_qm_dqget(mp, id, type, false, &dqp);
103362306a36Sopenharmony_ci		if (error == -ENOENT)
103462306a36Sopenharmony_ci			continue;
103562306a36Sopenharmony_ci		else if (error != 0)
103662306a36Sopenharmony_ci			break;
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci		if (!XFS_IS_DQUOT_UNINITIALIZED(dqp)) {
103962306a36Sopenharmony_ci			*dqpp = dqp;
104062306a36Sopenharmony_ci			return 0;
104162306a36Sopenharmony_ci		}
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci		xfs_qm_dqput(dqp);
104462306a36Sopenharmony_ci	}
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_ci	return error;
104762306a36Sopenharmony_ci}
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_ci/*
105062306a36Sopenharmony_ci * Release a reference to the dquot (decrement ref-count) and unlock it.
105162306a36Sopenharmony_ci *
105262306a36Sopenharmony_ci * If there is a group quota attached to this dquot, carefully release that
105362306a36Sopenharmony_ci * too without tripping over deadlocks'n'stuff.
105462306a36Sopenharmony_ci */
105562306a36Sopenharmony_civoid
105662306a36Sopenharmony_cixfs_qm_dqput(
105762306a36Sopenharmony_ci	struct xfs_dquot	*dqp)
105862306a36Sopenharmony_ci{
105962306a36Sopenharmony_ci	ASSERT(dqp->q_nrefs > 0);
106062306a36Sopenharmony_ci	ASSERT(XFS_DQ_IS_LOCKED(dqp));
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci	trace_xfs_dqput(dqp);
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci	if (--dqp->q_nrefs == 0) {
106562306a36Sopenharmony_ci		struct xfs_quotainfo	*qi = dqp->q_mount->m_quotainfo;
106662306a36Sopenharmony_ci		trace_xfs_dqput_free(dqp);
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_ci		if (list_lru_add(&qi->qi_lru, &dqp->q_lru))
106962306a36Sopenharmony_ci			XFS_STATS_INC(dqp->q_mount, xs_qm_dquot_unused);
107062306a36Sopenharmony_ci	}
107162306a36Sopenharmony_ci	xfs_dqunlock(dqp);
107262306a36Sopenharmony_ci}
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci/*
107562306a36Sopenharmony_ci * Release a dquot. Flush it if dirty, then dqput() it.
107662306a36Sopenharmony_ci * dquot must not be locked.
107762306a36Sopenharmony_ci */
107862306a36Sopenharmony_civoid
107962306a36Sopenharmony_cixfs_qm_dqrele(
108062306a36Sopenharmony_ci	struct xfs_dquot	*dqp)
108162306a36Sopenharmony_ci{
108262306a36Sopenharmony_ci	if (!dqp)
108362306a36Sopenharmony_ci		return;
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	trace_xfs_dqrele(dqp);
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_ci	xfs_dqlock(dqp);
108862306a36Sopenharmony_ci	/*
108962306a36Sopenharmony_ci	 * We don't care to flush it if the dquot is dirty here.
109062306a36Sopenharmony_ci	 * That will create stutters that we want to avoid.
109162306a36Sopenharmony_ci	 * Instead we do a delayed write when we try to reclaim
109262306a36Sopenharmony_ci	 * a dirty dquot. Also xfs_sync will take part of the burden...
109362306a36Sopenharmony_ci	 */
109462306a36Sopenharmony_ci	xfs_qm_dqput(dqp);
109562306a36Sopenharmony_ci}
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci/*
109862306a36Sopenharmony_ci * This is the dquot flushing I/O completion routine.  It is called
109962306a36Sopenharmony_ci * from interrupt level when the buffer containing the dquot is
110062306a36Sopenharmony_ci * flushed to disk.  It is responsible for removing the dquot logitem
110162306a36Sopenharmony_ci * from the AIL if it has not been re-logged, and unlocking the dquot's
110262306a36Sopenharmony_ci * flush lock. This behavior is very similar to that of inodes..
110362306a36Sopenharmony_ci */
110462306a36Sopenharmony_cistatic void
110562306a36Sopenharmony_cixfs_qm_dqflush_done(
110662306a36Sopenharmony_ci	struct xfs_log_item	*lip)
110762306a36Sopenharmony_ci{
110862306a36Sopenharmony_ci	struct xfs_dq_logitem	*qip = (struct xfs_dq_logitem *)lip;
110962306a36Sopenharmony_ci	struct xfs_dquot	*dqp = qip->qli_dquot;
111062306a36Sopenharmony_ci	struct xfs_ail		*ailp = lip->li_ailp;
111162306a36Sopenharmony_ci	xfs_lsn_t		tail_lsn;
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci	/*
111462306a36Sopenharmony_ci	 * We only want to pull the item from the AIL if its
111562306a36Sopenharmony_ci	 * location in the log has not changed since we started the flush.
111662306a36Sopenharmony_ci	 * Thus, we only bother if the dquot's lsn has
111762306a36Sopenharmony_ci	 * not changed. First we check the lsn outside the lock
111862306a36Sopenharmony_ci	 * since it's cheaper, and then we recheck while
111962306a36Sopenharmony_ci	 * holding the lock before removing the dquot from the AIL.
112062306a36Sopenharmony_ci	 */
112162306a36Sopenharmony_ci	if (test_bit(XFS_LI_IN_AIL, &lip->li_flags) &&
112262306a36Sopenharmony_ci	    ((lip->li_lsn == qip->qli_flush_lsn) ||
112362306a36Sopenharmony_ci	     test_bit(XFS_LI_FAILED, &lip->li_flags))) {
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci		spin_lock(&ailp->ail_lock);
112662306a36Sopenharmony_ci		xfs_clear_li_failed(lip);
112762306a36Sopenharmony_ci		if (lip->li_lsn == qip->qli_flush_lsn) {
112862306a36Sopenharmony_ci			/* xfs_ail_update_finish() drops the AIL lock */
112962306a36Sopenharmony_ci			tail_lsn = xfs_ail_delete_one(ailp, lip);
113062306a36Sopenharmony_ci			xfs_ail_update_finish(ailp, tail_lsn);
113162306a36Sopenharmony_ci		} else {
113262306a36Sopenharmony_ci			spin_unlock(&ailp->ail_lock);
113362306a36Sopenharmony_ci		}
113462306a36Sopenharmony_ci	}
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci	/*
113762306a36Sopenharmony_ci	 * Release the dq's flush lock since we're done with it.
113862306a36Sopenharmony_ci	 */
113962306a36Sopenharmony_ci	xfs_dqfunlock(dqp);
114062306a36Sopenharmony_ci}
114162306a36Sopenharmony_ci
114262306a36Sopenharmony_civoid
114362306a36Sopenharmony_cixfs_buf_dquot_iodone(
114462306a36Sopenharmony_ci	struct xfs_buf		*bp)
114562306a36Sopenharmony_ci{
114662306a36Sopenharmony_ci	struct xfs_log_item	*lip, *n;
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci	list_for_each_entry_safe(lip, n, &bp->b_li_list, li_bio_list) {
114962306a36Sopenharmony_ci		list_del_init(&lip->li_bio_list);
115062306a36Sopenharmony_ci		xfs_qm_dqflush_done(lip);
115162306a36Sopenharmony_ci	}
115262306a36Sopenharmony_ci}
115362306a36Sopenharmony_ci
115462306a36Sopenharmony_civoid
115562306a36Sopenharmony_cixfs_buf_dquot_io_fail(
115662306a36Sopenharmony_ci	struct xfs_buf		*bp)
115762306a36Sopenharmony_ci{
115862306a36Sopenharmony_ci	struct xfs_log_item	*lip;
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_ci	spin_lock(&bp->b_mount->m_ail->ail_lock);
116162306a36Sopenharmony_ci	list_for_each_entry(lip, &bp->b_li_list, li_bio_list)
116262306a36Sopenharmony_ci		xfs_set_li_failed(lip, bp);
116362306a36Sopenharmony_ci	spin_unlock(&bp->b_mount->m_ail->ail_lock);
116462306a36Sopenharmony_ci}
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci/* Check incore dquot for errors before we flush. */
116762306a36Sopenharmony_cistatic xfs_failaddr_t
116862306a36Sopenharmony_cixfs_qm_dqflush_check(
116962306a36Sopenharmony_ci	struct xfs_dquot	*dqp)
117062306a36Sopenharmony_ci{
117162306a36Sopenharmony_ci	xfs_dqtype_t		type = xfs_dquot_type(dqp);
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci	if (type != XFS_DQTYPE_USER &&
117462306a36Sopenharmony_ci	    type != XFS_DQTYPE_GROUP &&
117562306a36Sopenharmony_ci	    type != XFS_DQTYPE_PROJ)
117662306a36Sopenharmony_ci		return __this_address;
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci	if (dqp->q_id == 0)
117962306a36Sopenharmony_ci		return NULL;
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_ci	if (dqp->q_blk.softlimit && dqp->q_blk.count > dqp->q_blk.softlimit &&
118262306a36Sopenharmony_ci	    !dqp->q_blk.timer)
118362306a36Sopenharmony_ci		return __this_address;
118462306a36Sopenharmony_ci
118562306a36Sopenharmony_ci	if (dqp->q_ino.softlimit && dqp->q_ino.count > dqp->q_ino.softlimit &&
118662306a36Sopenharmony_ci	    !dqp->q_ino.timer)
118762306a36Sopenharmony_ci		return __this_address;
118862306a36Sopenharmony_ci
118962306a36Sopenharmony_ci	if (dqp->q_rtb.softlimit && dqp->q_rtb.count > dqp->q_rtb.softlimit &&
119062306a36Sopenharmony_ci	    !dqp->q_rtb.timer)
119162306a36Sopenharmony_ci		return __this_address;
119262306a36Sopenharmony_ci
119362306a36Sopenharmony_ci	/* bigtime flag should never be set on root dquots */
119462306a36Sopenharmony_ci	if (dqp->q_type & XFS_DQTYPE_BIGTIME) {
119562306a36Sopenharmony_ci		if (!xfs_has_bigtime(dqp->q_mount))
119662306a36Sopenharmony_ci			return __this_address;
119762306a36Sopenharmony_ci		if (dqp->q_id == 0)
119862306a36Sopenharmony_ci			return __this_address;
119962306a36Sopenharmony_ci	}
120062306a36Sopenharmony_ci
120162306a36Sopenharmony_ci	return NULL;
120262306a36Sopenharmony_ci}
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci/*
120562306a36Sopenharmony_ci * Write a modified dquot to disk.
120662306a36Sopenharmony_ci * The dquot must be locked and the flush lock too taken by caller.
120762306a36Sopenharmony_ci * The flush lock will not be unlocked until the dquot reaches the disk,
120862306a36Sopenharmony_ci * but the dquot is free to be unlocked and modified by the caller
120962306a36Sopenharmony_ci * in the interim. Dquot is still locked on return. This behavior is
121062306a36Sopenharmony_ci * identical to that of inodes.
121162306a36Sopenharmony_ci */
121262306a36Sopenharmony_ciint
121362306a36Sopenharmony_cixfs_qm_dqflush(
121462306a36Sopenharmony_ci	struct xfs_dquot	*dqp,
121562306a36Sopenharmony_ci	struct xfs_buf		**bpp)
121662306a36Sopenharmony_ci{
121762306a36Sopenharmony_ci	struct xfs_mount	*mp = dqp->q_mount;
121862306a36Sopenharmony_ci	struct xfs_log_item	*lip = &dqp->q_logitem.qli_item;
121962306a36Sopenharmony_ci	struct xfs_buf		*bp;
122062306a36Sopenharmony_ci	struct xfs_dqblk	*dqblk;
122162306a36Sopenharmony_ci	xfs_failaddr_t		fa;
122262306a36Sopenharmony_ci	int			error;
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci	ASSERT(XFS_DQ_IS_LOCKED(dqp));
122562306a36Sopenharmony_ci	ASSERT(!completion_done(&dqp->q_flush));
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	trace_xfs_dqflush(dqp);
122862306a36Sopenharmony_ci
122962306a36Sopenharmony_ci	*bpp = NULL;
123062306a36Sopenharmony_ci
123162306a36Sopenharmony_ci	xfs_qm_dqunpin_wait(dqp);
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_ci	/*
123462306a36Sopenharmony_ci	 * Get the buffer containing the on-disk dquot
123562306a36Sopenharmony_ci	 */
123662306a36Sopenharmony_ci	error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno,
123762306a36Sopenharmony_ci				   mp->m_quotainfo->qi_dqchunklen, XBF_TRYLOCK,
123862306a36Sopenharmony_ci				   &bp, &xfs_dquot_buf_ops);
123962306a36Sopenharmony_ci	if (error == -EAGAIN)
124062306a36Sopenharmony_ci		goto out_unlock;
124162306a36Sopenharmony_ci	if (error)
124262306a36Sopenharmony_ci		goto out_abort;
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_ci	fa = xfs_qm_dqflush_check(dqp);
124562306a36Sopenharmony_ci	if (fa) {
124662306a36Sopenharmony_ci		xfs_alert(mp, "corrupt dquot ID 0x%x in memory at %pS",
124762306a36Sopenharmony_ci				dqp->q_id, fa);
124862306a36Sopenharmony_ci		xfs_buf_relse(bp);
124962306a36Sopenharmony_ci		error = -EFSCORRUPTED;
125062306a36Sopenharmony_ci		goto out_abort;
125162306a36Sopenharmony_ci	}
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_ci	/* Flush the incore dquot to the ondisk buffer. */
125462306a36Sopenharmony_ci	dqblk = xfs_buf_offset(bp, dqp->q_bufoffset);
125562306a36Sopenharmony_ci	xfs_dquot_to_disk(&dqblk->dd_diskdq, dqp);
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_ci	/*
125862306a36Sopenharmony_ci	 * Clear the dirty field and remember the flush lsn for later use.
125962306a36Sopenharmony_ci	 */
126062306a36Sopenharmony_ci	dqp->q_flags &= ~XFS_DQFLAG_DIRTY;
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_ci	xfs_trans_ail_copy_lsn(mp->m_ail, &dqp->q_logitem.qli_flush_lsn,
126362306a36Sopenharmony_ci					&dqp->q_logitem.qli_item.li_lsn);
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ci	/*
126662306a36Sopenharmony_ci	 * copy the lsn into the on-disk dquot now while we have the in memory
126762306a36Sopenharmony_ci	 * dquot here. This can't be done later in the write verifier as we
126862306a36Sopenharmony_ci	 * can't get access to the log item at that point in time.
126962306a36Sopenharmony_ci	 *
127062306a36Sopenharmony_ci	 * We also calculate the CRC here so that the on-disk dquot in the
127162306a36Sopenharmony_ci	 * buffer always has a valid CRC. This ensures there is no possibility
127262306a36Sopenharmony_ci	 * of a dquot without an up-to-date CRC getting to disk.
127362306a36Sopenharmony_ci	 */
127462306a36Sopenharmony_ci	if (xfs_has_crc(mp)) {
127562306a36Sopenharmony_ci		dqblk->dd_lsn = cpu_to_be64(dqp->q_logitem.qli_item.li_lsn);
127662306a36Sopenharmony_ci		xfs_update_cksum((char *)dqblk, sizeof(struct xfs_dqblk),
127762306a36Sopenharmony_ci				 XFS_DQUOT_CRC_OFF);
127862306a36Sopenharmony_ci	}
127962306a36Sopenharmony_ci
128062306a36Sopenharmony_ci	/*
128162306a36Sopenharmony_ci	 * Attach the dquot to the buffer so that we can remove this dquot from
128262306a36Sopenharmony_ci	 * the AIL and release the flush lock once the dquot is synced to disk.
128362306a36Sopenharmony_ci	 */
128462306a36Sopenharmony_ci	bp->b_flags |= _XBF_DQUOTS;
128562306a36Sopenharmony_ci	list_add_tail(&dqp->q_logitem.qli_item.li_bio_list, &bp->b_li_list);
128662306a36Sopenharmony_ci
128762306a36Sopenharmony_ci	/*
128862306a36Sopenharmony_ci	 * If the buffer is pinned then push on the log so we won't
128962306a36Sopenharmony_ci	 * get stuck waiting in the write for too long.
129062306a36Sopenharmony_ci	 */
129162306a36Sopenharmony_ci	if (xfs_buf_ispinned(bp)) {
129262306a36Sopenharmony_ci		trace_xfs_dqflush_force(dqp);
129362306a36Sopenharmony_ci		xfs_log_force(mp, 0);
129462306a36Sopenharmony_ci	}
129562306a36Sopenharmony_ci
129662306a36Sopenharmony_ci	trace_xfs_dqflush_done(dqp);
129762306a36Sopenharmony_ci	*bpp = bp;
129862306a36Sopenharmony_ci	return 0;
129962306a36Sopenharmony_ci
130062306a36Sopenharmony_ciout_abort:
130162306a36Sopenharmony_ci	dqp->q_flags &= ~XFS_DQFLAG_DIRTY;
130262306a36Sopenharmony_ci	xfs_trans_ail_delete(lip, 0);
130362306a36Sopenharmony_ci	xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
130462306a36Sopenharmony_ciout_unlock:
130562306a36Sopenharmony_ci	xfs_dqfunlock(dqp);
130662306a36Sopenharmony_ci	return error;
130762306a36Sopenharmony_ci}
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_ci/*
131062306a36Sopenharmony_ci * Lock two xfs_dquot structures.
131162306a36Sopenharmony_ci *
131262306a36Sopenharmony_ci * To avoid deadlocks we always lock the quota structure with
131362306a36Sopenharmony_ci * the lowerd id first.
131462306a36Sopenharmony_ci */
131562306a36Sopenharmony_civoid
131662306a36Sopenharmony_cixfs_dqlock2(
131762306a36Sopenharmony_ci	struct xfs_dquot	*d1,
131862306a36Sopenharmony_ci	struct xfs_dquot	*d2)
131962306a36Sopenharmony_ci{
132062306a36Sopenharmony_ci	if (d1 && d2) {
132162306a36Sopenharmony_ci		ASSERT(d1 != d2);
132262306a36Sopenharmony_ci		if (d1->q_id > d2->q_id) {
132362306a36Sopenharmony_ci			mutex_lock(&d2->q_qlock);
132462306a36Sopenharmony_ci			mutex_lock_nested(&d1->q_qlock, XFS_QLOCK_NESTED);
132562306a36Sopenharmony_ci		} else {
132662306a36Sopenharmony_ci			mutex_lock(&d1->q_qlock);
132762306a36Sopenharmony_ci			mutex_lock_nested(&d2->q_qlock, XFS_QLOCK_NESTED);
132862306a36Sopenharmony_ci		}
132962306a36Sopenharmony_ci	} else if (d1) {
133062306a36Sopenharmony_ci		mutex_lock(&d1->q_qlock);
133162306a36Sopenharmony_ci	} else if (d2) {
133262306a36Sopenharmony_ci		mutex_lock(&d2->q_qlock);
133362306a36Sopenharmony_ci	}
133462306a36Sopenharmony_ci}
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ciint __init
133762306a36Sopenharmony_cixfs_qm_init(void)
133862306a36Sopenharmony_ci{
133962306a36Sopenharmony_ci	xfs_dquot_cache = kmem_cache_create("xfs_dquot",
134062306a36Sopenharmony_ci					  sizeof(struct xfs_dquot),
134162306a36Sopenharmony_ci					  0, 0, NULL);
134262306a36Sopenharmony_ci	if (!xfs_dquot_cache)
134362306a36Sopenharmony_ci		goto out;
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci	xfs_dqtrx_cache = kmem_cache_create("xfs_dqtrx",
134662306a36Sopenharmony_ci					     sizeof(struct xfs_dquot_acct),
134762306a36Sopenharmony_ci					     0, 0, NULL);
134862306a36Sopenharmony_ci	if (!xfs_dqtrx_cache)
134962306a36Sopenharmony_ci		goto out_free_dquot_cache;
135062306a36Sopenharmony_ci
135162306a36Sopenharmony_ci	return 0;
135262306a36Sopenharmony_ci
135362306a36Sopenharmony_ciout_free_dquot_cache:
135462306a36Sopenharmony_ci	kmem_cache_destroy(xfs_dquot_cache);
135562306a36Sopenharmony_ciout:
135662306a36Sopenharmony_ci	return -ENOMEM;
135762306a36Sopenharmony_ci}
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_civoid
136062306a36Sopenharmony_cixfs_qm_exit(void)
136162306a36Sopenharmony_ci{
136262306a36Sopenharmony_ci	kmem_cache_destroy(xfs_dqtrx_cache);
136362306a36Sopenharmony_ci	kmem_cache_destroy(xfs_dquot_cache);
136462306a36Sopenharmony_ci}
136562306a36Sopenharmony_ci
136662306a36Sopenharmony_ci/*
136762306a36Sopenharmony_ci * Iterate every dquot of a particular type.  The caller must ensure that the
136862306a36Sopenharmony_ci * particular quota type is active.  iter_fn can return negative error codes,
136962306a36Sopenharmony_ci * or -ECANCELED to indicate that it wants to stop iterating.
137062306a36Sopenharmony_ci */
137162306a36Sopenharmony_ciint
137262306a36Sopenharmony_cixfs_qm_dqiterate(
137362306a36Sopenharmony_ci	struct xfs_mount	*mp,
137462306a36Sopenharmony_ci	xfs_dqtype_t		type,
137562306a36Sopenharmony_ci	xfs_qm_dqiterate_fn	iter_fn,
137662306a36Sopenharmony_ci	void			*priv)
137762306a36Sopenharmony_ci{
137862306a36Sopenharmony_ci	struct xfs_dquot	*dq;
137962306a36Sopenharmony_ci	xfs_dqid_t		id = 0;
138062306a36Sopenharmony_ci	int			error;
138162306a36Sopenharmony_ci
138262306a36Sopenharmony_ci	do {
138362306a36Sopenharmony_ci		error = xfs_qm_dqget_next(mp, id, type, &dq);
138462306a36Sopenharmony_ci		if (error == -ENOENT)
138562306a36Sopenharmony_ci			return 0;
138662306a36Sopenharmony_ci		if (error)
138762306a36Sopenharmony_ci			return error;
138862306a36Sopenharmony_ci
138962306a36Sopenharmony_ci		error = iter_fn(dq, type, priv);
139062306a36Sopenharmony_ci		id = dq->q_id + 1;
139162306a36Sopenharmony_ci		xfs_qm_dqput(dq);
139262306a36Sopenharmony_ci	} while (error == 0 && id != 0);
139362306a36Sopenharmony_ci
139462306a36Sopenharmony_ci	return error;
139562306a36Sopenharmony_ci}
1396