xref: /linux/fs/xfs/libxfs/xfs_rmap.h (revision 1113a6d6d5d1336f4415fa1367aac0f853f0892d)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2016 Oracle.  All Rights Reserved.
4  * Author: Darrick J. Wong <darrick.wong@oracle.com>
5  */
6 #ifndef __XFS_RMAP_H__
7 #define __XFS_RMAP_H__
8 
9 struct xfs_perag;
10 struct xfs_rtgroup;
11 
12 static inline void
13 xfs_rmap_ino_bmbt_owner(
14 	struct xfs_owner_info	*oi,
15 	xfs_ino_t		ino,
16 	int			whichfork)
17 {
18 	oi->oi_owner = ino;
19 	oi->oi_offset = 0;
20 	oi->oi_flags = XFS_OWNER_INFO_BMBT_BLOCK;
21 	if (whichfork == XFS_ATTR_FORK)
22 		oi->oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
23 }
24 #define xfs_rmap_inode_bmbt_owner(oi, ip, whichfork) \
25 	xfs_rmap_ino_bmbt_owner(oi, I_INO(ip), whichfork)
26 
27 static inline void
28 xfs_rmap_ino_owner(
29 	struct xfs_owner_info	*oi,
30 	xfs_ino_t		ino,
31 	int			whichfork,
32 	xfs_fileoff_t		offset)
33 {
34 	oi->oi_owner = ino;
35 	oi->oi_offset = offset;
36 	oi->oi_flags = 0;
37 	if (whichfork == XFS_ATTR_FORK)
38 		oi->oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
39 }
40 #define xfs_rmap_inode_owner(oi, ip, whichfork, offset) \
41 	xfs_rmap_ino_owner(oi, I_INO(ip), whichfork, offset)
42 
43 static inline bool
44 xfs_rmap_should_skip_owner_update(
45 	const struct xfs_owner_info	*oi)
46 {
47 	return oi->oi_owner == XFS_RMAP_OWN_NULL;
48 }
49 
50 /* Reverse mapping functions. */
51 
52 struct xfs_buf;
53 
54 static inline __u64
55 xfs_rmap_irec_offset_pack(
56 	const struct xfs_rmap_irec	*irec)
57 {
58 	__u64			x;
59 
60 	x = XFS_RMAP_OFF(irec->rm_offset);
61 	if (irec->rm_flags & XFS_RMAP_ATTR_FORK)
62 		x |= XFS_RMAP_OFF_ATTR_FORK;
63 	if (irec->rm_flags & XFS_RMAP_BMBT_BLOCK)
64 		x |= XFS_RMAP_OFF_BMBT_BLOCK;
65 	if (irec->rm_flags & XFS_RMAP_UNWRITTEN)
66 		x |= XFS_RMAP_OFF_UNWRITTEN;
67 	return x;
68 }
69 
70 static inline xfs_failaddr_t
71 xfs_rmap_irec_offset_unpack(
72 	__u64			offset,
73 	struct xfs_rmap_irec	*irec)
74 {
75 	if (offset & ~(XFS_RMAP_OFF_MASK | XFS_RMAP_OFF_FLAGS))
76 		return __this_address;
77 
78 	irec->rm_offset = XFS_RMAP_OFF(offset);
79 	irec->rm_flags = 0;
80 	if (offset & XFS_RMAP_OFF_ATTR_FORK)
81 		irec->rm_flags |= XFS_RMAP_ATTR_FORK;
82 	if (offset & XFS_RMAP_OFF_BMBT_BLOCK)
83 		irec->rm_flags |= XFS_RMAP_BMBT_BLOCK;
84 	if (offset & XFS_RMAP_OFF_UNWRITTEN)
85 		irec->rm_flags |= XFS_RMAP_UNWRITTEN;
86 	return NULL;
87 }
88 
89 static inline void
90 xfs_owner_info_unpack(
91 	const struct xfs_owner_info	*oinfo,
92 	uint64_t			*owner,
93 	uint64_t			*offset,
94 	unsigned int			*flags)
95 {
96 	unsigned int			r = 0;
97 
98 	*owner = oinfo->oi_owner;
99 	*offset = oinfo->oi_offset;
100 	if (oinfo->oi_flags & XFS_OWNER_INFO_ATTR_FORK)
101 		r |= XFS_RMAP_ATTR_FORK;
102 	if (oinfo->oi_flags & XFS_OWNER_INFO_BMBT_BLOCK)
103 		r |= XFS_RMAP_BMBT_BLOCK;
104 	*flags = r;
105 }
106 
107 static inline void
108 xfs_owner_info_pack(
109 	struct xfs_owner_info	*oinfo,
110 	uint64_t		owner,
111 	uint64_t		offset,
112 	unsigned int		flags)
113 {
114 	oinfo->oi_owner = owner;
115 	oinfo->oi_offset = XFS_RMAP_OFF(offset);
116 	oinfo->oi_flags = 0;
117 	if (flags & XFS_RMAP_ATTR_FORK)
118 		oinfo->oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
119 	if (flags & XFS_RMAP_BMBT_BLOCK)
120 		oinfo->oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
121 }
122 
123 int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp,
124 		   struct xfs_perag *pag, xfs_agblock_t bno, xfs_extlen_t len,
125 		   const struct xfs_owner_info *oinfo);
126 int xfs_rmap_free(struct xfs_trans *tp, struct xfs_buf *agbp,
127 		  struct xfs_perag *pag, xfs_agblock_t bno, xfs_extlen_t len,
128 		  const struct xfs_owner_info *oinfo);
129 
130 int xfs_rmap_lookup_le(struct xfs_btree_cur *cur, xfs_agblock_t bno,
131 		uint64_t owner, uint64_t offset, unsigned int flags,
132 		struct xfs_rmap_irec *irec, int *stat);
133 int xfs_rmap_lookup_eq(struct xfs_btree_cur *cur, xfs_agblock_t bno,
134 		xfs_extlen_t len, uint64_t owner, uint64_t offset,
135 		unsigned int flags, int *stat);
136 int xfs_rmap_insert(struct xfs_btree_cur *rcur, xfs_agblock_t agbno,
137 		xfs_extlen_t len, uint64_t owner, uint64_t offset,
138 		unsigned int flags);
139 int xfs_rmap_get_rec(struct xfs_btree_cur *cur, struct xfs_rmap_irec *irec,
140 		int *stat);
141 
142 typedef int (*xfs_rmap_query_range_fn)(
143 	struct xfs_btree_cur		*cur,
144 	const struct xfs_rmap_irec	*rec,
145 	void				*priv);
146 
147 int xfs_rmap_query_range(struct xfs_btree_cur *cur,
148 		const struct xfs_rmap_irec *low_rec,
149 		const struct xfs_rmap_irec *high_rec,
150 		xfs_rmap_query_range_fn fn, void *priv);
151 int xfs_rmap_query_all(struct xfs_btree_cur *cur, xfs_rmap_query_range_fn fn,
152 		void *priv);
153 
154 enum xfs_rmap_intent_type {
155 	XFS_RMAP_MAP,
156 	XFS_RMAP_MAP_SHARED,
157 	XFS_RMAP_UNMAP,
158 	XFS_RMAP_UNMAP_SHARED,
159 	XFS_RMAP_CONVERT,
160 	XFS_RMAP_CONVERT_SHARED,
161 	XFS_RMAP_ALLOC,
162 	XFS_RMAP_FREE,
163 };
164 
165 #define XFS_RMAP_INTENT_STRINGS \
166 	{ XFS_RMAP_MAP,			"map" }, \
167 	{ XFS_RMAP_MAP_SHARED,		"map_shared" }, \
168 	{ XFS_RMAP_UNMAP,		"unmap" }, \
169 	{ XFS_RMAP_UNMAP_SHARED,	"unmap_shared" }, \
170 	{ XFS_RMAP_CONVERT,		"cvt" }, \
171 	{ XFS_RMAP_CONVERT_SHARED,	"cvt_shared" }, \
172 	{ XFS_RMAP_ALLOC,		"alloc" }, \
173 	{ XFS_RMAP_FREE,		"free" }
174 
175 struct xfs_rmap_intent {
176 	struct list_head			ri_list;
177 	enum xfs_rmap_intent_type		ri_type;
178 	int					ri_whichfork;
179 	uint64_t				ri_owner;
180 	struct xfs_bmbt_irec			ri_bmap;
181 	struct xfs_group			*ri_group;
182 	bool					ri_realtime;
183 };
184 
185 /* functions for updating the rmapbt based on bmbt map/unmap operations */
186 void xfs_rmap_map_extent(struct xfs_trans *tp, struct xfs_inode *ip,
187 		int whichfork, struct xfs_bmbt_irec *imap);
188 void xfs_rmap_unmap_extent(struct xfs_trans *tp, struct xfs_inode *ip,
189 		int whichfork, struct xfs_bmbt_irec *imap);
190 void xfs_rmap_convert_extent(struct xfs_mount *mp, struct xfs_trans *tp,
191 		struct xfs_inode *ip, int whichfork,
192 		struct xfs_bmbt_irec *imap);
193 void xfs_rmap_alloc_extent(struct xfs_trans *tp, bool isrt, xfs_fsblock_t fsbno,
194 		xfs_extlen_t len, uint64_t owner);
195 void xfs_rmap_free_extent(struct xfs_trans *tp, bool isrt, xfs_fsblock_t fsbno,
196 		xfs_extlen_t len, uint64_t owner);
197 
198 int xfs_rmap_finish_one(struct xfs_trans *tp, struct xfs_rmap_intent *ri,
199 		struct xfs_btree_cur **pcur);
200 int __xfs_rmap_finish_intent(struct xfs_btree_cur *rcur,
201 		enum xfs_rmap_intent_type op, xfs_agblock_t bno,
202 		xfs_extlen_t len, const struct xfs_owner_info *oinfo,
203 		bool unwritten);
204 
205 int xfs_rmap_lookup_le_range(struct xfs_btree_cur *cur, xfs_agblock_t bno,
206 		uint64_t owner, uint64_t offset, unsigned int flags,
207 		struct xfs_rmap_irec *irec, int	*stat);
208 int xfs_rmap_compare(const struct xfs_rmap_irec *a,
209 		const struct xfs_rmap_irec *b);
210 union xfs_btree_rec;
211 xfs_failaddr_t xfs_rmap_btrec_to_irec(const union xfs_btree_rec *rec,
212 		struct xfs_rmap_irec *irec);
213 xfs_failaddr_t xfs_rmap_check_irec(struct xfs_perag *pag,
214 		const struct xfs_rmap_irec *irec);
215 xfs_failaddr_t xfs_rtrmap_check_irec(struct xfs_rtgroup *rtg,
216 		const struct xfs_rmap_irec *irec);
217 
218 int xfs_rmap_has_records(struct xfs_btree_cur *cur, xfs_agblock_t bno,
219 		xfs_extlen_t len, enum xbtree_recpacking *outcome);
220 
221 struct xfs_rmap_matches {
222 	/* Number of owner matches. */
223 	unsigned long long	matches;
224 
225 	/* Number of non-owner matches. */
226 	unsigned long long	non_owner_matches;
227 
228 	/* Number of non-owner matches that conflict with the owner matches. */
229 	unsigned long long	bad_non_owner_matches;
230 };
231 
232 int xfs_rmap_count_owners(struct xfs_btree_cur *cur, xfs_agblock_t bno,
233 		xfs_extlen_t len, const struct xfs_owner_info *oinfo,
234 		struct xfs_rmap_matches *rmatch);
235 int xfs_rmap_has_other_keys(struct xfs_btree_cur *cur, xfs_agblock_t bno,
236 		xfs_extlen_t len, const struct xfs_owner_info *oinfo,
237 		bool *has_other);
238 int xfs_rmap_map_raw(struct xfs_btree_cur *cur, struct xfs_rmap_irec *rmap);
239 
240 extern const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE;
241 extern const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER;
242 extern const struct xfs_owner_info XFS_RMAP_OINFO_FS;
243 extern const struct xfs_owner_info XFS_RMAP_OINFO_LOG;
244 extern const struct xfs_owner_info XFS_RMAP_OINFO_AG;
245 extern const struct xfs_owner_info XFS_RMAP_OINFO_INOBT;
246 extern const struct xfs_owner_info XFS_RMAP_OINFO_INODES;
247 extern const struct xfs_owner_info XFS_RMAP_OINFO_REFC;
248 extern const struct xfs_owner_info XFS_RMAP_OINFO_COW;
249 
250 extern struct kmem_cache	*xfs_rmap_intent_cache;
251 
252 int __init xfs_rmap_intent_init_cache(void);
253 void xfs_rmap_intent_destroy_cache(void);
254 
255 /*
256  * Parameters for tracking reverse mapping changes.  The hook function arg
257  * parameter is enum xfs_rmap_intent_type, and the rest is below.
258  */
259 struct xfs_rmap_update_params {
260 	xfs_agblock_t			startblock;
261 	xfs_extlen_t			blockcount;
262 	struct xfs_owner_info		oinfo;
263 	bool				unwritten;
264 };
265 
266 #ifdef CONFIG_XFS_LIVE_HOOKS
267 
268 struct xfs_rmap_hook {
269 	struct xfs_hook			rmap_hook;
270 };
271 
272 void xfs_rmap_hook_disable(void);
273 void xfs_rmap_hook_enable(void);
274 
275 int xfs_rmap_hook_add(struct xfs_group *xg, struct xfs_rmap_hook *hook);
276 void xfs_rmap_hook_del(struct xfs_group *xg, struct xfs_rmap_hook *hook);
277 void xfs_rmap_hook_setup(struct xfs_rmap_hook *hook, notifier_fn_t mod_fn);
278 #endif
279 
280 #endif	/* __XFS_RMAP_H__ */
281