fs/xfs/xfs_dquot.c

Source file repositories/reference/linux-study-clean/fs/xfs/xfs_dquot.c

File Facts

System
Linux kernel
Corpus path
fs/xfs/xfs_dquot.c
Extension
.c
Size
39499 bytes
Lines
1552
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (xfs_has_crc(mp)) {
			uuid_copy(&d->dd_uuid, &mp->m_sb.sb_meta_uuid);
			xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk),
					 XFS_DQUOT_CRC_OFF);
		}
	}

	xfs_trans_dquot_buf(tp, bp, blftype);

	/*
	 * quotacheck uses delayed writes to update all the dquots on disk in an
	 * efficient manner instead of logging the individual dquot changes as
	 * they are made. However if we log the buffer allocated here and crash
	 * after quotacheck while the logged initialisation is still in the
	 * active region of the log, log recovery can replay the dquot buffer
	 * initialisation over the top of the checked dquots and corrupt quota
	 * accounting.
	 *
	 * To avoid this problem, quotacheck cannot log the initialised buffer.
	 * We must still dirty the buffer and write it back before the
	 * allocation transaction clears the log. Therefore, mark the buffer as
	 * ordered instead of logging it directly. This is safe for quotacheck
	 * because it detects and repairs allocated but initialized dquot blocks
	 * in the quota inodes.
	 */
	if (!(mp->m_qflags & qflag))
		xfs_trans_ordered_buf(tp, bp);
	else
		xfs_trans_log_buf(tp, bp, 0, BBTOB(q->qi_dqchunklen) - 1);
}

static void
xfs_dquot_set_prealloc(
	struct xfs_dquot_pre		*pre,
	const struct xfs_dquot_res	*res)
{
	xfs_qcnt_t			space;

	pre->q_prealloc_hi_wmark = res->hardlimit;
	pre->q_prealloc_lo_wmark = res->softlimit;

	space = div_u64(pre->q_prealloc_hi_wmark, 100);
	if (!pre->q_prealloc_lo_wmark)
		pre->q_prealloc_lo_wmark = space * 95;

	pre->q_low_space[XFS_QLOWSP_1_PCNT] = space;
	pre->q_low_space[XFS_QLOWSP_3_PCNT] = space * 3;
	pre->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5;
}

/*
 * Initialize the dynamic speculative preallocation thresholds. The lo/hi
 * watermarks correspond to the soft and hard limits by default. If a soft limit
 * is not specified, we use 95% of the hard limit.
 */
void
xfs_dquot_set_prealloc_limits(struct xfs_dquot *dqp)
{
	xfs_dquot_set_prealloc(&dqp->q_blk_prealloc, &dqp->q_blk);
	xfs_dquot_set_prealloc(&dqp->q_rtb_prealloc, &dqp->q_rtb);
}

/*
 * Ensure that the given in-core dquot has a buffer on disk backing it, and
 * return the buffer locked and held. This is called when the bmapi finds a
 * hole.
 */
STATIC int
xfs_dquot_disk_alloc(
	struct xfs_dquot	*dqp,
	struct xfs_buf		**bpp)
{
	struct xfs_bmbt_irec	map;
	struct xfs_trans	*tp;
	struct xfs_mount	*mp = dqp->q_mount;
	struct xfs_buf		*bp;
	xfs_dqtype_t		qtype = xfs_dquot_type(dqp);
	struct xfs_inode	*quotip = xfs_quota_inode(mp, qtype);
	int			nmaps = 1;
	int			error;

	trace_xfs_dqalloc(dqp);

	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_dqalloc,
			XFS_QM_DQALLOC_SPACE_RES(mp), 0, 0, &tp);
	if (error)
		return error;

	xfs_ilock(quotip, XFS_ILOCK_EXCL);
	xfs_trans_ijoin(tp, quotip, 0);

Annotation

Implementation Notes