diff options
author | Brian Foster | 2018-07-11 22:26:11 -0700 |
---|---|---|
committer | Darrick J. Wong | 2018-07-11 22:26:11 -0700 |
commit | 2ba13721257e2c76e90e8d83dfd9ba91c434355d (patch) | |
tree | 13cbd7ae5f70a2e13d7e800ab73501b3d7d3b144 /fs | |
parent | 32a9b7c65cfc7d9283055fc9d61e6393ee2aa984 (diff) |
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: Brian Foster <bfoster@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/xfs_dquot.c | 34 |
1 files changed, 20 insertions, 14 deletions
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 0973a0423bed..aa62f8b17376 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -286,8 +286,8 @@ xfs_dquot_disk_alloc( struct xfs_buf **bpp) { struct xfs_bmbt_irec map; - struct xfs_defer_ops dfops; - struct xfs_mount *mp = (*tpp)->t_mountp; + struct xfs_trans *tp = *tpp; + struct xfs_mount *mp = tp->t_mountp; struct xfs_buf *bp; struct xfs_inode *quotip = xfs_quota_inode(mp, dqp->dq_flags); xfs_fsblock_t firstblock; @@ -296,7 +296,8 @@ xfs_dquot_disk_alloc( trace_xfs_dqalloc(dqp); - xfs_defer_init(&dfops, &firstblock); + xfs_defer_init(tp->t_dfops, &firstblock); + xfs_ilock(quotip, XFS_ILOCK_EXCL); if (!xfs_this_quota_on(dqp->q_mount, dqp->dq_flags)) { /* @@ -308,11 +309,11 @@ xfs_dquot_disk_alloc( } /* Create the block mapping. */ - xfs_trans_ijoin(*tpp, quotip, XFS_ILOCK_EXCL); - error = xfs_bmapi_write(*tpp, quotip, dqp->q_fileoffset, + xfs_trans_ijoin(tp, quotip, XFS_ILOCK_EXCL); + error = xfs_bmapi_write(tp, quotip, dqp->q_fileoffset, XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA, &firstblock, XFS_QM_DQALLOC_SPACE_RES(mp), - &map, &nmaps, &dfops); + &map, &nmaps, tp->t_dfops); if (error) goto error0; 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); /* 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); if (!bp) { error = -ENOMEM; @@ -338,7 +339,7 @@ xfs_dquot_disk_alloc( * Make a chunk of dquots out of this buffer and log * 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); 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 * manually or by committing the transaction. */ - xfs_trans_bhold(*tpp, bp); - error = xfs_defer_bjoin(&dfops, bp); + xfs_trans_bhold(tp, bp); + error = xfs_defer_bjoin(tp->t_dfops, bp); if (error) { - xfs_trans_bhold_release(*tpp, bp); - xfs_trans_brelse(*tpp, bp); + xfs_trans_bhold_release(tp, bp); + xfs_trans_brelse(tp, bp); goto error1; } - error = xfs_defer_finish(tpp, &dfops); + error = xfs_defer_finish(tpp, tp->t_dfops); + tp = *tpp; if (error) { xfs_buf_relse(bp); goto error1; @@ -380,7 +382,7 @@ xfs_dquot_disk_alloc( return 0; error1: - xfs_defer_cancel(&dfops); + xfs_defer_cancel(tp->t_dfops); error0: return error; } @@ -538,13 +540,17 @@ xfs_qm_dqread_alloc( struct xfs_buf **bpp) { struct xfs_trans *tp; + struct xfs_defer_ops dfops; struct xfs_buf *bp; + xfs_fsblock_t firstblock; int error; error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_dqalloc, XFS_QM_DQALLOC_SPACE_RES(mp), 0, 0, &tp); if (error) goto err; + xfs_defer_init(&dfops, &firstblock); + tp->t_dfops = &dfops; error = xfs_dquot_disk_alloc(&tp, dqp, &bp); if (error) |