1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2014 Red Hat, Inc.
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_log_format.h"
11 #include "xfs_trans_resv.h"
13 #include "xfs_mount.h"
14 #include "xfs_defer.h"
15 #include "xfs_btree.h"
16 #include "xfs_trans.h"
17 #include "xfs_alloc.h"
19 #include "xfs_rmap_btree.h"
20 #include "xfs_trace.h"
21 #include "xfs_errortag.h"
22 #include "xfs_error.h"
23 #include "xfs_inode.h"
26 * Lookup the first record less than or equal to [bno, len, owner, offset]
27 * in the btree given by cur.
31 struct xfs_btree_cur
*cur
,
39 cur
->bc_rec
.r
.rm_startblock
= bno
;
40 cur
->bc_rec
.r
.rm_blockcount
= len
;
41 cur
->bc_rec
.r
.rm_owner
= owner
;
42 cur
->bc_rec
.r
.rm_offset
= offset
;
43 cur
->bc_rec
.r
.rm_flags
= flags
;
44 return xfs_btree_lookup(cur
, XFS_LOOKUP_LE
, stat
);
48 * Lookup the record exactly matching [bno, len, owner, offset]
49 * in the btree given by cur.
53 struct xfs_btree_cur
*cur
,
61 cur
->bc_rec
.r
.rm_startblock
= bno
;
62 cur
->bc_rec
.r
.rm_blockcount
= len
;
63 cur
->bc_rec
.r
.rm_owner
= owner
;
64 cur
->bc_rec
.r
.rm_offset
= offset
;
65 cur
->bc_rec
.r
.rm_flags
= flags
;
66 return xfs_btree_lookup(cur
, XFS_LOOKUP_EQ
, stat
);
70 * Update the record referred to by cur to the value given
71 * by [bno, len, owner, offset].
72 * This either works (return 0) or gets an EFSCORRUPTED error.
76 struct xfs_btree_cur
*cur
,
77 struct xfs_rmap_irec
*irec
)
79 union xfs_btree_rec rec
;
82 trace_xfs_rmap_update(cur
->bc_mp
, cur
->bc_ag
.agno
,
83 irec
->rm_startblock
, irec
->rm_blockcount
,
84 irec
->rm_owner
, irec
->rm_offset
, irec
->rm_flags
);
86 rec
.rmap
.rm_startblock
= cpu_to_be32(irec
->rm_startblock
);
87 rec
.rmap
.rm_blockcount
= cpu_to_be32(irec
->rm_blockcount
);
88 rec
.rmap
.rm_owner
= cpu_to_be64(irec
->rm_owner
);
89 rec
.rmap
.rm_offset
= cpu_to_be64(
90 xfs_rmap_irec_offset_pack(irec
));
91 error
= xfs_btree_update(cur
, &rec
);
93 trace_xfs_rmap_update_error(cur
->bc_mp
,
94 cur
->bc_ag
.agno
, error
, _RET_IP_
);
100 struct xfs_btree_cur
*rcur
,
110 trace_xfs_rmap_insert(rcur
->bc_mp
, rcur
->bc_ag
.agno
, agbno
,
111 len
, owner
, offset
, flags
);
113 error
= xfs_rmap_lookup_eq(rcur
, agbno
, len
, owner
, offset
, flags
, &i
);
116 if (XFS_IS_CORRUPT(rcur
->bc_mp
, i
!= 0)) {
117 error
= -EFSCORRUPTED
;
121 rcur
->bc_rec
.r
.rm_startblock
= agbno
;
122 rcur
->bc_rec
.r
.rm_blockcount
= len
;
123 rcur
->bc_rec
.r
.rm_owner
= owner
;
124 rcur
->bc_rec
.r
.rm_offset
= offset
;
125 rcur
->bc_rec
.r
.rm_flags
= flags
;
126 error
= xfs_btree_insert(rcur
, &i
);
129 if (XFS_IS_CORRUPT(rcur
->bc_mp
, i
!= 1)) {
130 error
= -EFSCORRUPTED
;
135 trace_xfs_rmap_insert_error(rcur
->bc_mp
,
136 rcur
->bc_ag
.agno
, error
, _RET_IP_
);
142 struct xfs_btree_cur
*rcur
,
152 trace_xfs_rmap_delete(rcur
->bc_mp
, rcur
->bc_ag
.agno
, agbno
,
153 len
, owner
, offset
, flags
);
155 error
= xfs_rmap_lookup_eq(rcur
, agbno
, len
, owner
, offset
, flags
, &i
);
158 if (XFS_IS_CORRUPT(rcur
->bc_mp
, i
!= 1)) {
159 error
= -EFSCORRUPTED
;
163 error
= xfs_btree_delete(rcur
, &i
);
166 if (XFS_IS_CORRUPT(rcur
->bc_mp
, i
!= 1)) {
167 error
= -EFSCORRUPTED
;
172 trace_xfs_rmap_delete_error(rcur
->bc_mp
,
173 rcur
->bc_ag
.agno
, error
, _RET_IP_
);
177 /* Convert an internal btree record to an rmap record. */
179 xfs_rmap_btrec_to_irec(
180 union xfs_btree_rec
*rec
,
181 struct xfs_rmap_irec
*irec
)
183 irec
->rm_startblock
= be32_to_cpu(rec
->rmap
.rm_startblock
);
184 irec
->rm_blockcount
= be32_to_cpu(rec
->rmap
.rm_blockcount
);
185 irec
->rm_owner
= be64_to_cpu(rec
->rmap
.rm_owner
);
186 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec
->rmap
.rm_offset
),
191 * Get the data from the pointed-to record.
195 struct xfs_btree_cur
*cur
,
196 struct xfs_rmap_irec
*irec
,
199 struct xfs_mount
*mp
= cur
->bc_mp
;
200 xfs_agnumber_t agno
= cur
->bc_ag
.agno
;
201 union xfs_btree_rec
*rec
;
204 error
= xfs_btree_get_rec(cur
, &rec
, stat
);
208 if (xfs_rmap_btrec_to_irec(rec
, irec
))
211 if (irec
->rm_blockcount
== 0)
213 if (irec
->rm_startblock
<= XFS_AGFL_BLOCK(mp
)) {
214 if (irec
->rm_owner
!= XFS_RMAP_OWN_FS
)
216 if (irec
->rm_blockcount
!= XFS_AGFL_BLOCK(mp
) + 1)
219 /* check for valid extent range, including overflow */
220 if (!xfs_verify_agbno(mp
, agno
, irec
->rm_startblock
))
222 if (irec
->rm_startblock
>
223 irec
->rm_startblock
+ irec
->rm_blockcount
)
225 if (!xfs_verify_agbno(mp
, agno
,
226 irec
->rm_startblock
+ irec
->rm_blockcount
- 1))
230 if (!(xfs_verify_ino(mp
, irec
->rm_owner
) ||
231 (irec
->rm_owner
<= XFS_RMAP_OWN_FS
&&
232 irec
->rm_owner
>= XFS_RMAP_OWN_MIN
)))
238 "Reverse Mapping BTree record corruption in AG %d detected!",
241 "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
242 irec
->rm_owner
, irec
->rm_flags
, irec
->rm_startblock
,
243 irec
->rm_blockcount
);
244 return -EFSCORRUPTED
;
247 struct xfs_find_left_neighbor_info
{
248 struct xfs_rmap_irec high
;
249 struct xfs_rmap_irec
*irec
;
253 /* For each rmap given, figure out if it matches the key we want. */
255 xfs_rmap_find_left_neighbor_helper(
256 struct xfs_btree_cur
*cur
,
257 struct xfs_rmap_irec
*rec
,
260 struct xfs_find_left_neighbor_info
*info
= priv
;
262 trace_xfs_rmap_find_left_neighbor_candidate(cur
->bc_mp
,
263 cur
->bc_ag
.agno
, rec
->rm_startblock
,
264 rec
->rm_blockcount
, rec
->rm_owner
, rec
->rm_offset
,
267 if (rec
->rm_owner
!= info
->high
.rm_owner
)
269 if (!XFS_RMAP_NON_INODE_OWNER(rec
->rm_owner
) &&
270 !(rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
) &&
271 rec
->rm_offset
+ rec
->rm_blockcount
- 1 != info
->high
.rm_offset
)
280 * Find the record to the left of the given extent, being careful only to
281 * return a match with the same owner and adjacent physical and logical
285 xfs_rmap_find_left_neighbor(
286 struct xfs_btree_cur
*cur
,
291 struct xfs_rmap_irec
*irec
,
294 struct xfs_find_left_neighbor_info info
;
300 info
.high
.rm_startblock
= bno
- 1;
301 info
.high
.rm_owner
= owner
;
302 if (!XFS_RMAP_NON_INODE_OWNER(owner
) &&
303 !(flags
& XFS_RMAP_BMBT_BLOCK
)) {
306 info
.high
.rm_offset
= offset
- 1;
308 info
.high
.rm_offset
= 0;
309 info
.high
.rm_flags
= flags
;
310 info
.high
.rm_blockcount
= 0;
314 trace_xfs_rmap_find_left_neighbor_query(cur
->bc_mp
,
315 cur
->bc_ag
.agno
, bno
, 0, owner
, offset
, flags
);
317 error
= xfs_rmap_query_range(cur
, &info
.high
, &info
.high
,
318 xfs_rmap_find_left_neighbor_helper
, &info
);
319 if (error
== -ECANCELED
)
322 trace_xfs_rmap_find_left_neighbor_result(cur
->bc_mp
,
323 cur
->bc_ag
.agno
, irec
->rm_startblock
,
324 irec
->rm_blockcount
, irec
->rm_owner
,
325 irec
->rm_offset
, irec
->rm_flags
);
329 /* For each rmap given, figure out if it matches the key we want. */
331 xfs_rmap_lookup_le_range_helper(
332 struct xfs_btree_cur
*cur
,
333 struct xfs_rmap_irec
*rec
,
336 struct xfs_find_left_neighbor_info
*info
= priv
;
338 trace_xfs_rmap_lookup_le_range_candidate(cur
->bc_mp
,
339 cur
->bc_ag
.agno
, rec
->rm_startblock
,
340 rec
->rm_blockcount
, rec
->rm_owner
, rec
->rm_offset
,
343 if (rec
->rm_owner
!= info
->high
.rm_owner
)
345 if (!XFS_RMAP_NON_INODE_OWNER(rec
->rm_owner
) &&
346 !(rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
) &&
347 (rec
->rm_offset
> info
->high
.rm_offset
||
348 rec
->rm_offset
+ rec
->rm_blockcount
<= info
->high
.rm_offset
))
357 * Find the record to the left of the given extent, being careful only to
358 * return a match with the same owner and overlapping physical and logical
359 * block ranges. This is the overlapping-interval version of
360 * xfs_rmap_lookup_le.
363 xfs_rmap_lookup_le_range(
364 struct xfs_btree_cur
*cur
,
369 struct xfs_rmap_irec
*irec
,
372 struct xfs_find_left_neighbor_info info
;
375 info
.high
.rm_startblock
= bno
;
376 info
.high
.rm_owner
= owner
;
377 if (!XFS_RMAP_NON_INODE_OWNER(owner
) && !(flags
& XFS_RMAP_BMBT_BLOCK
))
378 info
.high
.rm_offset
= offset
;
380 info
.high
.rm_offset
= 0;
381 info
.high
.rm_flags
= flags
;
382 info
.high
.rm_blockcount
= 0;
387 trace_xfs_rmap_lookup_le_range(cur
->bc_mp
,
388 cur
->bc_ag
.agno
, bno
, 0, owner
, offset
, flags
);
389 error
= xfs_rmap_query_range(cur
, &info
.high
, &info
.high
,
390 xfs_rmap_lookup_le_range_helper
, &info
);
391 if (error
== -ECANCELED
)
394 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
395 cur
->bc_ag
.agno
, irec
->rm_startblock
,
396 irec
->rm_blockcount
, irec
->rm_owner
,
397 irec
->rm_offset
, irec
->rm_flags
);
402 * Perform all the relevant owner checks for a removal op. If we're doing an
403 * unknown-owner removal then we have no owner information to check.
406 xfs_rmap_free_check_owner(
407 struct xfs_mount
*mp
,
409 struct xfs_rmap_irec
*rec
,
417 if (owner
== XFS_RMAP_OWN_UNKNOWN
)
420 /* Make sure the unwritten flag matches. */
421 if (XFS_IS_CORRUPT(mp
,
422 (flags
& XFS_RMAP_UNWRITTEN
) !=
423 (rec
->rm_flags
& XFS_RMAP_UNWRITTEN
))) {
424 error
= -EFSCORRUPTED
;
428 /* Make sure the owner matches what we expect to find in the tree. */
429 if (XFS_IS_CORRUPT(mp
, owner
!= rec
->rm_owner
)) {
430 error
= -EFSCORRUPTED
;
434 /* Check the offset, if necessary. */
435 if (XFS_RMAP_NON_INODE_OWNER(owner
))
438 if (flags
& XFS_RMAP_BMBT_BLOCK
) {
439 if (XFS_IS_CORRUPT(mp
,
440 !(rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
))) {
441 error
= -EFSCORRUPTED
;
445 if (XFS_IS_CORRUPT(mp
, rec
->rm_offset
> offset
)) {
446 error
= -EFSCORRUPTED
;
449 if (XFS_IS_CORRUPT(mp
,
450 offset
+ len
> ltoff
+ rec
->rm_blockcount
)) {
451 error
= -EFSCORRUPTED
;
461 * Find the extent in the rmap btree and remove it.
463 * The record we find should always be an exact match for the extent that we're
464 * looking for, since we insert them into the btree without modification.
466 * Special Case #1: when growing the filesystem, we "free" an extent when
467 * growing the last AG. This extent is new space and so it is not tracked as
468 * used space in the btree. The growfs code will pass in an owner of
469 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
470 * extent. We verify that - the extent lookup result in a record that does not
473 * Special Case #2: EFIs do not record the owner of the extent, so when
474 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
475 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
476 * corruption checks during log recovery.
480 struct xfs_btree_cur
*cur
,
484 const struct xfs_owner_info
*oinfo
)
486 struct xfs_mount
*mp
= cur
->bc_mp
;
487 struct xfs_rmap_irec ltrec
;
496 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
497 ignore_off
= XFS_RMAP_NON_INODE_OWNER(owner
) ||
498 (flags
& XFS_RMAP_BMBT_BLOCK
);
500 flags
|= XFS_RMAP_UNWRITTEN
;
501 trace_xfs_rmap_unmap(mp
, cur
->bc_ag
.agno
, bno
, len
,
505 * We should always have a left record because there's a static record
506 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
507 * will not ever be removed from the tree.
509 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
, &i
);
512 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
513 error
= -EFSCORRUPTED
;
517 error
= xfs_rmap_get_rec(cur
, <rec
, &i
);
520 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
521 error
= -EFSCORRUPTED
;
524 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
525 cur
->bc_ag
.agno
, ltrec
.rm_startblock
,
526 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
527 ltrec
.rm_offset
, ltrec
.rm_flags
);
528 ltoff
= ltrec
.rm_offset
;
531 * For growfs, the incoming extent must be beyond the left record we
532 * just found as it is new space and won't be used by anyone. This is
533 * just a corruption check as we don't actually do anything with this
534 * extent. Note that we need to use >= instead of > because it might
535 * be the case that the "left" extent goes all the way to EOFS.
537 if (owner
== XFS_RMAP_OWN_NULL
) {
538 if (XFS_IS_CORRUPT(mp
,
540 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
)) {
541 error
= -EFSCORRUPTED
;
548 * If we're doing an unknown-owner removal for EFI recovery, we expect
549 * to find the full range in the rmapbt or nothing at all. If we
550 * don't find any rmaps overlapping either end of the range, we're
551 * done. Hopefully this means that the EFI creator already queued
552 * (and finished) a RUI to remove the rmap.
554 if (owner
== XFS_RMAP_OWN_UNKNOWN
&&
555 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
<= bno
) {
556 struct xfs_rmap_irec rtrec
;
558 error
= xfs_btree_increment(cur
, 0, &i
);
563 error
= xfs_rmap_get_rec(cur
, &rtrec
, &i
);
566 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
567 error
= -EFSCORRUPTED
;
570 if (rtrec
.rm_startblock
>= bno
+ len
)
574 /* Make sure the extent we found covers the entire freeing range. */
575 if (XFS_IS_CORRUPT(mp
,
576 ltrec
.rm_startblock
> bno
||
577 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
<
579 error
= -EFSCORRUPTED
;
583 /* Check owner information. */
584 error
= xfs_rmap_free_check_owner(mp
, ltoff
, <rec
, len
, owner
,
589 if (ltrec
.rm_startblock
== bno
&& ltrec
.rm_blockcount
== len
) {
590 /* exact match, simply remove the record from rmap tree */
591 trace_xfs_rmap_delete(mp
, cur
->bc_ag
.agno
,
592 ltrec
.rm_startblock
, ltrec
.rm_blockcount
,
593 ltrec
.rm_owner
, ltrec
.rm_offset
,
595 error
= xfs_btree_delete(cur
, &i
);
598 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
599 error
= -EFSCORRUPTED
;
602 } else if (ltrec
.rm_startblock
== bno
) {
604 * overlap left hand side of extent: move the start, trim the
605 * length and update the current record.
608 * Orig: |oooooooooooooooooooo|
609 * Freeing: |fffffffff|
610 * Result: |rrrrrrrrrr|
613 ltrec
.rm_startblock
+= len
;
614 ltrec
.rm_blockcount
-= len
;
616 ltrec
.rm_offset
+= len
;
617 error
= xfs_rmap_update(cur
, <rec
);
620 } else if (ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
+ len
) {
622 * overlap right hand side of extent: trim the length and update
623 * the current record.
626 * Orig: |oooooooooooooooooooo|
627 * Freeing: |fffffffff|
628 * Result: |rrrrrrrrrr|
631 ltrec
.rm_blockcount
-= len
;
632 error
= xfs_rmap_update(cur
, <rec
);
638 * overlap middle of extent: trim the length of the existing
639 * record to the length of the new left-extent size, increment
640 * the insertion position so we can insert a new record
641 * containing the remaining right-extent space.
644 * Orig: |oooooooooooooooooooo|
645 * Freeing: |fffffffff|
646 * Result: |rrrrr| |rrrr|
649 xfs_extlen_t orig_len
= ltrec
.rm_blockcount
;
651 ltrec
.rm_blockcount
= bno
- ltrec
.rm_startblock
;
652 error
= xfs_rmap_update(cur
, <rec
);
656 error
= xfs_btree_increment(cur
, 0, &i
);
660 cur
->bc_rec
.r
.rm_startblock
= bno
+ len
;
661 cur
->bc_rec
.r
.rm_blockcount
= orig_len
- len
-
663 cur
->bc_rec
.r
.rm_owner
= ltrec
.rm_owner
;
665 cur
->bc_rec
.r
.rm_offset
= 0;
667 cur
->bc_rec
.r
.rm_offset
= offset
+ len
;
668 cur
->bc_rec
.r
.rm_flags
= flags
;
669 trace_xfs_rmap_insert(mp
, cur
->bc_ag
.agno
,
670 cur
->bc_rec
.r
.rm_startblock
,
671 cur
->bc_rec
.r
.rm_blockcount
,
672 cur
->bc_rec
.r
.rm_owner
,
673 cur
->bc_rec
.r
.rm_offset
,
674 cur
->bc_rec
.r
.rm_flags
);
675 error
= xfs_btree_insert(cur
, &i
);
681 trace_xfs_rmap_unmap_done(mp
, cur
->bc_ag
.agno
, bno
, len
,
685 trace_xfs_rmap_unmap_error(mp
, cur
->bc_ag
.agno
,
691 * Remove a reference to an extent in the rmap btree.
695 struct xfs_trans
*tp
,
696 struct xfs_buf
*agbp
,
700 const struct xfs_owner_info
*oinfo
)
702 struct xfs_mount
*mp
= tp
->t_mountp
;
703 struct xfs_btree_cur
*cur
;
706 if (!xfs_sb_version_hasrmapbt(&mp
->m_sb
))
709 cur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
711 error
= xfs_rmap_unmap(cur
, bno
, len
, false, oinfo
);
713 xfs_btree_del_cursor(cur
, error
);
718 * A mergeable rmap must have the same owner and the same values for
719 * the unwritten, attr_fork, and bmbt flags. The startblock and
720 * offset are checked separately.
723 xfs_rmap_is_mergeable(
724 struct xfs_rmap_irec
*irec
,
728 if (irec
->rm_owner
== XFS_RMAP_OWN_NULL
)
730 if (irec
->rm_owner
!= owner
)
732 if ((flags
& XFS_RMAP_UNWRITTEN
) ^
733 (irec
->rm_flags
& XFS_RMAP_UNWRITTEN
))
735 if ((flags
& XFS_RMAP_ATTR_FORK
) ^
736 (irec
->rm_flags
& XFS_RMAP_ATTR_FORK
))
738 if ((flags
& XFS_RMAP_BMBT_BLOCK
) ^
739 (irec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
))
745 * When we allocate a new block, the first thing we do is add a reference to
746 * the extent in the rmap btree. This takes the form of a [agbno, length,
747 * owner, offset] record. Flags are encoded in the high bits of the offset
752 struct xfs_btree_cur
*cur
,
756 const struct xfs_owner_info
*oinfo
)
758 struct xfs_mount
*mp
= cur
->bc_mp
;
759 struct xfs_rmap_irec ltrec
;
760 struct xfs_rmap_irec gtrec
;
767 unsigned int flags
= 0;
770 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
772 ignore_off
= XFS_RMAP_NON_INODE_OWNER(owner
) ||
773 (flags
& XFS_RMAP_BMBT_BLOCK
);
775 flags
|= XFS_RMAP_UNWRITTEN
;
776 trace_xfs_rmap_map(mp
, cur
->bc_ag
.agno
, bno
, len
,
778 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo
));
781 * For the initial lookup, look for an exact match or the left-adjacent
782 * record for our insertion point. This will also give us the record for
783 * start block contiguity tests.
785 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
,
790 error
= xfs_rmap_get_rec(cur
, <rec
, &have_lt
);
793 if (XFS_IS_CORRUPT(mp
, have_lt
!= 1)) {
794 error
= -EFSCORRUPTED
;
797 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
798 cur
->bc_ag
.agno
, ltrec
.rm_startblock
,
799 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
800 ltrec
.rm_offset
, ltrec
.rm_flags
);
802 if (!xfs_rmap_is_mergeable(<rec
, owner
, flags
))
806 if (XFS_IS_CORRUPT(mp
,
808 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
> bno
)) {
809 error
= -EFSCORRUPTED
;
814 * Increment the cursor to see if we have a right-adjacent record to our
815 * insertion point. This will give us the record for end block
818 error
= xfs_btree_increment(cur
, 0, &have_gt
);
822 error
= xfs_rmap_get_rec(cur
, >rec
, &have_gt
);
825 if (XFS_IS_CORRUPT(mp
, have_gt
!= 1)) {
826 error
= -EFSCORRUPTED
;
829 if (XFS_IS_CORRUPT(mp
, bno
+ len
> gtrec
.rm_startblock
)) {
830 error
= -EFSCORRUPTED
;
833 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
834 cur
->bc_ag
.agno
, gtrec
.rm_startblock
,
835 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
836 gtrec
.rm_offset
, gtrec
.rm_flags
);
837 if (!xfs_rmap_is_mergeable(>rec
, owner
, flags
))
842 * Note: cursor currently points one record to the right of ltrec, even
843 * if there is no record in the tree to the right.
846 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
&&
847 (ignore_off
|| ltrec
.rm_offset
+ ltrec
.rm_blockcount
== offset
)) {
849 * left edge contiguous, merge into left record.
853 * adding: |aaaaaaaaa|
854 * result: |rrrrrrrrrrrrrrrrrrr|
857 ltrec
.rm_blockcount
+= len
;
859 bno
+ len
== gtrec
.rm_startblock
&&
860 (ignore_off
|| offset
+ len
== gtrec
.rm_offset
) &&
861 (unsigned long)ltrec
.rm_blockcount
+ len
+
862 gtrec
.rm_blockcount
<= XFS_RMAP_LEN_MAX
) {
864 * right edge also contiguous, delete right record
865 * and merge into left record.
867 * ltbno ltlen gtbno gtlen
868 * orig: |ooooooooo| |ooooooooo|
869 * adding: |aaaaaaaaa|
870 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
872 ltrec
.rm_blockcount
+= gtrec
.rm_blockcount
;
873 trace_xfs_rmap_delete(mp
, cur
->bc_ag
.agno
,
879 error
= xfs_btree_delete(cur
, &i
);
882 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
883 error
= -EFSCORRUPTED
;
888 /* point the cursor back to the left record and update */
889 error
= xfs_btree_decrement(cur
, 0, &have_gt
);
892 error
= xfs_rmap_update(cur
, <rec
);
895 } else if (have_gt
&&
896 bno
+ len
== gtrec
.rm_startblock
&&
897 (ignore_off
|| offset
+ len
== gtrec
.rm_offset
)) {
899 * right edge contiguous, merge into right record.
903 * adding: |aaaaaaaaa|
904 * Result: |rrrrrrrrrrrrrrrrrrr|
907 gtrec
.rm_startblock
= bno
;
908 gtrec
.rm_blockcount
+= len
;
910 gtrec
.rm_offset
= offset
;
911 error
= xfs_rmap_update(cur
, >rec
);
916 * no contiguous edge with identical owner, insert
917 * new record at current cursor position.
919 cur
->bc_rec
.r
.rm_startblock
= bno
;
920 cur
->bc_rec
.r
.rm_blockcount
= len
;
921 cur
->bc_rec
.r
.rm_owner
= owner
;
922 cur
->bc_rec
.r
.rm_offset
= offset
;
923 cur
->bc_rec
.r
.rm_flags
= flags
;
924 trace_xfs_rmap_insert(mp
, cur
->bc_ag
.agno
, bno
, len
,
925 owner
, offset
, flags
);
926 error
= xfs_btree_insert(cur
, &i
);
929 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
930 error
= -EFSCORRUPTED
;
935 trace_xfs_rmap_map_done(mp
, cur
->bc_ag
.agno
, bno
, len
,
939 trace_xfs_rmap_map_error(mp
, cur
->bc_ag
.agno
,
945 * Add a reference to an extent in the rmap btree.
949 struct xfs_trans
*tp
,
950 struct xfs_buf
*agbp
,
954 const struct xfs_owner_info
*oinfo
)
956 struct xfs_mount
*mp
= tp
->t_mountp
;
957 struct xfs_btree_cur
*cur
;
960 if (!xfs_sb_version_hasrmapbt(&mp
->m_sb
))
963 cur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
964 error
= xfs_rmap_map(cur
, bno
, len
, false, oinfo
);
966 xfs_btree_del_cursor(cur
, error
);
970 #define RMAP_LEFT_CONTIG (1 << 0)
971 #define RMAP_RIGHT_CONTIG (1 << 1)
972 #define RMAP_LEFT_FILLING (1 << 2)
973 #define RMAP_RIGHT_FILLING (1 << 3)
974 #define RMAP_LEFT_VALID (1 << 6)
975 #define RMAP_RIGHT_VALID (1 << 7)
983 * Convert an unwritten extent to a real extent or vice versa.
984 * Does not handle overlapping extents.
988 struct xfs_btree_cur
*cur
,
992 const struct xfs_owner_info
*oinfo
)
994 struct xfs_mount
*mp
= cur
->bc_mp
;
995 struct xfs_rmap_irec r
[4]; /* neighbor extent entries */
996 /* left is 0, right is 1, */
997 /* prev is 2, new is 3 */
1000 uint64_t new_endoff
;
1001 unsigned int oldext
;
1002 unsigned int newext
;
1003 unsigned int flags
= 0;
1008 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1009 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner
) ||
1010 (flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
))));
1011 oldext
= unwritten
? XFS_RMAP_UNWRITTEN
: 0;
1012 new_endoff
= offset
+ len
;
1013 trace_xfs_rmap_convert(mp
, cur
->bc_ag
.agno
, bno
, len
,
1017 * For the initial lookup, look for an exact match or the left-adjacent
1018 * record for our insertion point. This will also give us the record for
1019 * start block contiguity tests.
1021 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, oldext
, &i
);
1024 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1025 error
= -EFSCORRUPTED
;
1029 error
= xfs_rmap_get_rec(cur
, &PREV
, &i
);
1032 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1033 error
= -EFSCORRUPTED
;
1036 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
1037 cur
->bc_ag
.agno
, PREV
.rm_startblock
,
1038 PREV
.rm_blockcount
, PREV
.rm_owner
,
1039 PREV
.rm_offset
, PREV
.rm_flags
);
1041 ASSERT(PREV
.rm_offset
<= offset
);
1042 ASSERT(PREV
.rm_offset
+ PREV
.rm_blockcount
>= new_endoff
);
1043 ASSERT((PREV
.rm_flags
& XFS_RMAP_UNWRITTEN
) == oldext
);
1044 newext
= ~oldext
& XFS_RMAP_UNWRITTEN
;
1047 * Set flags determining what part of the previous oldext allocation
1048 * extent is being replaced by a newext allocation.
1050 if (PREV
.rm_offset
== offset
)
1051 state
|= RMAP_LEFT_FILLING
;
1052 if (PREV
.rm_offset
+ PREV
.rm_blockcount
== new_endoff
)
1053 state
|= RMAP_RIGHT_FILLING
;
1056 * Decrement the cursor to see if we have a left-adjacent record to our
1057 * insertion point. This will give us the record for end block
1060 error
= xfs_btree_decrement(cur
, 0, &i
);
1064 state
|= RMAP_LEFT_VALID
;
1065 error
= xfs_rmap_get_rec(cur
, &LEFT
, &i
);
1068 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1069 error
= -EFSCORRUPTED
;
1072 if (XFS_IS_CORRUPT(mp
,
1073 LEFT
.rm_startblock
+ LEFT
.rm_blockcount
>
1075 error
= -EFSCORRUPTED
;
1078 trace_xfs_rmap_find_left_neighbor_result(cur
->bc_mp
,
1079 cur
->bc_ag
.agno
, LEFT
.rm_startblock
,
1080 LEFT
.rm_blockcount
, LEFT
.rm_owner
,
1081 LEFT
.rm_offset
, LEFT
.rm_flags
);
1082 if (LEFT
.rm_startblock
+ LEFT
.rm_blockcount
== bno
&&
1083 LEFT
.rm_offset
+ LEFT
.rm_blockcount
== offset
&&
1084 xfs_rmap_is_mergeable(&LEFT
, owner
, newext
))
1085 state
|= RMAP_LEFT_CONTIG
;
1089 * Increment the cursor to see if we have a right-adjacent record to our
1090 * insertion point. This will give us the record for end block
1093 error
= xfs_btree_increment(cur
, 0, &i
);
1096 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1097 error
= -EFSCORRUPTED
;
1100 error
= xfs_btree_increment(cur
, 0, &i
);
1104 state
|= RMAP_RIGHT_VALID
;
1105 error
= xfs_rmap_get_rec(cur
, &RIGHT
, &i
);
1108 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1109 error
= -EFSCORRUPTED
;
1112 if (XFS_IS_CORRUPT(mp
, bno
+ len
> RIGHT
.rm_startblock
)) {
1113 error
= -EFSCORRUPTED
;
1116 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1117 cur
->bc_ag
.agno
, RIGHT
.rm_startblock
,
1118 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1119 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1120 if (bno
+ len
== RIGHT
.rm_startblock
&&
1121 offset
+ len
== RIGHT
.rm_offset
&&
1122 xfs_rmap_is_mergeable(&RIGHT
, owner
, newext
))
1123 state
|= RMAP_RIGHT_CONTIG
;
1126 /* check that left + prev + right is not too long */
1127 if ((state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1128 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) ==
1129 (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1130 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
) &&
1131 (unsigned long)LEFT
.rm_blockcount
+ len
+
1132 RIGHT
.rm_blockcount
> XFS_RMAP_LEN_MAX
)
1133 state
&= ~RMAP_RIGHT_CONTIG
;
1135 trace_xfs_rmap_convert_state(mp
, cur
->bc_ag
.agno
, state
,
1138 /* reset the cursor back to PREV */
1139 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, oldext
, &i
);
1142 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1143 error
= -EFSCORRUPTED
;
1148 * Switch out based on the FILLING and CONTIG state bits.
1150 switch (state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1151 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) {
1152 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1153 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1155 * Setting all of a previous oldext extent to newext.
1156 * The left and right neighbors are both contiguous with new.
1158 error
= xfs_btree_increment(cur
, 0, &i
);
1161 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1162 error
= -EFSCORRUPTED
;
1165 trace_xfs_rmap_delete(mp
, cur
->bc_ag
.agno
,
1166 RIGHT
.rm_startblock
, RIGHT
.rm_blockcount
,
1167 RIGHT
.rm_owner
, RIGHT
.rm_offset
,
1169 error
= xfs_btree_delete(cur
, &i
);
1172 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1173 error
= -EFSCORRUPTED
;
1176 error
= xfs_btree_decrement(cur
, 0, &i
);
1179 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1180 error
= -EFSCORRUPTED
;
1183 trace_xfs_rmap_delete(mp
, cur
->bc_ag
.agno
,
1184 PREV
.rm_startblock
, PREV
.rm_blockcount
,
1185 PREV
.rm_owner
, PREV
.rm_offset
,
1187 error
= xfs_btree_delete(cur
, &i
);
1190 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1191 error
= -EFSCORRUPTED
;
1194 error
= xfs_btree_decrement(cur
, 0, &i
);
1197 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1198 error
= -EFSCORRUPTED
;
1202 NEW
.rm_blockcount
+= PREV
.rm_blockcount
+ RIGHT
.rm_blockcount
;
1203 error
= xfs_rmap_update(cur
, &NEW
);
1208 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1210 * Setting all of a previous oldext extent to newext.
1211 * The left neighbor is contiguous, the right is not.
1213 trace_xfs_rmap_delete(mp
, cur
->bc_ag
.agno
,
1214 PREV
.rm_startblock
, PREV
.rm_blockcount
,
1215 PREV
.rm_owner
, PREV
.rm_offset
,
1217 error
= xfs_btree_delete(cur
, &i
);
1220 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1221 error
= -EFSCORRUPTED
;
1224 error
= xfs_btree_decrement(cur
, 0, &i
);
1227 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1228 error
= -EFSCORRUPTED
;
1232 NEW
.rm_blockcount
+= PREV
.rm_blockcount
;
1233 error
= xfs_rmap_update(cur
, &NEW
);
1238 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1240 * Setting all of a previous oldext extent to newext.
1241 * The right neighbor is contiguous, the left is not.
1243 error
= xfs_btree_increment(cur
, 0, &i
);
1246 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1247 error
= -EFSCORRUPTED
;
1250 trace_xfs_rmap_delete(mp
, cur
->bc_ag
.agno
,
1251 RIGHT
.rm_startblock
, RIGHT
.rm_blockcount
,
1252 RIGHT
.rm_owner
, RIGHT
.rm_offset
,
1254 error
= xfs_btree_delete(cur
, &i
);
1257 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1258 error
= -EFSCORRUPTED
;
1261 error
= xfs_btree_decrement(cur
, 0, &i
);
1264 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1265 error
= -EFSCORRUPTED
;
1269 NEW
.rm_blockcount
= len
+ RIGHT
.rm_blockcount
;
1270 NEW
.rm_flags
= newext
;
1271 error
= xfs_rmap_update(cur
, &NEW
);
1276 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
:
1278 * Setting all of a previous oldext extent to newext.
1279 * Neither the left nor right neighbors are contiguous with
1283 NEW
.rm_flags
= newext
;
1284 error
= xfs_rmap_update(cur
, &NEW
);
1289 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
:
1291 * Setting the first part of a previous oldext extent to newext.
1292 * The left neighbor is contiguous.
1295 NEW
.rm_offset
+= len
;
1296 NEW
.rm_startblock
+= len
;
1297 NEW
.rm_blockcount
-= len
;
1298 error
= xfs_rmap_update(cur
, &NEW
);
1301 error
= xfs_btree_decrement(cur
, 0, &i
);
1305 NEW
.rm_blockcount
+= len
;
1306 error
= xfs_rmap_update(cur
, &NEW
);
1311 case RMAP_LEFT_FILLING
:
1313 * Setting the first part of a previous oldext extent to newext.
1314 * The left neighbor is not contiguous.
1317 NEW
.rm_startblock
+= len
;
1318 NEW
.rm_offset
+= len
;
1319 NEW
.rm_blockcount
-= len
;
1320 error
= xfs_rmap_update(cur
, &NEW
);
1323 NEW
.rm_startblock
= bno
;
1324 NEW
.rm_owner
= owner
;
1325 NEW
.rm_offset
= offset
;
1326 NEW
.rm_blockcount
= len
;
1327 NEW
.rm_flags
= newext
;
1328 cur
->bc_rec
.r
= NEW
;
1329 trace_xfs_rmap_insert(mp
, cur
->bc_ag
.agno
, bno
,
1330 len
, owner
, offset
, newext
);
1331 error
= xfs_btree_insert(cur
, &i
);
1334 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1335 error
= -EFSCORRUPTED
;
1340 case RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1342 * Setting the last part of a previous oldext extent to newext.
1343 * The right neighbor is contiguous with the new allocation.
1346 NEW
.rm_blockcount
-= len
;
1347 error
= xfs_rmap_update(cur
, &NEW
);
1350 error
= xfs_btree_increment(cur
, 0, &i
);
1354 NEW
.rm_offset
= offset
;
1355 NEW
.rm_startblock
= bno
;
1356 NEW
.rm_blockcount
+= len
;
1357 error
= xfs_rmap_update(cur
, &NEW
);
1362 case RMAP_RIGHT_FILLING
:
1364 * Setting the last part of a previous oldext extent to newext.
1365 * The right neighbor is not contiguous.
1368 NEW
.rm_blockcount
-= len
;
1369 error
= xfs_rmap_update(cur
, &NEW
);
1372 error
= xfs_rmap_lookup_eq(cur
, bno
, len
, owner
, offset
,
1376 if (XFS_IS_CORRUPT(mp
, i
!= 0)) {
1377 error
= -EFSCORRUPTED
;
1380 NEW
.rm_startblock
= bno
;
1381 NEW
.rm_owner
= owner
;
1382 NEW
.rm_offset
= offset
;
1383 NEW
.rm_blockcount
= len
;
1384 NEW
.rm_flags
= newext
;
1385 cur
->bc_rec
.r
= NEW
;
1386 trace_xfs_rmap_insert(mp
, cur
->bc_ag
.agno
, bno
,
1387 len
, owner
, offset
, newext
);
1388 error
= xfs_btree_insert(cur
, &i
);
1391 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1392 error
= -EFSCORRUPTED
;
1399 * Setting the middle part of a previous oldext extent to
1400 * newext. Contiguity is impossible here.
1401 * One extent becomes three extents.
1403 /* new right extent - oldext */
1404 NEW
.rm_startblock
= bno
+ len
;
1405 NEW
.rm_owner
= owner
;
1406 NEW
.rm_offset
= new_endoff
;
1407 NEW
.rm_blockcount
= PREV
.rm_offset
+ PREV
.rm_blockcount
-
1409 NEW
.rm_flags
= PREV
.rm_flags
;
1410 error
= xfs_rmap_update(cur
, &NEW
);
1413 /* new left extent - oldext */
1415 NEW
.rm_blockcount
= offset
- PREV
.rm_offset
;
1416 cur
->bc_rec
.r
= NEW
;
1417 trace_xfs_rmap_insert(mp
, cur
->bc_ag
.agno
,
1418 NEW
.rm_startblock
, NEW
.rm_blockcount
,
1419 NEW
.rm_owner
, NEW
.rm_offset
,
1421 error
= xfs_btree_insert(cur
, &i
);
1424 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1425 error
= -EFSCORRUPTED
;
1429 * Reset the cursor to the position of the new extent
1430 * we are about to insert as we can't trust it after
1431 * the previous insert.
1433 error
= xfs_rmap_lookup_eq(cur
, bno
, len
, owner
, offset
,
1437 if (XFS_IS_CORRUPT(mp
, i
!= 0)) {
1438 error
= -EFSCORRUPTED
;
1441 /* new middle extent - newext */
1442 cur
->bc_rec
.r
.rm_flags
&= ~XFS_RMAP_UNWRITTEN
;
1443 cur
->bc_rec
.r
.rm_flags
|= newext
;
1444 trace_xfs_rmap_insert(mp
, cur
->bc_ag
.agno
, bno
, len
,
1445 owner
, offset
, newext
);
1446 error
= xfs_btree_insert(cur
, &i
);
1449 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1450 error
= -EFSCORRUPTED
;
1455 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1456 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1457 case RMAP_LEFT_FILLING
| RMAP_RIGHT_CONTIG
:
1458 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1459 case RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1460 case RMAP_LEFT_CONTIG
:
1461 case RMAP_RIGHT_CONTIG
:
1463 * These cases are all impossible.
1468 trace_xfs_rmap_convert_done(mp
, cur
->bc_ag
.agno
, bno
, len
,
1472 trace_xfs_rmap_convert_error(cur
->bc_mp
,
1473 cur
->bc_ag
.agno
, error
, _RET_IP_
);
1478 * Convert an unwritten extent to a real extent or vice versa. If there is no
1479 * possibility of overlapping extents, delegate to the simpler convert
1483 xfs_rmap_convert_shared(
1484 struct xfs_btree_cur
*cur
,
1488 const struct xfs_owner_info
*oinfo
)
1490 struct xfs_mount
*mp
= cur
->bc_mp
;
1491 struct xfs_rmap_irec r
[4]; /* neighbor extent entries */
1492 /* left is 0, right is 1, */
1493 /* prev is 2, new is 3 */
1496 uint64_t new_endoff
;
1497 unsigned int oldext
;
1498 unsigned int newext
;
1499 unsigned int flags
= 0;
1504 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1505 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner
) ||
1506 (flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
))));
1507 oldext
= unwritten
? XFS_RMAP_UNWRITTEN
: 0;
1508 new_endoff
= offset
+ len
;
1509 trace_xfs_rmap_convert(mp
, cur
->bc_ag
.agno
, bno
, len
,
1513 * For the initial lookup, look for and exact match or the left-adjacent
1514 * record for our insertion point. This will also give us the record for
1515 * start block contiguity tests.
1517 error
= xfs_rmap_lookup_le_range(cur
, bno
, owner
, offset
, oldext
,
1521 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1522 error
= -EFSCORRUPTED
;
1526 ASSERT(PREV
.rm_offset
<= offset
);
1527 ASSERT(PREV
.rm_offset
+ PREV
.rm_blockcount
>= new_endoff
);
1528 ASSERT((PREV
.rm_flags
& XFS_RMAP_UNWRITTEN
) == oldext
);
1529 newext
= ~oldext
& XFS_RMAP_UNWRITTEN
;
1532 * Set flags determining what part of the previous oldext allocation
1533 * extent is being replaced by a newext allocation.
1535 if (PREV
.rm_offset
== offset
)
1536 state
|= RMAP_LEFT_FILLING
;
1537 if (PREV
.rm_offset
+ PREV
.rm_blockcount
== new_endoff
)
1538 state
|= RMAP_RIGHT_FILLING
;
1540 /* Is there a left record that abuts our range? */
1541 error
= xfs_rmap_find_left_neighbor(cur
, bno
, owner
, offset
, newext
,
1546 state
|= RMAP_LEFT_VALID
;
1547 if (XFS_IS_CORRUPT(mp
,
1548 LEFT
.rm_startblock
+ LEFT
.rm_blockcount
>
1550 error
= -EFSCORRUPTED
;
1553 if (xfs_rmap_is_mergeable(&LEFT
, owner
, newext
))
1554 state
|= RMAP_LEFT_CONTIG
;
1557 /* Is there a right record that abuts our range? */
1558 error
= xfs_rmap_lookup_eq(cur
, bno
+ len
, len
, owner
, offset
+ len
,
1563 state
|= RMAP_RIGHT_VALID
;
1564 error
= xfs_rmap_get_rec(cur
, &RIGHT
, &i
);
1567 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1568 error
= -EFSCORRUPTED
;
1571 if (XFS_IS_CORRUPT(mp
, bno
+ len
> RIGHT
.rm_startblock
)) {
1572 error
= -EFSCORRUPTED
;
1575 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1576 cur
->bc_ag
.agno
, RIGHT
.rm_startblock
,
1577 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1578 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1579 if (xfs_rmap_is_mergeable(&RIGHT
, owner
, newext
))
1580 state
|= RMAP_RIGHT_CONTIG
;
1583 /* check that left + prev + right is not too long */
1584 if ((state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1585 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) ==
1586 (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1587 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
) &&
1588 (unsigned long)LEFT
.rm_blockcount
+ len
+
1589 RIGHT
.rm_blockcount
> XFS_RMAP_LEN_MAX
)
1590 state
&= ~RMAP_RIGHT_CONTIG
;
1592 trace_xfs_rmap_convert_state(mp
, cur
->bc_ag
.agno
, state
,
1595 * Switch out based on the FILLING and CONTIG state bits.
1597 switch (state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1598 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) {
1599 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1600 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1602 * Setting all of a previous oldext extent to newext.
1603 * The left and right neighbors are both contiguous with new.
1605 error
= xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1606 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1607 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1610 error
= xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1611 PREV
.rm_blockcount
, PREV
.rm_owner
,
1612 PREV
.rm_offset
, PREV
.rm_flags
);
1616 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1617 NEW
.rm_blockcount
, NEW
.rm_owner
,
1618 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1621 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1622 error
= -EFSCORRUPTED
;
1625 NEW
.rm_blockcount
+= PREV
.rm_blockcount
+ RIGHT
.rm_blockcount
;
1626 error
= xfs_rmap_update(cur
, &NEW
);
1631 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1633 * Setting all of a previous oldext extent to newext.
1634 * The left neighbor is contiguous, the right is not.
1636 error
= xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1637 PREV
.rm_blockcount
, PREV
.rm_owner
,
1638 PREV
.rm_offset
, PREV
.rm_flags
);
1642 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1643 NEW
.rm_blockcount
, NEW
.rm_owner
,
1644 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1647 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1648 error
= -EFSCORRUPTED
;
1651 NEW
.rm_blockcount
+= PREV
.rm_blockcount
;
1652 error
= xfs_rmap_update(cur
, &NEW
);
1657 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1659 * Setting all of a previous oldext extent to newext.
1660 * The right neighbor is contiguous, the left is not.
1662 error
= xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1663 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1664 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1668 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1669 NEW
.rm_blockcount
, NEW
.rm_owner
,
1670 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1673 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1674 error
= -EFSCORRUPTED
;
1677 NEW
.rm_blockcount
+= RIGHT
.rm_blockcount
;
1678 NEW
.rm_flags
= RIGHT
.rm_flags
;
1679 error
= xfs_rmap_update(cur
, &NEW
);
1684 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
:
1686 * Setting all of a previous oldext extent to newext.
1687 * Neither the left nor right neighbors are contiguous with
1691 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1692 NEW
.rm_blockcount
, NEW
.rm_owner
,
1693 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1696 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1697 error
= -EFSCORRUPTED
;
1700 NEW
.rm_flags
= newext
;
1701 error
= xfs_rmap_update(cur
, &NEW
);
1706 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
:
1708 * Setting the first part of a previous oldext extent to newext.
1709 * The left neighbor is contiguous.
1712 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1713 NEW
.rm_blockcount
, NEW
.rm_owner
,
1714 NEW
.rm_offset
, NEW
.rm_flags
);
1717 NEW
.rm_offset
+= len
;
1718 NEW
.rm_startblock
+= len
;
1719 NEW
.rm_blockcount
-= len
;
1720 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1721 NEW
.rm_blockcount
, NEW
.rm_owner
,
1722 NEW
.rm_offset
, NEW
.rm_flags
);
1726 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1727 NEW
.rm_blockcount
, NEW
.rm_owner
,
1728 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1731 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1732 error
= -EFSCORRUPTED
;
1735 NEW
.rm_blockcount
+= len
;
1736 error
= xfs_rmap_update(cur
, &NEW
);
1741 case RMAP_LEFT_FILLING
:
1743 * Setting the first part of a previous oldext extent to newext.
1744 * The left neighbor is not contiguous.
1747 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1748 NEW
.rm_blockcount
, NEW
.rm_owner
,
1749 NEW
.rm_offset
, NEW
.rm_flags
);
1752 NEW
.rm_offset
+= len
;
1753 NEW
.rm_startblock
+= len
;
1754 NEW
.rm_blockcount
-= len
;
1755 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1756 NEW
.rm_blockcount
, NEW
.rm_owner
,
1757 NEW
.rm_offset
, NEW
.rm_flags
);
1760 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1765 case RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1767 * Setting the last part of a previous oldext extent to newext.
1768 * The right neighbor is contiguous with the new allocation.
1771 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1772 NEW
.rm_blockcount
, NEW
.rm_owner
,
1773 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1776 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1777 error
= -EFSCORRUPTED
;
1780 NEW
.rm_blockcount
= offset
- NEW
.rm_offset
;
1781 error
= xfs_rmap_update(cur
, &NEW
);
1785 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1786 NEW
.rm_blockcount
, NEW
.rm_owner
,
1787 NEW
.rm_offset
, NEW
.rm_flags
);
1790 NEW
.rm_offset
= offset
;
1791 NEW
.rm_startblock
= bno
;
1792 NEW
.rm_blockcount
+= len
;
1793 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1794 NEW
.rm_blockcount
, NEW
.rm_owner
,
1795 NEW
.rm_offset
, NEW
.rm_flags
);
1800 case RMAP_RIGHT_FILLING
:
1802 * Setting the last part of a previous oldext extent to newext.
1803 * The right neighbor is not contiguous.
1806 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1807 NEW
.rm_blockcount
, NEW
.rm_owner
,
1808 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1811 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1812 error
= -EFSCORRUPTED
;
1815 NEW
.rm_blockcount
-= len
;
1816 error
= xfs_rmap_update(cur
, &NEW
);
1819 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1826 * Setting the middle part of a previous oldext extent to
1827 * newext. Contiguity is impossible here.
1828 * One extent becomes three extents.
1830 /* new right extent - oldext */
1831 NEW
.rm_startblock
= bno
+ len
;
1832 NEW
.rm_owner
= owner
;
1833 NEW
.rm_offset
= new_endoff
;
1834 NEW
.rm_blockcount
= PREV
.rm_offset
+ PREV
.rm_blockcount
-
1836 NEW
.rm_flags
= PREV
.rm_flags
;
1837 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1838 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
1842 /* new left extent - oldext */
1844 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1845 NEW
.rm_blockcount
, NEW
.rm_owner
,
1846 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1849 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1850 error
= -EFSCORRUPTED
;
1853 NEW
.rm_blockcount
= offset
- NEW
.rm_offset
;
1854 error
= xfs_rmap_update(cur
, &NEW
);
1857 /* new middle extent - newext */
1858 NEW
.rm_startblock
= bno
;
1859 NEW
.rm_blockcount
= len
;
1860 NEW
.rm_owner
= owner
;
1861 NEW
.rm_offset
= offset
;
1862 NEW
.rm_flags
= newext
;
1863 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1864 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
1870 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1871 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1872 case RMAP_LEFT_FILLING
| RMAP_RIGHT_CONTIG
:
1873 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1874 case RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1875 case RMAP_LEFT_CONTIG
:
1876 case RMAP_RIGHT_CONTIG
:
1878 * These cases are all impossible.
1883 trace_xfs_rmap_convert_done(mp
, cur
->bc_ag
.agno
, bno
, len
,
1887 trace_xfs_rmap_convert_error(cur
->bc_mp
,
1888 cur
->bc_ag
.agno
, error
, _RET_IP_
);
1898 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1899 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1900 * that the prev/next records in the btree might belong to another owner.
1901 * Therefore we must use delete+insert to alter any of the key fields.
1903 * For every other situation there can only be one owner for a given extent,
1904 * so we can call the regular _free function.
1907 xfs_rmap_unmap_shared(
1908 struct xfs_btree_cur
*cur
,
1912 const struct xfs_owner_info
*oinfo
)
1914 struct xfs_mount
*mp
= cur
->bc_mp
;
1915 struct xfs_rmap_irec ltrec
;
1923 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1925 flags
|= XFS_RMAP_UNWRITTEN
;
1926 trace_xfs_rmap_unmap(mp
, cur
->bc_ag
.agno
, bno
, len
,
1930 * We should always have a left record because there's a static record
1931 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1932 * will not ever be removed from the tree.
1934 error
= xfs_rmap_lookup_le_range(cur
, bno
, owner
, offset
, flags
,
1938 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1939 error
= -EFSCORRUPTED
;
1942 ltoff
= ltrec
.rm_offset
;
1944 /* Make sure the extent we found covers the entire freeing range. */
1945 if (XFS_IS_CORRUPT(mp
,
1946 ltrec
.rm_startblock
> bno
||
1947 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
<
1949 error
= -EFSCORRUPTED
;
1953 /* Make sure the owner matches what we expect to find in the tree. */
1954 if (XFS_IS_CORRUPT(mp
, owner
!= ltrec
.rm_owner
)) {
1955 error
= -EFSCORRUPTED
;
1959 /* Make sure the unwritten flag matches. */
1960 if (XFS_IS_CORRUPT(mp
,
1961 (flags
& XFS_RMAP_UNWRITTEN
) !=
1962 (ltrec
.rm_flags
& XFS_RMAP_UNWRITTEN
))) {
1963 error
= -EFSCORRUPTED
;
1967 /* Check the offset. */
1968 if (XFS_IS_CORRUPT(mp
, ltrec
.rm_offset
> offset
)) {
1969 error
= -EFSCORRUPTED
;
1972 if (XFS_IS_CORRUPT(mp
, offset
> ltoff
+ ltrec
.rm_blockcount
)) {
1973 error
= -EFSCORRUPTED
;
1977 if (ltrec
.rm_startblock
== bno
&& ltrec
.rm_blockcount
== len
) {
1978 /* Exact match, simply remove the record from rmap tree. */
1979 error
= xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
1980 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1981 ltrec
.rm_offset
, ltrec
.rm_flags
);
1984 } else if (ltrec
.rm_startblock
== bno
) {
1986 * Overlap left hand side of extent: move the start, trim the
1987 * length and update the current record.
1990 * Orig: |oooooooooooooooooooo|
1991 * Freeing: |fffffffff|
1992 * Result: |rrrrrrrrrr|
1996 /* Delete prev rmap. */
1997 error
= xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
1998 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1999 ltrec
.rm_offset
, ltrec
.rm_flags
);
2003 /* Add an rmap at the new offset. */
2004 ltrec
.rm_startblock
+= len
;
2005 ltrec
.rm_blockcount
-= len
;
2006 ltrec
.rm_offset
+= len
;
2007 error
= xfs_rmap_insert(cur
, ltrec
.rm_startblock
,
2008 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
2009 ltrec
.rm_offset
, ltrec
.rm_flags
);
2012 } else if (ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
+ len
) {
2014 * Overlap right hand side of extent: trim the length and
2015 * update the current record.
2018 * Orig: |oooooooooooooooooooo|
2019 * Freeing: |fffffffff|
2020 * Result: |rrrrrrrrrr|
2023 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
2024 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
2025 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
2028 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
2029 error
= -EFSCORRUPTED
;
2032 ltrec
.rm_blockcount
-= len
;
2033 error
= xfs_rmap_update(cur
, <rec
);
2038 * Overlap middle of extent: trim the length of the existing
2039 * record to the length of the new left-extent size, increment
2040 * the insertion position so we can insert a new record
2041 * containing the remaining right-extent space.
2044 * Orig: |oooooooooooooooooooo|
2045 * Freeing: |fffffffff|
2046 * Result: |rrrrr| |rrrr|
2049 xfs_extlen_t orig_len
= ltrec
.rm_blockcount
;
2051 /* Shrink the left side of the rmap */
2052 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
2053 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
2054 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
2057 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
2058 error
= -EFSCORRUPTED
;
2061 ltrec
.rm_blockcount
= bno
- ltrec
.rm_startblock
;
2062 error
= xfs_rmap_update(cur
, <rec
);
2066 /* Add an rmap at the new offset */
2067 error
= xfs_rmap_insert(cur
, bno
+ len
,
2068 orig_len
- len
- ltrec
.rm_blockcount
,
2069 ltrec
.rm_owner
, offset
+ len
,
2075 trace_xfs_rmap_unmap_done(mp
, cur
->bc_ag
.agno
, bno
, len
,
2079 trace_xfs_rmap_unmap_error(cur
->bc_mp
,
2080 cur
->bc_ag
.agno
, error
, _RET_IP_
);
2085 * Find an extent in the rmap btree and map it. For rmap extent types that
2086 * can overlap (data fork rmaps on reflink filesystems) we must be careful
2087 * that the prev/next records in the btree might belong to another owner.
2088 * Therefore we must use delete+insert to alter any of the key fields.
2090 * For every other situation there can only be one owner for a given extent,
2091 * so we can call the regular _alloc function.
2094 xfs_rmap_map_shared(
2095 struct xfs_btree_cur
*cur
,
2099 const struct xfs_owner_info
*oinfo
)
2101 struct xfs_mount
*mp
= cur
->bc_mp
;
2102 struct xfs_rmap_irec ltrec
;
2103 struct xfs_rmap_irec gtrec
;
2110 unsigned int flags
= 0;
2112 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
2114 flags
|= XFS_RMAP_UNWRITTEN
;
2115 trace_xfs_rmap_map(mp
, cur
->bc_ag
.agno
, bno
, len
,
2118 /* Is there a left record that abuts our range? */
2119 error
= xfs_rmap_find_left_neighbor(cur
, bno
, owner
, offset
, flags
,
2124 !xfs_rmap_is_mergeable(<rec
, owner
, flags
))
2127 /* Is there a right record that abuts our range? */
2128 error
= xfs_rmap_lookup_eq(cur
, bno
+ len
, len
, owner
, offset
+ len
,
2133 error
= xfs_rmap_get_rec(cur
, >rec
, &have_gt
);
2136 if (XFS_IS_CORRUPT(mp
, have_gt
!= 1)) {
2137 error
= -EFSCORRUPTED
;
2140 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
2141 cur
->bc_ag
.agno
, gtrec
.rm_startblock
,
2142 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2143 gtrec
.rm_offset
, gtrec
.rm_flags
);
2145 if (!xfs_rmap_is_mergeable(>rec
, owner
, flags
))
2150 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
&&
2151 ltrec
.rm_offset
+ ltrec
.rm_blockcount
== offset
) {
2153 * Left edge contiguous, merge into left record.
2157 * adding: |aaaaaaaaa|
2158 * result: |rrrrrrrrrrrrrrrrrrr|
2161 ltrec
.rm_blockcount
+= len
;
2163 bno
+ len
== gtrec
.rm_startblock
&&
2164 offset
+ len
== gtrec
.rm_offset
) {
2166 * Right edge also contiguous, delete right record
2167 * and merge into left record.
2169 * ltbno ltlen gtbno gtlen
2170 * orig: |ooooooooo| |ooooooooo|
2171 * adding: |aaaaaaaaa|
2172 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
2174 ltrec
.rm_blockcount
+= gtrec
.rm_blockcount
;
2175 error
= xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
2176 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2177 gtrec
.rm_offset
, gtrec
.rm_flags
);
2182 /* Point the cursor back to the left record and update. */
2183 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
2184 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
2185 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
2188 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
2189 error
= -EFSCORRUPTED
;
2193 error
= xfs_rmap_update(cur
, <rec
);
2196 } else if (have_gt
&&
2197 bno
+ len
== gtrec
.rm_startblock
&&
2198 offset
+ len
== gtrec
.rm_offset
) {
2200 * Right edge contiguous, merge into right record.
2204 * adding: |aaaaaaaaa|
2205 * Result: |rrrrrrrrrrrrrrrrrrr|
2208 /* Delete the old record. */
2209 error
= xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
2210 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2211 gtrec
.rm_offset
, gtrec
.rm_flags
);
2215 /* Move the start and re-add it. */
2216 gtrec
.rm_startblock
= bno
;
2217 gtrec
.rm_blockcount
+= len
;
2218 gtrec
.rm_offset
= offset
;
2219 error
= xfs_rmap_insert(cur
, gtrec
.rm_startblock
,
2220 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2221 gtrec
.rm_offset
, gtrec
.rm_flags
);
2226 * No contiguous edge with identical owner, insert
2227 * new record at current cursor position.
2229 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, flags
);
2234 trace_xfs_rmap_map_done(mp
, cur
->bc_ag
.agno
, bno
, len
,
2238 trace_xfs_rmap_map_error(cur
->bc_mp
,
2239 cur
->bc_ag
.agno
, error
, _RET_IP_
);
2243 /* Insert a raw rmap into the rmapbt. */
2246 struct xfs_btree_cur
*cur
,
2247 struct xfs_rmap_irec
*rmap
)
2249 struct xfs_owner_info oinfo
;
2251 oinfo
.oi_owner
= rmap
->rm_owner
;
2252 oinfo
.oi_offset
= rmap
->rm_offset
;
2254 if (rmap
->rm_flags
& XFS_RMAP_ATTR_FORK
)
2255 oinfo
.oi_flags
|= XFS_OWNER_INFO_ATTR_FORK
;
2256 if (rmap
->rm_flags
& XFS_RMAP_BMBT_BLOCK
)
2257 oinfo
.oi_flags
|= XFS_OWNER_INFO_BMBT_BLOCK
;
2259 if (rmap
->rm_flags
|| XFS_RMAP_NON_INODE_OWNER(rmap
->rm_owner
))
2260 return xfs_rmap_map(cur
, rmap
->rm_startblock
,
2261 rmap
->rm_blockcount
,
2262 rmap
->rm_flags
& XFS_RMAP_UNWRITTEN
,
2265 return xfs_rmap_map_shared(cur
, rmap
->rm_startblock
,
2266 rmap
->rm_blockcount
,
2267 rmap
->rm_flags
& XFS_RMAP_UNWRITTEN
,
2271 struct xfs_rmap_query_range_info
{
2272 xfs_rmap_query_range_fn fn
;
2276 /* Format btree record and pass to our callback. */
2278 xfs_rmap_query_range_helper(
2279 struct xfs_btree_cur
*cur
,
2280 union xfs_btree_rec
*rec
,
2283 struct xfs_rmap_query_range_info
*query
= priv
;
2284 struct xfs_rmap_irec irec
;
2287 error
= xfs_rmap_btrec_to_irec(rec
, &irec
);
2290 return query
->fn(cur
, &irec
, query
->priv
);
2293 /* Find all rmaps between two keys. */
2295 xfs_rmap_query_range(
2296 struct xfs_btree_cur
*cur
,
2297 struct xfs_rmap_irec
*low_rec
,
2298 struct xfs_rmap_irec
*high_rec
,
2299 xfs_rmap_query_range_fn fn
,
2302 union xfs_btree_irec low_brec
;
2303 union xfs_btree_irec high_brec
;
2304 struct xfs_rmap_query_range_info query
;
2306 low_brec
.r
= *low_rec
;
2307 high_brec
.r
= *high_rec
;
2310 return xfs_btree_query_range(cur
, &low_brec
, &high_brec
,
2311 xfs_rmap_query_range_helper
, &query
);
2314 /* Find all rmaps. */
2317 struct xfs_btree_cur
*cur
,
2318 xfs_rmap_query_range_fn fn
,
2321 struct xfs_rmap_query_range_info query
;
2325 return xfs_btree_query_all(cur
, xfs_rmap_query_range_helper
, &query
);
2328 /* Clean up after calling xfs_rmap_finish_one. */
2330 xfs_rmap_finish_one_cleanup(
2331 struct xfs_trans
*tp
,
2332 struct xfs_btree_cur
*rcur
,
2335 struct xfs_buf
*agbp
;
2339 agbp
= rcur
->bc_ag
.agbp
;
2340 xfs_btree_del_cursor(rcur
, error
);
2342 xfs_trans_brelse(tp
, agbp
);
2346 * Process one of the deferred rmap operations. We pass back the
2347 * btree cursor to maintain our lock on the rmapbt between calls.
2348 * This saves time and eliminates a buffer deadlock between the
2349 * superblock and the AGF because we'll always grab them in the same
2353 xfs_rmap_finish_one(
2354 struct xfs_trans
*tp
,
2355 enum xfs_rmap_intent_type type
,
2358 xfs_fileoff_t startoff
,
2359 xfs_fsblock_t startblock
,
2360 xfs_filblks_t blockcount
,
2362 struct xfs_btree_cur
**pcur
)
2364 struct xfs_mount
*mp
= tp
->t_mountp
;
2365 struct xfs_btree_cur
*rcur
;
2366 struct xfs_buf
*agbp
= NULL
;
2368 xfs_agnumber_t agno
;
2369 struct xfs_owner_info oinfo
;
2373 agno
= XFS_FSB_TO_AGNO(mp
, startblock
);
2374 ASSERT(agno
!= NULLAGNUMBER
);
2375 bno
= XFS_FSB_TO_AGBNO(mp
, startblock
);
2377 trace_xfs_rmap_deferred(mp
, agno
, type
, bno
, owner
, whichfork
,
2378 startoff
, blockcount
, state
);
2380 if (XFS_TEST_ERROR(false, mp
,
2381 XFS_ERRTAG_RMAP_FINISH_ONE
))
2385 * If we haven't gotten a cursor or the cursor AG doesn't match
2386 * the startblock, get one now.
2389 if (rcur
!= NULL
&& rcur
->bc_ag
.agno
!= agno
) {
2390 xfs_rmap_finish_one_cleanup(tp
, rcur
, 0);
2396 * Refresh the freelist before we start changing the
2397 * rmapbt, because a shape change could cause us to
2400 error
= xfs_free_extent_fix_freelist(tp
, agno
, &agbp
);
2403 if (XFS_IS_CORRUPT(tp
->t_mountp
, !agbp
))
2404 return -EFSCORRUPTED
;
2406 rcur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
2410 xfs_rmap_ino_owner(&oinfo
, owner
, whichfork
, startoff
);
2411 unwritten
= state
== XFS_EXT_UNWRITTEN
;
2412 bno
= XFS_FSB_TO_AGBNO(rcur
->bc_mp
, startblock
);
2415 case XFS_RMAP_ALLOC
:
2417 error
= xfs_rmap_map(rcur
, bno
, blockcount
, unwritten
, &oinfo
);
2419 case XFS_RMAP_MAP_SHARED
:
2420 error
= xfs_rmap_map_shared(rcur
, bno
, blockcount
, unwritten
,
2424 case XFS_RMAP_UNMAP
:
2425 error
= xfs_rmap_unmap(rcur
, bno
, blockcount
, unwritten
,
2428 case XFS_RMAP_UNMAP_SHARED
:
2429 error
= xfs_rmap_unmap_shared(rcur
, bno
, blockcount
, unwritten
,
2432 case XFS_RMAP_CONVERT
:
2433 error
= xfs_rmap_convert(rcur
, bno
, blockcount
, !unwritten
,
2436 case XFS_RMAP_CONVERT_SHARED
:
2437 error
= xfs_rmap_convert_shared(rcur
, bno
, blockcount
,
2438 !unwritten
, &oinfo
);
2442 error
= -EFSCORRUPTED
;
2448 * Don't defer an rmap if we aren't an rmap filesystem.
2451 xfs_rmap_update_is_needed(
2452 struct xfs_mount
*mp
,
2455 return xfs_sb_version_hasrmapbt(&mp
->m_sb
) && whichfork
!= XFS_COW_FORK
;
2459 * Record a rmap intent; the list is kept sorted first by AG and then by
2464 struct xfs_trans
*tp
,
2465 enum xfs_rmap_intent_type type
,
2468 struct xfs_bmbt_irec
*bmap
)
2470 struct xfs_rmap_intent
*ri
;
2472 trace_xfs_rmap_defer(tp
->t_mountp
,
2473 XFS_FSB_TO_AGNO(tp
->t_mountp
, bmap
->br_startblock
),
2475 XFS_FSB_TO_AGBNO(tp
->t_mountp
, bmap
->br_startblock
),
2478 bmap
->br_blockcount
,
2481 ri
= kmem_alloc(sizeof(struct xfs_rmap_intent
), KM_NOFS
);
2482 INIT_LIST_HEAD(&ri
->ri_list
);
2484 ri
->ri_owner
= owner
;
2485 ri
->ri_whichfork
= whichfork
;
2486 ri
->ri_bmap
= *bmap
;
2488 xfs_defer_add(tp
, XFS_DEFER_OPS_TYPE_RMAP
, &ri
->ri_list
);
2491 /* Map an extent into a file. */
2493 xfs_rmap_map_extent(
2494 struct xfs_trans
*tp
,
2495 struct xfs_inode
*ip
,
2497 struct xfs_bmbt_irec
*PREV
)
2499 enum xfs_rmap_intent_type type
= XFS_RMAP_MAP
;
2501 if (!xfs_rmap_update_is_needed(tp
->t_mountp
, whichfork
))
2504 if (whichfork
!= XFS_ATTR_FORK
&& xfs_is_reflink_inode(ip
))
2505 type
= XFS_RMAP_MAP_SHARED
;
2507 __xfs_rmap_add(tp
, type
, ip
->i_ino
, whichfork
, PREV
);
2510 /* Unmap an extent out of a file. */
2512 xfs_rmap_unmap_extent(
2513 struct xfs_trans
*tp
,
2514 struct xfs_inode
*ip
,
2516 struct xfs_bmbt_irec
*PREV
)
2518 enum xfs_rmap_intent_type type
= XFS_RMAP_UNMAP
;
2520 if (!xfs_rmap_update_is_needed(tp
->t_mountp
, whichfork
))
2523 if (whichfork
!= XFS_ATTR_FORK
&& xfs_is_reflink_inode(ip
))
2524 type
= XFS_RMAP_UNMAP_SHARED
;
2526 __xfs_rmap_add(tp
, type
, ip
->i_ino
, whichfork
, PREV
);
2530 * Convert a data fork extent from unwritten to real or vice versa.
2532 * Note that tp can be NULL here as no transaction is used for COW fork
2533 * unwritten conversion.
2536 xfs_rmap_convert_extent(
2537 struct xfs_mount
*mp
,
2538 struct xfs_trans
*tp
,
2539 struct xfs_inode
*ip
,
2541 struct xfs_bmbt_irec
*PREV
)
2543 enum xfs_rmap_intent_type type
= XFS_RMAP_CONVERT
;
2545 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2548 if (whichfork
!= XFS_ATTR_FORK
&& xfs_is_reflink_inode(ip
))
2549 type
= XFS_RMAP_CONVERT_SHARED
;
2551 __xfs_rmap_add(tp
, type
, ip
->i_ino
, whichfork
, PREV
);
2554 /* Schedule the creation of an rmap for non-file data. */
2556 xfs_rmap_alloc_extent(
2557 struct xfs_trans
*tp
,
2558 xfs_agnumber_t agno
,
2563 struct xfs_bmbt_irec bmap
;
2565 if (!xfs_rmap_update_is_needed(tp
->t_mountp
, XFS_DATA_FORK
))
2568 bmap
.br_startblock
= XFS_AGB_TO_FSB(tp
->t_mountp
, agno
, bno
);
2569 bmap
.br_blockcount
= len
;
2570 bmap
.br_startoff
= 0;
2571 bmap
.br_state
= XFS_EXT_NORM
;
2573 __xfs_rmap_add(tp
, XFS_RMAP_ALLOC
, owner
, XFS_DATA_FORK
, &bmap
);
2576 /* Schedule the deletion of an rmap for non-file data. */
2578 xfs_rmap_free_extent(
2579 struct xfs_trans
*tp
,
2580 xfs_agnumber_t agno
,
2585 struct xfs_bmbt_irec bmap
;
2587 if (!xfs_rmap_update_is_needed(tp
->t_mountp
, XFS_DATA_FORK
))
2590 bmap
.br_startblock
= XFS_AGB_TO_FSB(tp
->t_mountp
, agno
, bno
);
2591 bmap
.br_blockcount
= len
;
2592 bmap
.br_startoff
= 0;
2593 bmap
.br_state
= XFS_EXT_NORM
;
2595 __xfs_rmap_add(tp
, XFS_RMAP_FREE
, owner
, XFS_DATA_FORK
, &bmap
);
2598 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2601 const struct xfs_rmap_irec
*a
,
2602 const struct xfs_rmap_irec
*b
)
2607 oa
= xfs_rmap_irec_offset_pack(a
);
2608 ob
= xfs_rmap_irec_offset_pack(b
);
2610 if (a
->rm_startblock
< b
->rm_startblock
)
2612 else if (a
->rm_startblock
> b
->rm_startblock
)
2614 else if (a
->rm_owner
< b
->rm_owner
)
2616 else if (a
->rm_owner
> b
->rm_owner
)
2626 /* Is there a record covering a given extent? */
2628 xfs_rmap_has_record(
2629 struct xfs_btree_cur
*cur
,
2634 union xfs_btree_irec low
;
2635 union xfs_btree_irec high
;
2637 memset(&low
, 0, sizeof(low
));
2638 low
.r
.rm_startblock
= bno
;
2639 memset(&high
, 0xFF, sizeof(high
));
2640 high
.r
.rm_startblock
= bno
+ len
- 1;
2642 return xfs_btree_has_record(cur
, &low
, &high
, exists
);
2646 * Is there a record for this owner completely covering a given physical
2647 * extent? If so, *has_rmap will be set to true. If there is no record
2648 * or the record only covers part of the range, we set *has_rmap to false.
2649 * This function doesn't perform range lookups or offset checks, so it is
2650 * not suitable for checking data fork blocks.
2653 xfs_rmap_record_exists(
2654 struct xfs_btree_cur
*cur
,
2657 const struct xfs_owner_info
*oinfo
,
2664 struct xfs_rmap_irec irec
;
2667 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
2668 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner
) ||
2669 (flags
& XFS_RMAP_BMBT_BLOCK
));
2671 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
,
2680 error
= xfs_rmap_get_rec(cur
, &irec
, &has_record
);
2688 *has_rmap
= (irec
.rm_owner
== owner
&& irec
.rm_startblock
<= bno
&&
2689 irec
.rm_startblock
+ irec
.rm_blockcount
>= bno
+ len
);
2693 struct xfs_rmap_key_state
{
2699 /* For each rmap given, figure out if it doesn't match the key we want. */
2701 xfs_rmap_has_other_keys_helper(
2702 struct xfs_btree_cur
*cur
,
2703 struct xfs_rmap_irec
*rec
,
2706 struct xfs_rmap_key_state
*rks
= priv
;
2708 if (rks
->owner
== rec
->rm_owner
&& rks
->offset
== rec
->rm_offset
&&
2709 ((rks
->flags
& rec
->rm_flags
) & XFS_RMAP_KEY_FLAGS
) == rks
->flags
)
2715 * Given an extent and some owner info, can we find records overlapping
2716 * the extent whose owner info does not match the given owner?
2719 xfs_rmap_has_other_keys(
2720 struct xfs_btree_cur
*cur
,
2723 const struct xfs_owner_info
*oinfo
,
2726 struct xfs_rmap_irec low
= {0};
2727 struct xfs_rmap_irec high
;
2728 struct xfs_rmap_key_state rks
;
2731 xfs_owner_info_unpack(oinfo
, &rks
.owner
, &rks
.offset
, &rks
.flags
);
2734 low
.rm_startblock
= bno
;
2735 memset(&high
, 0xFF, sizeof(high
));
2736 high
.rm_startblock
= bno
+ len
- 1;
2738 error
= xfs_rmap_query_range(cur
, &low
, &high
,
2739 xfs_rmap_has_other_keys_helper
, &rks
);
2740 if (error
== -ECANCELED
) {
2748 const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE
= {
2749 .oi_owner
= XFS_RMAP_OWN_NULL
,
2751 const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER
= {
2752 .oi_owner
= XFS_RMAP_OWN_UNKNOWN
,
2754 const struct xfs_owner_info XFS_RMAP_OINFO_FS
= {
2755 .oi_owner
= XFS_RMAP_OWN_FS
,
2757 const struct xfs_owner_info XFS_RMAP_OINFO_LOG
= {
2758 .oi_owner
= XFS_RMAP_OWN_LOG
,
2760 const struct xfs_owner_info XFS_RMAP_OINFO_AG
= {
2761 .oi_owner
= XFS_RMAP_OWN_AG
,
2763 const struct xfs_owner_info XFS_RMAP_OINFO_INOBT
= {
2764 .oi_owner
= XFS_RMAP_OWN_INOBT
,
2766 const struct xfs_owner_info XFS_RMAP_OINFO_INODES
= {
2767 .oi_owner
= XFS_RMAP_OWN_INODES
,
2769 const struct xfs_owner_info XFS_RMAP_OINFO_REFC
= {
2770 .oi_owner
= XFS_RMAP_OWN_REFC
,
2772 const struct xfs_owner_info XFS_RMAP_OINFO_COW
= {
2773 .oi_owner
= XFS_RMAP_OWN_COW
,