1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2014 Red Hat, Inc.
6 #include "libxfs_priv.h"
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_log_format.h"
11 #include "xfs_trans_resv.h"
14 #include "xfs_mount.h"
15 #include "xfs_defer.h"
16 #include "xfs_da_format.h"
17 #include "xfs_da_btree.h"
18 #include "xfs_btree.h"
19 #include "xfs_trans.h"
20 #include "xfs_alloc.h"
22 #include "xfs_rmap_btree.h"
23 #include "xfs_trans_space.h"
24 #include "xfs_trace.h"
25 #include "xfs_errortag.h"
27 #include "xfs_inode.h"
28 #include "xfs_ialloc.h"
31 * Lookup the first record less than or equal to [bno, len, owner, offset]
32 * in the btree given by cur.
36 struct xfs_btree_cur
*cur
,
44 cur
->bc_rec
.r
.rm_startblock
= bno
;
45 cur
->bc_rec
.r
.rm_blockcount
= len
;
46 cur
->bc_rec
.r
.rm_owner
= owner
;
47 cur
->bc_rec
.r
.rm_offset
= offset
;
48 cur
->bc_rec
.r
.rm_flags
= flags
;
49 return xfs_btree_lookup(cur
, XFS_LOOKUP_LE
, stat
);
53 * Lookup the record exactly matching [bno, len, owner, offset]
54 * in the btree given by cur.
58 struct xfs_btree_cur
*cur
,
66 cur
->bc_rec
.r
.rm_startblock
= bno
;
67 cur
->bc_rec
.r
.rm_blockcount
= len
;
68 cur
->bc_rec
.r
.rm_owner
= owner
;
69 cur
->bc_rec
.r
.rm_offset
= offset
;
70 cur
->bc_rec
.r
.rm_flags
= flags
;
71 return xfs_btree_lookup(cur
, XFS_LOOKUP_EQ
, stat
);
75 * Update the record referred to by cur to the value given
76 * by [bno, len, owner, offset].
77 * This either works (return 0) or gets an EFSCORRUPTED error.
81 struct xfs_btree_cur
*cur
,
82 struct xfs_rmap_irec
*irec
)
84 union xfs_btree_rec rec
;
87 trace_xfs_rmap_update(cur
->bc_mp
, cur
->bc_private
.a
.agno
,
88 irec
->rm_startblock
, irec
->rm_blockcount
,
89 irec
->rm_owner
, irec
->rm_offset
, irec
->rm_flags
);
91 rec
.rmap
.rm_startblock
= cpu_to_be32(irec
->rm_startblock
);
92 rec
.rmap
.rm_blockcount
= cpu_to_be32(irec
->rm_blockcount
);
93 rec
.rmap
.rm_owner
= cpu_to_be64(irec
->rm_owner
);
94 rec
.rmap
.rm_offset
= cpu_to_be64(
95 xfs_rmap_irec_offset_pack(irec
));
96 error
= xfs_btree_update(cur
, &rec
);
98 trace_xfs_rmap_update_error(cur
->bc_mp
,
99 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
105 struct xfs_btree_cur
*rcur
,
115 trace_xfs_rmap_insert(rcur
->bc_mp
, rcur
->bc_private
.a
.agno
, agbno
,
116 len
, owner
, offset
, flags
);
118 error
= xfs_rmap_lookup_eq(rcur
, agbno
, len
, owner
, offset
, flags
, &i
);
121 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 0, done
);
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
);
131 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 1, done
);
134 trace_xfs_rmap_insert_error(rcur
->bc_mp
,
135 rcur
->bc_private
.a
.agno
, error
, _RET_IP_
);
141 struct xfs_btree_cur
*rcur
,
151 trace_xfs_rmap_delete(rcur
->bc_mp
, rcur
->bc_private
.a
.agno
, agbno
,
152 len
, owner
, offset
, flags
);
154 error
= xfs_rmap_lookup_eq(rcur
, agbno
, len
, owner
, offset
, flags
, &i
);
157 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 1, done
);
159 error
= xfs_btree_delete(rcur
, &i
);
162 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 1, done
);
165 trace_xfs_rmap_delete_error(rcur
->bc_mp
,
166 rcur
->bc_private
.a
.agno
, error
, _RET_IP_
);
170 /* Convert an internal btree record to an rmap record. */
172 xfs_rmap_btrec_to_irec(
173 union xfs_btree_rec
*rec
,
174 struct xfs_rmap_irec
*irec
)
177 irec
->rm_startblock
= be32_to_cpu(rec
->rmap
.rm_startblock
);
178 irec
->rm_blockcount
= be32_to_cpu(rec
->rmap
.rm_blockcount
);
179 irec
->rm_owner
= be64_to_cpu(rec
->rmap
.rm_owner
);
180 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec
->rmap
.rm_offset
),
185 * Get the data from the pointed-to record.
189 struct xfs_btree_cur
*cur
,
190 struct xfs_rmap_irec
*irec
,
193 struct xfs_mount
*mp
= cur
->bc_mp
;
194 xfs_agnumber_t agno
= cur
->bc_private
.a
.agno
;
195 union xfs_btree_rec
*rec
;
198 error
= xfs_btree_get_rec(cur
, &rec
, stat
);
202 if (xfs_rmap_btrec_to_irec(rec
, irec
))
205 if (irec
->rm_blockcount
== 0)
207 if (irec
->rm_startblock
<= XFS_AGFL_BLOCK(mp
)) {
208 if (irec
->rm_owner
!= XFS_RMAP_OWN_FS
)
210 if (irec
->rm_blockcount
!= XFS_AGFL_BLOCK(mp
) + 1)
213 /* check for valid extent range, including overflow */
214 if (!xfs_verify_agbno(mp
, agno
, irec
->rm_startblock
))
216 if (irec
->rm_startblock
>
217 irec
->rm_startblock
+ irec
->rm_blockcount
)
219 if (!xfs_verify_agbno(mp
, agno
,
220 irec
->rm_startblock
+ irec
->rm_blockcount
- 1))
224 if (!(xfs_verify_ino(mp
, irec
->rm_owner
) ||
225 (irec
->rm_owner
<= XFS_RMAP_OWN_FS
&&
226 irec
->rm_owner
>= XFS_RMAP_OWN_MIN
)))
232 "Reverse Mapping BTree record corruption in AG %d detected!",
235 "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
236 irec
->rm_owner
, irec
->rm_flags
, irec
->rm_startblock
,
237 irec
->rm_blockcount
);
238 return -EFSCORRUPTED
;
241 struct xfs_find_left_neighbor_info
{
242 struct xfs_rmap_irec high
;
243 struct xfs_rmap_irec
*irec
;
247 /* For each rmap given, figure out if it matches the key we want. */
249 xfs_rmap_find_left_neighbor_helper(
250 struct xfs_btree_cur
*cur
,
251 struct xfs_rmap_irec
*rec
,
254 struct xfs_find_left_neighbor_info
*info
= priv
;
256 trace_xfs_rmap_find_left_neighbor_candidate(cur
->bc_mp
,
257 cur
->bc_private
.a
.agno
, rec
->rm_startblock
,
258 rec
->rm_blockcount
, rec
->rm_owner
, rec
->rm_offset
,
261 if (rec
->rm_owner
!= info
->high
.rm_owner
)
262 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
263 if (!XFS_RMAP_NON_INODE_OWNER(rec
->rm_owner
) &&
264 !(rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
) &&
265 rec
->rm_offset
+ rec
->rm_blockcount
- 1 != info
->high
.rm_offset
)
266 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
270 return XFS_BTREE_QUERY_RANGE_ABORT
;
274 * Find the record to the left of the given extent, being careful only to
275 * return a match with the same owner and adjacent physical and logical
279 xfs_rmap_find_left_neighbor(
280 struct xfs_btree_cur
*cur
,
285 struct xfs_rmap_irec
*irec
,
288 struct xfs_find_left_neighbor_info info
;
294 info
.high
.rm_startblock
= bno
- 1;
295 info
.high
.rm_owner
= owner
;
296 if (!XFS_RMAP_NON_INODE_OWNER(owner
) &&
297 !(flags
& XFS_RMAP_BMBT_BLOCK
)) {
300 info
.high
.rm_offset
= offset
- 1;
302 info
.high
.rm_offset
= 0;
303 info
.high
.rm_flags
= flags
;
304 info
.high
.rm_blockcount
= 0;
308 trace_xfs_rmap_find_left_neighbor_query(cur
->bc_mp
,
309 cur
->bc_private
.a
.agno
, bno
, 0, owner
, offset
, flags
);
311 error
= xfs_rmap_query_range(cur
, &info
.high
, &info
.high
,
312 xfs_rmap_find_left_neighbor_helper
, &info
);
313 if (error
== XFS_BTREE_QUERY_RANGE_ABORT
)
316 trace_xfs_rmap_find_left_neighbor_result(cur
->bc_mp
,
317 cur
->bc_private
.a
.agno
, irec
->rm_startblock
,
318 irec
->rm_blockcount
, irec
->rm_owner
,
319 irec
->rm_offset
, irec
->rm_flags
);
323 /* For each rmap given, figure out if it matches the key we want. */
325 xfs_rmap_lookup_le_range_helper(
326 struct xfs_btree_cur
*cur
,
327 struct xfs_rmap_irec
*rec
,
330 struct xfs_find_left_neighbor_info
*info
= priv
;
332 trace_xfs_rmap_lookup_le_range_candidate(cur
->bc_mp
,
333 cur
->bc_private
.a
.agno
, rec
->rm_startblock
,
334 rec
->rm_blockcount
, rec
->rm_owner
, rec
->rm_offset
,
337 if (rec
->rm_owner
!= info
->high
.rm_owner
)
338 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
339 if (!XFS_RMAP_NON_INODE_OWNER(rec
->rm_owner
) &&
340 !(rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
) &&
341 (rec
->rm_offset
> info
->high
.rm_offset
||
342 rec
->rm_offset
+ rec
->rm_blockcount
<= info
->high
.rm_offset
))
343 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
347 return XFS_BTREE_QUERY_RANGE_ABORT
;
351 * Find the record to the left of the given extent, being careful only to
352 * return a match with the same owner and overlapping physical and logical
353 * block ranges. This is the overlapping-interval version of
354 * xfs_rmap_lookup_le.
357 xfs_rmap_lookup_le_range(
358 struct xfs_btree_cur
*cur
,
363 struct xfs_rmap_irec
*irec
,
366 struct xfs_find_left_neighbor_info info
;
369 info
.high
.rm_startblock
= bno
;
370 info
.high
.rm_owner
= owner
;
371 if (!XFS_RMAP_NON_INODE_OWNER(owner
) && !(flags
& XFS_RMAP_BMBT_BLOCK
))
372 info
.high
.rm_offset
= offset
;
374 info
.high
.rm_offset
= 0;
375 info
.high
.rm_flags
= flags
;
376 info
.high
.rm_blockcount
= 0;
381 trace_xfs_rmap_lookup_le_range(cur
->bc_mp
,
382 cur
->bc_private
.a
.agno
, bno
, 0, owner
, offset
, flags
);
383 error
= xfs_rmap_query_range(cur
, &info
.high
, &info
.high
,
384 xfs_rmap_lookup_le_range_helper
, &info
);
385 if (error
== XFS_BTREE_QUERY_RANGE_ABORT
)
388 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
389 cur
->bc_private
.a
.agno
, irec
->rm_startblock
,
390 irec
->rm_blockcount
, irec
->rm_owner
,
391 irec
->rm_offset
, irec
->rm_flags
);
396 * Perform all the relevant owner checks for a removal op. If we're doing an
397 * unknown-owner removal then we have no owner information to check.
400 xfs_rmap_free_check_owner(
401 struct xfs_mount
*mp
,
403 struct xfs_rmap_irec
*rec
,
411 if (owner
== XFS_RMAP_OWN_UNKNOWN
)
414 /* Make sure the unwritten flag matches. */
415 XFS_WANT_CORRUPTED_GOTO(mp
, (flags
& XFS_RMAP_UNWRITTEN
) ==
416 (rec
->rm_flags
& XFS_RMAP_UNWRITTEN
), out
);
418 /* Make sure the owner matches what we expect to find in the tree. */
419 XFS_WANT_CORRUPTED_GOTO(mp
, owner
== rec
->rm_owner
, out
);
421 /* Check the offset, if necessary. */
422 if (XFS_RMAP_NON_INODE_OWNER(owner
))
425 if (flags
& XFS_RMAP_BMBT_BLOCK
) {
426 XFS_WANT_CORRUPTED_GOTO(mp
, rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
,
429 XFS_WANT_CORRUPTED_GOTO(mp
, rec
->rm_offset
<= offset
, out
);
430 XFS_WANT_CORRUPTED_GOTO(mp
,
431 ltoff
+ rec
->rm_blockcount
>= offset
+ len
,
440 * Find the extent in the rmap btree and remove it.
442 * The record we find should always be an exact match for the extent that we're
443 * looking for, since we insert them into the btree without modification.
445 * Special Case #1: when growing the filesystem, we "free" an extent when
446 * growing the last AG. This extent is new space and so it is not tracked as
447 * used space in the btree. The growfs code will pass in an owner of
448 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
449 * extent. We verify that - the extent lookup result in a record that does not
452 * Special Case #2: EFIs do not record the owner of the extent, so when
453 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
454 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
455 * corruption checks during log recovery.
459 struct xfs_btree_cur
*cur
,
463 struct xfs_owner_info
*oinfo
)
465 struct xfs_mount
*mp
= cur
->bc_mp
;
466 struct xfs_rmap_irec ltrec
;
475 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
476 ignore_off
= XFS_RMAP_NON_INODE_OWNER(owner
) ||
477 (flags
& XFS_RMAP_BMBT_BLOCK
);
479 flags
|= XFS_RMAP_UNWRITTEN
;
480 trace_xfs_rmap_unmap(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
484 * We should always have a left record because there's a static record
485 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
486 * will not ever be removed from the tree.
488 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
, &i
);
491 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
493 error
= xfs_rmap_get_rec(cur
, <rec
, &i
);
496 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
497 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
498 cur
->bc_private
.a
.agno
, ltrec
.rm_startblock
,
499 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
500 ltrec
.rm_offset
, ltrec
.rm_flags
);
501 ltoff
= ltrec
.rm_offset
;
504 * For growfs, the incoming extent must be beyond the left record we
505 * just found as it is new space and won't be used by anyone. This is
506 * just a corruption check as we don't actually do anything with this
507 * extent. Note that we need to use >= instead of > because it might
508 * be the case that the "left" extent goes all the way to EOFS.
510 if (owner
== XFS_RMAP_OWN_NULL
) {
511 XFS_WANT_CORRUPTED_GOTO(mp
, bno
>= ltrec
.rm_startblock
+
512 ltrec
.rm_blockcount
, out_error
);
517 * If we're doing an unknown-owner removal for EFI recovery, we expect
518 * to find the full range in the rmapbt or nothing at all. If we
519 * don't find any rmaps overlapping either end of the range, we're
520 * done. Hopefully this means that the EFI creator already queued
521 * (and finished) a RUI to remove the rmap.
523 if (owner
== XFS_RMAP_OWN_UNKNOWN
&&
524 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
<= bno
) {
525 struct xfs_rmap_irec rtrec
;
527 error
= xfs_btree_increment(cur
, 0, &i
);
532 error
= xfs_rmap_get_rec(cur
, &rtrec
, &i
);
535 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
536 if (rtrec
.rm_startblock
>= bno
+ len
)
540 /* Make sure the extent we found covers the entire freeing range. */
541 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_startblock
<= bno
&&
542 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
>=
543 bno
+ len
, out_error
);
545 /* Check owner information. */
546 error
= xfs_rmap_free_check_owner(mp
, ltoff
, <rec
, len
, owner
,
551 if (ltrec
.rm_startblock
== bno
&& ltrec
.rm_blockcount
== len
) {
552 /* exact match, simply remove the record from rmap tree */
553 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
554 ltrec
.rm_startblock
, ltrec
.rm_blockcount
,
555 ltrec
.rm_owner
, ltrec
.rm_offset
,
557 error
= xfs_btree_delete(cur
, &i
);
560 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
561 } else if (ltrec
.rm_startblock
== bno
) {
563 * overlap left hand side of extent: move the start, trim the
564 * length and update the current record.
567 * Orig: |oooooooooooooooooooo|
568 * Freeing: |fffffffff|
569 * Result: |rrrrrrrrrr|
572 ltrec
.rm_startblock
+= len
;
573 ltrec
.rm_blockcount
-= len
;
575 ltrec
.rm_offset
+= len
;
576 error
= xfs_rmap_update(cur
, <rec
);
579 } else if (ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
+ len
) {
581 * overlap right hand side of extent: trim the length and update
582 * the current record.
585 * Orig: |oooooooooooooooooooo|
586 * Freeing: |fffffffff|
587 * Result: |rrrrrrrrrr|
590 ltrec
.rm_blockcount
-= len
;
591 error
= xfs_rmap_update(cur
, <rec
);
597 * overlap middle of extent: trim the length of the existing
598 * record to the length of the new left-extent size, increment
599 * the insertion position so we can insert a new record
600 * containing the remaining right-extent space.
603 * Orig: |oooooooooooooooooooo|
604 * Freeing: |fffffffff|
605 * Result: |rrrrr| |rrrr|
608 xfs_extlen_t orig_len
= ltrec
.rm_blockcount
;
610 ltrec
.rm_blockcount
= bno
- ltrec
.rm_startblock
;
611 error
= xfs_rmap_update(cur
, <rec
);
615 error
= xfs_btree_increment(cur
, 0, &i
);
619 cur
->bc_rec
.r
.rm_startblock
= bno
+ len
;
620 cur
->bc_rec
.r
.rm_blockcount
= orig_len
- len
-
622 cur
->bc_rec
.r
.rm_owner
= ltrec
.rm_owner
;
624 cur
->bc_rec
.r
.rm_offset
= 0;
626 cur
->bc_rec
.r
.rm_offset
= offset
+ len
;
627 cur
->bc_rec
.r
.rm_flags
= flags
;
628 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
,
629 cur
->bc_rec
.r
.rm_startblock
,
630 cur
->bc_rec
.r
.rm_blockcount
,
631 cur
->bc_rec
.r
.rm_owner
,
632 cur
->bc_rec
.r
.rm_offset
,
633 cur
->bc_rec
.r
.rm_flags
);
634 error
= xfs_btree_insert(cur
, &i
);
640 trace_xfs_rmap_unmap_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
644 trace_xfs_rmap_unmap_error(mp
, cur
->bc_private
.a
.agno
,
650 * Remove a reference to an extent in the rmap btree.
654 struct xfs_trans
*tp
,
655 struct xfs_buf
*agbp
,
659 struct xfs_owner_info
*oinfo
)
661 struct xfs_mount
*mp
= tp
->t_mountp
;
662 struct xfs_btree_cur
*cur
;
665 if (!xfs_sb_version_hasrmapbt(&mp
->m_sb
))
668 cur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
670 error
= xfs_rmap_unmap(cur
, bno
, len
, false, oinfo
);
674 xfs_btree_del_cursor(cur
, XFS_BTREE_NOERROR
);
678 xfs_btree_del_cursor(cur
, XFS_BTREE_ERROR
);
683 * A mergeable rmap must have the same owner and the same values for
684 * the unwritten, attr_fork, and bmbt flags. The startblock and
685 * offset are checked separately.
688 xfs_rmap_is_mergeable(
689 struct xfs_rmap_irec
*irec
,
693 if (irec
->rm_owner
== XFS_RMAP_OWN_NULL
)
695 if (irec
->rm_owner
!= owner
)
697 if ((flags
& XFS_RMAP_UNWRITTEN
) ^
698 (irec
->rm_flags
& XFS_RMAP_UNWRITTEN
))
700 if ((flags
& XFS_RMAP_ATTR_FORK
) ^
701 (irec
->rm_flags
& XFS_RMAP_ATTR_FORK
))
703 if ((flags
& XFS_RMAP_BMBT_BLOCK
) ^
704 (irec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
))
710 * When we allocate a new block, the first thing we do is add a reference to
711 * the extent in the rmap btree. This takes the form of a [agbno, length,
712 * owner, offset] record. Flags are encoded in the high bits of the offset
717 struct xfs_btree_cur
*cur
,
721 struct xfs_owner_info
*oinfo
)
723 struct xfs_mount
*mp
= cur
->bc_mp
;
724 struct xfs_rmap_irec ltrec
;
725 struct xfs_rmap_irec gtrec
;
732 unsigned int flags
= 0;
735 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
737 ignore_off
= XFS_RMAP_NON_INODE_OWNER(owner
) ||
738 (flags
& XFS_RMAP_BMBT_BLOCK
);
740 flags
|= XFS_RMAP_UNWRITTEN
;
741 trace_xfs_rmap_map(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
743 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo
));
746 * For the initial lookup, look for an exact match or the left-adjacent
747 * record for our insertion point. This will also give us the record for
748 * start block contiguity tests.
750 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
,
754 XFS_WANT_CORRUPTED_GOTO(mp
, have_lt
== 1, out_error
);
756 error
= xfs_rmap_get_rec(cur
, <rec
, &have_lt
);
759 XFS_WANT_CORRUPTED_GOTO(mp
, have_lt
== 1, out_error
);
760 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
761 cur
->bc_private
.a
.agno
, ltrec
.rm_startblock
,
762 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
763 ltrec
.rm_offset
, ltrec
.rm_flags
);
765 if (!xfs_rmap_is_mergeable(<rec
, owner
, flags
))
768 XFS_WANT_CORRUPTED_GOTO(mp
,
770 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
<= bno
, out_error
);
773 * Increment the cursor to see if we have a right-adjacent record to our
774 * insertion point. This will give us the record for end block
777 error
= xfs_btree_increment(cur
, 0, &have_gt
);
781 error
= xfs_rmap_get_rec(cur
, >rec
, &have_gt
);
784 XFS_WANT_CORRUPTED_GOTO(mp
, have_gt
== 1, out_error
);
785 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= gtrec
.rm_startblock
,
787 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
788 cur
->bc_private
.a
.agno
, gtrec
.rm_startblock
,
789 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
790 gtrec
.rm_offset
, gtrec
.rm_flags
);
791 if (!xfs_rmap_is_mergeable(>rec
, owner
, flags
))
796 * Note: cursor currently points one record to the right of ltrec, even
797 * if there is no record in the tree to the right.
800 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
&&
801 (ignore_off
|| ltrec
.rm_offset
+ ltrec
.rm_blockcount
== offset
)) {
803 * left edge contiguous, merge into left record.
807 * adding: |aaaaaaaaa|
808 * result: |rrrrrrrrrrrrrrrrrrr|
811 ltrec
.rm_blockcount
+= len
;
813 bno
+ len
== gtrec
.rm_startblock
&&
814 (ignore_off
|| offset
+ len
== gtrec
.rm_offset
) &&
815 (unsigned long)ltrec
.rm_blockcount
+ len
+
816 gtrec
.rm_blockcount
<= XFS_RMAP_LEN_MAX
) {
818 * right edge also contiguous, delete right record
819 * and merge into left record.
821 * ltbno ltlen gtbno gtlen
822 * orig: |ooooooooo| |ooooooooo|
823 * adding: |aaaaaaaaa|
824 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
826 ltrec
.rm_blockcount
+= gtrec
.rm_blockcount
;
827 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
833 error
= xfs_btree_delete(cur
, &i
);
836 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
839 /* point the cursor back to the left record and update */
840 error
= xfs_btree_decrement(cur
, 0, &have_gt
);
843 error
= xfs_rmap_update(cur
, <rec
);
846 } else if (have_gt
&&
847 bno
+ len
== gtrec
.rm_startblock
&&
848 (ignore_off
|| offset
+ len
== gtrec
.rm_offset
)) {
850 * right edge contiguous, merge into right record.
854 * adding: |aaaaaaaaa|
855 * Result: |rrrrrrrrrrrrrrrrrrr|
858 gtrec
.rm_startblock
= bno
;
859 gtrec
.rm_blockcount
+= len
;
861 gtrec
.rm_offset
= offset
;
862 error
= xfs_rmap_update(cur
, >rec
);
867 * no contiguous edge with identical owner, insert
868 * new record at current cursor position.
870 cur
->bc_rec
.r
.rm_startblock
= bno
;
871 cur
->bc_rec
.r
.rm_blockcount
= len
;
872 cur
->bc_rec
.r
.rm_owner
= owner
;
873 cur
->bc_rec
.r
.rm_offset
= offset
;
874 cur
->bc_rec
.r
.rm_flags
= flags
;
875 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
876 owner
, offset
, flags
);
877 error
= xfs_btree_insert(cur
, &i
);
880 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
883 trace_xfs_rmap_map_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
887 trace_xfs_rmap_map_error(mp
, cur
->bc_private
.a
.agno
,
893 * Add a reference to an extent in the rmap btree.
897 struct xfs_trans
*tp
,
898 struct xfs_buf
*agbp
,
902 struct xfs_owner_info
*oinfo
)
904 struct xfs_mount
*mp
= tp
->t_mountp
;
905 struct xfs_btree_cur
*cur
;
908 if (!xfs_sb_version_hasrmapbt(&mp
->m_sb
))
911 cur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
912 error
= xfs_rmap_map(cur
, bno
, len
, false, oinfo
);
916 xfs_btree_del_cursor(cur
, XFS_BTREE_NOERROR
);
920 xfs_btree_del_cursor(cur
, XFS_BTREE_ERROR
);
924 #define RMAP_LEFT_CONTIG (1 << 0)
925 #define RMAP_RIGHT_CONTIG (1 << 1)
926 #define RMAP_LEFT_FILLING (1 << 2)
927 #define RMAP_RIGHT_FILLING (1 << 3)
928 #define RMAP_LEFT_VALID (1 << 6)
929 #define RMAP_RIGHT_VALID (1 << 7)
937 * Convert an unwritten extent to a real extent or vice versa.
938 * Does not handle overlapping extents.
942 struct xfs_btree_cur
*cur
,
946 struct xfs_owner_info
*oinfo
)
948 struct xfs_mount
*mp
= cur
->bc_mp
;
949 struct xfs_rmap_irec r
[4]; /* neighbor extent entries */
950 /* left is 0, right is 1, prev is 2 */
957 unsigned int flags
= 0;
962 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
963 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner
) ||
964 (flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
))));
965 oldext
= unwritten
? XFS_RMAP_UNWRITTEN
: 0;
966 new_endoff
= offset
+ len
;
967 trace_xfs_rmap_convert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
971 * For the initial lookup, look for an exact match or the left-adjacent
972 * record for our insertion point. This will also give us the record for
973 * start block contiguity tests.
975 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, oldext
, &i
);
978 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
980 error
= xfs_rmap_get_rec(cur
, &PREV
, &i
);
983 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
984 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
985 cur
->bc_private
.a
.agno
, PREV
.rm_startblock
,
986 PREV
.rm_blockcount
, PREV
.rm_owner
,
987 PREV
.rm_offset
, PREV
.rm_flags
);
989 ASSERT(PREV
.rm_offset
<= offset
);
990 ASSERT(PREV
.rm_offset
+ PREV
.rm_blockcount
>= new_endoff
);
991 ASSERT((PREV
.rm_flags
& XFS_RMAP_UNWRITTEN
) == oldext
);
992 newext
= ~oldext
& XFS_RMAP_UNWRITTEN
;
995 * Set flags determining what part of the previous oldext allocation
996 * extent is being replaced by a newext allocation.
998 if (PREV
.rm_offset
== offset
)
999 state
|= RMAP_LEFT_FILLING
;
1000 if (PREV
.rm_offset
+ PREV
.rm_blockcount
== new_endoff
)
1001 state
|= RMAP_RIGHT_FILLING
;
1004 * Decrement the cursor to see if we have a left-adjacent record to our
1005 * insertion point. This will give us the record for end block
1008 error
= xfs_btree_decrement(cur
, 0, &i
);
1012 state
|= RMAP_LEFT_VALID
;
1013 error
= xfs_rmap_get_rec(cur
, &LEFT
, &i
);
1016 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1017 XFS_WANT_CORRUPTED_GOTO(mp
,
1018 LEFT
.rm_startblock
+ LEFT
.rm_blockcount
<= bno
,
1020 trace_xfs_rmap_find_left_neighbor_result(cur
->bc_mp
,
1021 cur
->bc_private
.a
.agno
, LEFT
.rm_startblock
,
1022 LEFT
.rm_blockcount
, LEFT
.rm_owner
,
1023 LEFT
.rm_offset
, LEFT
.rm_flags
);
1024 if (LEFT
.rm_startblock
+ LEFT
.rm_blockcount
== bno
&&
1025 LEFT
.rm_offset
+ LEFT
.rm_blockcount
== offset
&&
1026 xfs_rmap_is_mergeable(&LEFT
, owner
, newext
))
1027 state
|= RMAP_LEFT_CONTIG
;
1031 * Increment the cursor to see if we have a right-adjacent record to our
1032 * insertion point. This will give us the record for end block
1035 error
= xfs_btree_increment(cur
, 0, &i
);
1038 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1039 error
= xfs_btree_increment(cur
, 0, &i
);
1043 state
|= RMAP_RIGHT_VALID
;
1044 error
= xfs_rmap_get_rec(cur
, &RIGHT
, &i
);
1047 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1048 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= RIGHT
.rm_startblock
,
1050 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1051 cur
->bc_private
.a
.agno
, RIGHT
.rm_startblock
,
1052 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1053 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1054 if (bno
+ len
== RIGHT
.rm_startblock
&&
1055 offset
+ len
== RIGHT
.rm_offset
&&
1056 xfs_rmap_is_mergeable(&RIGHT
, owner
, newext
))
1057 state
|= RMAP_RIGHT_CONTIG
;
1060 /* check that left + prev + right is not too long */
1061 if ((state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1062 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) ==
1063 (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1064 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
) &&
1065 (unsigned long)LEFT
.rm_blockcount
+ len
+
1066 RIGHT
.rm_blockcount
> XFS_RMAP_LEN_MAX
)
1067 state
&= ~RMAP_RIGHT_CONTIG
;
1069 trace_xfs_rmap_convert_state(mp
, cur
->bc_private
.a
.agno
, state
,
1072 /* reset the cursor back to PREV */
1073 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, oldext
, &i
);
1076 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1079 * Switch out based on the FILLING and CONTIG state bits.
1081 switch (state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1082 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) {
1083 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1084 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1086 * Setting all of a previous oldext extent to newext.
1087 * The left and right neighbors are both contiguous with new.
1089 error
= xfs_btree_increment(cur
, 0, &i
);
1092 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1093 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1094 RIGHT
.rm_startblock
, RIGHT
.rm_blockcount
,
1095 RIGHT
.rm_owner
, RIGHT
.rm_offset
,
1097 error
= xfs_btree_delete(cur
, &i
);
1100 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1101 error
= xfs_btree_decrement(cur
, 0, &i
);
1104 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1105 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1106 PREV
.rm_startblock
, PREV
.rm_blockcount
,
1107 PREV
.rm_owner
, PREV
.rm_offset
,
1109 error
= xfs_btree_delete(cur
, &i
);
1112 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1113 error
= xfs_btree_decrement(cur
, 0, &i
);
1116 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1118 NEW
.rm_blockcount
+= PREV
.rm_blockcount
+ RIGHT
.rm_blockcount
;
1119 error
= xfs_rmap_update(cur
, &NEW
);
1124 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1126 * Setting all of a previous oldext extent to newext.
1127 * The left neighbor is contiguous, the right is not.
1129 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1130 PREV
.rm_startblock
, PREV
.rm_blockcount
,
1131 PREV
.rm_owner
, PREV
.rm_offset
,
1133 error
= xfs_btree_delete(cur
, &i
);
1136 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1137 error
= xfs_btree_decrement(cur
, 0, &i
);
1140 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1142 NEW
.rm_blockcount
+= PREV
.rm_blockcount
;
1143 error
= xfs_rmap_update(cur
, &NEW
);
1148 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1150 * Setting all of a previous oldext extent to newext.
1151 * The right neighbor is contiguous, the left is not.
1153 error
= xfs_btree_increment(cur
, 0, &i
);
1156 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1157 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1158 RIGHT
.rm_startblock
, RIGHT
.rm_blockcount
,
1159 RIGHT
.rm_owner
, RIGHT
.rm_offset
,
1161 error
= xfs_btree_delete(cur
, &i
);
1164 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1165 error
= xfs_btree_decrement(cur
, 0, &i
);
1168 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1170 NEW
.rm_blockcount
= len
+ RIGHT
.rm_blockcount
;
1171 NEW
.rm_flags
= newext
;
1172 error
= xfs_rmap_update(cur
, &NEW
);
1177 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
:
1179 * Setting all of a previous oldext extent to newext.
1180 * Neither the left nor right neighbors are contiguous with
1184 NEW
.rm_flags
= newext
;
1185 error
= xfs_rmap_update(cur
, &NEW
);
1190 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
:
1192 * Setting the first part of a previous oldext extent to newext.
1193 * The left neighbor is contiguous.
1196 NEW
.rm_offset
+= len
;
1197 NEW
.rm_startblock
+= len
;
1198 NEW
.rm_blockcount
-= len
;
1199 error
= xfs_rmap_update(cur
, &NEW
);
1202 error
= xfs_btree_decrement(cur
, 0, &i
);
1206 NEW
.rm_blockcount
+= len
;
1207 error
= xfs_rmap_update(cur
, &NEW
);
1212 case RMAP_LEFT_FILLING
:
1214 * Setting the first part of a previous oldext extent to newext.
1215 * The left neighbor is not contiguous.
1218 NEW
.rm_startblock
+= len
;
1219 NEW
.rm_offset
+= len
;
1220 NEW
.rm_blockcount
-= len
;
1221 error
= xfs_rmap_update(cur
, &NEW
);
1224 NEW
.rm_startblock
= bno
;
1225 NEW
.rm_owner
= owner
;
1226 NEW
.rm_offset
= offset
;
1227 NEW
.rm_blockcount
= len
;
1228 NEW
.rm_flags
= newext
;
1229 cur
->bc_rec
.r
= NEW
;
1230 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
,
1231 len
, owner
, offset
, newext
);
1232 error
= xfs_btree_insert(cur
, &i
);
1235 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1238 case RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1240 * Setting the last part of a previous oldext extent to newext.
1241 * The right neighbor is contiguous with the new allocation.
1244 NEW
.rm_blockcount
-= len
;
1245 error
= xfs_rmap_update(cur
, &NEW
);
1248 error
= xfs_btree_increment(cur
, 0, &i
);
1252 NEW
.rm_offset
= offset
;
1253 NEW
.rm_startblock
= bno
;
1254 NEW
.rm_blockcount
+= len
;
1255 error
= xfs_rmap_update(cur
, &NEW
);
1260 case RMAP_RIGHT_FILLING
:
1262 * Setting the last part of a previous oldext extent to newext.
1263 * The right neighbor is not contiguous.
1266 NEW
.rm_blockcount
-= len
;
1267 error
= xfs_rmap_update(cur
, &NEW
);
1270 error
= xfs_rmap_lookup_eq(cur
, bno
, len
, owner
, offset
,
1274 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 0, done
);
1275 NEW
.rm_startblock
= bno
;
1276 NEW
.rm_owner
= owner
;
1277 NEW
.rm_offset
= offset
;
1278 NEW
.rm_blockcount
= len
;
1279 NEW
.rm_flags
= newext
;
1280 cur
->bc_rec
.r
= NEW
;
1281 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
,
1282 len
, owner
, offset
, newext
);
1283 error
= xfs_btree_insert(cur
, &i
);
1286 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1291 * Setting the middle part of a previous oldext extent to
1292 * newext. Contiguity is impossible here.
1293 * One extent becomes three extents.
1295 /* new right extent - oldext */
1296 NEW
.rm_startblock
= bno
+ len
;
1297 NEW
.rm_owner
= owner
;
1298 NEW
.rm_offset
= new_endoff
;
1299 NEW
.rm_blockcount
= PREV
.rm_offset
+ PREV
.rm_blockcount
-
1301 NEW
.rm_flags
= PREV
.rm_flags
;
1302 error
= xfs_rmap_update(cur
, &NEW
);
1305 /* new left extent - oldext */
1307 NEW
.rm_blockcount
= offset
- PREV
.rm_offset
;
1308 cur
->bc_rec
.r
= NEW
;
1309 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
,
1310 NEW
.rm_startblock
, NEW
.rm_blockcount
,
1311 NEW
.rm_owner
, NEW
.rm_offset
,
1313 error
= xfs_btree_insert(cur
, &i
);
1316 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1318 * Reset the cursor to the position of the new extent
1319 * we are about to insert as we can't trust it after
1320 * the previous insert.
1322 error
= xfs_rmap_lookup_eq(cur
, bno
, len
, owner
, offset
,
1326 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 0, done
);
1327 /* new middle extent - newext */
1328 cur
->bc_rec
.r
.rm_flags
&= ~XFS_RMAP_UNWRITTEN
;
1329 cur
->bc_rec
.r
.rm_flags
|= newext
;
1330 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1331 owner
, offset
, newext
);
1332 error
= xfs_btree_insert(cur
, &i
);
1335 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1338 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1339 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1340 case RMAP_LEFT_FILLING
| RMAP_RIGHT_CONTIG
:
1341 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1342 case RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1343 case RMAP_LEFT_CONTIG
:
1344 case RMAP_RIGHT_CONTIG
:
1346 * These cases are all impossible.
1351 trace_xfs_rmap_convert_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1355 trace_xfs_rmap_convert_error(cur
->bc_mp
,
1356 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1361 * Convert an unwritten extent to a real extent or vice versa. If there is no
1362 * possibility of overlapping extents, delegate to the simpler convert
1366 xfs_rmap_convert_shared(
1367 struct xfs_btree_cur
*cur
,
1371 struct xfs_owner_info
*oinfo
)
1373 struct xfs_mount
*mp
= cur
->bc_mp
;
1374 struct xfs_rmap_irec r
[4]; /* neighbor extent entries */
1375 /* left is 0, right is 1, prev is 2 */
1379 uint64_t new_endoff
;
1380 unsigned int oldext
;
1381 unsigned int newext
;
1382 unsigned int flags
= 0;
1387 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1388 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner
) ||
1389 (flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
))));
1390 oldext
= unwritten
? XFS_RMAP_UNWRITTEN
: 0;
1391 new_endoff
= offset
+ len
;
1392 trace_xfs_rmap_convert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1396 * For the initial lookup, look for and exact match or the left-adjacent
1397 * record for our insertion point. This will also give us the record for
1398 * start block contiguity tests.
1400 error
= xfs_rmap_lookup_le_range(cur
, bno
, owner
, offset
, flags
,
1404 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1406 ASSERT(PREV
.rm_offset
<= offset
);
1407 ASSERT(PREV
.rm_offset
+ PREV
.rm_blockcount
>= new_endoff
);
1408 ASSERT((PREV
.rm_flags
& XFS_RMAP_UNWRITTEN
) == oldext
);
1409 newext
= ~oldext
& XFS_RMAP_UNWRITTEN
;
1412 * Set flags determining what part of the previous oldext allocation
1413 * extent is being replaced by a newext allocation.
1415 if (PREV
.rm_offset
== offset
)
1416 state
|= RMAP_LEFT_FILLING
;
1417 if (PREV
.rm_offset
+ PREV
.rm_blockcount
== new_endoff
)
1418 state
|= RMAP_RIGHT_FILLING
;
1420 /* Is there a left record that abuts our range? */
1421 error
= xfs_rmap_find_left_neighbor(cur
, bno
, owner
, offset
, newext
,
1426 state
|= RMAP_LEFT_VALID
;
1427 XFS_WANT_CORRUPTED_GOTO(mp
,
1428 LEFT
.rm_startblock
+ LEFT
.rm_blockcount
<= bno
,
1430 if (xfs_rmap_is_mergeable(&LEFT
, owner
, newext
))
1431 state
|= RMAP_LEFT_CONTIG
;
1434 /* Is there a right record that abuts our range? */
1435 error
= xfs_rmap_lookup_eq(cur
, bno
+ len
, len
, owner
, offset
+ len
,
1440 state
|= RMAP_RIGHT_VALID
;
1441 error
= xfs_rmap_get_rec(cur
, &RIGHT
, &i
);
1444 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1445 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= RIGHT
.rm_startblock
,
1447 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1448 cur
->bc_private
.a
.agno
, RIGHT
.rm_startblock
,
1449 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1450 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1451 if (xfs_rmap_is_mergeable(&RIGHT
, owner
, newext
))
1452 state
|= RMAP_RIGHT_CONTIG
;
1455 /* check that left + prev + right is not too long */
1456 if ((state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1457 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) ==
1458 (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1459 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
) &&
1460 (unsigned long)LEFT
.rm_blockcount
+ len
+
1461 RIGHT
.rm_blockcount
> XFS_RMAP_LEN_MAX
)
1462 state
&= ~RMAP_RIGHT_CONTIG
;
1464 trace_xfs_rmap_convert_state(mp
, cur
->bc_private
.a
.agno
, state
,
1467 * Switch out based on the FILLING and CONTIG state bits.
1469 switch (state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1470 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) {
1471 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1472 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1474 * Setting all of a previous oldext extent to newext.
1475 * The left and right neighbors are both contiguous with new.
1477 error
= xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1478 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1479 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1482 error
= xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1483 PREV
.rm_blockcount
, PREV
.rm_owner
,
1484 PREV
.rm_offset
, PREV
.rm_flags
);
1488 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1489 NEW
.rm_blockcount
, NEW
.rm_owner
,
1490 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1493 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1494 NEW
.rm_blockcount
+= PREV
.rm_blockcount
+ RIGHT
.rm_blockcount
;
1495 error
= xfs_rmap_update(cur
, &NEW
);
1500 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1502 * Setting all of a previous oldext extent to newext.
1503 * The left neighbor is contiguous, the right is not.
1505 error
= xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1506 PREV
.rm_blockcount
, PREV
.rm_owner
,
1507 PREV
.rm_offset
, PREV
.rm_flags
);
1511 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1512 NEW
.rm_blockcount
, NEW
.rm_owner
,
1513 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1516 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1517 NEW
.rm_blockcount
+= PREV
.rm_blockcount
;
1518 error
= xfs_rmap_update(cur
, &NEW
);
1523 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1525 * Setting all of a previous oldext extent to newext.
1526 * The right neighbor is contiguous, the left is not.
1528 error
= xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1529 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1530 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1534 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1535 NEW
.rm_blockcount
, NEW
.rm_owner
,
1536 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1539 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1540 NEW
.rm_blockcount
+= RIGHT
.rm_blockcount
;
1541 NEW
.rm_flags
= RIGHT
.rm_flags
;
1542 error
= xfs_rmap_update(cur
, &NEW
);
1547 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
:
1549 * Setting all of a previous oldext extent to newext.
1550 * Neither the left nor right neighbors are contiguous with
1554 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1555 NEW
.rm_blockcount
, NEW
.rm_owner
,
1556 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1559 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1560 NEW
.rm_flags
= newext
;
1561 error
= xfs_rmap_update(cur
, &NEW
);
1566 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
:
1568 * Setting the first part of a previous oldext extent to newext.
1569 * The left neighbor is contiguous.
1572 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1573 NEW
.rm_blockcount
, NEW
.rm_owner
,
1574 NEW
.rm_offset
, NEW
.rm_flags
);
1577 NEW
.rm_offset
+= len
;
1578 NEW
.rm_startblock
+= len
;
1579 NEW
.rm_blockcount
-= len
;
1580 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1581 NEW
.rm_blockcount
, NEW
.rm_owner
,
1582 NEW
.rm_offset
, NEW
.rm_flags
);
1586 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1587 NEW
.rm_blockcount
, NEW
.rm_owner
,
1588 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1591 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1592 NEW
.rm_blockcount
+= len
;
1593 error
= xfs_rmap_update(cur
, &NEW
);
1598 case RMAP_LEFT_FILLING
:
1600 * Setting the first part of a previous oldext extent to newext.
1601 * The left neighbor is not contiguous.
1604 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1605 NEW
.rm_blockcount
, NEW
.rm_owner
,
1606 NEW
.rm_offset
, NEW
.rm_flags
);
1609 NEW
.rm_offset
+= len
;
1610 NEW
.rm_startblock
+= len
;
1611 NEW
.rm_blockcount
-= len
;
1612 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1613 NEW
.rm_blockcount
, NEW
.rm_owner
,
1614 NEW
.rm_offset
, NEW
.rm_flags
);
1617 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1622 case RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1624 * Setting the last part of a previous oldext extent to newext.
1625 * The right neighbor is contiguous with the new allocation.
1628 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1629 NEW
.rm_blockcount
, NEW
.rm_owner
,
1630 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1633 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1634 NEW
.rm_blockcount
= offset
- NEW
.rm_offset
;
1635 error
= xfs_rmap_update(cur
, &NEW
);
1639 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1640 NEW
.rm_blockcount
, NEW
.rm_owner
,
1641 NEW
.rm_offset
, NEW
.rm_flags
);
1644 NEW
.rm_offset
= offset
;
1645 NEW
.rm_startblock
= bno
;
1646 NEW
.rm_blockcount
+= len
;
1647 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1648 NEW
.rm_blockcount
, NEW
.rm_owner
,
1649 NEW
.rm_offset
, NEW
.rm_flags
);
1654 case RMAP_RIGHT_FILLING
:
1656 * Setting the last part of a previous oldext extent to newext.
1657 * The right neighbor is not contiguous.
1660 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1661 NEW
.rm_blockcount
, NEW
.rm_owner
,
1662 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1665 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1666 NEW
.rm_blockcount
-= len
;
1667 error
= xfs_rmap_update(cur
, &NEW
);
1670 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1677 * Setting the middle part of a previous oldext extent to
1678 * newext. Contiguity is impossible here.
1679 * One extent becomes three extents.
1681 /* new right extent - oldext */
1682 NEW
.rm_startblock
= bno
+ len
;
1683 NEW
.rm_owner
= owner
;
1684 NEW
.rm_offset
= new_endoff
;
1685 NEW
.rm_blockcount
= PREV
.rm_offset
+ PREV
.rm_blockcount
-
1687 NEW
.rm_flags
= PREV
.rm_flags
;
1688 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1689 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
1693 /* new left extent - oldext */
1695 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1696 NEW
.rm_blockcount
, NEW
.rm_owner
,
1697 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1700 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1701 NEW
.rm_blockcount
= offset
- NEW
.rm_offset
;
1702 error
= xfs_rmap_update(cur
, &NEW
);
1705 /* new middle extent - newext */
1706 NEW
.rm_startblock
= bno
;
1707 NEW
.rm_blockcount
= len
;
1708 NEW
.rm_owner
= owner
;
1709 NEW
.rm_offset
= offset
;
1710 NEW
.rm_flags
= newext
;
1711 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1712 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
1718 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1719 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1720 case RMAP_LEFT_FILLING
| RMAP_RIGHT_CONTIG
:
1721 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1722 case RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1723 case RMAP_LEFT_CONTIG
:
1724 case RMAP_RIGHT_CONTIG
:
1726 * These cases are all impossible.
1731 trace_xfs_rmap_convert_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1735 trace_xfs_rmap_convert_error(cur
->bc_mp
,
1736 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1746 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1747 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1748 * that the prev/next records in the btree might belong to another owner.
1749 * Therefore we must use delete+insert to alter any of the key fields.
1751 * For every other situation there can only be one owner for a given extent,
1752 * so we can call the regular _free function.
1755 xfs_rmap_unmap_shared(
1756 struct xfs_btree_cur
*cur
,
1760 struct xfs_owner_info
*oinfo
)
1762 struct xfs_mount
*mp
= cur
->bc_mp
;
1763 struct xfs_rmap_irec ltrec
;
1771 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1773 flags
|= XFS_RMAP_UNWRITTEN
;
1774 trace_xfs_rmap_unmap(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1778 * We should always have a left record because there's a static record
1779 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1780 * will not ever be removed from the tree.
1782 error
= xfs_rmap_lookup_le_range(cur
, bno
, owner
, offset
, flags
,
1786 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1787 ltoff
= ltrec
.rm_offset
;
1789 /* Make sure the extent we found covers the entire freeing range. */
1790 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_startblock
<= bno
&&
1791 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
>=
1792 bno
+ len
, out_error
);
1794 /* Make sure the owner matches what we expect to find in the tree. */
1795 XFS_WANT_CORRUPTED_GOTO(mp
, owner
== ltrec
.rm_owner
, out_error
);
1797 /* Make sure the unwritten flag matches. */
1798 XFS_WANT_CORRUPTED_GOTO(mp
, (flags
& XFS_RMAP_UNWRITTEN
) ==
1799 (ltrec
.rm_flags
& XFS_RMAP_UNWRITTEN
), out_error
);
1801 /* Check the offset. */
1802 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_offset
<= offset
, out_error
);
1803 XFS_WANT_CORRUPTED_GOTO(mp
, offset
<= ltoff
+ ltrec
.rm_blockcount
,
1806 if (ltrec
.rm_startblock
== bno
&& ltrec
.rm_blockcount
== len
) {
1807 /* Exact match, simply remove the record from rmap tree. */
1808 error
= xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
1809 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1810 ltrec
.rm_offset
, ltrec
.rm_flags
);
1813 } else if (ltrec
.rm_startblock
== bno
) {
1815 * Overlap left hand side of extent: move the start, trim the
1816 * length and update the current record.
1819 * Orig: |oooooooooooooooooooo|
1820 * Freeing: |fffffffff|
1821 * Result: |rrrrrrrrrr|
1825 /* Delete prev rmap. */
1826 error
= xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
1827 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1828 ltrec
.rm_offset
, ltrec
.rm_flags
);
1832 /* Add an rmap at the new offset. */
1833 ltrec
.rm_startblock
+= len
;
1834 ltrec
.rm_blockcount
-= len
;
1835 ltrec
.rm_offset
+= len
;
1836 error
= xfs_rmap_insert(cur
, ltrec
.rm_startblock
,
1837 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1838 ltrec
.rm_offset
, ltrec
.rm_flags
);
1841 } else if (ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
+ len
) {
1843 * Overlap right hand side of extent: trim the length and
1844 * update the current record.
1847 * Orig: |oooooooooooooooooooo|
1848 * Freeing: |fffffffff|
1849 * Result: |rrrrrrrrrr|
1852 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1853 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1854 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1857 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1858 ltrec
.rm_blockcount
-= len
;
1859 error
= xfs_rmap_update(cur
, <rec
);
1864 * Overlap middle of extent: trim the length of the existing
1865 * record to the length of the new left-extent size, increment
1866 * the insertion position so we can insert a new record
1867 * containing the remaining right-extent space.
1870 * Orig: |oooooooooooooooooooo|
1871 * Freeing: |fffffffff|
1872 * Result: |rrrrr| |rrrr|
1875 xfs_extlen_t orig_len
= ltrec
.rm_blockcount
;
1877 /* Shrink the left side of the rmap */
1878 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1879 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1880 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1883 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1884 ltrec
.rm_blockcount
= bno
- ltrec
.rm_startblock
;
1885 error
= xfs_rmap_update(cur
, <rec
);
1889 /* Add an rmap at the new offset */
1890 error
= xfs_rmap_insert(cur
, bno
+ len
,
1891 orig_len
- len
- ltrec
.rm_blockcount
,
1892 ltrec
.rm_owner
, offset
+ len
,
1898 trace_xfs_rmap_unmap_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1902 trace_xfs_rmap_unmap_error(cur
->bc_mp
,
1903 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1908 * Find an extent in the rmap btree and map it. For rmap extent types that
1909 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1910 * that the prev/next records in the btree might belong to another owner.
1911 * Therefore we must use delete+insert to alter any of the key fields.
1913 * For every other situation there can only be one owner for a given extent,
1914 * so we can call the regular _alloc function.
1917 xfs_rmap_map_shared(
1918 struct xfs_btree_cur
*cur
,
1922 struct xfs_owner_info
*oinfo
)
1924 struct xfs_mount
*mp
= cur
->bc_mp
;
1925 struct xfs_rmap_irec ltrec
;
1926 struct xfs_rmap_irec gtrec
;
1933 unsigned int flags
= 0;
1935 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1937 flags
|= XFS_RMAP_UNWRITTEN
;
1938 trace_xfs_rmap_map(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1941 /* Is there a left record that abuts our range? */
1942 error
= xfs_rmap_find_left_neighbor(cur
, bno
, owner
, offset
, flags
,
1947 !xfs_rmap_is_mergeable(<rec
, owner
, flags
))
1950 /* Is there a right record that abuts our range? */
1951 error
= xfs_rmap_lookup_eq(cur
, bno
+ len
, len
, owner
, offset
+ len
,
1956 error
= xfs_rmap_get_rec(cur
, >rec
, &have_gt
);
1959 XFS_WANT_CORRUPTED_GOTO(mp
, have_gt
== 1, out_error
);
1960 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1961 cur
->bc_private
.a
.agno
, gtrec
.rm_startblock
,
1962 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
1963 gtrec
.rm_offset
, gtrec
.rm_flags
);
1965 if (!xfs_rmap_is_mergeable(>rec
, owner
, flags
))
1970 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
&&
1971 ltrec
.rm_offset
+ ltrec
.rm_blockcount
== offset
) {
1973 * Left edge contiguous, merge into left record.
1977 * adding: |aaaaaaaaa|
1978 * result: |rrrrrrrrrrrrrrrrrrr|
1981 ltrec
.rm_blockcount
+= len
;
1983 bno
+ len
== gtrec
.rm_startblock
&&
1984 offset
+ len
== gtrec
.rm_offset
) {
1986 * Right edge also contiguous, delete right record
1987 * and merge into left record.
1989 * ltbno ltlen gtbno gtlen
1990 * orig: |ooooooooo| |ooooooooo|
1991 * adding: |aaaaaaaaa|
1992 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1994 ltrec
.rm_blockcount
+= gtrec
.rm_blockcount
;
1995 error
= xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
1996 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
1997 gtrec
.rm_offset
, gtrec
.rm_flags
);
2002 /* Point the cursor back to the left record and update. */
2003 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
2004 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
2005 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
2008 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
2010 error
= xfs_rmap_update(cur
, <rec
);
2013 } else if (have_gt
&&
2014 bno
+ len
== gtrec
.rm_startblock
&&
2015 offset
+ len
== gtrec
.rm_offset
) {
2017 * Right edge contiguous, merge into right record.
2021 * adding: |aaaaaaaaa|
2022 * Result: |rrrrrrrrrrrrrrrrrrr|
2025 /* Delete the old record. */
2026 error
= xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
2027 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2028 gtrec
.rm_offset
, gtrec
.rm_flags
);
2032 /* Move the start and re-add it. */
2033 gtrec
.rm_startblock
= bno
;
2034 gtrec
.rm_blockcount
+= len
;
2035 gtrec
.rm_offset
= offset
;
2036 error
= xfs_rmap_insert(cur
, gtrec
.rm_startblock
,
2037 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2038 gtrec
.rm_offset
, gtrec
.rm_flags
);
2043 * No contiguous edge with identical owner, insert
2044 * new record at current cursor position.
2046 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, flags
);
2051 trace_xfs_rmap_map_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
2055 trace_xfs_rmap_map_error(cur
->bc_mp
,
2056 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
2060 /* Insert a raw rmap into the rmapbt. */
2063 struct xfs_btree_cur
*cur
,
2064 struct xfs_rmap_irec
*rmap
)
2066 struct xfs_owner_info oinfo
;
2068 oinfo
.oi_owner
= rmap
->rm_owner
;
2069 oinfo
.oi_offset
= rmap
->rm_offset
;
2071 if (rmap
->rm_flags
& XFS_RMAP_ATTR_FORK
)
2072 oinfo
.oi_flags
|= XFS_OWNER_INFO_ATTR_FORK
;
2073 if (rmap
->rm_flags
& XFS_RMAP_BMBT_BLOCK
)
2074 oinfo
.oi_flags
|= XFS_OWNER_INFO_BMBT_BLOCK
;
2076 if (rmap
->rm_flags
|| XFS_RMAP_NON_INODE_OWNER(rmap
->rm_owner
))
2077 return xfs_rmap_map(cur
, rmap
->rm_startblock
,
2078 rmap
->rm_blockcount
,
2079 rmap
->rm_flags
& XFS_RMAP_UNWRITTEN
,
2082 return xfs_rmap_map_shared(cur
, rmap
->rm_startblock
,
2083 rmap
->rm_blockcount
,
2084 rmap
->rm_flags
& XFS_RMAP_UNWRITTEN
,
2088 struct xfs_rmap_query_range_info
{
2089 xfs_rmap_query_range_fn fn
;
2093 /* Format btree record and pass to our callback. */
2095 xfs_rmap_query_range_helper(
2096 struct xfs_btree_cur
*cur
,
2097 union xfs_btree_rec
*rec
,
2100 struct xfs_rmap_query_range_info
*query
= priv
;
2101 struct xfs_rmap_irec irec
;
2104 error
= xfs_rmap_btrec_to_irec(rec
, &irec
);
2107 return query
->fn(cur
, &irec
, query
->priv
);
2110 /* Find all rmaps between two keys. */
2112 xfs_rmap_query_range(
2113 struct xfs_btree_cur
*cur
,
2114 struct xfs_rmap_irec
*low_rec
,
2115 struct xfs_rmap_irec
*high_rec
,
2116 xfs_rmap_query_range_fn fn
,
2119 union xfs_btree_irec low_brec
;
2120 union xfs_btree_irec high_brec
;
2121 struct xfs_rmap_query_range_info query
;
2123 low_brec
.r
= *low_rec
;
2124 high_brec
.r
= *high_rec
;
2127 return xfs_btree_query_range(cur
, &low_brec
, &high_brec
,
2128 xfs_rmap_query_range_helper
, &query
);
2131 /* Find all rmaps. */
2134 struct xfs_btree_cur
*cur
,
2135 xfs_rmap_query_range_fn fn
,
2138 struct xfs_rmap_query_range_info query
;
2142 return xfs_btree_query_all(cur
, xfs_rmap_query_range_helper
, &query
);
2145 /* Clean up after calling xfs_rmap_finish_one. */
2147 xfs_rmap_finish_one_cleanup(
2148 struct xfs_trans
*tp
,
2149 struct xfs_btree_cur
*rcur
,
2152 struct xfs_buf
*agbp
;
2156 agbp
= rcur
->bc_private
.a
.agbp
;
2157 xfs_btree_del_cursor(rcur
, error
? XFS_BTREE_ERROR
: XFS_BTREE_NOERROR
);
2159 xfs_trans_brelse(tp
, agbp
);
2163 * Process one of the deferred rmap operations. We pass back the
2164 * btree cursor to maintain our lock on the rmapbt between calls.
2165 * This saves time and eliminates a buffer deadlock between the
2166 * superblock and the AGF because we'll always grab them in the same
2170 xfs_rmap_finish_one(
2171 struct xfs_trans
*tp
,
2172 enum xfs_rmap_intent_type type
,
2175 xfs_fileoff_t startoff
,
2176 xfs_fsblock_t startblock
,
2177 xfs_filblks_t blockcount
,
2179 struct xfs_btree_cur
**pcur
)
2181 struct xfs_mount
*mp
= tp
->t_mountp
;
2182 struct xfs_btree_cur
*rcur
;
2183 struct xfs_buf
*agbp
= NULL
;
2185 xfs_agnumber_t agno
;
2186 struct xfs_owner_info oinfo
;
2190 agno
= XFS_FSB_TO_AGNO(mp
, startblock
);
2191 ASSERT(agno
!= NULLAGNUMBER
);
2192 bno
= XFS_FSB_TO_AGBNO(mp
, startblock
);
2194 trace_xfs_rmap_deferred(mp
, agno
, type
, bno
, owner
, whichfork
,
2195 startoff
, blockcount
, state
);
2197 if (XFS_TEST_ERROR(false, mp
,
2198 XFS_ERRTAG_RMAP_FINISH_ONE
))
2202 * If we haven't gotten a cursor or the cursor AG doesn't match
2203 * the startblock, get one now.
2206 if (rcur
!= NULL
&& rcur
->bc_private
.a
.agno
!= agno
) {
2207 xfs_rmap_finish_one_cleanup(tp
, rcur
, 0);
2213 * Refresh the freelist before we start changing the
2214 * rmapbt, because a shape change could cause us to
2217 error
= xfs_free_extent_fix_freelist(tp
, agno
, &agbp
);
2221 return -EFSCORRUPTED
;
2223 rcur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
2231 xfs_rmap_ino_owner(&oinfo
, owner
, whichfork
, startoff
);
2232 unwritten
= state
== XFS_EXT_UNWRITTEN
;
2233 bno
= XFS_FSB_TO_AGBNO(rcur
->bc_mp
, startblock
);
2236 case XFS_RMAP_ALLOC
:
2238 error
= xfs_rmap_map(rcur
, bno
, blockcount
, unwritten
, &oinfo
);
2240 case XFS_RMAP_MAP_SHARED
:
2241 error
= xfs_rmap_map_shared(rcur
, bno
, blockcount
, unwritten
,
2245 case XFS_RMAP_UNMAP
:
2246 error
= xfs_rmap_unmap(rcur
, bno
, blockcount
, unwritten
,
2249 case XFS_RMAP_UNMAP_SHARED
:
2250 error
= xfs_rmap_unmap_shared(rcur
, bno
, blockcount
, unwritten
,
2253 case XFS_RMAP_CONVERT
:
2254 error
= xfs_rmap_convert(rcur
, bno
, blockcount
, !unwritten
,
2257 case XFS_RMAP_CONVERT_SHARED
:
2258 error
= xfs_rmap_convert_shared(rcur
, bno
, blockcount
,
2259 !unwritten
, &oinfo
);
2263 error
= -EFSCORRUPTED
;
2268 xfs_trans_brelse(tp
, agbp
);
2274 * Don't defer an rmap if we aren't an rmap filesystem.
2277 xfs_rmap_update_is_needed(
2278 struct xfs_mount
*mp
,
2281 return xfs_sb_version_hasrmapbt(&mp
->m_sb
) && whichfork
!= XFS_COW_FORK
;
2285 * Record a rmap intent; the list is kept sorted first by AG and then by
2290 struct xfs_mount
*mp
,
2291 struct xfs_defer_ops
*dfops
,
2292 enum xfs_rmap_intent_type type
,
2295 struct xfs_bmbt_irec
*bmap
)
2297 struct xfs_rmap_intent
*ri
;
2299 trace_xfs_rmap_defer(mp
, XFS_FSB_TO_AGNO(mp
, bmap
->br_startblock
),
2301 XFS_FSB_TO_AGBNO(mp
, bmap
->br_startblock
),
2304 bmap
->br_blockcount
,
2307 ri
= kmem_alloc(sizeof(struct xfs_rmap_intent
), KM_SLEEP
| KM_NOFS
);
2308 INIT_LIST_HEAD(&ri
->ri_list
);
2310 ri
->ri_owner
= owner
;
2311 ri
->ri_whichfork
= whichfork
;
2312 ri
->ri_bmap
= *bmap
;
2314 xfs_defer_add(dfops
, XFS_DEFER_OPS_TYPE_RMAP
, &ri
->ri_list
);
2318 /* Map an extent into a file. */
2320 xfs_rmap_map_extent(
2321 struct xfs_mount
*mp
,
2322 struct xfs_defer_ops
*dfops
,
2323 struct xfs_inode
*ip
,
2325 struct xfs_bmbt_irec
*PREV
)
2327 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2330 return __xfs_rmap_add(mp
, dfops
, xfs_is_reflink_inode(ip
) ?
2331 XFS_RMAP_MAP_SHARED
: XFS_RMAP_MAP
, ip
->i_ino
,
2335 /* Unmap an extent out of a file. */
2337 xfs_rmap_unmap_extent(
2338 struct xfs_mount
*mp
,
2339 struct xfs_defer_ops
*dfops
,
2340 struct xfs_inode
*ip
,
2342 struct xfs_bmbt_irec
*PREV
)
2344 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2347 return __xfs_rmap_add(mp
, dfops
, xfs_is_reflink_inode(ip
) ?
2348 XFS_RMAP_UNMAP_SHARED
: XFS_RMAP_UNMAP
, ip
->i_ino
,
2352 /* Convert a data fork extent from unwritten to real or vice versa. */
2354 xfs_rmap_convert_extent(
2355 struct xfs_mount
*mp
,
2356 struct xfs_defer_ops
*dfops
,
2357 struct xfs_inode
*ip
,
2359 struct xfs_bmbt_irec
*PREV
)
2361 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2364 return __xfs_rmap_add(mp
, dfops
, xfs_is_reflink_inode(ip
) ?
2365 XFS_RMAP_CONVERT_SHARED
: XFS_RMAP_CONVERT
, ip
->i_ino
,
2369 /* Schedule the creation of an rmap for non-file data. */
2371 xfs_rmap_alloc_extent(
2372 struct xfs_mount
*mp
,
2373 struct xfs_defer_ops
*dfops
,
2374 xfs_agnumber_t agno
,
2379 struct xfs_bmbt_irec bmap
;
2381 if (!xfs_rmap_update_is_needed(mp
, XFS_DATA_FORK
))
2384 bmap
.br_startblock
= XFS_AGB_TO_FSB(mp
, agno
, bno
);
2385 bmap
.br_blockcount
= len
;
2386 bmap
.br_startoff
= 0;
2387 bmap
.br_state
= XFS_EXT_NORM
;
2389 return __xfs_rmap_add(mp
, dfops
, XFS_RMAP_ALLOC
, owner
,
2390 XFS_DATA_FORK
, &bmap
);
2393 /* Schedule the deletion of an rmap for non-file data. */
2395 xfs_rmap_free_extent(
2396 struct xfs_mount
*mp
,
2397 struct xfs_defer_ops
*dfops
,
2398 xfs_agnumber_t agno
,
2403 struct xfs_bmbt_irec bmap
;
2405 if (!xfs_rmap_update_is_needed(mp
, XFS_DATA_FORK
))
2408 bmap
.br_startblock
= XFS_AGB_TO_FSB(mp
, agno
, bno
);
2409 bmap
.br_blockcount
= len
;
2410 bmap
.br_startoff
= 0;
2411 bmap
.br_state
= XFS_EXT_NORM
;
2413 return __xfs_rmap_add(mp
, dfops
, XFS_RMAP_FREE
, owner
,
2414 XFS_DATA_FORK
, &bmap
);
2417 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2420 const struct xfs_rmap_irec
*a
,
2421 const struct xfs_rmap_irec
*b
)
2426 oa
= xfs_rmap_irec_offset_pack(a
);
2427 ob
= xfs_rmap_irec_offset_pack(b
);
2429 if (a
->rm_startblock
< b
->rm_startblock
)
2431 else if (a
->rm_startblock
> b
->rm_startblock
)
2433 else if (a
->rm_owner
< b
->rm_owner
)
2435 else if (a
->rm_owner
> b
->rm_owner
)
2445 /* Is there a record covering a given extent? */
2447 xfs_rmap_has_record(
2448 struct xfs_btree_cur
*cur
,
2453 union xfs_btree_irec low
;
2454 union xfs_btree_irec high
;
2456 memset(&low
, 0, sizeof(low
));
2457 low
.r
.rm_startblock
= bno
;
2458 memset(&high
, 0xFF, sizeof(high
));
2459 high
.r
.rm_startblock
= bno
+ len
- 1;
2461 return xfs_btree_has_record(cur
, &low
, &high
, exists
);
2465 * Is there a record for this owner completely covering a given physical
2466 * extent? If so, *has_rmap will be set to true. If there is no record
2467 * or the record only covers part of the range, we set *has_rmap to false.
2468 * This function doesn't perform range lookups or offset checks, so it is
2469 * not suitable for checking data fork blocks.
2472 xfs_rmap_record_exists(
2473 struct xfs_btree_cur
*cur
,
2476 struct xfs_owner_info
*oinfo
,
2483 struct xfs_rmap_irec irec
;
2486 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
2487 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner
) ||
2488 (flags
& XFS_RMAP_BMBT_BLOCK
));
2490 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
,
2499 error
= xfs_rmap_get_rec(cur
, &irec
, &has_record
);
2507 *has_rmap
= (irec
.rm_owner
== owner
&& irec
.rm_startblock
<= bno
&&
2508 irec
.rm_startblock
+ irec
.rm_blockcount
>= bno
+ len
);
2512 struct xfs_rmap_key_state
{
2519 /* For each rmap given, figure out if it doesn't match the key we want. */
2521 xfs_rmap_has_other_keys_helper(
2522 struct xfs_btree_cur
*cur
,
2523 struct xfs_rmap_irec
*rec
,
2526 struct xfs_rmap_key_state
*rks
= priv
;
2528 if (rks
->owner
== rec
->rm_owner
&& rks
->offset
== rec
->rm_offset
&&
2529 ((rks
->flags
& rec
->rm_flags
) & XFS_RMAP_KEY_FLAGS
) == rks
->flags
)
2531 rks
->has_rmap
= true;
2532 return XFS_BTREE_QUERY_RANGE_ABORT
;
2536 * Given an extent and some owner info, can we find records overlapping
2537 * the extent whose owner info does not match the given owner?
2540 xfs_rmap_has_other_keys(
2541 struct xfs_btree_cur
*cur
,
2544 struct xfs_owner_info
*oinfo
,
2547 struct xfs_rmap_irec low
= {0};
2548 struct xfs_rmap_irec high
;
2549 struct xfs_rmap_key_state rks
;
2552 xfs_owner_info_unpack(oinfo
, &rks
.owner
, &rks
.offset
, &rks
.flags
);
2553 rks
.has_rmap
= false;
2555 low
.rm_startblock
= bno
;
2556 memset(&high
, 0xFF, sizeof(high
));
2557 high
.rm_startblock
= bno
+ len
- 1;
2559 error
= xfs_rmap_query_range(cur
, &low
, &high
,
2560 xfs_rmap_has_other_keys_helper
, &rks
);
2561 *has_rmap
= rks
.has_rmap
;