Skip to content

Commit a40fe30

Browse files
author
Darrick J. Wong
committed
xfs: separate dquot buffer reads from xfs_dqflush
The first step towards holding the dquot buffer in the li_buf instead of reading it in the AIL is to separate the part that reads the buffer from the actual flush code. There should be no functional changes. Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
1 parent 07137e9 commit a40fe30

4 files changed

Lines changed: 86 additions & 32 deletions

File tree

fs/xfs/xfs_dquot.c

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,42 @@ xfs_qm_dqflush_check(
12381238
return NULL;
12391239
}
12401240

1241+
/*
1242+
* Get the buffer containing the on-disk dquot.
1243+
*
1244+
* Requires dquot flush lock, will clear the dirty flag, delete the quota log
1245+
* item from the AIL, and shut down the system if something goes wrong.
1246+
*/
1247+
int
1248+
xfs_dquot_read_buf(
1249+
struct xfs_trans *tp,
1250+
struct xfs_dquot *dqp,
1251+
struct xfs_buf **bpp)
1252+
{
1253+
struct xfs_mount *mp = dqp->q_mount;
1254+
struct xfs_buf *bp = NULL;
1255+
int error;
1256+
1257+
error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, dqp->q_blkno,
1258+
mp->m_quotainfo->qi_dqchunklen, XBF_TRYLOCK,
1259+
&bp, &xfs_dquot_buf_ops);
1260+
if (error == -EAGAIN)
1261+
return error;
1262+
if (xfs_metadata_is_sick(error))
1263+
xfs_dquot_mark_sick(dqp);
1264+
if (error)
1265+
goto out_abort;
1266+
1267+
*bpp = bp;
1268+
return 0;
1269+
1270+
out_abort:
1271+
dqp->q_flags &= ~XFS_DQFLAG_DIRTY;
1272+
xfs_trans_ail_delete(&dqp->q_logitem.qli_item, 0);
1273+
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
1274+
return error;
1275+
}
1276+
12411277
/*
12421278
* Write a modified dquot to disk.
12431279
* The dquot must be locked and the flush lock too taken by caller.
@@ -1249,11 +1285,10 @@ xfs_qm_dqflush_check(
12491285
int
12501286
xfs_qm_dqflush(
12511287
struct xfs_dquot *dqp,
1252-
struct xfs_buf **bpp)
1288+
struct xfs_buf *bp)
12531289
{
12541290
struct xfs_mount *mp = dqp->q_mount;
12551291
struct xfs_log_item *lip = &dqp->q_logitem.qli_item;
1256-
struct xfs_buf *bp;
12571292
struct xfs_dqblk *dqblk;
12581293
xfs_failaddr_t fa;
12591294
int error;
@@ -1263,28 +1298,12 @@ xfs_qm_dqflush(
12631298

12641299
trace_xfs_dqflush(dqp);
12651300

1266-
*bpp = NULL;
1267-
12681301
xfs_qm_dqunpin_wait(dqp);
12691302

1270-
/*
1271-
* Get the buffer containing the on-disk dquot
1272-
*/
1273-
error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno,
1274-
mp->m_quotainfo->qi_dqchunklen, XBF_TRYLOCK,
1275-
&bp, &xfs_dquot_buf_ops);
1276-
if (error == -EAGAIN)
1277-
goto out_unlock;
1278-
if (xfs_metadata_is_sick(error))
1279-
xfs_dquot_mark_sick(dqp);
1280-
if (error)
1281-
goto out_abort;
1282-
12831303
fa = xfs_qm_dqflush_check(dqp);
12841304
if (fa) {
12851305
xfs_alert(mp, "corrupt dquot ID 0x%x in memory at %pS",
12861306
dqp->q_id, fa);
1287-
xfs_buf_relse(bp);
12881307
xfs_dquot_mark_sick(dqp);
12891308
error = -EFSCORRUPTED;
12901309
goto out_abort;
@@ -1334,14 +1353,12 @@ xfs_qm_dqflush(
13341353
}
13351354

13361355
trace_xfs_dqflush_done(dqp);
1337-
*bpp = bp;
13381356
return 0;
13391357

13401358
out_abort:
13411359
dqp->q_flags &= ~XFS_DQFLAG_DIRTY;
13421360
xfs_trans_ail_delete(lip, 0);
13431361
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
1344-
out_unlock:
13451362
xfs_dqfunlock(dqp);
13461363
return error;
13471364
}

fs/xfs/xfs_dquot.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,9 @@ void xfs_dquot_to_disk(struct xfs_disk_dquot *ddqp, struct xfs_dquot *dqp);
214214
#define XFS_DQ_IS_DIRTY(dqp) ((dqp)->q_flags & XFS_DQFLAG_DIRTY)
215215

216216
void xfs_qm_dqdestroy(struct xfs_dquot *dqp);
217-
int xfs_qm_dqflush(struct xfs_dquot *dqp, struct xfs_buf **bpp);
217+
int xfs_dquot_read_buf(struct xfs_trans *tp, struct xfs_dquot *dqp,
218+
struct xfs_buf **bpp);
219+
int xfs_qm_dqflush(struct xfs_dquot *dqp, struct xfs_buf *bp);
218220
void xfs_qm_dqunpin_wait(struct xfs_dquot *dqp);
219221
void xfs_qm_adjust_dqtimers(struct xfs_dquot *d);
220222
void xfs_qm_adjust_dqlimits(struct xfs_dquot *d);

fs/xfs/xfs_dquot_item.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,14 +155,26 @@ xfs_qm_dquot_logitem_push(
155155

156156
spin_unlock(&lip->li_ailp->ail_lock);
157157

158-
error = xfs_qm_dqflush(dqp, &bp);
158+
error = xfs_dquot_read_buf(NULL, dqp, &bp);
159+
if (error) {
160+
if (error == -EAGAIN)
161+
rval = XFS_ITEM_LOCKED;
162+
xfs_dqfunlock(dqp);
163+
goto out_relock_ail;
164+
}
165+
166+
/*
167+
* dqflush completes dqflock on error, and the delwri ioend does it on
168+
* success.
169+
*/
170+
error = xfs_qm_dqflush(dqp, bp);
159171
if (!error) {
160172
if (!xfs_buf_delwri_queue(bp, buffer_list))
161173
rval = XFS_ITEM_FLUSHING;
162-
xfs_buf_relse(bp);
163-
} else if (error == -EAGAIN)
164-
rval = XFS_ITEM_LOCKED;
174+
}
175+
xfs_buf_relse(bp);
165176

177+
out_relock_ail:
166178
spin_lock(&lip->li_ailp->ail_lock);
167179
out_unlock:
168180
xfs_dqunlock(dqp);

fs/xfs/xfs_qm.c

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -148,17 +148,28 @@ xfs_qm_dqpurge(
148148
* We don't care about getting disk errors here. We need
149149
* to purge this dquot anyway, so we go ahead regardless.
150150
*/
151-
error = xfs_qm_dqflush(dqp, &bp);
151+
error = xfs_dquot_read_buf(NULL, dqp, &bp);
152+
if (error == -EAGAIN) {
153+
xfs_dqfunlock(dqp);
154+
dqp->q_flags &= ~XFS_DQFLAG_FREEING;
155+
goto out_unlock;
156+
}
157+
if (error)
158+
goto out_funlock;
159+
160+
/*
161+
* dqflush completes dqflock on error, and the bwrite ioend
162+
* does it on success.
163+
*/
164+
error = xfs_qm_dqflush(dqp, bp);
152165
if (!error) {
153166
error = xfs_bwrite(bp);
154167
xfs_buf_relse(bp);
155-
} else if (error == -EAGAIN) {
156-
dqp->q_flags &= ~XFS_DQFLAG_FREEING;
157-
goto out_unlock;
158168
}
159169
xfs_dqflock(dqp);
160170
}
161171

172+
out_funlock:
162173
ASSERT(atomic_read(&dqp->q_pincount) == 0);
163174
ASSERT(xlog_is_shutdown(dqp->q_logitem.qli_item.li_log) ||
164175
!test_bit(XFS_LI_IN_AIL, &dqp->q_logitem.qli_item.li_flags));
@@ -494,7 +505,17 @@ xfs_qm_dquot_isolate(
494505
/* we have to drop the LRU lock to flush the dquot */
495506
spin_unlock(&lru->lock);
496507

497-
error = xfs_qm_dqflush(dqp, &bp);
508+
error = xfs_dquot_read_buf(NULL, dqp, &bp);
509+
if (error) {
510+
xfs_dqfunlock(dqp);
511+
goto out_unlock_dirty;
512+
}
513+
514+
/*
515+
* dqflush completes dqflock on error, and the delwri ioend
516+
* does it on success.
517+
*/
518+
error = xfs_qm_dqflush(dqp, bp);
498519
if (error)
499520
goto out_unlock_dirty;
500521

@@ -1489,11 +1510,13 @@ xfs_qm_flush_one(
14891510
goto out_unlock;
14901511
}
14911512

1492-
error = xfs_qm_dqflush(dqp, &bp);
1513+
error = xfs_dquot_read_buf(NULL, dqp, &bp);
14931514
if (error)
14941515
goto out_unlock;
14951516

1496-
xfs_buf_delwri_queue(bp, buffer_list);
1517+
error = xfs_qm_dqflush(dqp, bp);
1518+
if (!error)
1519+
xfs_buf_delwri_queue(bp, buffer_list);
14971520
xfs_buf_relse(bp);
14981521
out_unlock:
14991522
xfs_dqunlock(dqp);

0 commit comments

Comments
 (0)