Skip to content

Commit aa03f52

Browse files
author
Chandan Babu R
committed
Merge tag 'repair-quotacheck-6.9_2024-02-23' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux into xfs-6.9-mergeC
xfs: online repair of quota counters This series uses the inode scanner and live update hook functionality introduced in the last patchset to implement quotacheck on a live filesystem. The quotacheck scrubber builds an incore copy of the dquot resource usage counters and compares it to the live dquots to report discrepancies. If the user chooses to repair the quota counters, the repair function visits each incore dquot to update the counts from the live information. The live update hooks are key to keeping the incore copy up to date. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Chandan Babu R <chandanbabu@kernel.org> * tag 'repair-quotacheck-6.9_2024-02-23' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux: xfs: repair dquots based on live quotacheck results xfs: repair cannot update the summary counters when logging quota flags xfs: track quota updates during live quotacheck xfs: implement live quotacheck inode scan xfs: create a sparse load xfarray function xfs: create a helper to count per-device inode block usage xfs: create a xchk_trans_alloc_empty helper for scrub xfs: report the health of quota counts
2 parents 8e3ef44 + 96ed2ae commit aa03f52

25 files changed

Lines changed: 1645 additions & 26 deletions

fs/xfs/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ xfs-$(CONFIG_XFS_RT) += $(addprefix scrub/, \
180180
xfs-$(CONFIG_XFS_QUOTA) += $(addprefix scrub/, \
181181
dqiterate.o \
182182
quota.o \
183+
quotacheck.o \
183184
)
184185

185186
# online repair
@@ -203,6 +204,7 @@ xfs-$(CONFIG_XFS_RT) += $(addprefix scrub/, \
203204

204205
xfs-$(CONFIG_XFS_QUOTA) += $(addprefix scrub/, \
205206
quota_repair.o \
207+
quotacheck_repair.o \
206208
)
207209
endif
208210
endif

fs/xfs/libxfs/xfs_fs.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ struct xfs_fsop_geom {
195195
#define XFS_FSOP_GEOM_SICK_PQUOTA (1 << 3) /* project quota */
196196
#define XFS_FSOP_GEOM_SICK_RT_BITMAP (1 << 4) /* realtime bitmap */
197197
#define XFS_FSOP_GEOM_SICK_RT_SUMMARY (1 << 5) /* realtime summary */
198+
#define XFS_FSOP_GEOM_SICK_QUOTACHECK (1 << 6) /* quota counts */
198199

199200
/* Output for XFS_FS_COUNTS */
200201
typedef struct xfs_fsop_counts {
@@ -709,9 +710,10 @@ struct xfs_scrub_metadata {
709710
#define XFS_SCRUB_TYPE_GQUOTA 22 /* group quotas */
710711
#define XFS_SCRUB_TYPE_PQUOTA 23 /* project quotas */
711712
#define XFS_SCRUB_TYPE_FSCOUNTERS 24 /* fs summary counters */
713+
#define XFS_SCRUB_TYPE_QUOTACHECK 25 /* quota counters */
712714

713715
/* Number of scrub subcommands. */
714-
#define XFS_SCRUB_TYPE_NR 25
716+
#define XFS_SCRUB_TYPE_NR 26
715717

716718
/* i: Repair this metadata. */
717719
#define XFS_SCRUB_IFLAG_REPAIR (1u << 0)

fs/xfs/libxfs/xfs_health.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ struct xfs_fsop_geom;
4141
#define XFS_SICK_FS_UQUOTA (1 << 1) /* user quota */
4242
#define XFS_SICK_FS_GQUOTA (1 << 2) /* group quota */
4343
#define XFS_SICK_FS_PQUOTA (1 << 3) /* project quota */
44+
#define XFS_SICK_FS_QUOTACHECK (1 << 4) /* quota counts */
4445

4546
/* Observable health issues for realtime volume metadata. */
4647
#define XFS_SICK_RT_BITMAP (1 << 0) /* realtime bitmap */
@@ -77,7 +78,8 @@ struct xfs_fsop_geom;
7778
#define XFS_SICK_FS_PRIMARY (XFS_SICK_FS_COUNTERS | \
7879
XFS_SICK_FS_UQUOTA | \
7980
XFS_SICK_FS_GQUOTA | \
80-
XFS_SICK_FS_PQUOTA)
81+
XFS_SICK_FS_PQUOTA | \
82+
XFS_SICK_FS_QUOTACHECK)
8183

8284
#define XFS_SICK_RT_PRIMARY (XFS_SICK_RT_BITMAP | \
8385
XFS_SICK_RT_SUMMARY)

fs/xfs/scrub/common.c

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
#include "xfs_attr.h"
3030
#include "xfs_reflink.h"
3131
#include "xfs_ag.h"
32+
#include "xfs_error.h"
33+
#include "xfs_quota.h"
3234
#include "scrub/scrub.h"
3335
#include "scrub/common.h"
3436
#include "scrub/trace.h"
@@ -82,15 +84,23 @@ __xchk_process_error(
8284
sc->ip ? sc->ip : XFS_I(file_inode(sc->file)),
8385
sc->sm, *error);
8486
break;
87+
case -ECANCELED:
88+
/*
89+
* ECANCELED here means that the caller set one of the scrub
90+
* outcome flags (corrupt, xfail, xcorrupt) and wants to exit
91+
* quickly. Set error to zero and do not continue.
92+
*/
93+
trace_xchk_op_error(sc, agno, bno, *error, ret_ip);
94+
*error = 0;
95+
break;
8596
case -EFSBADCRC:
8697
case -EFSCORRUPTED:
8798
/* Note the badness but don't abort. */
8899
sc->sm->sm_flags |= errflag;
89100
*error = 0;
90101
fallthrough;
91102
default:
92-
trace_xchk_op_error(sc, agno, bno, *error,
93-
ret_ip);
103+
trace_xchk_op_error(sc, agno, bno, *error, ret_ip);
94104
break;
95105
}
96106
return false;
@@ -136,6 +146,16 @@ __xchk_fblock_process_error(
136146
/* Used to restart an op with deadlock avoidance. */
137147
trace_xchk_deadlock_retry(sc->ip, sc->sm, *error);
138148
break;
149+
case -ECANCELED:
150+
/*
151+
* ECANCELED here means that the caller set one of the scrub
152+
* outcome flags (corrupt, xfail, xcorrupt) and wants to exit
153+
* quickly. Set error to zero and do not continue.
154+
*/
155+
trace_xchk_file_op_error(sc, whichfork, offset, *error,
156+
ret_ip);
157+
*error = 0;
158+
break;
139159
case -EFSBADCRC:
140160
case -EFSCORRUPTED:
141161
/* Note the badness but don't abort. */
@@ -227,6 +247,19 @@ xchk_block_set_corrupt(
227247
trace_xchk_block_error(sc, xfs_buf_daddr(bp), __return_address);
228248
}
229249

250+
#ifdef CONFIG_XFS_QUOTA
251+
/* Record a corrupt quota counter. */
252+
void
253+
xchk_qcheck_set_corrupt(
254+
struct xfs_scrub *sc,
255+
unsigned int dqtype,
256+
xfs_dqid_t id)
257+
{
258+
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
259+
trace_xchk_qcheck_error(sc, dqtype, id, __return_address);
260+
}
261+
#endif
262+
230263
/* Record a corruption while cross-referencing. */
231264
void
232265
xchk_block_xref_set_corrupt(
@@ -653,6 +686,13 @@ xchk_trans_cancel(
653686
sc->tp = NULL;
654687
}
655688

689+
int
690+
xchk_trans_alloc_empty(
691+
struct xfs_scrub *sc)
692+
{
693+
return xfs_trans_alloc_empty(sc->mp, &sc->tp);
694+
}
695+
656696
/*
657697
* Grab an empty transaction so that we can re-grab locked buffers if
658698
* one of our btrees turns out to be cyclic.
@@ -672,7 +712,7 @@ xchk_trans_alloc(
672712
return xfs_trans_alloc(sc->mp, &M_RES(sc->mp)->tr_itruncate,
673713
resblks, 0, 0, &sc->tp);
674714

675-
return xfs_trans_alloc_empty(sc->mp, &sc->tp);
715+
return xchk_trans_alloc_empty(sc);
676716
}
677717

678718
/* Set us up with a transaction and an empty context. */
@@ -1259,6 +1299,9 @@ xchk_fsgates_enable(
12591299
if (scrub_fsgates & XCHK_FSGATES_DRAIN)
12601300
xfs_drain_wait_enable();
12611301

1302+
if (scrub_fsgates & XCHK_FSGATES_QUOTA)
1303+
xfs_dqtrx_hook_enable();
1304+
12621305
sc->flags |= scrub_fsgates;
12631306
}
12641307

fs/xfs/scrub/common.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ xchk_should_terminate(
3232
}
3333

3434
int xchk_trans_alloc(struct xfs_scrub *sc, uint resblks);
35+
int xchk_trans_alloc_empty(struct xfs_scrub *sc);
3536
void xchk_trans_cancel(struct xfs_scrub *sc);
3637

3738
bool xchk_process_error(struct xfs_scrub *sc, xfs_agnumber_t agno,
@@ -54,6 +55,10 @@ void xchk_block_set_corrupt(struct xfs_scrub *sc,
5455
void xchk_ino_set_corrupt(struct xfs_scrub *sc, xfs_ino_t ino);
5556
void xchk_fblock_set_corrupt(struct xfs_scrub *sc, int whichfork,
5657
xfs_fileoff_t offset);
58+
#ifdef CONFIG_XFS_QUOTA
59+
void xchk_qcheck_set_corrupt(struct xfs_scrub *sc, unsigned int dqtype,
60+
xfs_dqid_t id);
61+
#endif
5762

5863
void xchk_block_xref_set_corrupt(struct xfs_scrub *sc,
5964
struct xfs_buf *bp);
@@ -105,6 +110,7 @@ xchk_setup_rtsummary(struct xfs_scrub *sc)
105110
#ifdef CONFIG_XFS_QUOTA
106111
int xchk_ino_dqattach(struct xfs_scrub *sc);
107112
int xchk_setup_quota(struct xfs_scrub *sc);
113+
int xchk_setup_quotacheck(struct xfs_scrub *sc);
108114
#else
109115
static inline int
110116
xchk_ino_dqattach(struct xfs_scrub *sc)
@@ -116,6 +122,11 @@ xchk_setup_quota(struct xfs_scrub *sc)
116122
{
117123
return -ENOENT;
118124
}
125+
static inline int
126+
xchk_setup_quotacheck(struct xfs_scrub *sc)
127+
{
128+
return -ENOENT;
129+
}
119130
#endif
120131
int xchk_setup_fscounters(struct xfs_scrub *sc);
121132

fs/xfs/scrub/fscounters.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ xchk_setup_fscounters(
242242
return error;
243243
}
244244

245-
return xfs_trans_alloc_empty(sc->mp, &sc->tp);
245+
return xchk_trans_alloc_empty(sc);
246246
}
247247

248248
/*

fs/xfs/scrub/health.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ static const struct xchk_health_map type_to_health_flag[XFS_SCRUB_TYPE_NR] = {
105105
[XFS_SCRUB_TYPE_GQUOTA] = { XHG_FS, XFS_SICK_FS_GQUOTA },
106106
[XFS_SCRUB_TYPE_PQUOTA] = { XHG_FS, XFS_SICK_FS_PQUOTA },
107107
[XFS_SCRUB_TYPE_FSCOUNTERS] = { XHG_FS, XFS_SICK_FS_COUNTERS },
108+
[XFS_SCRUB_TYPE_QUOTACHECK] = { XHG_FS, XFS_SICK_FS_QUOTACHECK },
108109
};
109110

110111
/* Return the health status mask for this scrub type. */

0 commit comments

Comments
 (0)