• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2014 Red Hat, Inc.
4  * All Rights Reserved.
5  */
6 #include "xfs.h"
7 #include "xfs_fs.h"
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_log_format.h"
11 #include "xfs_trans_resv.h"
12 #include "xfs_bit.h"
13 #include "xfs_mount.h"
14 #include "xfs_sb.h"
15 #include "xfs_defer.h"
16 #include "xfs_btree.h"
17 #include "xfs_trans.h"
18 #include "xfs_alloc.h"
19 #include "xfs_rmap.h"
20 #include "xfs_rmap_btree.h"
21 #include "xfs_trace.h"
22 #include "xfs_errortag.h"
23 #include "xfs_error.h"
24 #include "xfs_inode.h"
25 #include "xfs_ag.h"
26 
27 /*
28  * Lookup the first record less than or equal to [bno, len, owner, offset]
29  * in the btree given by cur.
30  */
31 int
xfs_rmap_lookup_le(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,uint64_t owner,uint64_t offset,unsigned int flags,int * stat)32 xfs_rmap_lookup_le(
33 	struct xfs_btree_cur	*cur,
34 	xfs_agblock_t		bno,
35 	xfs_extlen_t		len,
36 	uint64_t		owner,
37 	uint64_t		offset,
38 	unsigned int		flags,
39 	int			*stat)
40 {
41 	cur->bc_rec.r.rm_startblock = bno;
42 	cur->bc_rec.r.rm_blockcount = len;
43 	cur->bc_rec.r.rm_owner = owner;
44 	cur->bc_rec.r.rm_offset = offset;
45 	cur->bc_rec.r.rm_flags = flags;
46 	return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
47 }
48 
49 /*
50  * Lookup the record exactly matching [bno, len, owner, offset]
51  * in the btree given by cur.
52  */
53 int
xfs_rmap_lookup_eq(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,uint64_t owner,uint64_t offset,unsigned int flags,int * stat)54 xfs_rmap_lookup_eq(
55 	struct xfs_btree_cur	*cur,
56 	xfs_agblock_t		bno,
57 	xfs_extlen_t		len,
58 	uint64_t		owner,
59 	uint64_t		offset,
60 	unsigned int		flags,
61 	int			*stat)
62 {
63 	cur->bc_rec.r.rm_startblock = bno;
64 	cur->bc_rec.r.rm_blockcount = len;
65 	cur->bc_rec.r.rm_owner = owner;
66 	cur->bc_rec.r.rm_offset = offset;
67 	cur->bc_rec.r.rm_flags = flags;
68 	return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
69 }
70 
71 /*
72  * Update the record referred to by cur to the value given
73  * by [bno, len, owner, offset].
74  * This either works (return 0) or gets an EFSCORRUPTED error.
75  */
76 STATIC int
xfs_rmap_update(struct xfs_btree_cur * cur,struct xfs_rmap_irec * irec)77 xfs_rmap_update(
78 	struct xfs_btree_cur	*cur,
79 	struct xfs_rmap_irec	*irec)
80 {
81 	union xfs_btree_rec	rec;
82 	int			error;
83 
84 	trace_xfs_rmap_update(cur->bc_mp, cur->bc_ag.pag->pag_agno,
85 			irec->rm_startblock, irec->rm_blockcount,
86 			irec->rm_owner, irec->rm_offset, irec->rm_flags);
87 
88 	rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
89 	rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
90 	rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
91 	rec.rmap.rm_offset = cpu_to_be64(
92 			xfs_rmap_irec_offset_pack(irec));
93 	error = xfs_btree_update(cur, &rec);
94 	if (error)
95 		trace_xfs_rmap_update_error(cur->bc_mp,
96 				cur->bc_ag.pag->pag_agno, error, _RET_IP_);
97 	return error;
98 }
99 
100 int
xfs_rmap_insert(struct xfs_btree_cur * rcur,xfs_agblock_t agbno,xfs_extlen_t len,uint64_t owner,uint64_t offset,unsigned int flags)101 xfs_rmap_insert(
102 	struct xfs_btree_cur	*rcur,
103 	xfs_agblock_t		agbno,
104 	xfs_extlen_t		len,
105 	uint64_t		owner,
106 	uint64_t		offset,
107 	unsigned int		flags)
108 {
109 	int			i;
110 	int			error;
111 
112 	trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno,
113 			len, owner, offset, flags);
114 
115 	error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
116 	if (error)
117 		goto done;
118 	if (XFS_IS_CORRUPT(rcur->bc_mp, i != 0)) {
119 		error = -EFSCORRUPTED;
120 		goto done;
121 	}
122 
123 	rcur->bc_rec.r.rm_startblock = agbno;
124 	rcur->bc_rec.r.rm_blockcount = len;
125 	rcur->bc_rec.r.rm_owner = owner;
126 	rcur->bc_rec.r.rm_offset = offset;
127 	rcur->bc_rec.r.rm_flags = flags;
128 	error = xfs_btree_insert(rcur, &i);
129 	if (error)
130 		goto done;
131 	if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
132 		error = -EFSCORRUPTED;
133 		goto done;
134 	}
135 done:
136 	if (error)
137 		trace_xfs_rmap_insert_error(rcur->bc_mp,
138 				rcur->bc_ag.pag->pag_agno, error, _RET_IP_);
139 	return error;
140 }
141 
142 STATIC int
xfs_rmap_delete(struct xfs_btree_cur * rcur,xfs_agblock_t agbno,xfs_extlen_t len,uint64_t owner,uint64_t offset,unsigned int flags)143 xfs_rmap_delete(
144 	struct xfs_btree_cur	*rcur,
145 	xfs_agblock_t		agbno,
146 	xfs_extlen_t		len,
147 	uint64_t		owner,
148 	uint64_t		offset,
149 	unsigned int		flags)
150 {
151 	int			i;
152 	int			error;
153 
154 	trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno,
155 			len, owner, offset, flags);
156 
157 	error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
158 	if (error)
159 		goto done;
160 	if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
161 		error = -EFSCORRUPTED;
162 		goto done;
163 	}
164 
165 	error = xfs_btree_delete(rcur, &i);
166 	if (error)
167 		goto done;
168 	if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
169 		error = -EFSCORRUPTED;
170 		goto done;
171 	}
172 done:
173 	if (error)
174 		trace_xfs_rmap_delete_error(rcur->bc_mp,
175 				rcur->bc_ag.pag->pag_agno, error, _RET_IP_);
176 	return error;
177 }
178 
179 /* Convert an internal btree record to an rmap record. */
180 int
xfs_rmap_btrec_to_irec(const union xfs_btree_rec * rec,struct xfs_rmap_irec * irec)181 xfs_rmap_btrec_to_irec(
182 	const union xfs_btree_rec	*rec,
183 	struct xfs_rmap_irec		*irec)
184 {
185 	irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
186 	irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
187 	irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
188 	return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
189 			irec);
190 }
191 
192 /*
193  * Get the data from the pointed-to record.
194  */
195 int
xfs_rmap_get_rec(struct xfs_btree_cur * cur,struct xfs_rmap_irec * irec,int * stat)196 xfs_rmap_get_rec(
197 	struct xfs_btree_cur	*cur,
198 	struct xfs_rmap_irec	*irec,
199 	int			*stat)
200 {
201 	struct xfs_mount	*mp = cur->bc_mp;
202 	xfs_agnumber_t		agno = cur->bc_ag.pag->pag_agno;
203 	union xfs_btree_rec	*rec;
204 	int			error;
205 
206 	error = xfs_btree_get_rec(cur, &rec, stat);
207 	if (error || !*stat)
208 		return error;
209 
210 	if (xfs_rmap_btrec_to_irec(rec, irec))
211 		goto out_bad_rec;
212 
213 	if (irec->rm_blockcount == 0)
214 		goto out_bad_rec;
215 	if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
216 		if (irec->rm_owner != XFS_RMAP_OWN_FS)
217 			goto out_bad_rec;
218 		if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
219 			goto out_bad_rec;
220 	} else {
221 		/* check for valid extent range, including overflow */
222 		if (!xfs_verify_agbno(mp, agno, irec->rm_startblock))
223 			goto out_bad_rec;
224 		if (irec->rm_startblock >
225 				irec->rm_startblock + irec->rm_blockcount)
226 			goto out_bad_rec;
227 		if (!xfs_verify_agbno(mp, agno,
228 				irec->rm_startblock + irec->rm_blockcount - 1))
229 			goto out_bad_rec;
230 	}
231 
232 	if (!(xfs_verify_ino(mp, irec->rm_owner) ||
233 	      (irec->rm_owner <= XFS_RMAP_OWN_FS &&
234 	       irec->rm_owner >= XFS_RMAP_OWN_MIN)))
235 		goto out_bad_rec;
236 
237 	return 0;
238 out_bad_rec:
239 	xfs_warn(mp,
240 		"Reverse Mapping BTree record corruption in AG %d detected!",
241 		agno);
242 	xfs_warn(mp,
243 		"Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
244 		irec->rm_owner, irec->rm_flags, irec->rm_startblock,
245 		irec->rm_blockcount);
246 	return -EFSCORRUPTED;
247 }
248 
249 struct xfs_find_left_neighbor_info {
250 	struct xfs_rmap_irec	high;
251 	struct xfs_rmap_irec	*irec;
252 	int			*stat;
253 };
254 
255 /* For each rmap given, figure out if it matches the key we want. */
256 STATIC int
xfs_rmap_find_left_neighbor_helper(struct xfs_btree_cur * cur,const struct xfs_rmap_irec * rec,void * priv)257 xfs_rmap_find_left_neighbor_helper(
258 	struct xfs_btree_cur		*cur,
259 	const struct xfs_rmap_irec	*rec,
260 	void				*priv)
261 {
262 	struct xfs_find_left_neighbor_info	*info = priv;
263 
264 	trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
265 			cur->bc_ag.pag->pag_agno, rec->rm_startblock,
266 			rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
267 			rec->rm_flags);
268 
269 	if (rec->rm_owner != info->high.rm_owner)
270 		return 0;
271 	if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
272 	    !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
273 	    rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
274 		return 0;
275 
276 	*info->irec = *rec;
277 	*info->stat = 1;
278 	return -ECANCELED;
279 }
280 
281 /*
282  * Find the record to the left of the given extent, being careful only to
283  * return a match with the same owner and adjacent physical and logical
284  * block ranges.
285  */
286 int
xfs_rmap_find_left_neighbor(struct xfs_btree_cur * cur,xfs_agblock_t bno,uint64_t owner,uint64_t offset,unsigned int flags,struct xfs_rmap_irec * irec,int * stat)287 xfs_rmap_find_left_neighbor(
288 	struct xfs_btree_cur	*cur,
289 	xfs_agblock_t		bno,
290 	uint64_t		owner,
291 	uint64_t		offset,
292 	unsigned int		flags,
293 	struct xfs_rmap_irec	*irec,
294 	int			*stat)
295 {
296 	struct xfs_find_left_neighbor_info	info;
297 	int			error;
298 
299 	*stat = 0;
300 	if (bno == 0)
301 		return 0;
302 	info.high.rm_startblock = bno - 1;
303 	info.high.rm_owner = owner;
304 	if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
305 	    !(flags & XFS_RMAP_BMBT_BLOCK)) {
306 		if (offset == 0)
307 			return 0;
308 		info.high.rm_offset = offset - 1;
309 	} else
310 		info.high.rm_offset = 0;
311 	info.high.rm_flags = flags;
312 	info.high.rm_blockcount = 0;
313 	info.irec = irec;
314 	info.stat = stat;
315 
316 	trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
317 			cur->bc_ag.pag->pag_agno, bno, 0, owner, offset, flags);
318 
319 	error = xfs_rmap_query_range(cur, &info.high, &info.high,
320 			xfs_rmap_find_left_neighbor_helper, &info);
321 	if (error == -ECANCELED)
322 		error = 0;
323 	if (*stat)
324 		trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
325 				cur->bc_ag.pag->pag_agno, irec->rm_startblock,
326 				irec->rm_blockcount, irec->rm_owner,
327 				irec->rm_offset, irec->rm_flags);
328 	return error;
329 }
330 
331 /* For each rmap given, figure out if it matches the key we want. */
332 STATIC int
xfs_rmap_lookup_le_range_helper(struct xfs_btree_cur * cur,const struct xfs_rmap_irec * rec,void * priv)333 xfs_rmap_lookup_le_range_helper(
334 	struct xfs_btree_cur		*cur,
335 	const struct xfs_rmap_irec	*rec,
336 	void				*priv)
337 {
338 	struct xfs_find_left_neighbor_info	*info = priv;
339 
340 	trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
341 			cur->bc_ag.pag->pag_agno, rec->rm_startblock,
342 			rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
343 			rec->rm_flags);
344 
345 	if (rec->rm_owner != info->high.rm_owner)
346 		return 0;
347 	if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
348 	    !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
349 	    (rec->rm_offset > info->high.rm_offset ||
350 	     rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
351 		return 0;
352 
353 	*info->irec = *rec;
354 	*info->stat = 1;
355 	return -ECANCELED;
356 }
357 
358 /*
359  * Find the record to the left of the given extent, being careful only to
360  * return a match with the same owner and overlapping physical and logical
361  * block ranges.  This is the overlapping-interval version of
362  * xfs_rmap_lookup_le.
363  */
364 int
xfs_rmap_lookup_le_range(struct xfs_btree_cur * cur,xfs_agblock_t bno,uint64_t owner,uint64_t offset,unsigned int flags,struct xfs_rmap_irec * irec,int * stat)365 xfs_rmap_lookup_le_range(
366 	struct xfs_btree_cur	*cur,
367 	xfs_agblock_t		bno,
368 	uint64_t		owner,
369 	uint64_t		offset,
370 	unsigned int		flags,
371 	struct xfs_rmap_irec	*irec,
372 	int			*stat)
373 {
374 	struct xfs_find_left_neighbor_info	info;
375 	int			error;
376 
377 	info.high.rm_startblock = bno;
378 	info.high.rm_owner = owner;
379 	if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
380 		info.high.rm_offset = offset;
381 	else
382 		info.high.rm_offset = 0;
383 	info.high.rm_flags = flags;
384 	info.high.rm_blockcount = 0;
385 	*stat = 0;
386 	info.irec = irec;
387 	info.stat = stat;
388 
389 	trace_xfs_rmap_lookup_le_range(cur->bc_mp,
390 			cur->bc_ag.pag->pag_agno, bno, 0, owner, offset, flags);
391 	error = xfs_rmap_query_range(cur, &info.high, &info.high,
392 			xfs_rmap_lookup_le_range_helper, &info);
393 	if (error == -ECANCELED)
394 		error = 0;
395 	if (*stat)
396 		trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
397 				cur->bc_ag.pag->pag_agno, irec->rm_startblock,
398 				irec->rm_blockcount, irec->rm_owner,
399 				irec->rm_offset, irec->rm_flags);
400 	return error;
401 }
402 
403 /*
404  * Perform all the relevant owner checks for a removal op.  If we're doing an
405  * unknown-owner removal then we have no owner information to check.
406  */
407 static int
xfs_rmap_free_check_owner(struct xfs_mount * mp,uint64_t ltoff,struct xfs_rmap_irec * rec,xfs_filblks_t len,uint64_t owner,uint64_t offset,unsigned int flags)408 xfs_rmap_free_check_owner(
409 	struct xfs_mount	*mp,
410 	uint64_t		ltoff,
411 	struct xfs_rmap_irec	*rec,
412 	xfs_filblks_t		len,
413 	uint64_t		owner,
414 	uint64_t		offset,
415 	unsigned int		flags)
416 {
417 	int			error = 0;
418 
419 	if (owner == XFS_RMAP_OWN_UNKNOWN)
420 		return 0;
421 
422 	/* Make sure the unwritten flag matches. */
423 	if (XFS_IS_CORRUPT(mp,
424 			   (flags & XFS_RMAP_UNWRITTEN) !=
425 			   (rec->rm_flags & XFS_RMAP_UNWRITTEN))) {
426 		error = -EFSCORRUPTED;
427 		goto out;
428 	}
429 
430 	/* Make sure the owner matches what we expect to find in the tree. */
431 	if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) {
432 		error = -EFSCORRUPTED;
433 		goto out;
434 	}
435 
436 	/* Check the offset, if necessary. */
437 	if (XFS_RMAP_NON_INODE_OWNER(owner))
438 		goto out;
439 
440 	if (flags & XFS_RMAP_BMBT_BLOCK) {
441 		if (XFS_IS_CORRUPT(mp,
442 				   !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) {
443 			error = -EFSCORRUPTED;
444 			goto out;
445 		}
446 	} else {
447 		if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) {
448 			error = -EFSCORRUPTED;
449 			goto out;
450 		}
451 		if (XFS_IS_CORRUPT(mp,
452 				   offset + len > ltoff + rec->rm_blockcount)) {
453 			error = -EFSCORRUPTED;
454 			goto out;
455 		}
456 	}
457 
458 out:
459 	return error;
460 }
461 
462 /*
463  * Find the extent in the rmap btree and remove it.
464  *
465  * The record we find should always be an exact match for the extent that we're
466  * looking for, since we insert them into the btree without modification.
467  *
468  * Special Case #1: when growing the filesystem, we "free" an extent when
469  * growing the last AG. This extent is new space and so it is not tracked as
470  * used space in the btree. The growfs code will pass in an owner of
471  * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
472  * extent. We verify that - the extent lookup result in a record that does not
473  * overlap.
474  *
475  * Special Case #2: EFIs do not record the owner of the extent, so when
476  * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
477  * btree to ignore the owner (i.e. wildcard match) so we don't trigger
478  * corruption checks during log recovery.
479  */
480 STATIC int
xfs_rmap_unmap(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,bool unwritten,const struct xfs_owner_info * oinfo)481 xfs_rmap_unmap(
482 	struct xfs_btree_cur		*cur,
483 	xfs_agblock_t			bno,
484 	xfs_extlen_t			len,
485 	bool				unwritten,
486 	const struct xfs_owner_info	*oinfo)
487 {
488 	struct xfs_mount		*mp = cur->bc_mp;
489 	struct xfs_rmap_irec		ltrec;
490 	uint64_t			ltoff;
491 	int				error = 0;
492 	int				i;
493 	uint64_t			owner;
494 	uint64_t			offset;
495 	unsigned int			flags;
496 	bool				ignore_off;
497 
498 	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
499 	ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
500 			(flags & XFS_RMAP_BMBT_BLOCK);
501 	if (unwritten)
502 		flags |= XFS_RMAP_UNWRITTEN;
503 	trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
504 			unwritten, oinfo);
505 
506 	/*
507 	 * We should always have a left record because there's a static record
508 	 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
509 	 * will not ever be removed from the tree.
510 	 */
511 	error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i);
512 	if (error)
513 		goto out_error;
514 	if (XFS_IS_CORRUPT(mp, i != 1)) {
515 		error = -EFSCORRUPTED;
516 		goto out_error;
517 	}
518 
519 	error = xfs_rmap_get_rec(cur, &ltrec, &i);
520 	if (error)
521 		goto out_error;
522 	if (XFS_IS_CORRUPT(mp, i != 1)) {
523 		error = -EFSCORRUPTED;
524 		goto out_error;
525 	}
526 	trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
527 			cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
528 			ltrec.rm_blockcount, ltrec.rm_owner,
529 			ltrec.rm_offset, ltrec.rm_flags);
530 	ltoff = ltrec.rm_offset;
531 
532 	/*
533 	 * For growfs, the incoming extent must be beyond the left record we
534 	 * just found as it is new space and won't be used by anyone. This is
535 	 * just a corruption check as we don't actually do anything with this
536 	 * extent.  Note that we need to use >= instead of > because it might
537 	 * be the case that the "left" extent goes all the way to EOFS.
538 	 */
539 	if (owner == XFS_RMAP_OWN_NULL) {
540 		if (XFS_IS_CORRUPT(mp,
541 				   bno <
542 				   ltrec.rm_startblock + ltrec.rm_blockcount)) {
543 			error = -EFSCORRUPTED;
544 			goto out_error;
545 		}
546 		goto out_done;
547 	}
548 
549 	/*
550 	 * If we're doing an unknown-owner removal for EFI recovery, we expect
551 	 * to find the full range in the rmapbt or nothing at all.  If we
552 	 * don't find any rmaps overlapping either end of the range, we're
553 	 * done.  Hopefully this means that the EFI creator already queued
554 	 * (and finished) a RUI to remove the rmap.
555 	 */
556 	if (owner == XFS_RMAP_OWN_UNKNOWN &&
557 	    ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
558 		struct xfs_rmap_irec    rtrec;
559 
560 		error = xfs_btree_increment(cur, 0, &i);
561 		if (error)
562 			goto out_error;
563 		if (i == 0)
564 			goto out_done;
565 		error = xfs_rmap_get_rec(cur, &rtrec, &i);
566 		if (error)
567 			goto out_error;
568 		if (XFS_IS_CORRUPT(mp, i != 1)) {
569 			error = -EFSCORRUPTED;
570 			goto out_error;
571 		}
572 		if (rtrec.rm_startblock >= bno + len)
573 			goto out_done;
574 	}
575 
576 	/* Make sure the extent we found covers the entire freeing range. */
577 	if (XFS_IS_CORRUPT(mp,
578 			   ltrec.rm_startblock > bno ||
579 			   ltrec.rm_startblock + ltrec.rm_blockcount <
580 			   bno + len)) {
581 		error = -EFSCORRUPTED;
582 		goto out_error;
583 	}
584 
585 	/* Check owner information. */
586 	error = xfs_rmap_free_check_owner(mp, ltoff, &ltrec, len, owner,
587 			offset, flags);
588 	if (error)
589 		goto out_error;
590 
591 	if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
592 		/* exact match, simply remove the record from rmap tree */
593 		trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
594 				ltrec.rm_startblock, ltrec.rm_blockcount,
595 				ltrec.rm_owner, ltrec.rm_offset,
596 				ltrec.rm_flags);
597 		error = xfs_btree_delete(cur, &i);
598 		if (error)
599 			goto out_error;
600 		if (XFS_IS_CORRUPT(mp, i != 1)) {
601 			error = -EFSCORRUPTED;
602 			goto out_error;
603 		}
604 	} else if (ltrec.rm_startblock == bno) {
605 		/*
606 		 * overlap left hand side of extent: move the start, trim the
607 		 * length and update the current record.
608 		 *
609 		 *       ltbno                ltlen
610 		 * Orig:    |oooooooooooooooooooo|
611 		 * Freeing: |fffffffff|
612 		 * Result:            |rrrrrrrrrr|
613 		 *         bno       len
614 		 */
615 		ltrec.rm_startblock += len;
616 		ltrec.rm_blockcount -= len;
617 		if (!ignore_off)
618 			ltrec.rm_offset += len;
619 		error = xfs_rmap_update(cur, &ltrec);
620 		if (error)
621 			goto out_error;
622 	} else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
623 		/*
624 		 * overlap right hand side of extent: trim the length and update
625 		 * the current record.
626 		 *
627 		 *       ltbno                ltlen
628 		 * Orig:    |oooooooooooooooooooo|
629 		 * Freeing:            |fffffffff|
630 		 * Result:  |rrrrrrrrrr|
631 		 *                    bno       len
632 		 */
633 		ltrec.rm_blockcount -= len;
634 		error = xfs_rmap_update(cur, &ltrec);
635 		if (error)
636 			goto out_error;
637 	} else {
638 
639 		/*
640 		 * overlap middle of extent: trim the length of the existing
641 		 * record to the length of the new left-extent size, increment
642 		 * the insertion position so we can insert a new record
643 		 * containing the remaining right-extent space.
644 		 *
645 		 *       ltbno                ltlen
646 		 * Orig:    |oooooooooooooooooooo|
647 		 * Freeing:       |fffffffff|
648 		 * Result:  |rrrrr|         |rrrr|
649 		 *               bno       len
650 		 */
651 		xfs_extlen_t	orig_len = ltrec.rm_blockcount;
652 
653 		ltrec.rm_blockcount = bno - ltrec.rm_startblock;
654 		error = xfs_rmap_update(cur, &ltrec);
655 		if (error)
656 			goto out_error;
657 
658 		error = xfs_btree_increment(cur, 0, &i);
659 		if (error)
660 			goto out_error;
661 
662 		cur->bc_rec.r.rm_startblock = bno + len;
663 		cur->bc_rec.r.rm_blockcount = orig_len - len -
664 						     ltrec.rm_blockcount;
665 		cur->bc_rec.r.rm_owner = ltrec.rm_owner;
666 		if (ignore_off)
667 			cur->bc_rec.r.rm_offset = 0;
668 		else
669 			cur->bc_rec.r.rm_offset = offset + len;
670 		cur->bc_rec.r.rm_flags = flags;
671 		trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
672 				cur->bc_rec.r.rm_startblock,
673 				cur->bc_rec.r.rm_blockcount,
674 				cur->bc_rec.r.rm_owner,
675 				cur->bc_rec.r.rm_offset,
676 				cur->bc_rec.r.rm_flags);
677 		error = xfs_btree_insert(cur, &i);
678 		if (error)
679 			goto out_error;
680 	}
681 
682 out_done:
683 	trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
684 			unwritten, oinfo);
685 out_error:
686 	if (error)
687 		trace_xfs_rmap_unmap_error(mp, cur->bc_ag.pag->pag_agno,
688 				error, _RET_IP_);
689 	return error;
690 }
691 
692 /*
693  * Remove a reference to an extent in the rmap btree.
694  */
695 int
xfs_rmap_free(struct xfs_trans * tp,struct xfs_buf * agbp,struct xfs_perag * pag,xfs_agblock_t bno,xfs_extlen_t len,const struct xfs_owner_info * oinfo)696 xfs_rmap_free(
697 	struct xfs_trans		*tp,
698 	struct xfs_buf			*agbp,
699 	struct xfs_perag		*pag,
700 	xfs_agblock_t			bno,
701 	xfs_extlen_t			len,
702 	const struct xfs_owner_info	*oinfo)
703 {
704 	struct xfs_mount		*mp = tp->t_mountp;
705 	struct xfs_btree_cur		*cur;
706 	int				error;
707 
708 	if (!xfs_has_rmapbt(mp))
709 		return 0;
710 
711 	cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
712 
713 	error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
714 
715 	xfs_btree_del_cursor(cur, error);
716 	return error;
717 }
718 
719 /*
720  * A mergeable rmap must have the same owner and the same values for
721  * the unwritten, attr_fork, and bmbt flags.  The startblock and
722  * offset are checked separately.
723  */
724 static bool
xfs_rmap_is_mergeable(struct xfs_rmap_irec * irec,uint64_t owner,unsigned int flags)725 xfs_rmap_is_mergeable(
726 	struct xfs_rmap_irec	*irec,
727 	uint64_t		owner,
728 	unsigned int		flags)
729 {
730 	if (irec->rm_owner == XFS_RMAP_OWN_NULL)
731 		return false;
732 	if (irec->rm_owner != owner)
733 		return false;
734 	if ((flags & XFS_RMAP_UNWRITTEN) ^
735 	    (irec->rm_flags & XFS_RMAP_UNWRITTEN))
736 		return false;
737 	if ((flags & XFS_RMAP_ATTR_FORK) ^
738 	    (irec->rm_flags & XFS_RMAP_ATTR_FORK))
739 		return false;
740 	if ((flags & XFS_RMAP_BMBT_BLOCK) ^
741 	    (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
742 		return false;
743 	return true;
744 }
745 
746 /*
747  * When we allocate a new block, the first thing we do is add a reference to
748  * the extent in the rmap btree. This takes the form of a [agbno, length,
749  * owner, offset] record.  Flags are encoded in the high bits of the offset
750  * field.
751  */
752 STATIC int
xfs_rmap_map(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,bool unwritten,const struct xfs_owner_info * oinfo)753 xfs_rmap_map(
754 	struct xfs_btree_cur		*cur,
755 	xfs_agblock_t			bno,
756 	xfs_extlen_t			len,
757 	bool				unwritten,
758 	const struct xfs_owner_info	*oinfo)
759 {
760 	struct xfs_mount		*mp = cur->bc_mp;
761 	struct xfs_rmap_irec		ltrec;
762 	struct xfs_rmap_irec		gtrec;
763 	int				have_gt;
764 	int				have_lt;
765 	int				error = 0;
766 	int				i;
767 	uint64_t			owner;
768 	uint64_t			offset;
769 	unsigned int			flags = 0;
770 	bool				ignore_off;
771 
772 	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
773 	ASSERT(owner != 0);
774 	ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
775 			(flags & XFS_RMAP_BMBT_BLOCK);
776 	if (unwritten)
777 		flags |= XFS_RMAP_UNWRITTEN;
778 	trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
779 			unwritten, oinfo);
780 	ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
781 
782 	/*
783 	 * For the initial lookup, look for an exact match or the left-adjacent
784 	 * record for our insertion point. This will also give us the record for
785 	 * start block contiguity tests.
786 	 */
787 	error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
788 			&have_lt);
789 	if (error)
790 		goto out_error;
791 	if (have_lt) {
792 		error = xfs_rmap_get_rec(cur, &ltrec, &have_lt);
793 		if (error)
794 			goto out_error;
795 		if (XFS_IS_CORRUPT(mp, have_lt != 1)) {
796 			error = -EFSCORRUPTED;
797 			goto out_error;
798 		}
799 		trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
800 				cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
801 				ltrec.rm_blockcount, ltrec.rm_owner,
802 				ltrec.rm_offset, ltrec.rm_flags);
803 
804 		if (!xfs_rmap_is_mergeable(&ltrec, owner, flags))
805 			have_lt = 0;
806 	}
807 
808 	if (XFS_IS_CORRUPT(mp,
809 			   have_lt != 0 &&
810 			   ltrec.rm_startblock + ltrec.rm_blockcount > bno)) {
811 		error = -EFSCORRUPTED;
812 		goto out_error;
813 	}
814 
815 	/*
816 	 * Increment the cursor to see if we have a right-adjacent record to our
817 	 * insertion point. This will give us the record for end block
818 	 * contiguity tests.
819 	 */
820 	error = xfs_btree_increment(cur, 0, &have_gt);
821 	if (error)
822 		goto out_error;
823 	if (have_gt) {
824 		error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
825 		if (error)
826 			goto out_error;
827 		if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
828 			error = -EFSCORRUPTED;
829 			goto out_error;
830 		}
831 		if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) {
832 			error = -EFSCORRUPTED;
833 			goto out_error;
834 		}
835 		trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
836 			cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
837 			gtrec.rm_blockcount, gtrec.rm_owner,
838 			gtrec.rm_offset, gtrec.rm_flags);
839 		if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
840 			have_gt = 0;
841 	}
842 
843 	/*
844 	 * Note: cursor currently points one record to the right of ltrec, even
845 	 * if there is no record in the tree to the right.
846 	 */
847 	if (have_lt &&
848 	    ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
849 	    (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
850 		/*
851 		 * left edge contiguous, merge into left record.
852 		 *
853 		 *       ltbno     ltlen
854 		 * orig:   |ooooooooo|
855 		 * adding:           |aaaaaaaaa|
856 		 * result: |rrrrrrrrrrrrrrrrrrr|
857 		 *                  bno       len
858 		 */
859 		ltrec.rm_blockcount += len;
860 		if (have_gt &&
861 		    bno + len == gtrec.rm_startblock &&
862 		    (ignore_off || offset + len == gtrec.rm_offset) &&
863 		    (unsigned long)ltrec.rm_blockcount + len +
864 				gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
865 			/*
866 			 * right edge also contiguous, delete right record
867 			 * and merge into left record.
868 			 *
869 			 *       ltbno     ltlen    gtbno     gtlen
870 			 * orig:   |ooooooooo|         |ooooooooo|
871 			 * adding:           |aaaaaaaaa|
872 			 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
873 			 */
874 			ltrec.rm_blockcount += gtrec.rm_blockcount;
875 			trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
876 					gtrec.rm_startblock,
877 					gtrec.rm_blockcount,
878 					gtrec.rm_owner,
879 					gtrec.rm_offset,
880 					gtrec.rm_flags);
881 			error = xfs_btree_delete(cur, &i);
882 			if (error)
883 				goto out_error;
884 			if (XFS_IS_CORRUPT(mp, i != 1)) {
885 				error = -EFSCORRUPTED;
886 				goto out_error;
887 			}
888 		}
889 
890 		/* point the cursor back to the left record and update */
891 		error = xfs_btree_decrement(cur, 0, &have_gt);
892 		if (error)
893 			goto out_error;
894 		error = xfs_rmap_update(cur, &ltrec);
895 		if (error)
896 			goto out_error;
897 	} else if (have_gt &&
898 		   bno + len == gtrec.rm_startblock &&
899 		   (ignore_off || offset + len == gtrec.rm_offset)) {
900 		/*
901 		 * right edge contiguous, merge into right record.
902 		 *
903 		 *                 gtbno     gtlen
904 		 * Orig:             |ooooooooo|
905 		 * adding: |aaaaaaaaa|
906 		 * Result: |rrrrrrrrrrrrrrrrrrr|
907 		 *        bno       len
908 		 */
909 		gtrec.rm_startblock = bno;
910 		gtrec.rm_blockcount += len;
911 		if (!ignore_off)
912 			gtrec.rm_offset = offset;
913 		error = xfs_rmap_update(cur, &gtrec);
914 		if (error)
915 			goto out_error;
916 	} else {
917 		/*
918 		 * no contiguous edge with identical owner, insert
919 		 * new record at current cursor position.
920 		 */
921 		cur->bc_rec.r.rm_startblock = bno;
922 		cur->bc_rec.r.rm_blockcount = len;
923 		cur->bc_rec.r.rm_owner = owner;
924 		cur->bc_rec.r.rm_offset = offset;
925 		cur->bc_rec.r.rm_flags = flags;
926 		trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
927 			owner, offset, flags);
928 		error = xfs_btree_insert(cur, &i);
929 		if (error)
930 			goto out_error;
931 		if (XFS_IS_CORRUPT(mp, i != 1)) {
932 			error = -EFSCORRUPTED;
933 			goto out_error;
934 		}
935 	}
936 
937 	trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
938 			unwritten, oinfo);
939 out_error:
940 	if (error)
941 		trace_xfs_rmap_map_error(mp, cur->bc_ag.pag->pag_agno,
942 				error, _RET_IP_);
943 	return error;
944 }
945 
946 /*
947  * Add a reference to an extent in the rmap btree.
948  */
949 int
xfs_rmap_alloc(struct xfs_trans * tp,struct xfs_buf * agbp,struct xfs_perag * pag,xfs_agblock_t bno,xfs_extlen_t len,const struct xfs_owner_info * oinfo)950 xfs_rmap_alloc(
951 	struct xfs_trans		*tp,
952 	struct xfs_buf			*agbp,
953 	struct xfs_perag		*pag,
954 	xfs_agblock_t			bno,
955 	xfs_extlen_t			len,
956 	const struct xfs_owner_info	*oinfo)
957 {
958 	struct xfs_mount		*mp = tp->t_mountp;
959 	struct xfs_btree_cur		*cur;
960 	int				error;
961 
962 	if (!xfs_has_rmapbt(mp))
963 		return 0;
964 
965 	cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
966 	error = xfs_rmap_map(cur, bno, len, false, oinfo);
967 
968 	xfs_btree_del_cursor(cur, error);
969 	return error;
970 }
971 
972 #define RMAP_LEFT_CONTIG	(1 << 0)
973 #define RMAP_RIGHT_CONTIG	(1 << 1)
974 #define RMAP_LEFT_FILLING	(1 << 2)
975 #define RMAP_RIGHT_FILLING	(1 << 3)
976 #define RMAP_LEFT_VALID		(1 << 6)
977 #define RMAP_RIGHT_VALID	(1 << 7)
978 
979 #define LEFT		r[0]
980 #define RIGHT		r[1]
981 #define PREV		r[2]
982 #define NEW		r[3]
983 
984 /*
985  * Convert an unwritten extent to a real extent or vice versa.
986  * Does not handle overlapping extents.
987  */
988 STATIC int
xfs_rmap_convert(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,bool unwritten,const struct xfs_owner_info * oinfo)989 xfs_rmap_convert(
990 	struct xfs_btree_cur		*cur,
991 	xfs_agblock_t			bno,
992 	xfs_extlen_t			len,
993 	bool				unwritten,
994 	const struct xfs_owner_info	*oinfo)
995 {
996 	struct xfs_mount		*mp = cur->bc_mp;
997 	struct xfs_rmap_irec		r[4];	/* neighbor extent entries */
998 						/* left is 0, right is 1, */
999 						/* prev is 2, new is 3 */
1000 	uint64_t		owner;
1001 	uint64_t		offset;
1002 	uint64_t		new_endoff;
1003 	unsigned int		oldext;
1004 	unsigned int		newext;
1005 	unsigned int		flags = 0;
1006 	int			i;
1007 	int			state = 0;
1008 	int			error;
1009 
1010 	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1011 	ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1012 			(flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1013 	oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1014 	new_endoff = offset + len;
1015 	trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1016 			unwritten, oinfo);
1017 
1018 	/*
1019 	 * For the initial lookup, look for an exact match or the left-adjacent
1020 	 * record for our insertion point. This will also give us the record for
1021 	 * start block contiguity tests.
1022 	 */
1023 	error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1024 	if (error)
1025 		goto done;
1026 	if (XFS_IS_CORRUPT(mp, i != 1)) {
1027 		error = -EFSCORRUPTED;
1028 		goto done;
1029 	}
1030 
1031 	error = xfs_rmap_get_rec(cur, &PREV, &i);
1032 	if (error)
1033 		goto done;
1034 	if (XFS_IS_CORRUPT(mp, i != 1)) {
1035 		error = -EFSCORRUPTED;
1036 		goto done;
1037 	}
1038 	trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
1039 			cur->bc_ag.pag->pag_agno, PREV.rm_startblock,
1040 			PREV.rm_blockcount, PREV.rm_owner,
1041 			PREV.rm_offset, PREV.rm_flags);
1042 
1043 	ASSERT(PREV.rm_offset <= offset);
1044 	ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1045 	ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1046 	newext = ~oldext & XFS_RMAP_UNWRITTEN;
1047 
1048 	/*
1049 	 * Set flags determining what part of the previous oldext allocation
1050 	 * extent is being replaced by a newext allocation.
1051 	 */
1052 	if (PREV.rm_offset == offset)
1053 		state |= RMAP_LEFT_FILLING;
1054 	if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1055 		state |= RMAP_RIGHT_FILLING;
1056 
1057 	/*
1058 	 * Decrement the cursor to see if we have a left-adjacent record to our
1059 	 * insertion point. This will give us the record for end block
1060 	 * contiguity tests.
1061 	 */
1062 	error = xfs_btree_decrement(cur, 0, &i);
1063 	if (error)
1064 		goto done;
1065 	if (i) {
1066 		state |= RMAP_LEFT_VALID;
1067 		error = xfs_rmap_get_rec(cur, &LEFT, &i);
1068 		if (error)
1069 			goto done;
1070 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1071 			error = -EFSCORRUPTED;
1072 			goto done;
1073 		}
1074 		if (XFS_IS_CORRUPT(mp,
1075 				   LEFT.rm_startblock + LEFT.rm_blockcount >
1076 				   bno)) {
1077 			error = -EFSCORRUPTED;
1078 			goto done;
1079 		}
1080 		trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
1081 				cur->bc_ag.pag->pag_agno, LEFT.rm_startblock,
1082 				LEFT.rm_blockcount, LEFT.rm_owner,
1083 				LEFT.rm_offset, LEFT.rm_flags);
1084 		if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1085 		    LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1086 		    xfs_rmap_is_mergeable(&LEFT, owner, newext))
1087 			state |= RMAP_LEFT_CONTIG;
1088 	}
1089 
1090 	/*
1091 	 * Increment the cursor to see if we have a right-adjacent record to our
1092 	 * insertion point. This will give us the record for end block
1093 	 * contiguity tests.
1094 	 */
1095 	error = xfs_btree_increment(cur, 0, &i);
1096 	if (error)
1097 		goto done;
1098 	if (XFS_IS_CORRUPT(mp, i != 1)) {
1099 		error = -EFSCORRUPTED;
1100 		goto done;
1101 	}
1102 	error = xfs_btree_increment(cur, 0, &i);
1103 	if (error)
1104 		goto done;
1105 	if (i) {
1106 		state |= RMAP_RIGHT_VALID;
1107 		error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1108 		if (error)
1109 			goto done;
1110 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1111 			error = -EFSCORRUPTED;
1112 			goto done;
1113 		}
1114 		if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1115 			error = -EFSCORRUPTED;
1116 			goto done;
1117 		}
1118 		trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1119 				cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
1120 				RIGHT.rm_blockcount, RIGHT.rm_owner,
1121 				RIGHT.rm_offset, RIGHT.rm_flags);
1122 		if (bno + len == RIGHT.rm_startblock &&
1123 		    offset + len == RIGHT.rm_offset &&
1124 		    xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1125 			state |= RMAP_RIGHT_CONTIG;
1126 	}
1127 
1128 	/* check that left + prev + right is not too long */
1129 	if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1130 			 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1131 	    (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1132 	     RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1133 	    (unsigned long)LEFT.rm_blockcount + len +
1134 	     RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1135 		state &= ~RMAP_RIGHT_CONTIG;
1136 
1137 	trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
1138 			_RET_IP_);
1139 
1140 	/* reset the cursor back to PREV */
1141 	error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1142 	if (error)
1143 		goto done;
1144 	if (XFS_IS_CORRUPT(mp, i != 1)) {
1145 		error = -EFSCORRUPTED;
1146 		goto done;
1147 	}
1148 
1149 	/*
1150 	 * Switch out based on the FILLING and CONTIG state bits.
1151 	 */
1152 	switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1153 			 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1154 	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1155 	     RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1156 		/*
1157 		 * Setting all of a previous oldext extent to newext.
1158 		 * The left and right neighbors are both contiguous with new.
1159 		 */
1160 		error = xfs_btree_increment(cur, 0, &i);
1161 		if (error)
1162 			goto done;
1163 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1164 			error = -EFSCORRUPTED;
1165 			goto done;
1166 		}
1167 		trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1168 				RIGHT.rm_startblock, RIGHT.rm_blockcount,
1169 				RIGHT.rm_owner, RIGHT.rm_offset,
1170 				RIGHT.rm_flags);
1171 		error = xfs_btree_delete(cur, &i);
1172 		if (error)
1173 			goto done;
1174 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1175 			error = -EFSCORRUPTED;
1176 			goto done;
1177 		}
1178 		error = xfs_btree_decrement(cur, 0, &i);
1179 		if (error)
1180 			goto done;
1181 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1182 			error = -EFSCORRUPTED;
1183 			goto done;
1184 		}
1185 		trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1186 				PREV.rm_startblock, PREV.rm_blockcount,
1187 				PREV.rm_owner, PREV.rm_offset,
1188 				PREV.rm_flags);
1189 		error = xfs_btree_delete(cur, &i);
1190 		if (error)
1191 			goto done;
1192 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1193 			error = -EFSCORRUPTED;
1194 			goto done;
1195 		}
1196 		error = xfs_btree_decrement(cur, 0, &i);
1197 		if (error)
1198 			goto done;
1199 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1200 			error = -EFSCORRUPTED;
1201 			goto done;
1202 		}
1203 		NEW = LEFT;
1204 		NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1205 		error = xfs_rmap_update(cur, &NEW);
1206 		if (error)
1207 			goto done;
1208 		break;
1209 
1210 	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1211 		/*
1212 		 * Setting all of a previous oldext extent to newext.
1213 		 * The left neighbor is contiguous, the right is not.
1214 		 */
1215 		trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1216 				PREV.rm_startblock, PREV.rm_blockcount,
1217 				PREV.rm_owner, PREV.rm_offset,
1218 				PREV.rm_flags);
1219 		error = xfs_btree_delete(cur, &i);
1220 		if (error)
1221 			goto done;
1222 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1223 			error = -EFSCORRUPTED;
1224 			goto done;
1225 		}
1226 		error = xfs_btree_decrement(cur, 0, &i);
1227 		if (error)
1228 			goto done;
1229 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1230 			error = -EFSCORRUPTED;
1231 			goto done;
1232 		}
1233 		NEW = LEFT;
1234 		NEW.rm_blockcount += PREV.rm_blockcount;
1235 		error = xfs_rmap_update(cur, &NEW);
1236 		if (error)
1237 			goto done;
1238 		break;
1239 
1240 	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1241 		/*
1242 		 * Setting all of a previous oldext extent to newext.
1243 		 * The right neighbor is contiguous, the left is not.
1244 		 */
1245 		error = xfs_btree_increment(cur, 0, &i);
1246 		if (error)
1247 			goto done;
1248 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1249 			error = -EFSCORRUPTED;
1250 			goto done;
1251 		}
1252 		trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1253 				RIGHT.rm_startblock, RIGHT.rm_blockcount,
1254 				RIGHT.rm_owner, RIGHT.rm_offset,
1255 				RIGHT.rm_flags);
1256 		error = xfs_btree_delete(cur, &i);
1257 		if (error)
1258 			goto done;
1259 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1260 			error = -EFSCORRUPTED;
1261 			goto done;
1262 		}
1263 		error = xfs_btree_decrement(cur, 0, &i);
1264 		if (error)
1265 			goto done;
1266 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1267 			error = -EFSCORRUPTED;
1268 			goto done;
1269 		}
1270 		NEW = PREV;
1271 		NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1272 		NEW.rm_flags = newext;
1273 		error = xfs_rmap_update(cur, &NEW);
1274 		if (error)
1275 			goto done;
1276 		break;
1277 
1278 	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1279 		/*
1280 		 * Setting all of a previous oldext extent to newext.
1281 		 * Neither the left nor right neighbors are contiguous with
1282 		 * the new one.
1283 		 */
1284 		NEW = PREV;
1285 		NEW.rm_flags = newext;
1286 		error = xfs_rmap_update(cur, &NEW);
1287 		if (error)
1288 			goto done;
1289 		break;
1290 
1291 	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1292 		/*
1293 		 * Setting the first part of a previous oldext extent to newext.
1294 		 * The left neighbor is contiguous.
1295 		 */
1296 		NEW = PREV;
1297 		NEW.rm_offset += len;
1298 		NEW.rm_startblock += len;
1299 		NEW.rm_blockcount -= len;
1300 		error = xfs_rmap_update(cur, &NEW);
1301 		if (error)
1302 			goto done;
1303 		error = xfs_btree_decrement(cur, 0, &i);
1304 		if (error)
1305 			goto done;
1306 		NEW = LEFT;
1307 		NEW.rm_blockcount += len;
1308 		error = xfs_rmap_update(cur, &NEW);
1309 		if (error)
1310 			goto done;
1311 		break;
1312 
1313 	case RMAP_LEFT_FILLING:
1314 		/*
1315 		 * Setting the first part of a previous oldext extent to newext.
1316 		 * The left neighbor is not contiguous.
1317 		 */
1318 		NEW = PREV;
1319 		NEW.rm_startblock += len;
1320 		NEW.rm_offset += len;
1321 		NEW.rm_blockcount -= len;
1322 		error = xfs_rmap_update(cur, &NEW);
1323 		if (error)
1324 			goto done;
1325 		NEW.rm_startblock = bno;
1326 		NEW.rm_owner = owner;
1327 		NEW.rm_offset = offset;
1328 		NEW.rm_blockcount = len;
1329 		NEW.rm_flags = newext;
1330 		cur->bc_rec.r = NEW;
1331 		trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
1332 				len, owner, offset, newext);
1333 		error = xfs_btree_insert(cur, &i);
1334 		if (error)
1335 			goto done;
1336 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1337 			error = -EFSCORRUPTED;
1338 			goto done;
1339 		}
1340 		break;
1341 
1342 	case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1343 		/*
1344 		 * Setting the last part of a previous oldext extent to newext.
1345 		 * The right neighbor is contiguous with the new allocation.
1346 		 */
1347 		NEW = PREV;
1348 		NEW.rm_blockcount -= len;
1349 		error = xfs_rmap_update(cur, &NEW);
1350 		if (error)
1351 			goto done;
1352 		error = xfs_btree_increment(cur, 0, &i);
1353 		if (error)
1354 			goto done;
1355 		NEW = RIGHT;
1356 		NEW.rm_offset = offset;
1357 		NEW.rm_startblock = bno;
1358 		NEW.rm_blockcount += len;
1359 		error = xfs_rmap_update(cur, &NEW);
1360 		if (error)
1361 			goto done;
1362 		break;
1363 
1364 	case RMAP_RIGHT_FILLING:
1365 		/*
1366 		 * Setting the last part of a previous oldext extent to newext.
1367 		 * The right neighbor is not contiguous.
1368 		 */
1369 		NEW = PREV;
1370 		NEW.rm_blockcount -= len;
1371 		error = xfs_rmap_update(cur, &NEW);
1372 		if (error)
1373 			goto done;
1374 		error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1375 				oldext, &i);
1376 		if (error)
1377 			goto done;
1378 		if (XFS_IS_CORRUPT(mp, i != 0)) {
1379 			error = -EFSCORRUPTED;
1380 			goto done;
1381 		}
1382 		NEW.rm_startblock = bno;
1383 		NEW.rm_owner = owner;
1384 		NEW.rm_offset = offset;
1385 		NEW.rm_blockcount = len;
1386 		NEW.rm_flags = newext;
1387 		cur->bc_rec.r = NEW;
1388 		trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
1389 				len, owner, offset, newext);
1390 		error = xfs_btree_insert(cur, &i);
1391 		if (error)
1392 			goto done;
1393 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1394 			error = -EFSCORRUPTED;
1395 			goto done;
1396 		}
1397 		break;
1398 
1399 	case 0:
1400 		/*
1401 		 * Setting the middle part of a previous oldext extent to
1402 		 * newext.  Contiguity is impossible here.
1403 		 * One extent becomes three extents.
1404 		 */
1405 		/* new right extent - oldext */
1406 		NEW.rm_startblock = bno + len;
1407 		NEW.rm_owner = owner;
1408 		NEW.rm_offset = new_endoff;
1409 		NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1410 				new_endoff;
1411 		NEW.rm_flags = PREV.rm_flags;
1412 		error = xfs_rmap_update(cur, &NEW);
1413 		if (error)
1414 			goto done;
1415 		/* new left extent - oldext */
1416 		NEW = PREV;
1417 		NEW.rm_blockcount = offset - PREV.rm_offset;
1418 		cur->bc_rec.r = NEW;
1419 		trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
1420 				NEW.rm_startblock, NEW.rm_blockcount,
1421 				NEW.rm_owner, NEW.rm_offset,
1422 				NEW.rm_flags);
1423 		error = xfs_btree_insert(cur, &i);
1424 		if (error)
1425 			goto done;
1426 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1427 			error = -EFSCORRUPTED;
1428 			goto done;
1429 		}
1430 		/*
1431 		 * Reset the cursor to the position of the new extent
1432 		 * we are about to insert as we can't trust it after
1433 		 * the previous insert.
1434 		 */
1435 		error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1436 				oldext, &i);
1437 		if (error)
1438 			goto done;
1439 		if (XFS_IS_CORRUPT(mp, i != 0)) {
1440 			error = -EFSCORRUPTED;
1441 			goto done;
1442 		}
1443 		/* new middle extent - newext */
1444 		cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1445 		cur->bc_rec.r.rm_flags |= newext;
1446 		trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1447 				owner, offset, newext);
1448 		error = xfs_btree_insert(cur, &i);
1449 		if (error)
1450 			goto done;
1451 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1452 			error = -EFSCORRUPTED;
1453 			goto done;
1454 		}
1455 		break;
1456 
1457 	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1458 	case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1459 	case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1460 	case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1461 	case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1462 	case RMAP_LEFT_CONTIG:
1463 	case RMAP_RIGHT_CONTIG:
1464 		/*
1465 		 * These cases are all impossible.
1466 		 */
1467 		ASSERT(0);
1468 	}
1469 
1470 	trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1471 			unwritten, oinfo);
1472 done:
1473 	if (error)
1474 		trace_xfs_rmap_convert_error(cur->bc_mp,
1475 				cur->bc_ag.pag->pag_agno, error, _RET_IP_);
1476 	return error;
1477 }
1478 
1479 /*
1480  * Convert an unwritten extent to a real extent or vice versa.  If there is no
1481  * possibility of overlapping extents, delegate to the simpler convert
1482  * function.
1483  */
1484 STATIC int
xfs_rmap_convert_shared(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,bool unwritten,const struct xfs_owner_info * oinfo)1485 xfs_rmap_convert_shared(
1486 	struct xfs_btree_cur		*cur,
1487 	xfs_agblock_t			bno,
1488 	xfs_extlen_t			len,
1489 	bool				unwritten,
1490 	const struct xfs_owner_info	*oinfo)
1491 {
1492 	struct xfs_mount		*mp = cur->bc_mp;
1493 	struct xfs_rmap_irec		r[4];	/* neighbor extent entries */
1494 						/* left is 0, right is 1, */
1495 						/* prev is 2, new is 3 */
1496 	uint64_t		owner;
1497 	uint64_t		offset;
1498 	uint64_t		new_endoff;
1499 	unsigned int		oldext;
1500 	unsigned int		newext;
1501 	unsigned int		flags = 0;
1502 	int			i;
1503 	int			state = 0;
1504 	int			error;
1505 
1506 	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1507 	ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1508 			(flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1509 	oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1510 	new_endoff = offset + len;
1511 	trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1512 			unwritten, oinfo);
1513 
1514 	/*
1515 	 * For the initial lookup, look for and exact match or the left-adjacent
1516 	 * record for our insertion point. This will also give us the record for
1517 	 * start block contiguity tests.
1518 	 */
1519 	error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, oldext,
1520 			&PREV, &i);
1521 	if (error)
1522 		goto done;
1523 	if (XFS_IS_CORRUPT(mp, i != 1)) {
1524 		error = -EFSCORRUPTED;
1525 		goto done;
1526 	}
1527 
1528 	ASSERT(PREV.rm_offset <= offset);
1529 	ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1530 	ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1531 	newext = ~oldext & XFS_RMAP_UNWRITTEN;
1532 
1533 	/*
1534 	 * Set flags determining what part of the previous oldext allocation
1535 	 * extent is being replaced by a newext allocation.
1536 	 */
1537 	if (PREV.rm_offset == offset)
1538 		state |= RMAP_LEFT_FILLING;
1539 	if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1540 		state |= RMAP_RIGHT_FILLING;
1541 
1542 	/* Is there a left record that abuts our range? */
1543 	error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1544 			&LEFT, &i);
1545 	if (error)
1546 		goto done;
1547 	if (i) {
1548 		state |= RMAP_LEFT_VALID;
1549 		if (XFS_IS_CORRUPT(mp,
1550 				   LEFT.rm_startblock + LEFT.rm_blockcount >
1551 				   bno)) {
1552 			error = -EFSCORRUPTED;
1553 			goto done;
1554 		}
1555 		if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1556 			state |= RMAP_LEFT_CONTIG;
1557 	}
1558 
1559 	/* Is there a right record that abuts our range? */
1560 	error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1561 			newext, &i);
1562 	if (error)
1563 		goto done;
1564 	if (i) {
1565 		state |= RMAP_RIGHT_VALID;
1566 		error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1567 		if (error)
1568 			goto done;
1569 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1570 			error = -EFSCORRUPTED;
1571 			goto done;
1572 		}
1573 		if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1574 			error = -EFSCORRUPTED;
1575 			goto done;
1576 		}
1577 		trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1578 				cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
1579 				RIGHT.rm_blockcount, RIGHT.rm_owner,
1580 				RIGHT.rm_offset, RIGHT.rm_flags);
1581 		if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1582 			state |= RMAP_RIGHT_CONTIG;
1583 	}
1584 
1585 	/* check that left + prev + right is not too long */
1586 	if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1587 			 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1588 	    (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1589 	     RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1590 	    (unsigned long)LEFT.rm_blockcount + len +
1591 	     RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1592 		state &= ~RMAP_RIGHT_CONTIG;
1593 
1594 	trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
1595 			_RET_IP_);
1596 	/*
1597 	 * Switch out based on the FILLING and CONTIG state bits.
1598 	 */
1599 	switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1600 			 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1601 	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1602 	     RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1603 		/*
1604 		 * Setting all of a previous oldext extent to newext.
1605 		 * The left and right neighbors are both contiguous with new.
1606 		 */
1607 		error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1608 				RIGHT.rm_blockcount, RIGHT.rm_owner,
1609 				RIGHT.rm_offset, RIGHT.rm_flags);
1610 		if (error)
1611 			goto done;
1612 		error = xfs_rmap_delete(cur, PREV.rm_startblock,
1613 				PREV.rm_blockcount, PREV.rm_owner,
1614 				PREV.rm_offset, PREV.rm_flags);
1615 		if (error)
1616 			goto done;
1617 		NEW = LEFT;
1618 		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1619 				NEW.rm_blockcount, NEW.rm_owner,
1620 				NEW.rm_offset, NEW.rm_flags, &i);
1621 		if (error)
1622 			goto done;
1623 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1624 			error = -EFSCORRUPTED;
1625 			goto done;
1626 		}
1627 		NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1628 		error = xfs_rmap_update(cur, &NEW);
1629 		if (error)
1630 			goto done;
1631 		break;
1632 
1633 	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1634 		/*
1635 		 * Setting all of a previous oldext extent to newext.
1636 		 * The left neighbor is contiguous, the right is not.
1637 		 */
1638 		error = xfs_rmap_delete(cur, PREV.rm_startblock,
1639 				PREV.rm_blockcount, PREV.rm_owner,
1640 				PREV.rm_offset, PREV.rm_flags);
1641 		if (error)
1642 			goto done;
1643 		NEW = LEFT;
1644 		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1645 				NEW.rm_blockcount, NEW.rm_owner,
1646 				NEW.rm_offset, NEW.rm_flags, &i);
1647 		if (error)
1648 			goto done;
1649 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1650 			error = -EFSCORRUPTED;
1651 			goto done;
1652 		}
1653 		NEW.rm_blockcount += PREV.rm_blockcount;
1654 		error = xfs_rmap_update(cur, &NEW);
1655 		if (error)
1656 			goto done;
1657 		break;
1658 
1659 	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1660 		/*
1661 		 * Setting all of a previous oldext extent to newext.
1662 		 * The right neighbor is contiguous, the left is not.
1663 		 */
1664 		error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1665 				RIGHT.rm_blockcount, RIGHT.rm_owner,
1666 				RIGHT.rm_offset, RIGHT.rm_flags);
1667 		if (error)
1668 			goto done;
1669 		NEW = PREV;
1670 		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1671 				NEW.rm_blockcount, NEW.rm_owner,
1672 				NEW.rm_offset, NEW.rm_flags, &i);
1673 		if (error)
1674 			goto done;
1675 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1676 			error = -EFSCORRUPTED;
1677 			goto done;
1678 		}
1679 		NEW.rm_blockcount += RIGHT.rm_blockcount;
1680 		NEW.rm_flags = RIGHT.rm_flags;
1681 		error = xfs_rmap_update(cur, &NEW);
1682 		if (error)
1683 			goto done;
1684 		break;
1685 
1686 	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1687 		/*
1688 		 * Setting all of a previous oldext extent to newext.
1689 		 * Neither the left nor right neighbors are contiguous with
1690 		 * the new one.
1691 		 */
1692 		NEW = PREV;
1693 		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1694 				NEW.rm_blockcount, NEW.rm_owner,
1695 				NEW.rm_offset, NEW.rm_flags, &i);
1696 		if (error)
1697 			goto done;
1698 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1699 			error = -EFSCORRUPTED;
1700 			goto done;
1701 		}
1702 		NEW.rm_flags = newext;
1703 		error = xfs_rmap_update(cur, &NEW);
1704 		if (error)
1705 			goto done;
1706 		break;
1707 
1708 	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1709 		/*
1710 		 * Setting the first part of a previous oldext extent to newext.
1711 		 * The left neighbor is contiguous.
1712 		 */
1713 		NEW = PREV;
1714 		error = xfs_rmap_delete(cur, NEW.rm_startblock,
1715 				NEW.rm_blockcount, NEW.rm_owner,
1716 				NEW.rm_offset, NEW.rm_flags);
1717 		if (error)
1718 			goto done;
1719 		NEW.rm_offset += len;
1720 		NEW.rm_startblock += len;
1721 		NEW.rm_blockcount -= len;
1722 		error = xfs_rmap_insert(cur, NEW.rm_startblock,
1723 				NEW.rm_blockcount, NEW.rm_owner,
1724 				NEW.rm_offset, NEW.rm_flags);
1725 		if (error)
1726 			goto done;
1727 		NEW = LEFT;
1728 		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1729 				NEW.rm_blockcount, NEW.rm_owner,
1730 				NEW.rm_offset, NEW.rm_flags, &i);
1731 		if (error)
1732 			goto done;
1733 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1734 			error = -EFSCORRUPTED;
1735 			goto done;
1736 		}
1737 		NEW.rm_blockcount += len;
1738 		error = xfs_rmap_update(cur, &NEW);
1739 		if (error)
1740 			goto done;
1741 		break;
1742 
1743 	case RMAP_LEFT_FILLING:
1744 		/*
1745 		 * Setting the first part of a previous oldext extent to newext.
1746 		 * The left neighbor is not contiguous.
1747 		 */
1748 		NEW = PREV;
1749 		error = xfs_rmap_delete(cur, NEW.rm_startblock,
1750 				NEW.rm_blockcount, NEW.rm_owner,
1751 				NEW.rm_offset, NEW.rm_flags);
1752 		if (error)
1753 			goto done;
1754 		NEW.rm_offset += len;
1755 		NEW.rm_startblock += len;
1756 		NEW.rm_blockcount -= len;
1757 		error = xfs_rmap_insert(cur, NEW.rm_startblock,
1758 				NEW.rm_blockcount, NEW.rm_owner,
1759 				NEW.rm_offset, NEW.rm_flags);
1760 		if (error)
1761 			goto done;
1762 		error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1763 		if (error)
1764 			goto done;
1765 		break;
1766 
1767 	case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1768 		/*
1769 		 * Setting the last part of a previous oldext extent to newext.
1770 		 * The right neighbor is contiguous with the new allocation.
1771 		 */
1772 		NEW = PREV;
1773 		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1774 				NEW.rm_blockcount, NEW.rm_owner,
1775 				NEW.rm_offset, NEW.rm_flags, &i);
1776 		if (error)
1777 			goto done;
1778 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1779 			error = -EFSCORRUPTED;
1780 			goto done;
1781 		}
1782 		NEW.rm_blockcount = offset - NEW.rm_offset;
1783 		error = xfs_rmap_update(cur, &NEW);
1784 		if (error)
1785 			goto done;
1786 		NEW = RIGHT;
1787 		error = xfs_rmap_delete(cur, NEW.rm_startblock,
1788 				NEW.rm_blockcount, NEW.rm_owner,
1789 				NEW.rm_offset, NEW.rm_flags);
1790 		if (error)
1791 			goto done;
1792 		NEW.rm_offset = offset;
1793 		NEW.rm_startblock = bno;
1794 		NEW.rm_blockcount += len;
1795 		error = xfs_rmap_insert(cur, NEW.rm_startblock,
1796 				NEW.rm_blockcount, NEW.rm_owner,
1797 				NEW.rm_offset, NEW.rm_flags);
1798 		if (error)
1799 			goto done;
1800 		break;
1801 
1802 	case RMAP_RIGHT_FILLING:
1803 		/*
1804 		 * Setting the last part of a previous oldext extent to newext.
1805 		 * The right neighbor is not contiguous.
1806 		 */
1807 		NEW = PREV;
1808 		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1809 				NEW.rm_blockcount, NEW.rm_owner,
1810 				NEW.rm_offset, NEW.rm_flags, &i);
1811 		if (error)
1812 			goto done;
1813 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1814 			error = -EFSCORRUPTED;
1815 			goto done;
1816 		}
1817 		NEW.rm_blockcount -= len;
1818 		error = xfs_rmap_update(cur, &NEW);
1819 		if (error)
1820 			goto done;
1821 		error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1822 		if (error)
1823 			goto done;
1824 		break;
1825 
1826 	case 0:
1827 		/*
1828 		 * Setting the middle part of a previous oldext extent to
1829 		 * newext.  Contiguity is impossible here.
1830 		 * One extent becomes three extents.
1831 		 */
1832 		/* new right extent - oldext */
1833 		NEW.rm_startblock = bno + len;
1834 		NEW.rm_owner = owner;
1835 		NEW.rm_offset = new_endoff;
1836 		NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1837 				new_endoff;
1838 		NEW.rm_flags = PREV.rm_flags;
1839 		error = xfs_rmap_insert(cur, NEW.rm_startblock,
1840 				NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1841 				NEW.rm_flags);
1842 		if (error)
1843 			goto done;
1844 		/* new left extent - oldext */
1845 		NEW = PREV;
1846 		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1847 				NEW.rm_blockcount, NEW.rm_owner,
1848 				NEW.rm_offset, NEW.rm_flags, &i);
1849 		if (error)
1850 			goto done;
1851 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1852 			error = -EFSCORRUPTED;
1853 			goto done;
1854 		}
1855 		NEW.rm_blockcount = offset - NEW.rm_offset;
1856 		error = xfs_rmap_update(cur, &NEW);
1857 		if (error)
1858 			goto done;
1859 		/* new middle extent - newext */
1860 		NEW.rm_startblock = bno;
1861 		NEW.rm_blockcount = len;
1862 		NEW.rm_owner = owner;
1863 		NEW.rm_offset = offset;
1864 		NEW.rm_flags = newext;
1865 		error = xfs_rmap_insert(cur, NEW.rm_startblock,
1866 				NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1867 				NEW.rm_flags);
1868 		if (error)
1869 			goto done;
1870 		break;
1871 
1872 	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1873 	case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1874 	case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1875 	case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1876 	case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1877 	case RMAP_LEFT_CONTIG:
1878 	case RMAP_RIGHT_CONTIG:
1879 		/*
1880 		 * These cases are all impossible.
1881 		 */
1882 		ASSERT(0);
1883 	}
1884 
1885 	trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1886 			unwritten, oinfo);
1887 done:
1888 	if (error)
1889 		trace_xfs_rmap_convert_error(cur->bc_mp,
1890 				cur->bc_ag.pag->pag_agno, error, _RET_IP_);
1891 	return error;
1892 }
1893 
1894 #undef	NEW
1895 #undef	LEFT
1896 #undef	RIGHT
1897 #undef	PREV
1898 
1899 /*
1900  * Find an extent in the rmap btree and unmap it.  For rmap extent types that
1901  * can overlap (data fork rmaps on reflink filesystems) we must be careful
1902  * that the prev/next records in the btree might belong to another owner.
1903  * Therefore we must use delete+insert to alter any of the key fields.
1904  *
1905  * For every other situation there can only be one owner for a given extent,
1906  * so we can call the regular _free function.
1907  */
1908 STATIC int
xfs_rmap_unmap_shared(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,bool unwritten,const struct xfs_owner_info * oinfo)1909 xfs_rmap_unmap_shared(
1910 	struct xfs_btree_cur		*cur,
1911 	xfs_agblock_t			bno,
1912 	xfs_extlen_t			len,
1913 	bool				unwritten,
1914 	const struct xfs_owner_info	*oinfo)
1915 {
1916 	struct xfs_mount		*mp = cur->bc_mp;
1917 	struct xfs_rmap_irec		ltrec;
1918 	uint64_t			ltoff;
1919 	int				error = 0;
1920 	int				i;
1921 	uint64_t			owner;
1922 	uint64_t			offset;
1923 	unsigned int			flags;
1924 
1925 	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1926 	if (unwritten)
1927 		flags |= XFS_RMAP_UNWRITTEN;
1928 	trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
1929 			unwritten, oinfo);
1930 
1931 	/*
1932 	 * We should always have a left record because there's a static record
1933 	 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1934 	 * will not ever be removed from the tree.
1935 	 */
1936 	error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1937 			&ltrec, &i);
1938 	if (error)
1939 		goto out_error;
1940 	if (XFS_IS_CORRUPT(mp, i != 1)) {
1941 		error = -EFSCORRUPTED;
1942 		goto out_error;
1943 	}
1944 	ltoff = ltrec.rm_offset;
1945 
1946 	/* Make sure the extent we found covers the entire freeing range. */
1947 	if (XFS_IS_CORRUPT(mp,
1948 			   ltrec.rm_startblock > bno ||
1949 			   ltrec.rm_startblock + ltrec.rm_blockcount <
1950 			   bno + len)) {
1951 		error = -EFSCORRUPTED;
1952 		goto out_error;
1953 	}
1954 
1955 	/* Make sure the owner matches what we expect to find in the tree. */
1956 	if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) {
1957 		error = -EFSCORRUPTED;
1958 		goto out_error;
1959 	}
1960 
1961 	/* Make sure the unwritten flag matches. */
1962 	if (XFS_IS_CORRUPT(mp,
1963 			   (flags & XFS_RMAP_UNWRITTEN) !=
1964 			   (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) {
1965 		error = -EFSCORRUPTED;
1966 		goto out_error;
1967 	}
1968 
1969 	/* Check the offset. */
1970 	if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) {
1971 		error = -EFSCORRUPTED;
1972 		goto out_error;
1973 	}
1974 	if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) {
1975 		error = -EFSCORRUPTED;
1976 		goto out_error;
1977 	}
1978 
1979 	if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
1980 		/* Exact match, simply remove the record from rmap tree. */
1981 		error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1982 				ltrec.rm_blockcount, ltrec.rm_owner,
1983 				ltrec.rm_offset, ltrec.rm_flags);
1984 		if (error)
1985 			goto out_error;
1986 	} else if (ltrec.rm_startblock == bno) {
1987 		/*
1988 		 * Overlap left hand side of extent: move the start, trim the
1989 		 * length and update the current record.
1990 		 *
1991 		 *       ltbno                ltlen
1992 		 * Orig:    |oooooooooooooooooooo|
1993 		 * Freeing: |fffffffff|
1994 		 * Result:            |rrrrrrrrrr|
1995 		 *         bno       len
1996 		 */
1997 
1998 		/* Delete prev rmap. */
1999 		error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2000 				ltrec.rm_blockcount, ltrec.rm_owner,
2001 				ltrec.rm_offset, ltrec.rm_flags);
2002 		if (error)
2003 			goto out_error;
2004 
2005 		/* Add an rmap at the new offset. */
2006 		ltrec.rm_startblock += len;
2007 		ltrec.rm_blockcount -= len;
2008 		ltrec.rm_offset += len;
2009 		error = xfs_rmap_insert(cur, ltrec.rm_startblock,
2010 				ltrec.rm_blockcount, ltrec.rm_owner,
2011 				ltrec.rm_offset, ltrec.rm_flags);
2012 		if (error)
2013 			goto out_error;
2014 	} else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
2015 		/*
2016 		 * Overlap right hand side of extent: trim the length and
2017 		 * update the current record.
2018 		 *
2019 		 *       ltbno                ltlen
2020 		 * Orig:    |oooooooooooooooooooo|
2021 		 * Freeing:            |fffffffff|
2022 		 * Result:  |rrrrrrrrrr|
2023 		 *                    bno       len
2024 		 */
2025 		error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2026 				ltrec.rm_blockcount, ltrec.rm_owner,
2027 				ltrec.rm_offset, ltrec.rm_flags, &i);
2028 		if (error)
2029 			goto out_error;
2030 		if (XFS_IS_CORRUPT(mp, i != 1)) {
2031 			error = -EFSCORRUPTED;
2032 			goto out_error;
2033 		}
2034 		ltrec.rm_blockcount -= len;
2035 		error = xfs_rmap_update(cur, &ltrec);
2036 		if (error)
2037 			goto out_error;
2038 	} else {
2039 		/*
2040 		 * Overlap middle of extent: trim the length of the existing
2041 		 * record to the length of the new left-extent size, increment
2042 		 * the insertion position so we can insert a new record
2043 		 * containing the remaining right-extent space.
2044 		 *
2045 		 *       ltbno                ltlen
2046 		 * Orig:    |oooooooooooooooooooo|
2047 		 * Freeing:       |fffffffff|
2048 		 * Result:  |rrrrr|         |rrrr|
2049 		 *               bno       len
2050 		 */
2051 		xfs_extlen_t	orig_len = ltrec.rm_blockcount;
2052 
2053 		/* Shrink the left side of the rmap */
2054 		error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2055 				ltrec.rm_blockcount, ltrec.rm_owner,
2056 				ltrec.rm_offset, ltrec.rm_flags, &i);
2057 		if (error)
2058 			goto out_error;
2059 		if (XFS_IS_CORRUPT(mp, i != 1)) {
2060 			error = -EFSCORRUPTED;
2061 			goto out_error;
2062 		}
2063 		ltrec.rm_blockcount = bno - ltrec.rm_startblock;
2064 		error = xfs_rmap_update(cur, &ltrec);
2065 		if (error)
2066 			goto out_error;
2067 
2068 		/* Add an rmap at the new offset */
2069 		error = xfs_rmap_insert(cur, bno + len,
2070 				orig_len - len - ltrec.rm_blockcount,
2071 				ltrec.rm_owner, offset + len,
2072 				ltrec.rm_flags);
2073 		if (error)
2074 			goto out_error;
2075 	}
2076 
2077 	trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2078 			unwritten, oinfo);
2079 out_error:
2080 	if (error)
2081 		trace_xfs_rmap_unmap_error(cur->bc_mp,
2082 				cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2083 	return error;
2084 }
2085 
2086 /*
2087  * Find an extent in the rmap btree and map it.  For rmap extent types that
2088  * can overlap (data fork rmaps on reflink filesystems) we must be careful
2089  * that the prev/next records in the btree might belong to another owner.
2090  * Therefore we must use delete+insert to alter any of the key fields.
2091  *
2092  * For every other situation there can only be one owner for a given extent,
2093  * so we can call the regular _alloc function.
2094  */
2095 STATIC int
xfs_rmap_map_shared(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,bool unwritten,const struct xfs_owner_info * oinfo)2096 xfs_rmap_map_shared(
2097 	struct xfs_btree_cur		*cur,
2098 	xfs_agblock_t			bno,
2099 	xfs_extlen_t			len,
2100 	bool				unwritten,
2101 	const struct xfs_owner_info	*oinfo)
2102 {
2103 	struct xfs_mount		*mp = cur->bc_mp;
2104 	struct xfs_rmap_irec		ltrec;
2105 	struct xfs_rmap_irec		gtrec;
2106 	int				have_gt;
2107 	int				have_lt;
2108 	int				error = 0;
2109 	int				i;
2110 	uint64_t			owner;
2111 	uint64_t			offset;
2112 	unsigned int			flags = 0;
2113 
2114 	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2115 	if (unwritten)
2116 		flags |= XFS_RMAP_UNWRITTEN;
2117 	trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
2118 			unwritten, oinfo);
2119 
2120 	/* Is there a left record that abuts our range? */
2121 	error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
2122 			&ltrec, &have_lt);
2123 	if (error)
2124 		goto out_error;
2125 	if (have_lt &&
2126 	    !xfs_rmap_is_mergeable(&ltrec, owner, flags))
2127 		have_lt = 0;
2128 
2129 	/* Is there a right record that abuts our range? */
2130 	error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
2131 			flags, &have_gt);
2132 	if (error)
2133 		goto out_error;
2134 	if (have_gt) {
2135 		error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
2136 		if (error)
2137 			goto out_error;
2138 		if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
2139 			error = -EFSCORRUPTED;
2140 			goto out_error;
2141 		}
2142 		trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
2143 			cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
2144 			gtrec.rm_blockcount, gtrec.rm_owner,
2145 			gtrec.rm_offset, gtrec.rm_flags);
2146 
2147 		if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
2148 			have_gt = 0;
2149 	}
2150 
2151 	if (have_lt &&
2152 	    ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
2153 	    ltrec.rm_offset + ltrec.rm_blockcount == offset) {
2154 		/*
2155 		 * Left edge contiguous, merge into left record.
2156 		 *
2157 		 *       ltbno     ltlen
2158 		 * orig:   |ooooooooo|
2159 		 * adding:           |aaaaaaaaa|
2160 		 * result: |rrrrrrrrrrrrrrrrrrr|
2161 		 *                  bno       len
2162 		 */
2163 		ltrec.rm_blockcount += len;
2164 		if (have_gt &&
2165 		    bno + len == gtrec.rm_startblock &&
2166 		    offset + len == gtrec.rm_offset) {
2167 			/*
2168 			 * Right edge also contiguous, delete right record
2169 			 * and merge into left record.
2170 			 *
2171 			 *       ltbno     ltlen    gtbno     gtlen
2172 			 * orig:   |ooooooooo|         |ooooooooo|
2173 			 * adding:           |aaaaaaaaa|
2174 			 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
2175 			 */
2176 			ltrec.rm_blockcount += gtrec.rm_blockcount;
2177 			error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2178 					gtrec.rm_blockcount, gtrec.rm_owner,
2179 					gtrec.rm_offset, gtrec.rm_flags);
2180 			if (error)
2181 				goto out_error;
2182 		}
2183 
2184 		/* Point the cursor back to the left record and update. */
2185 		error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2186 				ltrec.rm_blockcount, ltrec.rm_owner,
2187 				ltrec.rm_offset, ltrec.rm_flags, &i);
2188 		if (error)
2189 			goto out_error;
2190 		if (XFS_IS_CORRUPT(mp, i != 1)) {
2191 			error = -EFSCORRUPTED;
2192 			goto out_error;
2193 		}
2194 
2195 		error = xfs_rmap_update(cur, &ltrec);
2196 		if (error)
2197 			goto out_error;
2198 	} else if (have_gt &&
2199 		   bno + len == gtrec.rm_startblock &&
2200 		   offset + len == gtrec.rm_offset) {
2201 		/*
2202 		 * Right edge contiguous, merge into right record.
2203 		 *
2204 		 *                 gtbno     gtlen
2205 		 * Orig:             |ooooooooo|
2206 		 * adding: |aaaaaaaaa|
2207 		 * Result: |rrrrrrrrrrrrrrrrrrr|
2208 		 *        bno       len
2209 		 */
2210 		/* Delete the old record. */
2211 		error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2212 				gtrec.rm_blockcount, gtrec.rm_owner,
2213 				gtrec.rm_offset, gtrec.rm_flags);
2214 		if (error)
2215 			goto out_error;
2216 
2217 		/* Move the start and re-add it. */
2218 		gtrec.rm_startblock = bno;
2219 		gtrec.rm_blockcount += len;
2220 		gtrec.rm_offset = offset;
2221 		error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2222 				gtrec.rm_blockcount, gtrec.rm_owner,
2223 				gtrec.rm_offset, gtrec.rm_flags);
2224 		if (error)
2225 			goto out_error;
2226 	} else {
2227 		/*
2228 		 * No contiguous edge with identical owner, insert
2229 		 * new record at current cursor position.
2230 		 */
2231 		error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2232 		if (error)
2233 			goto out_error;
2234 	}
2235 
2236 	trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2237 			unwritten, oinfo);
2238 out_error:
2239 	if (error)
2240 		trace_xfs_rmap_map_error(cur->bc_mp,
2241 				cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2242 	return error;
2243 }
2244 
2245 /* Insert a raw rmap into the rmapbt. */
2246 int
xfs_rmap_map_raw(struct xfs_btree_cur * cur,struct xfs_rmap_irec * rmap)2247 xfs_rmap_map_raw(
2248 	struct xfs_btree_cur	*cur,
2249 	struct xfs_rmap_irec	*rmap)
2250 {
2251 	struct xfs_owner_info	oinfo;
2252 
2253 	oinfo.oi_owner = rmap->rm_owner;
2254 	oinfo.oi_offset = rmap->rm_offset;
2255 	oinfo.oi_flags = 0;
2256 	if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
2257 		oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
2258 	if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
2259 		oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
2260 
2261 	if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2262 		return xfs_rmap_map(cur, rmap->rm_startblock,
2263 				rmap->rm_blockcount,
2264 				rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2265 				&oinfo);
2266 
2267 	return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2268 			rmap->rm_blockcount,
2269 			rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2270 			&oinfo);
2271 }
2272 
2273 struct xfs_rmap_query_range_info {
2274 	xfs_rmap_query_range_fn	fn;
2275 	void				*priv;
2276 };
2277 
2278 /* Format btree record and pass to our callback. */
2279 STATIC int
xfs_rmap_query_range_helper(struct xfs_btree_cur * cur,const union xfs_btree_rec * rec,void * priv)2280 xfs_rmap_query_range_helper(
2281 	struct xfs_btree_cur		*cur,
2282 	const union xfs_btree_rec	*rec,
2283 	void				*priv)
2284 {
2285 	struct xfs_rmap_query_range_info	*query = priv;
2286 	struct xfs_rmap_irec			irec;
2287 	int					error;
2288 
2289 	error = xfs_rmap_btrec_to_irec(rec, &irec);
2290 	if (error)
2291 		return error;
2292 	return query->fn(cur, &irec, query->priv);
2293 }
2294 
2295 /* Find all rmaps between two keys. */
2296 int
xfs_rmap_query_range(struct xfs_btree_cur * cur,const struct xfs_rmap_irec * low_rec,const struct xfs_rmap_irec * high_rec,xfs_rmap_query_range_fn fn,void * priv)2297 xfs_rmap_query_range(
2298 	struct xfs_btree_cur			*cur,
2299 	const struct xfs_rmap_irec		*low_rec,
2300 	const struct xfs_rmap_irec		*high_rec,
2301 	xfs_rmap_query_range_fn			fn,
2302 	void					*priv)
2303 {
2304 	union xfs_btree_irec			low_brec;
2305 	union xfs_btree_irec			high_brec;
2306 	struct xfs_rmap_query_range_info	query;
2307 
2308 	low_brec.r = *low_rec;
2309 	high_brec.r = *high_rec;
2310 	query.priv = priv;
2311 	query.fn = fn;
2312 	return xfs_btree_query_range(cur, &low_brec, &high_brec,
2313 			xfs_rmap_query_range_helper, &query);
2314 }
2315 
2316 /* Find all rmaps. */
2317 int
xfs_rmap_query_all(struct xfs_btree_cur * cur,xfs_rmap_query_range_fn fn,void * priv)2318 xfs_rmap_query_all(
2319 	struct xfs_btree_cur			*cur,
2320 	xfs_rmap_query_range_fn			fn,
2321 	void					*priv)
2322 {
2323 	struct xfs_rmap_query_range_info	query;
2324 
2325 	query.priv = priv;
2326 	query.fn = fn;
2327 	return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2328 }
2329 
2330 /* Clean up after calling xfs_rmap_finish_one. */
2331 void
xfs_rmap_finish_one_cleanup(struct xfs_trans * tp,struct xfs_btree_cur * rcur,int error)2332 xfs_rmap_finish_one_cleanup(
2333 	struct xfs_trans	*tp,
2334 	struct xfs_btree_cur	*rcur,
2335 	int			error)
2336 {
2337 	struct xfs_buf		*agbp;
2338 
2339 	if (rcur == NULL)
2340 		return;
2341 	agbp = rcur->bc_ag.agbp;
2342 	xfs_btree_del_cursor(rcur, error);
2343 	if (error)
2344 		xfs_trans_brelse(tp, agbp);
2345 }
2346 
2347 /*
2348  * Process one of the deferred rmap operations.  We pass back the
2349  * btree cursor to maintain our lock on the rmapbt between calls.
2350  * This saves time and eliminates a buffer deadlock between the
2351  * superblock and the AGF because we'll always grab them in the same
2352  * order.
2353  */
2354 int
xfs_rmap_finish_one(struct xfs_trans * tp,enum xfs_rmap_intent_type type,uint64_t owner,int whichfork,xfs_fileoff_t startoff,xfs_fsblock_t startblock,xfs_filblks_t blockcount,xfs_exntst_t state,struct xfs_btree_cur ** pcur)2355 xfs_rmap_finish_one(
2356 	struct xfs_trans		*tp,
2357 	enum xfs_rmap_intent_type	type,
2358 	uint64_t			owner,
2359 	int				whichfork,
2360 	xfs_fileoff_t			startoff,
2361 	xfs_fsblock_t			startblock,
2362 	xfs_filblks_t			blockcount,
2363 	xfs_exntst_t			state,
2364 	struct xfs_btree_cur		**pcur)
2365 {
2366 	struct xfs_mount		*mp = tp->t_mountp;
2367 	struct xfs_perag		*pag;
2368 	struct xfs_btree_cur		*rcur;
2369 	struct xfs_buf			*agbp = NULL;
2370 	int				error = 0;
2371 	struct xfs_owner_info		oinfo;
2372 	xfs_agblock_t			bno;
2373 	bool				unwritten;
2374 
2375 	pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, startblock));
2376 	bno = XFS_FSB_TO_AGBNO(mp, startblock);
2377 
2378 	trace_xfs_rmap_deferred(mp, pag->pag_agno, type, bno, owner, whichfork,
2379 			startoff, blockcount, state);
2380 
2381 	if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE)) {
2382 		error = -EIO;
2383 		goto out_drop;
2384 	}
2385 
2386 
2387 	/*
2388 	 * If we haven't gotten a cursor or the cursor AG doesn't match
2389 	 * the startblock, get one now.
2390 	 */
2391 	rcur = *pcur;
2392 	if (rcur != NULL && rcur->bc_ag.pag != pag) {
2393 		xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2394 		rcur = NULL;
2395 		*pcur = NULL;
2396 	}
2397 	if (rcur == NULL) {
2398 		/*
2399 		 * Refresh the freelist before we start changing the
2400 		 * rmapbt, because a shape change could cause us to
2401 		 * allocate blocks.
2402 		 */
2403 		error = xfs_free_extent_fix_freelist(tp, pag, &agbp);
2404 		if (error)
2405 			goto out_drop;
2406 		if (XFS_IS_CORRUPT(tp->t_mountp, !agbp)) {
2407 			error = -EFSCORRUPTED;
2408 			goto out_drop;
2409 		}
2410 
2411 		rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
2412 	}
2413 	*pcur = rcur;
2414 
2415 	xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2416 	unwritten = state == XFS_EXT_UNWRITTEN;
2417 	bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2418 
2419 	switch (type) {
2420 	case XFS_RMAP_ALLOC:
2421 	case XFS_RMAP_MAP:
2422 		error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2423 		break;
2424 	case XFS_RMAP_MAP_SHARED:
2425 		error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2426 				&oinfo);
2427 		break;
2428 	case XFS_RMAP_FREE:
2429 	case XFS_RMAP_UNMAP:
2430 		error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2431 				&oinfo);
2432 		break;
2433 	case XFS_RMAP_UNMAP_SHARED:
2434 		error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2435 				&oinfo);
2436 		break;
2437 	case XFS_RMAP_CONVERT:
2438 		error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2439 				&oinfo);
2440 		break;
2441 	case XFS_RMAP_CONVERT_SHARED:
2442 		error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2443 				!unwritten, &oinfo);
2444 		break;
2445 	default:
2446 		ASSERT(0);
2447 		error = -EFSCORRUPTED;
2448 	}
2449 out_drop:
2450 	xfs_perag_put(pag);
2451 	return error;
2452 }
2453 
2454 /*
2455  * Don't defer an rmap if we aren't an rmap filesystem.
2456  */
2457 static bool
xfs_rmap_update_is_needed(struct xfs_mount * mp,int whichfork)2458 xfs_rmap_update_is_needed(
2459 	struct xfs_mount	*mp,
2460 	int			whichfork)
2461 {
2462 	return xfs_has_rmapbt(mp) && whichfork != XFS_COW_FORK;
2463 }
2464 
2465 /*
2466  * Record a rmap intent; the list is kept sorted first by AG and then by
2467  * increasing age.
2468  */
2469 static void
__xfs_rmap_add(struct xfs_trans * tp,enum xfs_rmap_intent_type type,uint64_t owner,int whichfork,struct xfs_bmbt_irec * bmap)2470 __xfs_rmap_add(
2471 	struct xfs_trans		*tp,
2472 	enum xfs_rmap_intent_type	type,
2473 	uint64_t			owner,
2474 	int				whichfork,
2475 	struct xfs_bmbt_irec		*bmap)
2476 {
2477 	struct xfs_rmap_intent		*ri;
2478 
2479 	trace_xfs_rmap_defer(tp->t_mountp,
2480 			XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock),
2481 			type,
2482 			XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock),
2483 			owner, whichfork,
2484 			bmap->br_startoff,
2485 			bmap->br_blockcount,
2486 			bmap->br_state);
2487 
2488 	ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_NOFS);
2489 	INIT_LIST_HEAD(&ri->ri_list);
2490 	ri->ri_type = type;
2491 	ri->ri_owner = owner;
2492 	ri->ri_whichfork = whichfork;
2493 	ri->ri_bmap = *bmap;
2494 
2495 	xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
2496 }
2497 
2498 /* Map an extent into a file. */
2499 void
xfs_rmap_map_extent(struct xfs_trans * tp,struct xfs_inode * ip,int whichfork,struct xfs_bmbt_irec * PREV)2500 xfs_rmap_map_extent(
2501 	struct xfs_trans	*tp,
2502 	struct xfs_inode	*ip,
2503 	int			whichfork,
2504 	struct xfs_bmbt_irec	*PREV)
2505 {
2506 	enum xfs_rmap_intent_type type = XFS_RMAP_MAP;
2507 
2508 	if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2509 		return;
2510 
2511 	if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2512 		type = XFS_RMAP_MAP_SHARED;
2513 
2514 	__xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2515 }
2516 
2517 /* Unmap an extent out of a file. */
2518 void
xfs_rmap_unmap_extent(struct xfs_trans * tp,struct xfs_inode * ip,int whichfork,struct xfs_bmbt_irec * PREV)2519 xfs_rmap_unmap_extent(
2520 	struct xfs_trans	*tp,
2521 	struct xfs_inode	*ip,
2522 	int			whichfork,
2523 	struct xfs_bmbt_irec	*PREV)
2524 {
2525 	enum xfs_rmap_intent_type type = XFS_RMAP_UNMAP;
2526 
2527 	if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2528 		return;
2529 
2530 	if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2531 		type = XFS_RMAP_UNMAP_SHARED;
2532 
2533 	__xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2534 }
2535 
2536 /*
2537  * Convert a data fork extent from unwritten to real or vice versa.
2538  *
2539  * Note that tp can be NULL here as no transaction is used for COW fork
2540  * unwritten conversion.
2541  */
2542 void
xfs_rmap_convert_extent(struct xfs_mount * mp,struct xfs_trans * tp,struct xfs_inode * ip,int whichfork,struct xfs_bmbt_irec * PREV)2543 xfs_rmap_convert_extent(
2544 	struct xfs_mount	*mp,
2545 	struct xfs_trans	*tp,
2546 	struct xfs_inode	*ip,
2547 	int			whichfork,
2548 	struct xfs_bmbt_irec	*PREV)
2549 {
2550 	enum xfs_rmap_intent_type type = XFS_RMAP_CONVERT;
2551 
2552 	if (!xfs_rmap_update_is_needed(mp, whichfork))
2553 		return;
2554 
2555 	if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2556 		type = XFS_RMAP_CONVERT_SHARED;
2557 
2558 	__xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2559 }
2560 
2561 /* Schedule the creation of an rmap for non-file data. */
2562 void
xfs_rmap_alloc_extent(struct xfs_trans * tp,xfs_agnumber_t agno,xfs_agblock_t bno,xfs_extlen_t len,uint64_t owner)2563 xfs_rmap_alloc_extent(
2564 	struct xfs_trans	*tp,
2565 	xfs_agnumber_t		agno,
2566 	xfs_agblock_t		bno,
2567 	xfs_extlen_t		len,
2568 	uint64_t		owner)
2569 {
2570 	struct xfs_bmbt_irec	bmap;
2571 
2572 	if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2573 		return;
2574 
2575 	bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2576 	bmap.br_blockcount = len;
2577 	bmap.br_startoff = 0;
2578 	bmap.br_state = XFS_EXT_NORM;
2579 
2580 	__xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
2581 }
2582 
2583 /* Schedule the deletion of an rmap for non-file data. */
2584 void
xfs_rmap_free_extent(struct xfs_trans * tp,xfs_agnumber_t agno,xfs_agblock_t bno,xfs_extlen_t len,uint64_t owner)2585 xfs_rmap_free_extent(
2586 	struct xfs_trans	*tp,
2587 	xfs_agnumber_t		agno,
2588 	xfs_agblock_t		bno,
2589 	xfs_extlen_t		len,
2590 	uint64_t		owner)
2591 {
2592 	struct xfs_bmbt_irec	bmap;
2593 
2594 	if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2595 		return;
2596 
2597 	bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2598 	bmap.br_blockcount = len;
2599 	bmap.br_startoff = 0;
2600 	bmap.br_state = XFS_EXT_NORM;
2601 
2602 	__xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
2603 }
2604 
2605 /* Compare rmap records.  Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2606 int
xfs_rmap_compare(const struct xfs_rmap_irec * a,const struct xfs_rmap_irec * b)2607 xfs_rmap_compare(
2608 	const struct xfs_rmap_irec	*a,
2609 	const struct xfs_rmap_irec	*b)
2610 {
2611 	__u64				oa;
2612 	__u64				ob;
2613 
2614 	oa = xfs_rmap_irec_offset_pack(a);
2615 	ob = xfs_rmap_irec_offset_pack(b);
2616 
2617 	if (a->rm_startblock < b->rm_startblock)
2618 		return -1;
2619 	else if (a->rm_startblock > b->rm_startblock)
2620 		return 1;
2621 	else if (a->rm_owner < b->rm_owner)
2622 		return -1;
2623 	else if (a->rm_owner > b->rm_owner)
2624 		return 1;
2625 	else if (oa < ob)
2626 		return -1;
2627 	else if (oa > ob)
2628 		return 1;
2629 	else
2630 		return 0;
2631 }
2632 
2633 /* Is there a record covering a given extent? */
2634 int
xfs_rmap_has_record(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,bool * exists)2635 xfs_rmap_has_record(
2636 	struct xfs_btree_cur	*cur,
2637 	xfs_agblock_t		bno,
2638 	xfs_extlen_t		len,
2639 	bool			*exists)
2640 {
2641 	union xfs_btree_irec	low;
2642 	union xfs_btree_irec	high;
2643 
2644 	memset(&low, 0, sizeof(low));
2645 	low.r.rm_startblock = bno;
2646 	memset(&high, 0xFF, sizeof(high));
2647 	high.r.rm_startblock = bno + len - 1;
2648 
2649 	return xfs_btree_has_record(cur, &low, &high, exists);
2650 }
2651 
2652 /*
2653  * Is there a record for this owner completely covering a given physical
2654  * extent?  If so, *has_rmap will be set to true.  If there is no record
2655  * or the record only covers part of the range, we set *has_rmap to false.
2656  * This function doesn't perform range lookups or offset checks, so it is
2657  * not suitable for checking data fork blocks.
2658  */
2659 int
xfs_rmap_record_exists(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,const struct xfs_owner_info * oinfo,bool * has_rmap)2660 xfs_rmap_record_exists(
2661 	struct xfs_btree_cur		*cur,
2662 	xfs_agblock_t			bno,
2663 	xfs_extlen_t			len,
2664 	const struct xfs_owner_info	*oinfo,
2665 	bool				*has_rmap)
2666 {
2667 	uint64_t			owner;
2668 	uint64_t			offset;
2669 	unsigned int			flags;
2670 	int				has_record;
2671 	struct xfs_rmap_irec		irec;
2672 	int				error;
2673 
2674 	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2675 	ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
2676 	       (flags & XFS_RMAP_BMBT_BLOCK));
2677 
2678 	error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
2679 			&has_record);
2680 	if (error)
2681 		return error;
2682 	if (!has_record) {
2683 		*has_rmap = false;
2684 		return 0;
2685 	}
2686 
2687 	error = xfs_rmap_get_rec(cur, &irec, &has_record);
2688 	if (error)
2689 		return error;
2690 	if (!has_record) {
2691 		*has_rmap = false;
2692 		return 0;
2693 	}
2694 
2695 	*has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
2696 		     irec.rm_startblock + irec.rm_blockcount >= bno + len);
2697 	return 0;
2698 }
2699 
2700 struct xfs_rmap_key_state {
2701 	uint64_t			owner;
2702 	uint64_t			offset;
2703 	unsigned int			flags;
2704 };
2705 
2706 /* For each rmap given, figure out if it doesn't match the key we want. */
2707 STATIC int
xfs_rmap_has_other_keys_helper(struct xfs_btree_cur * cur,const struct xfs_rmap_irec * rec,void * priv)2708 xfs_rmap_has_other_keys_helper(
2709 	struct xfs_btree_cur		*cur,
2710 	const struct xfs_rmap_irec	*rec,
2711 	void				*priv)
2712 {
2713 	struct xfs_rmap_key_state	*rks = priv;
2714 
2715 	if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset &&
2716 	    ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags)
2717 		return 0;
2718 	return -ECANCELED;
2719 }
2720 
2721 /*
2722  * Given an extent and some owner info, can we find records overlapping
2723  * the extent whose owner info does not match the given owner?
2724  */
2725 int
xfs_rmap_has_other_keys(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,const struct xfs_owner_info * oinfo,bool * has_rmap)2726 xfs_rmap_has_other_keys(
2727 	struct xfs_btree_cur		*cur,
2728 	xfs_agblock_t			bno,
2729 	xfs_extlen_t			len,
2730 	const struct xfs_owner_info	*oinfo,
2731 	bool				*has_rmap)
2732 {
2733 	struct xfs_rmap_irec		low = {0};
2734 	struct xfs_rmap_irec		high;
2735 	struct xfs_rmap_key_state	rks;
2736 	int				error;
2737 
2738 	xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags);
2739 	*has_rmap = false;
2740 
2741 	low.rm_startblock = bno;
2742 	memset(&high, 0xFF, sizeof(high));
2743 	high.rm_startblock = bno + len - 1;
2744 
2745 	error = xfs_rmap_query_range(cur, &low, &high,
2746 			xfs_rmap_has_other_keys_helper, &rks);
2747 	if (error == -ECANCELED) {
2748 		*has_rmap = true;
2749 		return 0;
2750 	}
2751 
2752 	return error;
2753 }
2754 
2755 const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
2756 	.oi_owner = XFS_RMAP_OWN_NULL,
2757 };
2758 const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
2759 	.oi_owner = XFS_RMAP_OWN_UNKNOWN,
2760 };
2761 const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
2762 	.oi_owner = XFS_RMAP_OWN_FS,
2763 };
2764 const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
2765 	.oi_owner = XFS_RMAP_OWN_LOG,
2766 };
2767 const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
2768 	.oi_owner = XFS_RMAP_OWN_AG,
2769 };
2770 const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
2771 	.oi_owner = XFS_RMAP_OWN_INOBT,
2772 };
2773 const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
2774 	.oi_owner = XFS_RMAP_OWN_INODES,
2775 };
2776 const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
2777 	.oi_owner = XFS_RMAP_OWN_REFC,
2778 };
2779 const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
2780 	.oi_owner = XFS_RMAP_OWN_COW,
2781 };
2782