summaryrefslogtreecommitdiff
path: root/fs/xfs/scrub/repair.h
blob: 8a7d03396bb90132d951ca648e3985e56ba77d69 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2018 Oracle.  All Rights Reserved.
 * Author: Darrick J. Wong <darrick.wong@oracle.com>
 */
#ifndef __XFS_SCRUB_REPAIR_H__
#define __XFS_SCRUB_REPAIR_H__

#include "xfs_btree.h"
#include "xfs_btree_staging.h"
#include "xfs_quota_defs.h"
#include "scrub/bitmap.h"

union xfs_btree_ptr;

static inline int xrep_notsupported(struct xfs_scrub *sc)
{
	return -EOPNOTSUPP;
}

#ifdef CONFIG_XFS_ONLINE_REPAIR

/* Repair helpers */

int xrep_attempt(struct xfs_scrub *sc);
void xrep_failure(struct xfs_mount *mp);
int xrep_roll_ag_trans(struct xfs_scrub *sc);
int xrep_roll_trans(struct xfs_scrub *sc);
bool xrep_ag_has_space(struct xfs_perag *pag, xfs_extlen_t nr_blocks,
		enum xfs_ag_resv_type type);
xfs_extlen_t xrep_calc_ag_resblks(struct xfs_scrub *sc);
int xrep_alloc_ag_block(struct xfs_scrub *sc,
		const struct xfs_owner_info *oinfo, xfs_fsblock_t *fsbno,
		enum xfs_ag_resv_type resv);
int xrep_init_btblock(struct xfs_scrub *sc, xfs_fsblock_t fsb,
		struct xfs_buf **bpp, xfs_btnum_t btnum,
		const struct xfs_buf_ops *ops);

static inline int
xrep_trans_commit(
	struct xfs_scrub	*sc)
{
	int			error = xfs_trans_commit(sc->tp);

	sc->tp = NULL;
	return error;
}

struct xbitmap;

int xrep_fix_freelist(struct xfs_scrub *sc, int alloc_flags);
int xrep_reap_extents(struct xfs_scrub *sc, struct xbitmap *exlist,
		const struct xfs_owner_info *oinfo, enum xfs_ag_resv_type type);
int xrep_reap_fork(struct xfs_scrub *sc, struct xfs_inode *ip, int whichfork);

struct xrep_find_ag_btree {
	/* in: rmap owner of the btree we're looking for */
	uint64_t			rmap_owner;

	/* in: buffer ops */
	const struct xfs_buf_ops	*buf_ops;

	/* in: maximum btree height */
	unsigned int			maxlevels;

	/* out: the highest btree block found and the tree height */
	xfs_agblock_t			root;
	unsigned int			height;
};

int xrep_find_ag_btree_roots(struct xfs_scrub *sc, struct xfs_buf *agf_bp,
		struct xrep_find_ag_btree *btree_info, struct xfs_buf *agfl_bp);
void xrep_force_quotacheck(struct xfs_scrub *sc, xfs_dqtype_t type);
int xrep_ino_dqattach(struct xfs_scrub *sc);
int xrep_reset_perag_resv(struct xfs_scrub *sc);
int xrep_bmap(struct xfs_scrub *sc, int whichfork, bool allow_unwritten);
int xrep_metadata_inode_forks(struct xfs_scrub *sc);
int xrep_setup_rtsummary(struct xfs_scrub *sc, unsigned int *resblks);
int xrep_setup_xattr(struct xfs_scrub *sc);
int xrep_setup_directory(struct xfs_scrub *sc);
int xrep_setup_parent(struct xfs_scrub *sc);
int xrep_setup_rtbitmap(struct xfs_scrub *sc, unsigned int *resblks);
int xrep_setup_nlinks(struct xfs_scrub *sc, unsigned int *buf_bytes);

int xrep_xattr_reset_fork(struct xfs_scrub *sc, struct xfs_inode *ip);

/* Repair setup functions */
int xrep_setup_ag_allocbt(struct xfs_scrub *sc);

void xrep_ag_btcur_init(struct xfs_scrub *sc, struct xchk_ag *sa);
int xrep_ag_init(struct xfs_scrub *sc, struct xfs_perag *pag,
		struct xchk_ag *sa);
void xrep_rt_btcur_init(struct xfs_scrub *sc, struct xchk_rt *sr);
int xrep_check_ino_btree_mapping(struct xfs_scrub *sc,
		const struct xfs_rmap_irec *rec);

#ifdef CONFIG_XFS_RT
int xrep_require_rtext_inuse(struct xfs_scrub *sc, xfs_rtblock_t rtbno,
		xfs_filblks_t len, bool must_align);
#else
# define xrep_require_rtext_inuse(sc, rtbno, len, align)	(-ENOSYS)
#endif
bool xrep_is_rtmeta_ino(struct xfs_scrub *sc, xfs_ino_t ino);

/* Metadata revalidators */

int xrep_revalidate_allocbt(struct xfs_scrub *sc);
int xrep_revalidate_iallocbt(struct xfs_scrub *sc);

/* Buffer cache scan context. */
struct xrep_buf_scan {
	/* Disk address for the buffers we want to scan. */
	xfs_daddr_t		daddr;

	/* Maximum number of sectors to scan. */
	xfs_daddr_t		max_sectors;

	/* Each round, increment the search length by this number of sectors. */
	xfs_daddr_t		daddr_step;

	/* Internal scan state; initialize to zero. */
	xfs_daddr_t		__sector_count;
};

xfs_daddr_t xrep_max_buf_sectors(struct xfs_mount *mp, xfs_extlen_t fsblocks);
struct xfs_buf *xrep_buf_scan_advance(struct xfs_mount *mp,
		struct xrep_buf_scan *scan);

/* Metadata repairers */

int xrep_probe(struct xfs_scrub *sc);
int xrep_superblock(struct xfs_scrub *sc);
int xrep_agf(struct xfs_scrub *sc);
int xrep_agfl(struct xfs_scrub *sc);
int xrep_agi(struct xfs_scrub *sc);
int xrep_allocbt(struct xfs_scrub *sc);
int xrep_iallocbt(struct xfs_scrub *sc);
int xrep_rmapbt(struct xfs_scrub *sc);
int xrep_refcountbt(struct xfs_scrub *sc);
int xrep_inode(struct xfs_scrub *sc);
int xrep_bmap_data(struct xfs_scrub *sc);
int xrep_bmap_attr(struct xfs_scrub *sc);
int xrep_symlink(struct xfs_scrub *sc);
int xrep_fscounters(struct xfs_scrub *sc);
int xrep_xattr(struct xfs_scrub *sc);
int xrep_directory(struct xfs_scrub *sc);
int xrep_parent(struct xfs_scrub *sc);
int xrep_nlinks(struct xfs_scrub *sc);

#ifdef CONFIG_XFS_QUOTA
int xrep_quota(struct xfs_scrub *sc);
int xrep_quotacheck(struct xfs_scrub *sc);
#else
# define xrep_quota			xrep_notsupported
# define xrep_quotacheck		xrep_notsupported
#endif /* CONFIG_XFS_QUOTA */

#ifdef CONFIG_XFS_RT
int xrep_rtsummary(struct xfs_scrub *sc);
int xrep_rtbitmap(struct xfs_scrub *sc);
int xrep_rtrmapbt(struct xfs_scrub *sc);
int xrep_rtrefcountbt(struct xfs_scrub *sc);
#else
# define xrep_rtsummary			xrep_notsupported
# define xrep_rtbitmap			xrep_notsupported
# define xrep_rtrmapbt			xrep_notsupported
# define xrep_rtrefcountbt		xrep_notsupported
#endif /* CONFIG_XFS_RT */

struct xrep_newbt_resv {
	/* Link to list of extents that we've reserved. */
	struct list_head	list;

	struct xfs_log_item	*efi;

	/* FSB of the block we reserved. */
	xfs_fsblock_t		fsbno;

	/* Length of the reservation. */
	xfs_extlen_t		len;

	/* How much of this reservation has been used. */
	xfs_extlen_t		used;
};

struct xfs_alloc_arg;

struct xrep_newbt {
	struct xfs_scrub	*sc;

	/* Custom allocation function, or NULL for xfs_alloc_vextent */
	int			(*alloc_vextent)(struct xfs_scrub *sc,
						 struct xfs_alloc_arg *args);

	/* List of extents that we've reserved. */
	struct list_head	resv_list;

	/* Fake root for new btree. */
	union {
		struct xbtree_afakeroot	afake;
		struct xbtree_ifakeroot	ifake;
	};

	/* rmap owner of these blocks */
	struct xfs_owner_info	oinfo;

	/* Allocation hint */
	xfs_fsblock_t		alloc_hint;

	/* per-ag reservation type */
	enum xfs_ag_resv_type	resv;
};

#define for_each_xrep_newbt_reservation(xnr, resv, n)	\
	list_for_each_entry_safe((resv), (n), &(xnr)->resv_list, list)

void xrep_newbt_init_bare(struct xrep_newbt *xnr, struct xfs_scrub *sc);
void xrep_newbt_init_ag(struct xrep_newbt *xnr, struct xfs_scrub *sc,
		const struct xfs_owner_info *oinfo, xfs_fsblock_t alloc_hint,
		enum xfs_ag_resv_type resv);
void xrep_newbt_init_inode(struct xrep_newbt *xnr, struct xfs_scrub *sc,
		int whichfork, const struct xfs_owner_info *oinfo);
int xrep_newbt_add_blocks(struct xrep_newbt *xnr, xfs_fsblock_t fsbno,
		xfs_extlen_t len);
int xrep_newbt_alloc_blocks(struct xrep_newbt *xnr, uint64_t nr_blocks);
void xrep_newbt_destroy(struct xrep_newbt *xnr, int error);
int xrep_newbt_claim_block(struct xfs_btree_cur *cur, struct xrep_newbt *xnr,
		union xfs_btree_ptr *ptr);
void xrep_bload_estimate_slack(struct xfs_scrub *sc,
		struct xfs_btree_bload *bload);
int xrep_newbt_relog_efis(struct xrep_newbt *xnr);

bool xrep_buf_verify_struct(struct xfs_buf *bp, const struct xfs_buf_ops *ops);
xfs_ino_t xrep_dotdot_lookup(struct xfs_scrub *sc);
void xrep_inode_set_nblocks(struct xfs_scrub *sc, int64_t new_blocks);
int xrep_reset_imeta_reservation(struct xfs_scrub *sc);

#else

static inline int
xrep_attempt(
	struct xfs_scrub	*sc)
{
	return -EOPNOTSUPP;
}

static inline void xrep_failure(struct xfs_mount *mp) {}

static inline xfs_extlen_t
xrep_calc_ag_resblks(
	struct xfs_scrub	*sc)
{
	return 0;
}

static inline int
xrep_reset_perag_resv(
	struct xfs_scrub	*sc)
{
	if (!(sc->flags & XREP_RESET_PERAG_RESV))
		return 0;

	ASSERT(0);
	return -EOPNOTSUPP;
}

/* repair setup functions for no-repair */
static inline int
xrep_setup_nothing(
	struct xfs_scrub	*sc)
{
	return 0;
}
#define xrep_setup_ag_allocbt		xrep_setup_nothing
#define xrep_setup_xattr		xrep_setup_nothing
#define xrep_setup_directory		xrep_setup_nothing
#define xrep_setup_parent		xrep_setup_nothing

static inline int
xrep_setup_rtsummary(struct xfs_scrub *sc, unsigned int *whatever)
{
	return 0;
}
#define xrep_setup_rtbitmap		xrep_setup_rtsummary
#define xrep_setup_nlinks		xrep_setup_rtsummary

#define xrep_revalidate_allocbt		(NULL)
#define xrep_revalidate_iallocbt	(NULL)

#define xrep_probe			xrep_notsupported
#define xrep_superblock			xrep_notsupported
#define xrep_agf			xrep_notsupported
#define xrep_agfl			xrep_notsupported
#define xrep_agi			xrep_notsupported
#define xrep_allocbt			xrep_notsupported
#define xrep_iallocbt			xrep_notsupported
#define xrep_rmapbt			xrep_notsupported
#define xrep_refcountbt			xrep_notsupported
#define xrep_inode			xrep_notsupported
#define xrep_bmap_data			xrep_notsupported
#define xrep_bmap_attr			xrep_notsupported
#define xrep_symlink			xrep_notsupported
#define xrep_quota			xrep_notsupported
#define xrep_quotacheck			xrep_notsupported
#define xrep_fscounters			xrep_notsupported
#define xrep_rtsummary			xrep_notsupported
#define xrep_xattr			xrep_notsupported
#define xrep_directory			xrep_notsupported
#define xrep_parent			xrep_notsupported
#define xrep_rtbitmap			xrep_notsupported
#define xrep_rtrmapbt			xrep_notsupported
#define xrep_rtrefcountbt		xrep_notsupported
#define xrep_nlinks			xrep_notsupported

#endif /* CONFIG_XFS_ONLINE_REPAIR */

#endif	/* __XFS_SCRUB_REPAIR_H__ */