[PATCH 09/24] xfs: use direct calls for dquot IO completion

Dave Chinner
2020-05-22T03:50:43Z

From: Dave Chinner <dchinner@redhat.com>

Similar to inodes, we can call the dquot IO completion functions
directly from the buffer completion code, removing another user of
log item callbacks for IO completion processing.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
fs/xfs/xfs_buf_item.c | 18 +++++++++++++++++-
fs/xfs/xfs_dquot.c | 27 +++++++++++++++++++++++----
fs/xfs/xfs_dquot.h | 1 +
3 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index e376f778bf57c..57e5d37f6852e 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -15,6 +15,9 @@
#include "xfs_buf_item.h"
#include "xfs_inode.h"
#include "xfs_inode_item.h"
+#include "xfs_quota.h"
+#include "xfs_dquot_item.h"
+#include "xfs_dquot.h"
#include "xfs_trans_priv.h"
#include "xfs_trace.h"
#include "xfs_log.h"
@@ -1209,7 +1212,20 @@ void
xfs_buf_dquot_iodone(
struct xfs_buf *bp)
{
- xfs_buf_run_callbacks(bp);
+ struct xfs_buf_log_item *blip = bp->b_log_item;
+ struct xfs_log_item *lip;
+
+ if (xfs_buf_had_callback_errors(bp))
+ return;
+
+ /* a newly allocated dquot buffer might have a log item attached */
+ if (blip) {
+ lip = &blip->bli_item;
+ lip->li_cb(bp, lip);
+ bp->b_log_item = NULL;
+ }
+
+ xfs_dquot_done(bp);
xfs_buf_ioend_finish(bp);
}

diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 25592b701db40..1d7f34a9bc989 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -1043,9 +1043,8 @@ xfs_qm_dqrele(
* from the AIL if it has not been re-logged, and unlocking the dquot's
* flush lock. This behavior is very similar to that of inodes..
*/
-STATIC void
+static void
xfs_qm_dqflush_done(
- struct xfs_buf *bp,
struct xfs_log_item *lip)
{
struct xfs_dq_logitem *qip = (struct xfs_dq_logitem *)lip;
@@ -1086,6 +1085,27 @@ xfs_qm_dqflush_done(
xfs_dqfunlock(dqp);
}

+void
+xfs_dquot_done(
+ struct xfs_buf *bp)
+{
+ struct xfs_log_item *lip;
+
+ while (!list_empty(&bp->b_li_list)) {
+ lip = list_first_entry(&bp->b_li_list, struct xfs_log_item,
+ li_bio_list);
+
+ /*
+ * Remove the item from the list, so we don't have any
+ * confusion if the item is added to another buf.
+ * Don't touch the log item after calling its
+ * callback, because it could have freed itself.
+ */
+ list_del_init(&lip->li_bio_list);
+ xfs_qm_dqflush_done(lip);
+ }
+}
+
/*
* Write a modified dquot to disk.
* The dquot must be locked and the flush lock too taken by caller.
@@ -1175,8 +1195,7 @@ xfs_qm_dqflush(
* AIL and release the flush lock once the dquot is synced to disk.
*/
bp->b_flags |= _XBF_DQUOTS;
- xfs_buf_attach_iodone(bp, xfs_qm_dqflush_done,
- &dqp->q_logitem.qli_item);
+ xfs_buf_attach_iodone(bp, NULL, &dqp->q_logitem.qli_item);

/*
* If the buffer is pinned then push on the log so we won't
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index fe3e46df604b4..f1924288986d3 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -174,6 +174,7 @@ void xfs_qm_dqput(struct xfs_dquot *dqp);
void xfs_dqlock2(struct xfs_dquot *, struct xfs_dquot *);

void xfs_dquot_set_prealloc_limits(struct xfs_dquot *);
+void xfs_dquot_done(struct xfs_buf *);

static inline struct xfs_dquot *xfs_qm_dqhold(struct xfs_dquot *dqp)
{
--
2.26.2.761.g0e0b3e54be