Skip to content

Commit fd43925

Browse files
author
Chandan Babu R
committed
Merge tag 'repair-rmap-btree-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 rmap btrees We have now constructed the four tools that we need to scan the filesystem looking for reverse mappings: an inode scanner, hooks to receive live updates from other writer threads, the ability to construct btrees in memory, and a btree bulk loader. This series glues those three together, enabling us to scan the filesystem for mappings and keep it up to date while other writers run, and then commit the new btree to disk atomically. To reduce the size of each patch, the functionality is left disabled until the end of the series and broken up into three patches: one to create the mechanics of scanning the filesystem, a second to transition to in-memory btrees, and a third to set up the live hooks. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Chandan Babu R <chandanbabu@kernel.org> * tag 'repair-rmap-btree-6.9_2024-02-23' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux: xfs: hook live rmap operations during a repair operation xfs: create a shadow rmap btree during rmap repair xfs: repair the rmapbt xfs: create agblock bitmap helper to count the number of set regions xfs: create a helper to decide if a file mapping targets the rt volume
2 parents 8394a97 + 7e1b84b commit fd43925

31 files changed

Lines changed: 2336 additions & 70 deletions

fs/xfs/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ xfs-y += $(addprefix scrub/, \
201201
reap.o \
202202
refcount_repair.o \
203203
repair.o \
204+
rmap_repair.o \
204205
)
205206

206207
xfs-$(CONFIG_XFS_RT) += $(addprefix scrub/, \

fs/xfs/libxfs/xfs_ag.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ xfs_initialize_perag(
417417
init_waitqueue_head(&pag->pag_active_wq);
418418
pag->pagb_count = 0;
419419
pag->pagb_tree = RB_ROOT;
420+
xfs_hooks_init(&pag->pag_rmap_update_hooks);
420421
#endif /* __KERNEL__ */
421422

422423
error = xfs_buf_cache_init(&pag->pag_bcache);

fs/xfs/libxfs/xfs_ag.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ struct xfs_perag {
9090
uint8_t pagf_repair_bno_level;
9191
uint8_t pagf_repair_cnt_level;
9292
uint8_t pagf_repair_refcount_level;
93+
uint8_t pagf_repair_rmap_level;
9394
#endif
9495

9596
spinlock_t pag_state_lock;
@@ -119,6 +120,9 @@ struct xfs_perag {
119120
* inconsistencies.
120121
*/
121122
struct xfs_defer_drain pag_intents_drain;
123+
124+
/* Hook to feed rmapbt updates to an active online repair. */
125+
struct xfs_hooks pag_rmap_update_hooks;
122126
#endif /* __KERNEL__ */
123127
};
124128

fs/xfs/libxfs/xfs_bmap.c

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4913,7 +4913,7 @@ xfs_bmap_del_extent_delay(
49134913

49144914
XFS_STATS_INC(mp, xs_del_exlist);
49154915

4916-
isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
4916+
isrt = xfs_ifork_is_realtime(ip, whichfork);
49174917
del_endoff = del->br_startoff + del->br_blockcount;
49184918
got_endoff = got->br_startoff + got->br_blockcount;
49194919
da_old = startblockval(got->br_startblock);
@@ -5149,7 +5149,7 @@ xfs_bmap_del_extent_real(
51495149
return -ENOSPC;
51505150

51515151
*logflagsp = XFS_ILOG_CORE;
5152-
if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) {
5152+
if (xfs_ifork_is_realtime(ip, whichfork)) {
51535153
if (!(bflags & XFS_BMAPI_REMAP)) {
51545154
error = xfs_rtfree_blocks(tp, del->br_startblock,
51555155
del->br_blockcount);
@@ -5396,7 +5396,7 @@ __xfs_bunmapi(
53965396
return 0;
53975397
}
53985398
XFS_STATS_INC(mp, xs_blk_unmap);
5399-
isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
5399+
isrt = xfs_ifork_is_realtime(ip, whichfork);
54005400
end = start + len;
54015401

54025402
if (!xfs_iext_lookup_extent_before(ip, ifp, &end, &icur, &got)) {
@@ -6379,3 +6379,46 @@ xfs_bunmapi_range(
63796379
out:
63806380
return error;
63816381
}
6382+
6383+
struct xfs_bmap_query_range {
6384+
xfs_bmap_query_range_fn fn;
6385+
void *priv;
6386+
};
6387+
6388+
/* Format btree record and pass to our callback. */
6389+
STATIC int
6390+
xfs_bmap_query_range_helper(
6391+
struct xfs_btree_cur *cur,
6392+
const union xfs_btree_rec *rec,
6393+
void *priv)
6394+
{
6395+
struct xfs_bmap_query_range *query = priv;
6396+
struct xfs_bmbt_irec irec;
6397+
xfs_failaddr_t fa;
6398+
6399+
xfs_bmbt_disk_get_all(&rec->bmbt, &irec);
6400+
fa = xfs_bmap_validate_extent(cur->bc_ino.ip, cur->bc_ino.whichfork,
6401+
&irec);
6402+
if (fa) {
6403+
xfs_btree_mark_sick(cur);
6404+
return xfs_bmap_complain_bad_rec(cur->bc_ino.ip,
6405+
cur->bc_ino.whichfork, fa, &irec);
6406+
}
6407+
6408+
return query->fn(cur, &irec, query->priv);
6409+
}
6410+
6411+
/* Find all bmaps. */
6412+
int
6413+
xfs_bmap_query_all(
6414+
struct xfs_btree_cur *cur,
6415+
xfs_bmap_query_range_fn fn,
6416+
void *priv)
6417+
{
6418+
struct xfs_bmap_query_range query = {
6419+
.priv = priv,
6420+
.fn = fn,
6421+
};
6422+
6423+
return xfs_btree_query_all(cur, xfs_bmap_query_range_helper, &query);
6424+
}

fs/xfs/libxfs/xfs_bmap.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,4 +280,12 @@ extern struct kmem_cache *xfs_bmap_intent_cache;
280280
int __init xfs_bmap_intent_init_cache(void);
281281
void xfs_bmap_intent_destroy_cache(void);
282282

283+
typedef int (*xfs_bmap_query_range_fn)(
284+
struct xfs_btree_cur *cur,
285+
struct xfs_bmbt_irec *rec,
286+
void *priv);
287+
288+
int xfs_bmap_query_all(struct xfs_btree_cur *cur, xfs_bmap_query_range_fn fn,
289+
void *priv);
290+
283291
#endif /* __XFS_BMAP_H__ */

fs/xfs/libxfs/xfs_inode_fork.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,3 +813,12 @@ xfs_iext_count_upgrade(
813813

814814
return 0;
815815
}
816+
817+
/* Decide if a file mapping is on the realtime device or not. */
818+
bool
819+
xfs_ifork_is_realtime(
820+
struct xfs_inode *ip,
821+
int whichfork)
822+
{
823+
return XFS_IS_REALTIME_INODE(ip) && whichfork != XFS_ATTR_FORK;
824+
}

fs/xfs/libxfs/xfs_inode_fork.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ int xfs_iext_count_may_overflow(struct xfs_inode *ip, int whichfork,
260260
int nr_to_add);
261261
int xfs_iext_count_upgrade(struct xfs_trans *tp, struct xfs_inode *ip,
262262
uint nr_to_add);
263+
bool xfs_ifork_is_realtime(struct xfs_inode *ip, int whichfork);
263264

264265
/* returns true if the fork has extents but they are not read in yet. */
265266
static inline bool xfs_need_iread_extents(const struct xfs_ifork *ifp)

0 commit comments

Comments
 (0)