Skip to content

Commit df78332

Browse files
author
Chandan Babu R
committed
Merge tag 'scrub-rtsummary-6.6_2023-08-10' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux into xfs-6.6-mergeA
xfs: online scrubbing of realtime summary files This patchset implements an online checker for the realtime summary file. The first few changes are some general cleanups -- scrub should get its own references to all inodes, and we also wrap the inode lock functions so that we can standardize unlocking and releasing inodes that are the focus of a scrub. With that out of the way, we move on to constructing a shadow copy of the rtsummary information from the rtbitmap, and compare the new copy against the ondisk copy. This has been running on the djcloud for years with no problems. Enjoy! Signed-off-by: Darrick J. Wong <[email protected]> Signed-off-by: Chandan Babu R <[email protected]> * tag 'scrub-rtsummary-6.6_2023-08-10' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux: xfs: implement online scrubbing of rtsummary info xfs: move the realtime summary file scrubber to a separate source file xfs: wrap ilock/iunlock operations on sc->ip xfs: get our own reference to inodes that we want to scrub
2 parents 889b09b + 526aab5 commit df78332

File tree

13 files changed

+421
-82
lines changed

13 files changed

+421
-82
lines changed

fs/xfs/Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,12 @@ xfs-y += $(addprefix scrub/, \
169169
)
170170

171171
xfs-$(CONFIG_XFS_ONLINE_SCRUB_STATS) += scrub/stats.o
172-
xfs-$(CONFIG_XFS_RT) += scrub/rtbitmap.o
172+
173+
xfs-$(CONFIG_XFS_RT) += $(addprefix scrub/, \
174+
rtbitmap.o \
175+
rtsummary.o \
176+
)
177+
173178
xfs-$(CONFIG_XFS_QUOTA) += scrub/quota.o
174179

175180
# online repair

fs/xfs/scrub/bmap.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ xchk_setup_inode_bmap(
3838
if (error)
3939
goto out;
4040

41-
sc->ilock_flags = XFS_IOLOCK_EXCL;
42-
xfs_ilock(sc->ip, XFS_IOLOCK_EXCL);
41+
xchk_ilock(sc, XFS_IOLOCK_EXCL);
4342

4443
/*
4544
* We don't want any ephemeral data/cow fork updates sitting around
@@ -50,8 +49,7 @@ xchk_setup_inode_bmap(
5049
sc->sm->sm_type != XFS_SCRUB_TYPE_BMBTA) {
5150
struct address_space *mapping = VFS_I(sc->ip)->i_mapping;
5251

53-
sc->ilock_flags |= XFS_MMAPLOCK_EXCL;
54-
xfs_ilock(sc->ip, XFS_MMAPLOCK_EXCL);
52+
xchk_ilock(sc, XFS_MMAPLOCK_EXCL);
5553

5654
inode_dio_wait(VFS_I(sc->ip));
5755

@@ -79,9 +77,8 @@ xchk_setup_inode_bmap(
7977
error = xchk_trans_alloc(sc, 0);
8078
if (error)
8179
goto out;
82-
sc->ilock_flags |= XFS_ILOCK_EXCL;
83-
xfs_ilock(sc->ip, XFS_ILOCK_EXCL);
8480

81+
xchk_ilock(sc, XFS_ILOCK_EXCL);
8582
out:
8683
/* scrub teardown will unlock and release the inode */
8784
return error;

fs/xfs/scrub/common.c

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,25 @@ xchk_install_handle_inode(
831831
return 0;
832832
}
833833

834+
/*
835+
* Install an already-referenced inode for scrubbing. Get our own reference to
836+
* the inode to make disposal simpler. The inode must not be in I_FREEING or
837+
* I_WILL_FREE state!
838+
*/
839+
int
840+
xchk_install_live_inode(
841+
struct xfs_scrub *sc,
842+
struct xfs_inode *ip)
843+
{
844+
if (!igrab(VFS_I(ip))) {
845+
xchk_ino_set_corrupt(sc, ip->i_ino);
846+
return -EFSCORRUPTED;
847+
}
848+
849+
sc->ip = ip;
850+
return 0;
851+
}
852+
834853
/*
835854
* In preparation to scrub metadata structures that hang off of an inode,
836855
* grab either the inode referenced in the scrub control structure or the
@@ -854,10 +873,8 @@ xchk_iget_for_scrubbing(
854873
ASSERT(sc->tp == NULL);
855874

856875
/* We want to scan the inode we already had opened. */
857-
if (sc->sm->sm_ino == 0 || sc->sm->sm_ino == ip_in->i_ino) {
858-
sc->ip = ip_in;
859-
return 0;
860-
}
876+
if (sc->sm->sm_ino == 0 || sc->sm->sm_ino == ip_in->i_ino)
877+
return xchk_install_live_inode(sc, ip_in);
861878

862879
/* Reject internal metadata files and obviously bad inode numbers. */
863880
if (xfs_internal_inum(mp, sc->sm->sm_ino))
@@ -1005,20 +1022,48 @@ xchk_setup_inode_contents(
10051022
return error;
10061023

10071024
/* Lock the inode so the VFS cannot touch this file. */
1008-
sc->ilock_flags = XFS_IOLOCK_EXCL;
1009-
xfs_ilock(sc->ip, sc->ilock_flags);
1025+
xchk_ilock(sc, XFS_IOLOCK_EXCL);
10101026

10111027
error = xchk_trans_alloc(sc, resblks);
10121028
if (error)
10131029
goto out;
1014-
sc->ilock_flags |= XFS_ILOCK_EXCL;
1015-
xfs_ilock(sc->ip, XFS_ILOCK_EXCL);
1016-
1030+
xchk_ilock(sc, XFS_ILOCK_EXCL);
10171031
out:
10181032
/* scrub teardown will unlock and release the inode for us */
10191033
return error;
10201034
}
10211035

1036+
void
1037+
xchk_ilock(
1038+
struct xfs_scrub *sc,
1039+
unsigned int ilock_flags)
1040+
{
1041+
xfs_ilock(sc->ip, ilock_flags);
1042+
sc->ilock_flags |= ilock_flags;
1043+
}
1044+
1045+
bool
1046+
xchk_ilock_nowait(
1047+
struct xfs_scrub *sc,
1048+
unsigned int ilock_flags)
1049+
{
1050+
if (xfs_ilock_nowait(sc->ip, ilock_flags)) {
1051+
sc->ilock_flags |= ilock_flags;
1052+
return true;
1053+
}
1054+
1055+
return false;
1056+
}
1057+
1058+
void
1059+
xchk_iunlock(
1060+
struct xfs_scrub *sc,
1061+
unsigned int ilock_flags)
1062+
{
1063+
sc->ilock_flags &= ~ilock_flags;
1064+
xfs_iunlock(sc->ip, ilock_flags);
1065+
}
1066+
10221067
/*
10231068
* Predicate that decides if we need to evaluate the cross-reference check.
10241069
* If there was an error accessing the cross-reference btree, just delete

fs/xfs/scrub/common.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,16 @@ int xchk_setup_xattr(struct xfs_scrub *sc);
8888
int xchk_setup_symlink(struct xfs_scrub *sc);
8989
int xchk_setup_parent(struct xfs_scrub *sc);
9090
#ifdef CONFIG_XFS_RT
91-
int xchk_setup_rt(struct xfs_scrub *sc);
91+
int xchk_setup_rtbitmap(struct xfs_scrub *sc);
92+
int xchk_setup_rtsummary(struct xfs_scrub *sc);
9293
#else
9394
static inline int
94-
xchk_setup_rt(struct xfs_scrub *sc)
95+
xchk_setup_rtbitmap(struct xfs_scrub *sc)
96+
{
97+
return -ENOENT;
98+
}
99+
static inline int
100+
xchk_setup_rtsummary(struct xfs_scrub *sc)
95101
{
96102
return -ENOENT;
97103
}
@@ -137,6 +143,12 @@ int xchk_count_rmap_ownedby_ag(struct xfs_scrub *sc, struct xfs_btree_cur *cur,
137143
int xchk_setup_ag_btree(struct xfs_scrub *sc, bool force_log);
138144
int xchk_iget_for_scrubbing(struct xfs_scrub *sc);
139145
int xchk_setup_inode_contents(struct xfs_scrub *sc, unsigned int resblks);
146+
int xchk_install_live_inode(struct xfs_scrub *sc, struct xfs_inode *ip);
147+
148+
void xchk_ilock(struct xfs_scrub *sc, unsigned int ilock_flags);
149+
bool xchk_ilock_nowait(struct xfs_scrub *sc, unsigned int ilock_flags);
150+
void xchk_iunlock(struct xfs_scrub *sc, unsigned int ilock_flags);
151+
140152
void xchk_buffer_recheck(struct xfs_scrub *sc, struct xfs_buf *bp);
141153

142154
int xchk_iget(struct xfs_scrub *sc, xfs_ino_t inum, struct xfs_inode **ipp);
@@ -157,6 +169,14 @@ static inline bool xchk_skip_xref(struct xfs_scrub_metadata *sm)
157169

158170
int xchk_metadata_inode_forks(struct xfs_scrub *sc);
159171

172+
/*
173+
* Helper macros to allocate and format xfile description strings.
174+
* Callers must kfree the pointer returned.
175+
*/
176+
#define xchk_xfile_descr(sc, fmt, ...) \
177+
kasprintf(XCHK_GFP_FLAGS, "XFS (%s): " fmt, \
178+
(sc)->mp->m_super->s_id, ##__VA_ARGS__)
179+
160180
/*
161181
* Setting up a hook to wait for intents to drain is costly -- we have to take
162182
* the CPU hotplug lock and force an i-cache flush on all CPUs once to set it

fs/xfs/scrub/inode.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,13 @@ xchk_prepare_iscrub(
3232
{
3333
int error;
3434

35-
sc->ilock_flags = XFS_IOLOCK_EXCL;
36-
xfs_ilock(sc->ip, sc->ilock_flags);
35+
xchk_ilock(sc, XFS_IOLOCK_EXCL);
3736

3837
error = xchk_trans_alloc(sc, 0);
3938
if (error)
4039
return error;
4140

42-
sc->ilock_flags |= XFS_ILOCK_EXCL;
43-
xfs_ilock(sc->ip, XFS_ILOCK_EXCL);
41+
xchk_ilock(sc, XFS_ILOCK_EXCL);
4442
return 0;
4543
}
4644

@@ -83,7 +81,10 @@ xchk_setup_inode(
8381

8482
/* We want to scan the opened inode, so lock it and exit. */
8583
if (sc->sm->sm_ino == 0 || sc->sm->sm_ino == ip_in->i_ino) {
86-
sc->ip = ip_in;
84+
error = xchk_install_live_inode(sc, ip_in);
85+
if (error)
86+
return error;
87+
8788
return xchk_prepare_iscrub(sc);
8889
}
8990

fs/xfs/scrub/parent.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,8 @@ xchk_parent_validate(
150150

151151
lock_mode = xchk_parent_ilock_dir(dp);
152152
if (!lock_mode) {
153-
xfs_iunlock(sc->ip, XFS_ILOCK_EXCL);
154-
xfs_ilock(sc->ip, XFS_ILOCK_EXCL);
153+
xchk_iunlock(sc, XFS_ILOCK_EXCL);
154+
xchk_ilock(sc, XFS_ILOCK_EXCL);
155155
error = -EAGAIN;
156156
goto out_rele;
157157
}

fs/xfs/scrub/quota.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,12 @@ xchk_setup_quota(
5959
error = xchk_setup_fs(sc);
6060
if (error)
6161
return error;
62-
sc->ip = xfs_quota_inode(sc->mp, dqtype);
63-
xfs_ilock(sc->ip, XFS_ILOCK_EXCL);
64-
sc->ilock_flags = XFS_ILOCK_EXCL;
62+
63+
error = xchk_install_live_inode(sc, xfs_quota_inode(sc->mp, dqtype));
64+
if (error)
65+
return error;
66+
67+
xchk_ilock(sc, XFS_ILOCK_EXCL);
6568
return 0;
6669
}
6770

@@ -235,13 +238,11 @@ xchk_quota(
235238
* data fork we have to drop ILOCK_EXCL to use the regular dquot
236239
* functions.
237240
*/
238-
xfs_iunlock(sc->ip, sc->ilock_flags);
239-
sc->ilock_flags = 0;
241+
xchk_iunlock(sc, sc->ilock_flags);
240242
sqi.sc = sc;
241243
sqi.last_id = 0;
242244
error = xfs_qm_dqiterate(mp, dqtype, xchk_quota_item, &sqi);
243-
sc->ilock_flags = XFS_ILOCK_EXCL;
244-
xfs_ilock(sc->ip, sc->ilock_flags);
245+
xchk_ilock(sc, XFS_ILOCK_EXCL);
245246
if (error == -ECANCELED)
246247
error = 0;
247248
if (!xchk_fblock_process_error(sc, XFS_DATA_FORK,

fs/xfs/scrub/rtbitmap.c

Lines changed: 6 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,20 @@
1919

2020
/* Set us up with the realtime metadata locked. */
2121
int
22-
xchk_setup_rt(
22+
xchk_setup_rtbitmap(
2323
struct xfs_scrub *sc)
2424
{
2525
int error;
2626

27-
error = xchk_setup_fs(sc);
27+
error = xchk_trans_alloc(sc, 0);
2828
if (error)
2929
return error;
3030

31-
sc->ilock_flags = XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP;
32-
sc->ip = sc->mp->m_rbmip;
33-
xfs_ilock(sc->ip, sc->ilock_flags);
31+
error = xchk_install_live_inode(sc, sc->mp->m_rbmip);
32+
if (error)
33+
return error;
3434

35+
xchk_ilock(sc, XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP);
3536
return 0;
3637
}
3738

@@ -123,43 +124,6 @@ xchk_rtbitmap(
123124
return error;
124125
}
125126

126-
/* Scrub the realtime summary. */
127-
int
128-
xchk_rtsummary(
129-
struct xfs_scrub *sc)
130-
{
131-
struct xfs_inode *rsumip = sc->mp->m_rsumip;
132-
struct xfs_inode *old_ip = sc->ip;
133-
uint old_ilock_flags = sc->ilock_flags;
134-
int error = 0;
135-
136-
/*
137-
* We ILOCK'd the rt bitmap ip in the setup routine, now lock the
138-
* rt summary ip in compliance with the rt inode locking rules.
139-
*
140-
* Since we switch sc->ip to rsumip we have to save the old ilock
141-
* flags so that we don't mix up the inode state that @sc tracks.
142-
*/
143-
sc->ip = rsumip;
144-
sc->ilock_flags = XFS_ILOCK_EXCL | XFS_ILOCK_RTSUM;
145-
xfs_ilock(sc->ip, sc->ilock_flags);
146-
147-
/* Invoke the fork scrubber. */
148-
error = xchk_metadata_inode_forks(sc);
149-
if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
150-
goto out;
151-
152-
/* XXX: implement this some day */
153-
xchk_set_incomplete(sc);
154-
out:
155-
/* Switch back to the rtbitmap inode and lock flags. */
156-
xfs_iunlock(sc->ip, sc->ilock_flags);
157-
sc->ilock_flags = old_ilock_flags;
158-
sc->ip = old_ip;
159-
return error;
160-
}
161-
162-
163127
/* xref check that the extent is not free in the rtbitmap */
164128
void
165129
xchk_xref_is_used_rt_space(

0 commit comments

Comments
 (0)