Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2ba13721 authored by Brian Foster's avatar Brian Foster Committed by Darrick J. Wong
Browse files

xfs: use ->t_dfops in dqalloc transaction



xfs_dquot_disk_alloc() receives a transaction from the caller and
passes a local dfops along to xfs_bmapi_write(). If we attach this
dfops to the transaction, we have to make sure to clear it before
returning to avoid invalid access of stack memory.

Since xfs_qm_dqread_alloc() is the only caller, pull dfops into the
caller and attach it to the transaction to eliminate this pattern
entirely.

Signed-off-by: default avatarBrian Foster <bfoster@redhat.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
parent 32a9b7c6
Loading
Loading
Loading
Loading
+20 −14
Original line number Original line Diff line number Diff line
@@ -286,8 +286,8 @@ xfs_dquot_disk_alloc(
	struct xfs_buf		**bpp)
	struct xfs_buf		**bpp)
{
{
	struct xfs_bmbt_irec	map;
	struct xfs_bmbt_irec	map;
	struct xfs_defer_ops	dfops;
	struct xfs_trans	*tp = *tpp;
	struct xfs_mount	*mp = (*tpp)->t_mountp;
	struct xfs_mount	*mp = tp->t_mountp;
	struct xfs_buf		*bp;
	struct xfs_buf		*bp;
	struct xfs_inode	*quotip = xfs_quota_inode(mp, dqp->dq_flags);
	struct xfs_inode	*quotip = xfs_quota_inode(mp, dqp->dq_flags);
	xfs_fsblock_t		firstblock;
	xfs_fsblock_t		firstblock;
@@ -296,7 +296,8 @@ xfs_dquot_disk_alloc(


	trace_xfs_dqalloc(dqp);
	trace_xfs_dqalloc(dqp);


	xfs_defer_init(&dfops, &firstblock);
	xfs_defer_init(tp->t_dfops, &firstblock);

	xfs_ilock(quotip, XFS_ILOCK_EXCL);
	xfs_ilock(quotip, XFS_ILOCK_EXCL);
	if (!xfs_this_quota_on(dqp->q_mount, dqp->dq_flags)) {
	if (!xfs_this_quota_on(dqp->q_mount, dqp->dq_flags)) {
		/*
		/*
@@ -308,11 +309,11 @@ xfs_dquot_disk_alloc(
	}
	}


	/* Create the block mapping. */
	/* Create the block mapping. */
	xfs_trans_ijoin(*tpp, quotip, XFS_ILOCK_EXCL);
	xfs_trans_ijoin(tp, quotip, XFS_ILOCK_EXCL);
	error = xfs_bmapi_write(*tpp, quotip, dqp->q_fileoffset,
	error = xfs_bmapi_write(tp, quotip, dqp->q_fileoffset,
			XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA,
			XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA,
			&firstblock, XFS_QM_DQALLOC_SPACE_RES(mp),
			&firstblock, XFS_QM_DQALLOC_SPACE_RES(mp),
			&map, &nmaps, &dfops);
			&map, &nmaps, tp->t_dfops);
	if (error)
	if (error)
		goto error0;
		goto error0;
	ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB);
	ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB);
@@ -326,7 +327,7 @@ xfs_dquot_disk_alloc(
	dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock);
	dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock);


	/* now we can just get the buffer (there's nothing to read yet) */
	/* now we can just get the buffer (there's nothing to read yet) */
	bp = xfs_trans_get_buf(*tpp, mp->m_ddev_targp, dqp->q_blkno,
	bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, dqp->q_blkno,
			mp->m_quotainfo->qi_dqchunklen, 0);
			mp->m_quotainfo->qi_dqchunklen, 0);
	if (!bp) {
	if (!bp) {
		error = -ENOMEM;
		error = -ENOMEM;
@@ -338,7 +339,7 @@ xfs_dquot_disk_alloc(
	 * Make a chunk of dquots out of this buffer and log
	 * Make a chunk of dquots out of this buffer and log
	 * the entire thing.
	 * the entire thing.
	 */
	 */
	xfs_qm_init_dquot_blk(*tpp, mp, be32_to_cpu(dqp->q_core.d_id),
	xfs_qm_init_dquot_blk(tp, mp, be32_to_cpu(dqp->q_core.d_id),
			      dqp->dq_flags & XFS_DQ_ALLTYPES, bp);
			      dqp->dq_flags & XFS_DQ_ALLTYPES, bp);
	xfs_buf_set_ref(bp, XFS_DQUOT_REF);
	xfs_buf_set_ref(bp, XFS_DQUOT_REF);


@@ -364,14 +365,15 @@ xfs_dquot_disk_alloc(
	 * is responsible for unlocking any buffer passed back, either
	 * is responsible for unlocking any buffer passed back, either
	 * manually or by committing the transaction.
	 * manually or by committing the transaction.
	 */
	 */
	xfs_trans_bhold(*tpp, bp);
	xfs_trans_bhold(tp, bp);
	error = xfs_defer_bjoin(&dfops, bp);
	error = xfs_defer_bjoin(tp->t_dfops, bp);
	if (error) {
	if (error) {
		xfs_trans_bhold_release(*tpp, bp);
		xfs_trans_bhold_release(tp, bp);
		xfs_trans_brelse(*tpp, bp);
		xfs_trans_brelse(tp, bp);
		goto error1;
		goto error1;
	}
	}
	error = xfs_defer_finish(tpp, &dfops);
	error = xfs_defer_finish(tpp, tp->t_dfops);
	tp = *tpp;
	if (error) {
	if (error) {
		xfs_buf_relse(bp);
		xfs_buf_relse(bp);
		goto error1;
		goto error1;
@@ -380,7 +382,7 @@ xfs_dquot_disk_alloc(
	return 0;
	return 0;


error1:
error1:
	xfs_defer_cancel(&dfops);
	xfs_defer_cancel(tp->t_dfops);
error0:
error0:
	return error;
	return error;
}
}
@@ -538,13 +540,17 @@ xfs_qm_dqread_alloc(
	struct xfs_buf		**bpp)
	struct xfs_buf		**bpp)
{
{
	struct xfs_trans	*tp;
	struct xfs_trans	*tp;
	struct xfs_defer_ops	dfops;
	struct xfs_buf		*bp;
	struct xfs_buf		*bp;
	xfs_fsblock_t		firstblock;
	int			error;
	int			error;


	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_dqalloc,
	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_dqalloc,
			XFS_QM_DQALLOC_SPACE_RES(mp), 0, 0, &tp);
			XFS_QM_DQALLOC_SPACE_RES(mp), 0, 0, &tp);
	if (error)
	if (error)
		goto err;
		goto err;
	xfs_defer_init(&dfops, &firstblock);
	tp->t_dfops = &dfops;


	error = xfs_dquot_disk_alloc(&tp, dqp, &bp);
	error = xfs_dquot_disk_alloc(&tp, dqp, &bp);
	if (error)
	if (error)