Skip to content

Commit 88accf1

Browse files
author
Darrick J. Wong
committed
xfs: scrub should use ECHRNG to signal that the drain is needed
In the previous patch, we added jump labels to the intent drain code so that regular filesystem operations need not pay the price of checking for someone (scrub) waiting on intents to drain from some part of the filesystem when that someone isn't running. However, I observed that xfs/285 now spends a lot more time pushing the AIL from the inode btree scrubber than it used to. This is because the inobt scrubber will try push the AIL to try to get logged inode cores written to the filesystem when it sees a weird discrepancy between the ondisk inode and the inobt records. This AIL push is triggered when the setup function sees TRY_HARDER is set; and the requisite EDEADLOCK return is initiated when the discrepancy is seen. The solution to this performance slow down is to use a different result code (ECHRNG) for scrub code to signal that it needs to wait for deferred intent work items to drain out of some part of the filesystem. When this happens, set a new scrub state flag (XCHK_NEED_DRAIN) so that setup functions will activate the jump label. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Dave Chinner <dchinner@redhat.com>
1 parent 466c525 commit 88accf1

8 files changed

Lines changed: 21 additions & 2 deletions

File tree

fs/xfs/scrub/btree.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ __xchk_btree_process_error(
3636

3737
switch (*error) {
3838
case -EDEADLOCK:
39+
case -ECHRNG:
3940
/* Used to restart an op with deadlock avoidance. */
4041
trace_xchk_deadlock_retry(sc->ip, sc->sm, *error);
4142
break;

fs/xfs/scrub/common.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ __xchk_process_error(
7575
case 0:
7676
return true;
7777
case -EDEADLOCK:
78+
case -ECHRNG:
7879
/* Used to restart an op with deadlock avoidance. */
7980
trace_xchk_deadlock_retry(
8081
sc->ip ? sc->ip : XFS_I(file_inode(sc->file)),
@@ -130,6 +131,7 @@ __xchk_fblock_process_error(
130131
case 0:
131132
return true;
132133
case -EDEADLOCK:
134+
case -ECHRNG:
133135
/* Used to restart an op with deadlock avoidance. */
134136
trace_xchk_deadlock_retry(sc->ip, sc->sm, *error);
135137
break;
@@ -488,7 +490,7 @@ xchk_perag_drain_and_lock(
488490
}
489491

490492
if (!(sc->flags & XCHK_FSGATES_DRAIN))
491-
return -EDEADLOCK;
493+
return -ECHRNG;
492494
error = xfs_perag_intent_drain(sa->pag);
493495
if (error == -ERESTARTSYS)
494496
error = -EINTR;

fs/xfs/scrub/common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ void xchk_start_reaping(struct xfs_scrub *sc);
161161
*/
162162
static inline bool xchk_need_intent_drain(struct xfs_scrub *sc)
163163
{
164-
return sc->flags & XCHK_TRY_HARDER;
164+
return sc->flags & XCHK_NEED_DRAIN;
165165
}
166166

167167
void xchk_fsgates_enable(struct xfs_scrub *sc, unsigned int scrub_fshooks);

fs/xfs/scrub/dabtree.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ xchk_da_process_error(
3939

4040
switch (*error) {
4141
case -EDEADLOCK:
42+
case -ECHRNG:
4243
/* Used to restart an op with deadlock avoidance. */
4344
trace_xchk_deadlock_retry(sc->ip, sc->sm, *error);
4445
break;

fs/xfs/scrub/repair.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ xrep_attempt(
6060
sc->sm->sm_flags &= ~XFS_SCRUB_FLAGS_OUT;
6161
sc->flags |= XREP_ALREADY_FIXED;
6262
return -EAGAIN;
63+
case -ECHRNG:
64+
sc->flags |= XCHK_NEED_DRAIN;
65+
return -EAGAIN;
6366
case -EDEADLOCK:
6467
/* Tell the caller to try again having grabbed all the locks. */
6568
if (!(sc->flags & XCHK_TRY_HARDER)) {

fs/xfs/scrub/scrub.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,13 +510,17 @@ xfs_scrub_metadata(
510510
error = sc->ops->setup(sc);
511511
if (error == -EDEADLOCK && !(sc->flags & XCHK_TRY_HARDER))
512512
goto try_harder;
513+
if (error == -ECHRNG && !(sc->flags & XCHK_NEED_DRAIN))
514+
goto need_drain;
513515
if (error)
514516
goto out_teardown;
515517

516518
/* Scrub for errors. */
517519
error = sc->ops->scrub(sc);
518520
if (error == -EDEADLOCK && !(sc->flags & XCHK_TRY_HARDER))
519521
goto try_harder;
522+
if (error == -ECHRNG && !(sc->flags & XCHK_NEED_DRAIN))
523+
goto need_drain;
520524
if (error || (sm->sm_flags & XFS_SCRUB_OFLAG_INCOMPLETE))
521525
goto out_teardown;
522526

@@ -575,6 +579,12 @@ xfs_scrub_metadata(
575579
error = 0;
576580
}
577581
return error;
582+
need_drain:
583+
error = xchk_teardown(sc, 0);
584+
if (error)
585+
goto out_sc;
586+
sc->flags |= XCHK_NEED_DRAIN;
587+
goto retry_op;
578588
try_harder:
579589
/*
580590
* Scrubbers return -EDEADLOCK to mean 'try harder'. Tear down

fs/xfs/scrub/scrub.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ struct xfs_scrub {
9898
#define XCHK_TRY_HARDER (1 << 0) /* can't get resources, try again */
9999
#define XCHK_REAPING_DISABLED (1 << 1) /* background block reaping paused */
100100
#define XCHK_FSGATES_DRAIN (1 << 2) /* defer ops draining enabled */
101+
#define XCHK_NEED_DRAIN (1 << 3) /* scrub needs to drain defer ops */
101102
#define XREP_ALREADY_FIXED (1 << 31) /* checking our repair work */
102103

103104
/*

fs/xfs/scrub/trace.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_FSCOUNTERS);
100100
{ XCHK_TRY_HARDER, "try_harder" }, \
101101
{ XCHK_REAPING_DISABLED, "reaping_disabled" }, \
102102
{ XCHK_FSGATES_DRAIN, "fsgates_drain" }, \
103+
{ XCHK_NEED_DRAIN, "need_drain" }, \
103104
{ XREP_ALREADY_FIXED, "already_fixed" }
104105

105106
DECLARE_EVENT_CLASS(xchk_class,

0 commit comments

Comments
 (0)