xfs: refactor xfs_qm_dqtobp and xfs_qm_dqalloc

Separate the disk dquot read and allocation functionality into
two helper functions, then refactor dqread to call them directly.
Signed-off-by: NDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: NBrian Foster <bfoster@redhat.com>
上级 617cd5c1
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
......@@ -288,49 +288,43 @@ xfs_dquot_set_prealloc_limits(struct xfs_dquot *dqp)
}
/*
* Allocate a block and fill it with dquots.
* This is called when the bmapi finds a hole.
* Ensure that the given in-core dquot has a buffer on disk backing it, and
* return the buffer. This is called when the bmapi finds a hole.
*/
STATIC int
xfs_qm_dqalloc(
xfs_trans_t **tpp,
xfs_mount_t *mp,
xfs_dquot_t *dqp,
xfs_inode_t *quotip,
xfs_fileoff_t offset_fsb,
xfs_buf_t **O_bpp)
xfs_dquot_disk_alloc(
struct xfs_trans **tpp,
struct xfs_dquot *dqp,
struct xfs_buf **bpp)
{
xfs_fsblock_t firstblock;
struct xfs_defer_ops dfops;
xfs_bmbt_irec_t map;
int nmaps, error;
xfs_buf_t *bp;
xfs_trans_t *tp = *tpp;
ASSERT(tp != NULL);
struct xfs_bmbt_irec map;
struct xfs_defer_ops dfops;
struct xfs_mount *mp = (*tpp)->t_mountp;
struct xfs_buf *bp;
struct xfs_inode *quotip = xfs_quota_inode(mp, dqp->dq_flags);
xfs_fsblock_t firstblock;
int nmaps = 1;
int error;
trace_xfs_dqalloc(dqp);
/*
* Initialize the bmap freelist prior to calling bmapi code.
*/
xfs_defer_init(&dfops, &firstblock);
xfs_ilock(quotip, XFS_ILOCK_EXCL);
/*
* Return if this type of quotas is turned off while we didn't
* have an inode lock
*/
if (!xfs_this_quota_on(dqp->q_mount, dqp->dq_flags)) {
/*
* Return if this type of quotas is turned off while we didn't
* have an inode lock
*/
xfs_iunlock(quotip, XFS_ILOCK_EXCL);
return -ESRCH;
}
xfs_trans_ijoin(tp, quotip, XFS_ILOCK_EXCL);
nmaps = 1;
error = xfs_bmapi_write(tp, quotip, offset_fsb,
XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA,
&firstblock, XFS_QM_DQALLOC_SPACE_RES(mp),
&map, &nmaps, &dfops);
/* Create the block mapping. */
xfs_trans_ijoin(*tpp, quotip, XFS_ILOCK_EXCL);
error = xfs_bmapi_write(*tpp, quotip, dqp->q_fileoffset,
XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA,
&firstblock, XFS_QM_DQALLOC_SPACE_RES(mp),
&map, &nmaps, &dfops);
if (error)
goto error0;
ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB);
......@@ -344,10 +338,8 @@ xfs_qm_dqalloc(
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(tp, mp->m_ddev_targp,
dqp->q_blkno,
mp->m_quotainfo->qi_dqchunklen,
0);
bp = xfs_trans_get_buf(*tpp, mp->m_ddev_targp, dqp->q_blkno,
mp->m_quotainfo->qi_dqchunklen, 0);
if (!bp) {
error = -ENOMEM;
goto error1;
......@@ -358,8 +350,9 @@ xfs_qm_dqalloc(
* Make a chunk of dquots out of this buffer and log
* the entire thing.
*/
xfs_qm_init_dquot_blk(tp, mp, be32_to_cpu(dqp->q_core.d_id),
xfs_qm_init_dquot_blk(*tpp, mp, be32_to_cpu(dqp->q_core.d_id),
dqp->dq_flags & XFS_DQ_ALLTYPES, bp);
xfs_buf_set_ref(bp, XFS_DQUOT_REF);
/*
* Hold the buffer and join it to the dfops so that we'll still own
......@@ -379,7 +372,7 @@ xfs_qm_dqalloc(
* transaction, so we must _buf_relse it.
*
* If everything succeeds, the caller of this function is returned a
* buffer that is locked and joined to the transaction. The caller
* buffer that is locked and held to the transaction. The caller
* is responsible for unlocking any buffer passed back, either
* manually or by committing the transaction.
*/
......@@ -395,8 +388,7 @@ xfs_qm_dqalloc(
xfs_buf_relse(bp);
goto error1;
}
xfs_trans_bhold_release(*tpp, bp);
*O_bpp = bp;
*bpp = bp;
return 0;
error1:
......@@ -406,32 +398,24 @@ xfs_qm_dqalloc(
}
/*
* Maps a dquot to the buffer containing its on-disk version.
* This returns a ptr to the buffer containing the on-disk dquot
* in the bpp param, and a ptr to the on-disk dquot within that buffer
* Read in the in-core dquot's on-disk metadata and return the buffer.
* Returns ENOENT to signal a hole.
*/
STATIC int
xfs_qm_dqtobp(
xfs_trans_t **tpp,
xfs_dquot_t *dqp,
xfs_disk_dquot_t **O_ddpp,
xfs_buf_t **O_bpp,
uint flags)
xfs_dquot_disk_read(
struct xfs_mount *mp,
struct xfs_dquot *dqp,
struct xfs_buf **bpp)
{
struct xfs_bmbt_irec map;
int nmaps = 1, error;
struct xfs_buf *bp;
struct xfs_inode *quotip;
struct xfs_mount *mp = dqp->q_mount;
xfs_dqid_t id = be32_to_cpu(dqp->q_core.d_id);
struct xfs_trans *tp = (tpp ? *tpp : NULL);
struct xfs_inode *quotip = xfs_quota_inode(mp, dqp->dq_flags);
uint lock_mode;
quotip = xfs_quota_inode(dqp->q_mount, dqp->dq_flags);
dqp->q_fileoffset = (xfs_fileoff_t)id / mp->m_quotainfo->qi_dqperchunk;
int nmaps = 1;
int error;
lock_mode = xfs_ilock_data_map_shared(quotip);
if (!xfs_this_quota_on(dqp->q_mount, dqp->dq_flags)) {
if (!xfs_this_quota_on(mp, dqp->dq_flags)) {
/*
* Return if this type of quotas is turned off while we
* didn't have the quota inode lock.
......@@ -444,57 +428,36 @@ xfs_qm_dqtobp(
* Find the block map; no allocations yet
*/
error = xfs_bmapi_read(quotip, dqp->q_fileoffset,
XFS_DQUOT_CLUSTER_SIZE_FSB, &map, &nmaps, 0);
XFS_DQUOT_CLUSTER_SIZE_FSB, &map, &nmaps, 0);
xfs_iunlock(quotip, lock_mode);
if (error)
return error;
ASSERT(nmaps == 1);
ASSERT(map.br_blockcount == 1);
ASSERT(map.br_blockcount >= 1);
ASSERT(map.br_startblock != DELAYSTARTBLOCK);
if (map.br_startblock == HOLESTARTBLOCK)
return -ENOENT;
trace_xfs_dqtobp_read(dqp);
/*
* Offset of dquot in the (fixed sized) dquot chunk.
* store the blkno etc so that we don't have to do the
* mapping all the time
*/
dqp->q_bufoffset = (id % mp->m_quotainfo->qi_dqperchunk) *
sizeof(xfs_dqblk_t);
ASSERT(map.br_startblock != DELAYSTARTBLOCK);
if (map.br_startblock == HOLESTARTBLOCK) {
/*
* We don't allocate unless we're asked to
*/
if (!(flags & XFS_QMOPT_DQALLOC))
return -ENOENT;
ASSERT(tp);
error = xfs_qm_dqalloc(tpp, mp, dqp, quotip,
dqp->q_fileoffset, &bp);
if (error)
return error;
tp = *tpp;
} else {
trace_xfs_dqtobp_read(dqp);
dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock);
/*
* store the blkno etc so that we don't have to do the
* mapping all the time
*/
dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock);
error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
dqp->q_blkno,
mp->m_quotainfo->qi_dqchunklen,
0, &bp, &xfs_dquot_buf_ops);
if (error) {
ASSERT(bp == NULL);
return error;
}
error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno,
mp->m_quotainfo->qi_dqchunklen, 0, &bp,
&xfs_dquot_buf_ops);
if (error) {
ASSERT(bp == NULL);
return error;
}
ASSERT(xfs_buf_islocked(bp));
*O_bpp = bp;
*O_ddpp = bp->b_addr + dqp->q_bufoffset;
xfs_buf_set_ref(bp, XFS_DQUOT_REF);
*bpp = bp;
return 0;
}
......@@ -516,6 +479,12 @@ xfs_dquot_alloc(
INIT_LIST_HEAD(&dqp->q_lru);
mutex_init(&dqp->q_qlock);
init_waitqueue_head(&dqp->q_pinwait);
dqp->q_fileoffset = (xfs_fileoff_t)id / mp->m_quotainfo->qi_dqperchunk;
/*
* Offset of dquot in the (fixed sized) dquot chunk.
*/
dqp->q_bufoffset = (id % mp->m_quotainfo->qi_dqperchunk) *
sizeof(xfs_dqblk_t);
/*
* Because we want to use a counting completion, complete
......@@ -554,8 +523,10 @@ xfs_dquot_alloc(
STATIC void
xfs_dquot_from_disk(
struct xfs_dquot *dqp,
struct xfs_disk_dquot *ddqp)
struct xfs_buf *bp)
{
struct xfs_disk_dquot *ddqp = bp->b_addr + dqp->q_bufoffset;
/* copy everything from disk dquot to the incore dquot */
memcpy(&dqp->q_core, ddqp, sizeof(xfs_disk_dquot_t));
......@@ -571,6 +542,44 @@ xfs_dquot_from_disk(
xfs_dquot_set_prealloc_limits(dqp);
}
/* Allocate and initialize the dquot buffer for this in-core dquot. */
static int
xfs_qm_dqread_alloc(
struct xfs_mount *mp,
struct xfs_dquot *dqp,
struct xfs_buf **bpp)
{
struct xfs_trans *tp;
struct xfs_buf *bp;
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;
error = xfs_dquot_disk_alloc(&tp, dqp, &bp);
if (error)
goto err_cancel;
error = xfs_trans_commit(tp);
if (error) {
/*
* Buffer was held to the transaction, so we have to unlock it
* manually here because we're not passing it back.
*/
xfs_buf_relse(bp);
goto err;
}
*bpp = bp;
return 0;
err_cancel:
xfs_trans_cancel(tp);
err:
return error;
}
/*
* Read in the ondisk dquot using dqtobp() then copy it to an incore version,
* and release the buffer immediately.
......@@ -583,74 +592,39 @@ xfs_qm_dqread(
xfs_dqid_t id,
uint type,
uint flags,
struct xfs_dquot **O_dqpp)
struct xfs_dquot **dqpp)
{
struct xfs_dquot *dqp;
struct xfs_disk_dquot *ddqp;
struct xfs_buf *bp;
struct xfs_trans *tp = NULL;
int error;
dqp = xfs_dquot_alloc(mp, id, type);
trace_xfs_dqread(dqp);
if (flags & XFS_QMOPT_DQALLOC) {
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_dqalloc,
XFS_QM_DQALLOC_SPACE_RES(mp), 0, 0, &tp);
if (error)
goto error0;
}
/*
* get a pointer to the on-disk dquot and the buffer containing it
* dqp already knows its own type (GROUP/USER).
*/
error = xfs_qm_dqtobp(&tp, dqp, &ddqp, &bp, flags);
if (error) {
/*
* This can happen if quotas got turned off (ESRCH),
* or if the dquot didn't exist on disk and we ask to
* allocate (ENOENT).
*/
trace_xfs_dqread_fail(dqp);
goto error1;
}
xfs_dquot_from_disk(dqp, ddqp);
/* Mark the buf so that this will stay incore a little longer */
xfs_buf_set_ref(bp, XFS_DQUOT_REF);
/* Try to read the buffer, allocating if necessary. */
error = xfs_dquot_disk_read(mp, dqp, &bp);
if (error == -ENOENT && (flags & XFS_QMOPT_DQALLOC))
error = xfs_qm_dqread_alloc(mp, dqp, &bp);
if (error)
goto err;
/*
* We got the buffer with a xfs_trans_read_buf() (in dqtobp())
* So we need to release with xfs_trans_brelse().
* The strategy here is identical to that of inodes; we lock
* the dquot in xfs_qm_dqget() before making it accessible to
* others. This is because dquots, like inodes, need a good level of
* concurrency, and we don't want to take locks on the entire buffers
* for dquot accesses.
* Note also that the dquot buffer may even be dirty at this point, if
* this particular dquot was repaired. We still aren't afraid to
* brelse it because we have the changes incore.
* At this point we should have a clean locked buffer. Copy the data
* to the incore dquot and release the buffer since the incore dquot
* has its own locking protocol so we needn't tie up the buffer any
* further.
*/
ASSERT(xfs_buf_islocked(bp));
xfs_trans_brelse(tp, bp);
if (tp) {
error = xfs_trans_commit(tp);
if (error)
goto error0;
}
xfs_dquot_from_disk(dqp, bp);
*O_dqpp = dqp;
xfs_buf_relse(bp);
*dqpp = dqp;
return error;
error1:
if (tp)
xfs_trans_cancel(tp);
error0:
err:
trace_xfs_dqread_fail(dqp);
xfs_qm_dqdestroy(dqp);
*O_dqpp = NULL;
*dqpp = NULL;
return error;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部