Skip to content

Commit cd5b26f

Browse files
author
Darrick J. Wong
committed
xfs: add rtgroup-based realtime scrubbing context management
Create a state tracking structure and helpers to initialize the tracking structure so that we can check metadata records against the realtime space management metadata. Right now this is limited to grabbing the incore rtgroup object, but we'll eventually add to the tracking structure the ILOCK state and btree cursors. Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]>
1 parent 65b1231 commit cd5b26f

File tree

6 files changed

+181
-0
lines changed

6 files changed

+181
-0
lines changed

fs/xfs/scrub/common.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "xfs_quota.h"
3535
#include "xfs_exchmaps.h"
3636
#include "xfs_rtbitmap.h"
37+
#include "xfs_rtgroup.h"
3738
#include "scrub/scrub.h"
3839
#include "scrub/common.h"
3940
#include "scrub/trace.h"
@@ -121,6 +122,17 @@ xchk_process_error(
121122
XFS_SCRUB_OFLAG_CORRUPT, __return_address);
122123
}
123124

125+
bool
126+
xchk_process_rt_error(
127+
struct xfs_scrub *sc,
128+
xfs_rgnumber_t rgno,
129+
xfs_rgblock_t rgbno,
130+
int *error)
131+
{
132+
return __xchk_process_error(sc, rgno, rgbno, error,
133+
XFS_SCRUB_OFLAG_CORRUPT, __return_address);
134+
}
135+
124136
bool
125137
xchk_xref_process_error(
126138
struct xfs_scrub *sc,
@@ -684,6 +696,72 @@ xchk_ag_init(
684696
return 0;
685697
}
686698

699+
#ifdef CONFIG_XFS_RT
700+
/*
701+
* For scrubbing a realtime group, grab all the in-core resources we'll need to
702+
* check the metadata, which means taking the ILOCK of the realtime group's
703+
* metadata inodes. Callers must not join these inodes to the transaction with
704+
* non-zero lockflags or concurrency problems will result. The @rtglock_flags
705+
* argument takes XFS_RTGLOCK_* flags.
706+
*/
707+
int
708+
xchk_rtgroup_init(
709+
struct xfs_scrub *sc,
710+
xfs_rgnumber_t rgno,
711+
struct xchk_rt *sr)
712+
{
713+
ASSERT(sr->rtg == NULL);
714+
ASSERT(sr->rtlock_flags == 0);
715+
716+
sr->rtg = xfs_rtgroup_get(sc->mp, rgno);
717+
if (!sr->rtg)
718+
return -ENOENT;
719+
return 0;
720+
}
721+
722+
void
723+
xchk_rtgroup_lock(
724+
struct xchk_rt *sr,
725+
unsigned int rtglock_flags)
726+
{
727+
xfs_rtgroup_lock(sr->rtg, rtglock_flags);
728+
sr->rtlock_flags = rtglock_flags;
729+
}
730+
731+
/*
732+
* Unlock the realtime group. This must be done /after/ committing (or
733+
* cancelling) the scrub transaction.
734+
*/
735+
static void
736+
xchk_rtgroup_unlock(
737+
struct xchk_rt *sr)
738+
{
739+
ASSERT(sr->rtg != NULL);
740+
741+
if (sr->rtlock_flags) {
742+
xfs_rtgroup_unlock(sr->rtg, sr->rtlock_flags);
743+
sr->rtlock_flags = 0;
744+
}
745+
}
746+
747+
/*
748+
* Unlock the realtime group and release its resources. This must be done
749+
* /after/ committing (or cancelling) the scrub transaction.
750+
*/
751+
void
752+
xchk_rtgroup_free(
753+
struct xfs_scrub *sc,
754+
struct xchk_rt *sr)
755+
{
756+
ASSERT(sr->rtg != NULL);
757+
758+
xchk_rtgroup_unlock(sr);
759+
760+
xfs_rtgroup_put(sr->rtg);
761+
sr->rtg = NULL;
762+
}
763+
#endif /* CONFIG_XFS_RT */
764+
687765
/* Per-scrubber setup functions */
688766

689767
void

fs/xfs/scrub/common.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ void xchk_trans_cancel(struct xfs_scrub *sc);
1212

1313
bool xchk_process_error(struct xfs_scrub *sc, xfs_agnumber_t agno,
1414
xfs_agblock_t bno, int *error);
15+
bool xchk_process_rt_error(struct xfs_scrub *sc, xfs_rgnumber_t rgno,
16+
xfs_rgblock_t rgbno, int *error);
1517
bool xchk_fblock_process_error(struct xfs_scrub *sc, int whichfork,
1618
xfs_fileoff_t offset, int *error);
1719

@@ -118,6 +120,34 @@ xchk_ag_init_existing(
118120
return error == -ENOENT ? -EFSCORRUPTED : error;
119121
}
120122

123+
#ifdef CONFIG_XFS_RT
124+
125+
/* All the locks we need to check an rtgroup. */
126+
#define XCHK_RTGLOCK_ALL (XFS_RTGLOCK_BITMAP)
127+
128+
int xchk_rtgroup_init(struct xfs_scrub *sc, xfs_rgnumber_t rgno,
129+
struct xchk_rt *sr);
130+
131+
static inline int
132+
xchk_rtgroup_init_existing(
133+
struct xfs_scrub *sc,
134+
xfs_rgnumber_t rgno,
135+
struct xchk_rt *sr)
136+
{
137+
int error = xchk_rtgroup_init(sc, rgno, sr);
138+
139+
return error == -ENOENT ? -EFSCORRUPTED : error;
140+
}
141+
142+
void xchk_rtgroup_lock(struct xchk_rt *sr, unsigned int rtglock_flags);
143+
void xchk_rtgroup_free(struct xfs_scrub *sc, struct xchk_rt *sr);
144+
#else
145+
# define xchk_rtgroup_init(sc, rgno, sr) (-EFSCORRUPTED)
146+
# define xchk_rtgroup_init_existing(sc, rgno, sr) (-EFSCORRUPTED)
147+
# define xchk_rtgroup_lock(sc, lockflags) do { } while (0)
148+
# define xchk_rtgroup_free(sc, sr) do { } while (0)
149+
#endif /* CONFIG_XFS_RT */
150+
121151
int xchk_ag_read_headers(struct xfs_scrub *sc, xfs_agnumber_t agno,
122152
struct xchk_ag *sa);
123153
void xchk_ag_btcur_free(struct xchk_ag *sa);

fs/xfs/scrub/repair.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "xfs_rmap.h"
2222
#include "xfs_rmap_btree.h"
2323
#include "xfs_refcount_btree.h"
24+
#include "xfs_rtgroup.h"
2425
#include "xfs_extent_busy.h"
2526
#include "xfs_ag.h"
2627
#include "xfs_ag_resv.h"
@@ -952,6 +953,29 @@ xrep_ag_init(
952953
return 0;
953954
}
954955

956+
#ifdef CONFIG_XFS_RT
957+
/*
958+
* Given a reference to a rtgroup structure, lock rtgroup btree inodes and
959+
* create btree cursors. Must only be called to repair a regular rt file.
960+
*/
961+
int
962+
xrep_rtgroup_init(
963+
struct xfs_scrub *sc,
964+
struct xfs_rtgroup *rtg,
965+
struct xchk_rt *sr,
966+
unsigned int rtglock_flags)
967+
{
968+
ASSERT(sr->rtg == NULL);
969+
970+
xfs_rtgroup_lock(rtg, rtglock_flags);
971+
sr->rtlock_flags = rtglock_flags;
972+
973+
/* Grab our own passive reference from the caller's ref. */
974+
sr->rtg = xfs_rtgroup_hold(rtg);
975+
return 0;
976+
}
977+
#endif /* CONFIG_XFS_RT */
978+
955979
/* Reinitialize the per-AG block reservation for the AG we just fixed. */
956980
int
957981
xrep_reset_perag_resv(

fs/xfs/scrub/repair.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "xfs_quota_defs.h"
1010

11+
struct xfs_rtgroup;
1112
struct xchk_stats_run;
1213

1314
static inline int xrep_notsupported(struct xfs_scrub *sc)
@@ -106,6 +107,12 @@ int xrep_setup_inode(struct xfs_scrub *sc, const struct xfs_imap *imap);
106107
void xrep_ag_btcur_init(struct xfs_scrub *sc, struct xchk_ag *sa);
107108
int xrep_ag_init(struct xfs_scrub *sc, struct xfs_perag *pag,
108109
struct xchk_ag *sa);
110+
#ifdef CONFIG_XFS_RT
111+
int xrep_rtgroup_init(struct xfs_scrub *sc, struct xfs_rtgroup *rtg,
112+
struct xchk_rt *sr, unsigned int rtglock_flags);
113+
#else
114+
# define xrep_rtgroup_init(sc, rtg, sr, lockflags) (-ENOSYS)
115+
#endif /* CONFIG_XFS_RT */
109116

110117
/* Metadata revalidators */
111118

fs/xfs/scrub/scrub.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ xchk_teardown(
225225
xfs_trans_cancel(sc->tp);
226226
sc->tp = NULL;
227227
}
228+
if (sc->sr.rtg)
229+
xchk_rtgroup_free(sc, &sc->sr);
228230
if (sc->ip) {
229231
if (sc->ilock_flags)
230232
xchk_iunlock(sc, sc->ilock_flags);
@@ -498,6 +500,33 @@ xchk_validate_inputs(
498500
break;
499501
case ST_GENERIC:
500502
break;
503+
case ST_RTGROUP:
504+
if (sm->sm_ino || sm->sm_gen)
505+
goto out;
506+
if (xfs_has_rtgroups(mp)) {
507+
/*
508+
* On a rtgroups filesystem, there won't be an rtbitmap
509+
* or rtsummary file for group 0 unless there's
510+
* actually a realtime volume attached. However, older
511+
* xfs_scrub always calls the rtbitmap/rtsummary
512+
* scrubbers with sm_agno==0 so transform the error
513+
* code to ENOENT.
514+
*/
515+
if (sm->sm_agno >= mp->m_sb.sb_rgcount) {
516+
if (sm->sm_agno == 0)
517+
error = -ENOENT;
518+
goto out;
519+
}
520+
} else {
521+
/*
522+
* Prior to rtgroups, the rtbitmap/rtsummary scrubbers
523+
* accepted sm_agno==0, so we still accept that for
524+
* scrubbing pre-rtgroups filesystems.
525+
*/
526+
if (sm->sm_agno != 0)
527+
goto out;
528+
}
529+
break;
501530
default:
502531
goto out;
503532
}

fs/xfs/scrub/scrub.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ enum xchk_type {
7474
ST_FS, /* per-FS metadata */
7575
ST_INODE, /* per-inode metadata */
7676
ST_GENERIC, /* determined by the scrubber */
77+
ST_RTGROUP, /* rtgroup metadata */
7778
};
7879

7980
struct xchk_meta_ops {
@@ -118,6 +119,15 @@ struct xchk_ag {
118119
struct xfs_btree_cur *refc_cur;
119120
};
120121

122+
/* Inode lock state for the RT volume. */
123+
struct xchk_rt {
124+
/* incore rtgroup, if applicable */
125+
struct xfs_rtgroup *rtg;
126+
127+
/* XFS_RTGLOCK_* lock state if locked */
128+
unsigned int rtlock_flags;
129+
};
130+
121131
struct xfs_scrub {
122132
/* General scrub state. */
123133
struct xfs_mount *mp;
@@ -179,6 +189,9 @@ struct xfs_scrub {
179189

180190
/* State tracking for single-AG operations. */
181191
struct xchk_ag sa;
192+
193+
/* State tracking for realtime operations. */
194+
struct xchk_rt sr;
182195
};
183196

184197
/* XCHK state flags grow up from zero, XREP state flags grown down from 2^31 */

0 commit comments

Comments
 (0)