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
);
672 xfs_btree_del_cursor(cur
, error
);
677 * A mergeable rmap must have the same owner and the same values for
678 * the unwritten, attr_fork, and bmbt flags. The startblock and
679 * offset are checked separately.
682 xfs_rmap_is_mergeable(
683 struct xfs_rmap_irec
*irec
,
687 if (irec
->rm_owner
== XFS_RMAP_OWN_NULL
)
689 if (irec
->rm_owner
!= owner
)
691 if ((flags
& XFS_RMAP_UNWRITTEN
) ^
692 (irec
->rm_flags
& XFS_RMAP_UNWRITTEN
))
694 if ((flags
& XFS_RMAP_ATTR_FORK
) ^
695 (irec
->rm_flags
& XFS_RMAP_ATTR_FORK
))
697 if ((flags
& XFS_RMAP_BMBT_BLOCK
) ^
698 (irec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
))
704 * When we allocate a new block, the first thing we do is add a reference to
705 * the extent in the rmap btree. This takes the form of a [agbno, length,
706 * owner, offset] record. Flags are encoded in the high bits of the offset
711 struct xfs_btree_cur
*cur
,
715 struct xfs_owner_info
*oinfo
)
717 struct xfs_mount
*mp
= cur
->bc_mp
;
718 struct xfs_rmap_irec ltrec
;
719 struct xfs_rmap_irec gtrec
;
726 unsigned int flags
= 0;
729 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
731 ignore_off
= XFS_RMAP_NON_INODE_OWNER(owner
) ||
732 (flags
& XFS_RMAP_BMBT_BLOCK
);
734 flags
|= XFS_RMAP_UNWRITTEN
;
735 trace_xfs_rmap_map(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
737 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo
));
740 * For the initial lookup, look for an exact match or the left-adjacent
741 * record for our insertion point. This will also give us the record for
742 * start block contiguity tests.
744 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
,
749 error
= xfs_rmap_get_rec(cur
, <rec
, &have_lt
);
752 XFS_WANT_CORRUPTED_GOTO(mp
, have_lt
== 1, out_error
);
753 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
754 cur
->bc_private
.a
.agno
, ltrec
.rm_startblock
,
755 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
756 ltrec
.rm_offset
, ltrec
.rm_flags
);
758 if (!xfs_rmap_is_mergeable(<rec
, owner
, flags
))
762 XFS_WANT_CORRUPTED_GOTO(mp
,
764 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
<= bno
, out_error
);
767 * Increment the cursor to see if we have a right-adjacent record to our
768 * insertion point. This will give us the record for end block
771 error
= xfs_btree_increment(cur
, 0, &have_gt
);
775 error
= xfs_rmap_get_rec(cur
, >rec
, &have_gt
);
778 XFS_WANT_CORRUPTED_GOTO(mp
, have_gt
== 1, out_error
);
779 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= gtrec
.rm_startblock
,
781 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
782 cur
->bc_private
.a
.agno
, gtrec
.rm_startblock
,
783 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
784 gtrec
.rm_offset
, gtrec
.rm_flags
);
785 if (!xfs_rmap_is_mergeable(>rec
, owner
, flags
))
790 * Note: cursor currently points one record to the right of ltrec, even
791 * if there is no record in the tree to the right.
794 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
&&
795 (ignore_off
|| ltrec
.rm_offset
+ ltrec
.rm_blockcount
== offset
)) {
797 * left edge contiguous, merge into left record.
801 * adding: |aaaaaaaaa|
802 * result: |rrrrrrrrrrrrrrrrrrr|
805 ltrec
.rm_blockcount
+= len
;
807 bno
+ len
== gtrec
.rm_startblock
&&
808 (ignore_off
|| offset
+ len
== gtrec
.rm_offset
) &&
809 (unsigned long)ltrec
.rm_blockcount
+ len
+
810 gtrec
.rm_blockcount
<= XFS_RMAP_LEN_MAX
) {
812 * right edge also contiguous, delete right record
813 * and merge into left record.
815 * ltbno ltlen gtbno gtlen
816 * orig: |ooooooooo| |ooooooooo|
817 * adding: |aaaaaaaaa|
818 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
820 ltrec
.rm_blockcount
+= gtrec
.rm_blockcount
;
821 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
827 error
= xfs_btree_delete(cur
, &i
);
830 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
833 /* point the cursor back to the left record and update */
834 error
= xfs_btree_decrement(cur
, 0, &have_gt
);
837 error
= xfs_rmap_update(cur
, <rec
);
840 } else if (have_gt
&&
841 bno
+ len
== gtrec
.rm_startblock
&&
842 (ignore_off
|| offset
+ len
== gtrec
.rm_offset
)) {
844 * right edge contiguous, merge into right record.
848 * adding: |aaaaaaaaa|
849 * Result: |rrrrrrrrrrrrrrrrrrr|
852 gtrec
.rm_startblock
= bno
;
853 gtrec
.rm_blockcount
+= len
;
855 gtrec
.rm_offset
= offset
;
856 error
= xfs_rmap_update(cur
, >rec
);
861 * no contiguous edge with identical owner, insert
862 * new record at current cursor position.
864 cur
->bc_rec
.r
.rm_startblock
= bno
;
865 cur
->bc_rec
.r
.rm_blockcount
= len
;
866 cur
->bc_rec
.r
.rm_owner
= owner
;
867 cur
->bc_rec
.r
.rm_offset
= offset
;
868 cur
->bc_rec
.r
.rm_flags
= flags
;
869 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
870 owner
, offset
, flags
);
871 error
= xfs_btree_insert(cur
, &i
);
874 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
877 trace_xfs_rmap_map_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
881 trace_xfs_rmap_map_error(mp
, cur
->bc_private
.a
.agno
,
887 * Add a reference to an extent in the rmap btree.
891 struct xfs_trans
*tp
,
892 struct xfs_buf
*agbp
,
896 struct xfs_owner_info
*oinfo
)
898 struct xfs_mount
*mp
= tp
->t_mountp
;
899 struct xfs_btree_cur
*cur
;
902 if (!xfs_sb_version_hasrmapbt(&mp
->m_sb
))
905 cur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
906 error
= xfs_rmap_map(cur
, bno
, len
, false, oinfo
);
908 xfs_btree_del_cursor(cur
, error
);
912 #define RMAP_LEFT_CONTIG (1 << 0)
913 #define RMAP_RIGHT_CONTIG (1 << 1)
914 #define RMAP_LEFT_FILLING (1 << 2)
915 #define RMAP_RIGHT_FILLING (1 << 3)
916 #define RMAP_LEFT_VALID (1 << 6)
917 #define RMAP_RIGHT_VALID (1 << 7)
925 * Convert an unwritten extent to a real extent or vice versa.
926 * Does not handle overlapping extents.
930 struct xfs_btree_cur
*cur
,
934 struct xfs_owner_info
*oinfo
)
936 struct xfs_mount
*mp
= cur
->bc_mp
;
937 struct xfs_rmap_irec r
[4]; /* neighbor extent entries */
938 /* left is 0, right is 1, prev is 2 */
945 unsigned int flags
= 0;
950 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
951 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner
) ||
952 (flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
))));
953 oldext
= unwritten
? XFS_RMAP_UNWRITTEN
: 0;
954 new_endoff
= offset
+ len
;
955 trace_xfs_rmap_convert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
959 * For the initial lookup, look for an exact match or the left-adjacent
960 * record for our insertion point. This will also give us the record for
961 * start block contiguity tests.
963 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, oldext
, &i
);
966 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
968 error
= xfs_rmap_get_rec(cur
, &PREV
, &i
);
971 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
972 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
973 cur
->bc_private
.a
.agno
, PREV
.rm_startblock
,
974 PREV
.rm_blockcount
, PREV
.rm_owner
,
975 PREV
.rm_offset
, PREV
.rm_flags
);
977 ASSERT(PREV
.rm_offset
<= offset
);
978 ASSERT(PREV
.rm_offset
+ PREV
.rm_blockcount
>= new_endoff
);
979 ASSERT((PREV
.rm_flags
& XFS_RMAP_UNWRITTEN
) == oldext
);
980 newext
= ~oldext
& XFS_RMAP_UNWRITTEN
;
983 * Set flags determining what part of the previous oldext allocation
984 * extent is being replaced by a newext allocation.
986 if (PREV
.rm_offset
== offset
)
987 state
|= RMAP_LEFT_FILLING
;
988 if (PREV
.rm_offset
+ PREV
.rm_blockcount
== new_endoff
)
989 state
|= RMAP_RIGHT_FILLING
;
992 * Decrement the cursor to see if we have a left-adjacent record to our
993 * insertion point. This will give us the record for end block
996 error
= xfs_btree_decrement(cur
, 0, &i
);
1000 state
|= RMAP_LEFT_VALID
;
1001 error
= xfs_rmap_get_rec(cur
, &LEFT
, &i
);
1004 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1005 XFS_WANT_CORRUPTED_GOTO(mp
,
1006 LEFT
.rm_startblock
+ LEFT
.rm_blockcount
<= bno
,
1008 trace_xfs_rmap_find_left_neighbor_result(cur
->bc_mp
,
1009 cur
->bc_private
.a
.agno
, LEFT
.rm_startblock
,
1010 LEFT
.rm_blockcount
, LEFT
.rm_owner
,
1011 LEFT
.rm_offset
, LEFT
.rm_flags
);
1012 if (LEFT
.rm_startblock
+ LEFT
.rm_blockcount
== bno
&&
1013 LEFT
.rm_offset
+ LEFT
.rm_blockcount
== offset
&&
1014 xfs_rmap_is_mergeable(&LEFT
, owner
, newext
))
1015 state
|= RMAP_LEFT_CONTIG
;
1019 * Increment the cursor to see if we have a right-adjacent record to our
1020 * insertion point. This will give us the record for end block
1023 error
= xfs_btree_increment(cur
, 0, &i
);
1026 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1027 error
= xfs_btree_increment(cur
, 0, &i
);
1031 state
|= RMAP_RIGHT_VALID
;
1032 error
= xfs_rmap_get_rec(cur
, &RIGHT
, &i
);
1035 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1036 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= RIGHT
.rm_startblock
,
1038 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1039 cur
->bc_private
.a
.agno
, RIGHT
.rm_startblock
,
1040 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1041 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1042 if (bno
+ len
== RIGHT
.rm_startblock
&&
1043 offset
+ len
== RIGHT
.rm_offset
&&
1044 xfs_rmap_is_mergeable(&RIGHT
, owner
, newext
))
1045 state
|= RMAP_RIGHT_CONTIG
;
1048 /* check that left + prev + right is not too long */
1049 if ((state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1050 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) ==
1051 (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1052 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
) &&
1053 (unsigned long)LEFT
.rm_blockcount
+ len
+
1054 RIGHT
.rm_blockcount
> XFS_RMAP_LEN_MAX
)
1055 state
&= ~RMAP_RIGHT_CONTIG
;
1057 trace_xfs_rmap_convert_state(mp
, cur
->bc_private
.a
.agno
, state
,
1060 /* reset the cursor back to PREV */
1061 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, oldext
, &i
);
1064 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1067 * Switch out based on the FILLING and CONTIG state bits.
1069 switch (state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1070 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) {
1071 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1072 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1074 * Setting all of a previous oldext extent to newext.
1075 * The left and right neighbors are both contiguous with new.
1077 error
= xfs_btree_increment(cur
, 0, &i
);
1080 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1081 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1082 RIGHT
.rm_startblock
, RIGHT
.rm_blockcount
,
1083 RIGHT
.rm_owner
, RIGHT
.rm_offset
,
1085 error
= xfs_btree_delete(cur
, &i
);
1088 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1089 error
= xfs_btree_decrement(cur
, 0, &i
);
1092 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1093 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1094 PREV
.rm_startblock
, PREV
.rm_blockcount
,
1095 PREV
.rm_owner
, PREV
.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
);
1106 NEW
.rm_blockcount
+= PREV
.rm_blockcount
+ RIGHT
.rm_blockcount
;
1107 error
= xfs_rmap_update(cur
, &NEW
);
1112 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1114 * Setting all of a previous oldext extent to newext.
1115 * The left neighbor is contiguous, the right is not.
1117 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1118 PREV
.rm_startblock
, PREV
.rm_blockcount
,
1119 PREV
.rm_owner
, PREV
.rm_offset
,
1121 error
= xfs_btree_delete(cur
, &i
);
1124 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1125 error
= xfs_btree_decrement(cur
, 0, &i
);
1128 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1130 NEW
.rm_blockcount
+= PREV
.rm_blockcount
;
1131 error
= xfs_rmap_update(cur
, &NEW
);
1136 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1138 * Setting all of a previous oldext extent to newext.
1139 * The right neighbor is contiguous, the left is not.
1141 error
= xfs_btree_increment(cur
, 0, &i
);
1144 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1145 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1146 RIGHT
.rm_startblock
, RIGHT
.rm_blockcount
,
1147 RIGHT
.rm_owner
, RIGHT
.rm_offset
,
1149 error
= xfs_btree_delete(cur
, &i
);
1152 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1153 error
= xfs_btree_decrement(cur
, 0, &i
);
1156 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1158 NEW
.rm_blockcount
= len
+ RIGHT
.rm_blockcount
;
1159 NEW
.rm_flags
= newext
;
1160 error
= xfs_rmap_update(cur
, &NEW
);
1165 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
:
1167 * Setting all of a previous oldext extent to newext.
1168 * Neither the left nor right neighbors are contiguous with
1172 NEW
.rm_flags
= newext
;
1173 error
= xfs_rmap_update(cur
, &NEW
);
1178 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
:
1180 * Setting the first part of a previous oldext extent to newext.
1181 * The left neighbor is contiguous.
1184 NEW
.rm_offset
+= len
;
1185 NEW
.rm_startblock
+= len
;
1186 NEW
.rm_blockcount
-= len
;
1187 error
= xfs_rmap_update(cur
, &NEW
);
1190 error
= xfs_btree_decrement(cur
, 0, &i
);
1194 NEW
.rm_blockcount
+= len
;
1195 error
= xfs_rmap_update(cur
, &NEW
);
1200 case RMAP_LEFT_FILLING
:
1202 * Setting the first part of a previous oldext extent to newext.
1203 * The left neighbor is not contiguous.
1206 NEW
.rm_startblock
+= len
;
1207 NEW
.rm_offset
+= len
;
1208 NEW
.rm_blockcount
-= len
;
1209 error
= xfs_rmap_update(cur
, &NEW
);
1212 NEW
.rm_startblock
= bno
;
1213 NEW
.rm_owner
= owner
;
1214 NEW
.rm_offset
= offset
;
1215 NEW
.rm_blockcount
= len
;
1216 NEW
.rm_flags
= newext
;
1217 cur
->bc_rec
.r
= NEW
;
1218 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
,
1219 len
, owner
, offset
, newext
);
1220 error
= xfs_btree_insert(cur
, &i
);
1223 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1226 case RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1228 * Setting the last part of a previous oldext extent to newext.
1229 * The right neighbor is contiguous with the new allocation.
1232 NEW
.rm_blockcount
-= len
;
1233 error
= xfs_rmap_update(cur
, &NEW
);
1236 error
= xfs_btree_increment(cur
, 0, &i
);
1240 NEW
.rm_offset
= offset
;
1241 NEW
.rm_startblock
= bno
;
1242 NEW
.rm_blockcount
+= len
;
1243 error
= xfs_rmap_update(cur
, &NEW
);
1248 case RMAP_RIGHT_FILLING
:
1250 * Setting the last part of a previous oldext extent to newext.
1251 * The right neighbor is not contiguous.
1254 NEW
.rm_blockcount
-= len
;
1255 error
= xfs_rmap_update(cur
, &NEW
);
1258 error
= xfs_rmap_lookup_eq(cur
, bno
, len
, owner
, offset
,
1262 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 0, done
);
1263 NEW
.rm_startblock
= bno
;
1264 NEW
.rm_owner
= owner
;
1265 NEW
.rm_offset
= offset
;
1266 NEW
.rm_blockcount
= len
;
1267 NEW
.rm_flags
= newext
;
1268 cur
->bc_rec
.r
= NEW
;
1269 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
,
1270 len
, owner
, offset
, newext
);
1271 error
= xfs_btree_insert(cur
, &i
);
1274 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1279 * Setting the middle part of a previous oldext extent to
1280 * newext. Contiguity is impossible here.
1281 * One extent becomes three extents.
1283 /* new right extent - oldext */
1284 NEW
.rm_startblock
= bno
+ len
;
1285 NEW
.rm_owner
= owner
;
1286 NEW
.rm_offset
= new_endoff
;
1287 NEW
.rm_blockcount
= PREV
.rm_offset
+ PREV
.rm_blockcount
-
1289 NEW
.rm_flags
= PREV
.rm_flags
;
1290 error
= xfs_rmap_update(cur
, &NEW
);
1293 /* new left extent - oldext */
1295 NEW
.rm_blockcount
= offset
- PREV
.rm_offset
;
1296 cur
->bc_rec
.r
= NEW
;
1297 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
,
1298 NEW
.rm_startblock
, NEW
.rm_blockcount
,
1299 NEW
.rm_owner
, NEW
.rm_offset
,
1301 error
= xfs_btree_insert(cur
, &i
);
1304 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1306 * Reset the cursor to the position of the new extent
1307 * we are about to insert as we can't trust it after
1308 * the previous insert.
1310 error
= xfs_rmap_lookup_eq(cur
, bno
, len
, owner
, offset
,
1314 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 0, done
);
1315 /* new middle extent - newext */
1316 cur
->bc_rec
.r
.rm_flags
&= ~XFS_RMAP_UNWRITTEN
;
1317 cur
->bc_rec
.r
.rm_flags
|= newext
;
1318 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1319 owner
, offset
, newext
);
1320 error
= xfs_btree_insert(cur
, &i
);
1323 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1326 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1327 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1328 case RMAP_LEFT_FILLING
| RMAP_RIGHT_CONTIG
:
1329 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1330 case RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1331 case RMAP_LEFT_CONTIG
:
1332 case RMAP_RIGHT_CONTIG
:
1334 * These cases are all impossible.
1339 trace_xfs_rmap_convert_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1343 trace_xfs_rmap_convert_error(cur
->bc_mp
,
1344 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1349 * Convert an unwritten extent to a real extent or vice versa. If there is no
1350 * possibility of overlapping extents, delegate to the simpler convert
1354 xfs_rmap_convert_shared(
1355 struct xfs_btree_cur
*cur
,
1359 struct xfs_owner_info
*oinfo
)
1361 struct xfs_mount
*mp
= cur
->bc_mp
;
1362 struct xfs_rmap_irec r
[4]; /* neighbor extent entries */
1363 /* left is 0, right is 1, prev is 2 */
1367 uint64_t new_endoff
;
1368 unsigned int oldext
;
1369 unsigned int newext
;
1370 unsigned int flags
= 0;
1375 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1376 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner
) ||
1377 (flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
))));
1378 oldext
= unwritten
? XFS_RMAP_UNWRITTEN
: 0;
1379 new_endoff
= offset
+ len
;
1380 trace_xfs_rmap_convert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1384 * For the initial lookup, look for and exact match or the left-adjacent
1385 * record for our insertion point. This will also give us the record for
1386 * start block contiguity tests.
1388 error
= xfs_rmap_lookup_le_range(cur
, bno
, owner
, offset
, flags
,
1392 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1394 ASSERT(PREV
.rm_offset
<= offset
);
1395 ASSERT(PREV
.rm_offset
+ PREV
.rm_blockcount
>= new_endoff
);
1396 ASSERT((PREV
.rm_flags
& XFS_RMAP_UNWRITTEN
) == oldext
);
1397 newext
= ~oldext
& XFS_RMAP_UNWRITTEN
;
1400 * Set flags determining what part of the previous oldext allocation
1401 * extent is being replaced by a newext allocation.
1403 if (PREV
.rm_offset
== offset
)
1404 state
|= RMAP_LEFT_FILLING
;
1405 if (PREV
.rm_offset
+ PREV
.rm_blockcount
== new_endoff
)
1406 state
|= RMAP_RIGHT_FILLING
;
1408 /* Is there a left record that abuts our range? */
1409 error
= xfs_rmap_find_left_neighbor(cur
, bno
, owner
, offset
, newext
,
1414 state
|= RMAP_LEFT_VALID
;
1415 XFS_WANT_CORRUPTED_GOTO(mp
,
1416 LEFT
.rm_startblock
+ LEFT
.rm_blockcount
<= bno
,
1418 if (xfs_rmap_is_mergeable(&LEFT
, owner
, newext
))
1419 state
|= RMAP_LEFT_CONTIG
;
1422 /* Is there a right record that abuts our range? */
1423 error
= xfs_rmap_lookup_eq(cur
, bno
+ len
, len
, owner
, offset
+ len
,
1428 state
|= RMAP_RIGHT_VALID
;
1429 error
= xfs_rmap_get_rec(cur
, &RIGHT
, &i
);
1432 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1433 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= RIGHT
.rm_startblock
,
1435 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1436 cur
->bc_private
.a
.agno
, RIGHT
.rm_startblock
,
1437 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1438 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1439 if (xfs_rmap_is_mergeable(&RIGHT
, owner
, newext
))
1440 state
|= RMAP_RIGHT_CONTIG
;
1443 /* check that left + prev + right is not too long */
1444 if ((state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1445 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) ==
1446 (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1447 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
) &&
1448 (unsigned long)LEFT
.rm_blockcount
+ len
+
1449 RIGHT
.rm_blockcount
> XFS_RMAP_LEN_MAX
)
1450 state
&= ~RMAP_RIGHT_CONTIG
;
1452 trace_xfs_rmap_convert_state(mp
, cur
->bc_private
.a
.agno
, state
,
1455 * Switch out based on the FILLING and CONTIG state bits.
1457 switch (state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1458 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) {
1459 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1460 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1462 * Setting all of a previous oldext extent to newext.
1463 * The left and right neighbors are both contiguous with new.
1465 error
= xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1466 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1467 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1470 error
= xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1471 PREV
.rm_blockcount
, PREV
.rm_owner
,
1472 PREV
.rm_offset
, PREV
.rm_flags
);
1476 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1477 NEW
.rm_blockcount
, NEW
.rm_owner
,
1478 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1481 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1482 NEW
.rm_blockcount
+= PREV
.rm_blockcount
+ RIGHT
.rm_blockcount
;
1483 error
= xfs_rmap_update(cur
, &NEW
);
1488 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1490 * Setting all of a previous oldext extent to newext.
1491 * The left neighbor is contiguous, the right is not.
1493 error
= xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1494 PREV
.rm_blockcount
, PREV
.rm_owner
,
1495 PREV
.rm_offset
, PREV
.rm_flags
);
1499 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1500 NEW
.rm_blockcount
, NEW
.rm_owner
,
1501 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1504 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1505 NEW
.rm_blockcount
+= PREV
.rm_blockcount
;
1506 error
= xfs_rmap_update(cur
, &NEW
);
1511 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1513 * Setting all of a previous oldext extent to newext.
1514 * The right neighbor is contiguous, the left is not.
1516 error
= xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1517 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1518 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1522 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1523 NEW
.rm_blockcount
, NEW
.rm_owner
,
1524 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1527 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1528 NEW
.rm_blockcount
+= RIGHT
.rm_blockcount
;
1529 NEW
.rm_flags
= RIGHT
.rm_flags
;
1530 error
= xfs_rmap_update(cur
, &NEW
);
1535 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
:
1537 * Setting all of a previous oldext extent to newext.
1538 * Neither the left nor right neighbors are contiguous with
1542 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1543 NEW
.rm_blockcount
, NEW
.rm_owner
,
1544 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1547 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1548 NEW
.rm_flags
= newext
;
1549 error
= xfs_rmap_update(cur
, &NEW
);
1554 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
:
1556 * Setting the first part of a previous oldext extent to newext.
1557 * The left neighbor is contiguous.
1560 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1561 NEW
.rm_blockcount
, NEW
.rm_owner
,
1562 NEW
.rm_offset
, NEW
.rm_flags
);
1565 NEW
.rm_offset
+= len
;
1566 NEW
.rm_startblock
+= len
;
1567 NEW
.rm_blockcount
-= len
;
1568 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1569 NEW
.rm_blockcount
, NEW
.rm_owner
,
1570 NEW
.rm_offset
, NEW
.rm_flags
);
1574 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1575 NEW
.rm_blockcount
, NEW
.rm_owner
,
1576 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1579 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1580 NEW
.rm_blockcount
+= len
;
1581 error
= xfs_rmap_update(cur
, &NEW
);
1586 case RMAP_LEFT_FILLING
:
1588 * Setting the first part of a previous oldext extent to newext.
1589 * The left neighbor is not contiguous.
1592 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1593 NEW
.rm_blockcount
, NEW
.rm_owner
,
1594 NEW
.rm_offset
, NEW
.rm_flags
);
1597 NEW
.rm_offset
+= len
;
1598 NEW
.rm_startblock
+= len
;
1599 NEW
.rm_blockcount
-= len
;
1600 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1601 NEW
.rm_blockcount
, NEW
.rm_owner
,
1602 NEW
.rm_offset
, NEW
.rm_flags
);
1605 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1610 case RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1612 * Setting the last part of a previous oldext extent to newext.
1613 * The right neighbor is contiguous with the new allocation.
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 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1622 NEW
.rm_blockcount
= offset
- NEW
.rm_offset
;
1623 error
= xfs_rmap_update(cur
, &NEW
);
1627 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1628 NEW
.rm_blockcount
, NEW
.rm_owner
,
1629 NEW
.rm_offset
, NEW
.rm_flags
);
1632 NEW
.rm_offset
= offset
;
1633 NEW
.rm_startblock
= bno
;
1634 NEW
.rm_blockcount
+= len
;
1635 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1636 NEW
.rm_blockcount
, NEW
.rm_owner
,
1637 NEW
.rm_offset
, NEW
.rm_flags
);
1642 case RMAP_RIGHT_FILLING
:
1644 * Setting the last part of a previous oldext extent to newext.
1645 * The right neighbor is not contiguous.
1648 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1649 NEW
.rm_blockcount
, NEW
.rm_owner
,
1650 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1653 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1654 NEW
.rm_blockcount
-= len
;
1655 error
= xfs_rmap_update(cur
, &NEW
);
1658 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1665 * Setting the middle part of a previous oldext extent to
1666 * newext. Contiguity is impossible here.
1667 * One extent becomes three extents.
1669 /* new right extent - oldext */
1670 NEW
.rm_startblock
= bno
+ len
;
1671 NEW
.rm_owner
= owner
;
1672 NEW
.rm_offset
= new_endoff
;
1673 NEW
.rm_blockcount
= PREV
.rm_offset
+ PREV
.rm_blockcount
-
1675 NEW
.rm_flags
= PREV
.rm_flags
;
1676 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1677 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
1681 /* new left extent - oldext */
1683 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1684 NEW
.rm_blockcount
, NEW
.rm_owner
,
1685 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1688 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1689 NEW
.rm_blockcount
= offset
- NEW
.rm_offset
;
1690 error
= xfs_rmap_update(cur
, &NEW
);
1693 /* new middle extent - newext */
1694 NEW
.rm_startblock
= bno
;
1695 NEW
.rm_blockcount
= len
;
1696 NEW
.rm_owner
= owner
;
1697 NEW
.rm_offset
= offset
;
1698 NEW
.rm_flags
= newext
;
1699 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1700 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
1706 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1707 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1708 case RMAP_LEFT_FILLING
| RMAP_RIGHT_CONTIG
:
1709 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1710 case RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1711 case RMAP_LEFT_CONTIG
:
1712 case RMAP_RIGHT_CONTIG
:
1714 * These cases are all impossible.
1719 trace_xfs_rmap_convert_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1723 trace_xfs_rmap_convert_error(cur
->bc_mp
,
1724 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1734 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1735 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1736 * that the prev/next records in the btree might belong to another owner.
1737 * Therefore we must use delete+insert to alter any of the key fields.
1739 * For every other situation there can only be one owner for a given extent,
1740 * so we can call the regular _free function.
1743 xfs_rmap_unmap_shared(
1744 struct xfs_btree_cur
*cur
,
1748 struct xfs_owner_info
*oinfo
)
1750 struct xfs_mount
*mp
= cur
->bc_mp
;
1751 struct xfs_rmap_irec ltrec
;
1759 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1761 flags
|= XFS_RMAP_UNWRITTEN
;
1762 trace_xfs_rmap_unmap(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1766 * We should always have a left record because there's a static record
1767 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1768 * will not ever be removed from the tree.
1770 error
= xfs_rmap_lookup_le_range(cur
, bno
, owner
, offset
, flags
,
1774 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1775 ltoff
= ltrec
.rm_offset
;
1777 /* Make sure the extent we found covers the entire freeing range. */
1778 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_startblock
<= bno
&&
1779 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
>=
1780 bno
+ len
, out_error
);
1782 /* Make sure the owner matches what we expect to find in the tree. */
1783 XFS_WANT_CORRUPTED_GOTO(mp
, owner
== ltrec
.rm_owner
, out_error
);
1785 /* Make sure the unwritten flag matches. */
1786 XFS_WANT_CORRUPTED_GOTO(mp
, (flags
& XFS_RMAP_UNWRITTEN
) ==
1787 (ltrec
.rm_flags
& XFS_RMAP_UNWRITTEN
), out_error
);
1789 /* Check the offset. */
1790 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_offset
<= offset
, out_error
);
1791 XFS_WANT_CORRUPTED_GOTO(mp
, offset
<= ltoff
+ ltrec
.rm_blockcount
,
1794 if (ltrec
.rm_startblock
== bno
&& ltrec
.rm_blockcount
== len
) {
1795 /* Exact match, simply remove the record from rmap tree. */
1796 error
= xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
1797 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1798 ltrec
.rm_offset
, ltrec
.rm_flags
);
1801 } else if (ltrec
.rm_startblock
== bno
) {
1803 * Overlap left hand side of extent: move the start, trim the
1804 * length and update the current record.
1807 * Orig: |oooooooooooooooooooo|
1808 * Freeing: |fffffffff|
1809 * Result: |rrrrrrrrrr|
1813 /* Delete prev rmap. */
1814 error
= xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
1815 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1816 ltrec
.rm_offset
, ltrec
.rm_flags
);
1820 /* Add an rmap at the new offset. */
1821 ltrec
.rm_startblock
+= len
;
1822 ltrec
.rm_blockcount
-= len
;
1823 ltrec
.rm_offset
+= len
;
1824 error
= xfs_rmap_insert(cur
, ltrec
.rm_startblock
,
1825 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1826 ltrec
.rm_offset
, ltrec
.rm_flags
);
1829 } else if (ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
+ len
) {
1831 * Overlap right hand side of extent: trim the length and
1832 * update the current record.
1835 * Orig: |oooooooooooooooooooo|
1836 * Freeing: |fffffffff|
1837 * Result: |rrrrrrrrrr|
1840 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1841 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1842 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1845 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1846 ltrec
.rm_blockcount
-= len
;
1847 error
= xfs_rmap_update(cur
, <rec
);
1852 * Overlap middle of extent: trim the length of the existing
1853 * record to the length of the new left-extent size, increment
1854 * the insertion position so we can insert a new record
1855 * containing the remaining right-extent space.
1858 * Orig: |oooooooooooooooooooo|
1859 * Freeing: |fffffffff|
1860 * Result: |rrrrr| |rrrr|
1863 xfs_extlen_t orig_len
= ltrec
.rm_blockcount
;
1865 /* Shrink the left side of the rmap */
1866 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1867 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1868 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1871 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1872 ltrec
.rm_blockcount
= bno
- ltrec
.rm_startblock
;
1873 error
= xfs_rmap_update(cur
, <rec
);
1877 /* Add an rmap at the new offset */
1878 error
= xfs_rmap_insert(cur
, bno
+ len
,
1879 orig_len
- len
- ltrec
.rm_blockcount
,
1880 ltrec
.rm_owner
, offset
+ len
,
1886 trace_xfs_rmap_unmap_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1890 trace_xfs_rmap_unmap_error(cur
->bc_mp
,
1891 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1896 * Find an extent in the rmap btree and map it. For rmap extent types that
1897 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1898 * that the prev/next records in the btree might belong to another owner.
1899 * Therefore we must use delete+insert to alter any of the key fields.
1901 * For every other situation there can only be one owner for a given extent,
1902 * so we can call the regular _alloc function.
1905 xfs_rmap_map_shared(
1906 struct xfs_btree_cur
*cur
,
1910 struct xfs_owner_info
*oinfo
)
1912 struct xfs_mount
*mp
= cur
->bc_mp
;
1913 struct xfs_rmap_irec ltrec
;
1914 struct xfs_rmap_irec gtrec
;
1921 unsigned int flags
= 0;
1923 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1925 flags
|= XFS_RMAP_UNWRITTEN
;
1926 trace_xfs_rmap_map(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1929 /* Is there a left record that abuts our range? */
1930 error
= xfs_rmap_find_left_neighbor(cur
, bno
, owner
, offset
, flags
,
1935 !xfs_rmap_is_mergeable(<rec
, owner
, flags
))
1938 /* Is there a right record that abuts our range? */
1939 error
= xfs_rmap_lookup_eq(cur
, bno
+ len
, len
, owner
, offset
+ len
,
1944 error
= xfs_rmap_get_rec(cur
, >rec
, &have_gt
);
1947 XFS_WANT_CORRUPTED_GOTO(mp
, have_gt
== 1, out_error
);
1948 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1949 cur
->bc_private
.a
.agno
, gtrec
.rm_startblock
,
1950 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
1951 gtrec
.rm_offset
, gtrec
.rm_flags
);
1953 if (!xfs_rmap_is_mergeable(>rec
, owner
, flags
))
1958 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
&&
1959 ltrec
.rm_offset
+ ltrec
.rm_blockcount
== offset
) {
1961 * Left edge contiguous, merge into left record.
1965 * adding: |aaaaaaaaa|
1966 * result: |rrrrrrrrrrrrrrrrrrr|
1969 ltrec
.rm_blockcount
+= len
;
1971 bno
+ len
== gtrec
.rm_startblock
&&
1972 offset
+ len
== gtrec
.rm_offset
) {
1974 * Right edge also contiguous, delete right record
1975 * and merge into left record.
1977 * ltbno ltlen gtbno gtlen
1978 * orig: |ooooooooo| |ooooooooo|
1979 * adding: |aaaaaaaaa|
1980 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1982 ltrec
.rm_blockcount
+= gtrec
.rm_blockcount
;
1983 error
= xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
1984 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
1985 gtrec
.rm_offset
, gtrec
.rm_flags
);
1990 /* Point the cursor back to the left record and update. */
1991 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1992 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1993 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1996 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1998 error
= xfs_rmap_update(cur
, <rec
);
2001 } else if (have_gt
&&
2002 bno
+ len
== gtrec
.rm_startblock
&&
2003 offset
+ len
== gtrec
.rm_offset
) {
2005 * Right edge contiguous, merge into right record.
2009 * adding: |aaaaaaaaa|
2010 * Result: |rrrrrrrrrrrrrrrrrrr|
2013 /* Delete the old record. */
2014 error
= xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
2015 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2016 gtrec
.rm_offset
, gtrec
.rm_flags
);
2020 /* Move the start and re-add it. */
2021 gtrec
.rm_startblock
= bno
;
2022 gtrec
.rm_blockcount
+= len
;
2023 gtrec
.rm_offset
= offset
;
2024 error
= xfs_rmap_insert(cur
, gtrec
.rm_startblock
,
2025 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2026 gtrec
.rm_offset
, gtrec
.rm_flags
);
2031 * No contiguous edge with identical owner, insert
2032 * new record at current cursor position.
2034 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, flags
);
2039 trace_xfs_rmap_map_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
2043 trace_xfs_rmap_map_error(cur
->bc_mp
,
2044 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
2048 /* Insert a raw rmap into the rmapbt. */
2051 struct xfs_btree_cur
*cur
,
2052 struct xfs_rmap_irec
*rmap
)
2054 struct xfs_owner_info oinfo
;
2056 oinfo
.oi_owner
= rmap
->rm_owner
;
2057 oinfo
.oi_offset
= rmap
->rm_offset
;
2059 if (rmap
->rm_flags
& XFS_RMAP_ATTR_FORK
)
2060 oinfo
.oi_flags
|= XFS_OWNER_INFO_ATTR_FORK
;
2061 if (rmap
->rm_flags
& XFS_RMAP_BMBT_BLOCK
)
2062 oinfo
.oi_flags
|= XFS_OWNER_INFO_BMBT_BLOCK
;
2064 if (rmap
->rm_flags
|| XFS_RMAP_NON_INODE_OWNER(rmap
->rm_owner
))
2065 return xfs_rmap_map(cur
, rmap
->rm_startblock
,
2066 rmap
->rm_blockcount
,
2067 rmap
->rm_flags
& XFS_RMAP_UNWRITTEN
,
2070 return xfs_rmap_map_shared(cur
, rmap
->rm_startblock
,
2071 rmap
->rm_blockcount
,
2072 rmap
->rm_flags
& XFS_RMAP_UNWRITTEN
,
2076 struct xfs_rmap_query_range_info
{
2077 xfs_rmap_query_range_fn fn
;
2081 /* Format btree record and pass to our callback. */
2083 xfs_rmap_query_range_helper(
2084 struct xfs_btree_cur
*cur
,
2085 union xfs_btree_rec
*rec
,
2088 struct xfs_rmap_query_range_info
*query
= priv
;
2089 struct xfs_rmap_irec irec
;
2092 error
= xfs_rmap_btrec_to_irec(rec
, &irec
);
2095 return query
->fn(cur
, &irec
, query
->priv
);
2098 /* Find all rmaps between two keys. */
2100 xfs_rmap_query_range(
2101 struct xfs_btree_cur
*cur
,
2102 struct xfs_rmap_irec
*low_rec
,
2103 struct xfs_rmap_irec
*high_rec
,
2104 xfs_rmap_query_range_fn fn
,
2107 union xfs_btree_irec low_brec
;
2108 union xfs_btree_irec high_brec
;
2109 struct xfs_rmap_query_range_info query
;
2111 low_brec
.r
= *low_rec
;
2112 high_brec
.r
= *high_rec
;
2115 return xfs_btree_query_range(cur
, &low_brec
, &high_brec
,
2116 xfs_rmap_query_range_helper
, &query
);
2119 /* Find all rmaps. */
2122 struct xfs_btree_cur
*cur
,
2123 xfs_rmap_query_range_fn fn
,
2126 struct xfs_rmap_query_range_info query
;
2130 return xfs_btree_query_all(cur
, xfs_rmap_query_range_helper
, &query
);
2133 /* Clean up after calling xfs_rmap_finish_one. */
2135 xfs_rmap_finish_one_cleanup(
2136 struct xfs_trans
*tp
,
2137 struct xfs_btree_cur
*rcur
,
2140 struct xfs_buf
*agbp
;
2144 agbp
= rcur
->bc_private
.a
.agbp
;
2145 xfs_btree_del_cursor(rcur
, error
);
2147 xfs_trans_brelse(tp
, agbp
);
2151 * Process one of the deferred rmap operations. We pass back the
2152 * btree cursor to maintain our lock on the rmapbt between calls.
2153 * This saves time and eliminates a buffer deadlock between the
2154 * superblock and the AGF because we'll always grab them in the same
2158 xfs_rmap_finish_one(
2159 struct xfs_trans
*tp
,
2160 enum xfs_rmap_intent_type type
,
2163 xfs_fileoff_t startoff
,
2164 xfs_fsblock_t startblock
,
2165 xfs_filblks_t blockcount
,
2167 struct xfs_btree_cur
**pcur
)
2169 struct xfs_mount
*mp
= tp
->t_mountp
;
2170 struct xfs_btree_cur
*rcur
;
2171 struct xfs_buf
*agbp
= NULL
;
2173 xfs_agnumber_t agno
;
2174 struct xfs_owner_info oinfo
;
2178 agno
= XFS_FSB_TO_AGNO(mp
, startblock
);
2179 ASSERT(agno
!= NULLAGNUMBER
);
2180 bno
= XFS_FSB_TO_AGBNO(mp
, startblock
);
2182 trace_xfs_rmap_deferred(mp
, agno
, type
, bno
, owner
, whichfork
,
2183 startoff
, blockcount
, state
);
2185 if (XFS_TEST_ERROR(false, mp
,
2186 XFS_ERRTAG_RMAP_FINISH_ONE
))
2190 * If we haven't gotten a cursor or the cursor AG doesn't match
2191 * the startblock, get one now.
2194 if (rcur
!= NULL
&& rcur
->bc_private
.a
.agno
!= agno
) {
2195 xfs_rmap_finish_one_cleanup(tp
, rcur
, 0);
2201 * Refresh the freelist before we start changing the
2202 * rmapbt, because a shape change could cause us to
2205 error
= xfs_free_extent_fix_freelist(tp
, agno
, &agbp
);
2209 return -EFSCORRUPTED
;
2211 rcur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
2219 xfs_rmap_ino_owner(&oinfo
, owner
, whichfork
, startoff
);
2220 unwritten
= state
== XFS_EXT_UNWRITTEN
;
2221 bno
= XFS_FSB_TO_AGBNO(rcur
->bc_mp
, startblock
);
2224 case XFS_RMAP_ALLOC
:
2226 error
= xfs_rmap_map(rcur
, bno
, blockcount
, unwritten
, &oinfo
);
2228 case XFS_RMAP_MAP_SHARED
:
2229 error
= xfs_rmap_map_shared(rcur
, bno
, blockcount
, unwritten
,
2233 case XFS_RMAP_UNMAP
:
2234 error
= xfs_rmap_unmap(rcur
, bno
, blockcount
, unwritten
,
2237 case XFS_RMAP_UNMAP_SHARED
:
2238 error
= xfs_rmap_unmap_shared(rcur
, bno
, blockcount
, unwritten
,
2241 case XFS_RMAP_CONVERT
:
2242 error
= xfs_rmap_convert(rcur
, bno
, blockcount
, !unwritten
,
2245 case XFS_RMAP_CONVERT_SHARED
:
2246 error
= xfs_rmap_convert_shared(rcur
, bno
, blockcount
,
2247 !unwritten
, &oinfo
);
2251 error
= -EFSCORRUPTED
;
2256 xfs_trans_brelse(tp
, agbp
);
2262 * Don't defer an rmap if we aren't an rmap filesystem.
2265 xfs_rmap_update_is_needed(
2266 struct xfs_mount
*mp
,
2269 return xfs_sb_version_hasrmapbt(&mp
->m_sb
) && whichfork
!= XFS_COW_FORK
;
2273 * Record a rmap intent; the list is kept sorted first by AG and then by
2278 struct xfs_trans
*tp
,
2279 enum xfs_rmap_intent_type type
,
2282 struct xfs_bmbt_irec
*bmap
)
2284 struct xfs_rmap_intent
*ri
;
2286 trace_xfs_rmap_defer(tp
->t_mountp
,
2287 XFS_FSB_TO_AGNO(tp
->t_mountp
, bmap
->br_startblock
),
2289 XFS_FSB_TO_AGBNO(tp
->t_mountp
, bmap
->br_startblock
),
2292 bmap
->br_blockcount
,
2295 ri
= kmem_alloc(sizeof(struct xfs_rmap_intent
), KM_SLEEP
| KM_NOFS
);
2296 INIT_LIST_HEAD(&ri
->ri_list
);
2298 ri
->ri_owner
= owner
;
2299 ri
->ri_whichfork
= whichfork
;
2300 ri
->ri_bmap
= *bmap
;
2302 xfs_defer_add(tp
, XFS_DEFER_OPS_TYPE_RMAP
, &ri
->ri_list
);
2306 /* Map an extent into a file. */
2308 xfs_rmap_map_extent(
2309 struct xfs_trans
*tp
,
2310 struct xfs_inode
*ip
,
2312 struct xfs_bmbt_irec
*PREV
)
2314 if (!xfs_rmap_update_is_needed(tp
->t_mountp
, whichfork
))
2317 return __xfs_rmap_add(tp
, xfs_is_reflink_inode(ip
) ?
2318 XFS_RMAP_MAP_SHARED
: XFS_RMAP_MAP
, ip
->i_ino
,
2322 /* Unmap an extent out of a file. */
2324 xfs_rmap_unmap_extent(
2325 struct xfs_trans
*tp
,
2326 struct xfs_inode
*ip
,
2328 struct xfs_bmbt_irec
*PREV
)
2330 if (!xfs_rmap_update_is_needed(tp
->t_mountp
, whichfork
))
2333 return __xfs_rmap_add(tp
, xfs_is_reflink_inode(ip
) ?
2334 XFS_RMAP_UNMAP_SHARED
: XFS_RMAP_UNMAP
, ip
->i_ino
,
2339 * Convert a data fork extent from unwritten to real or vice versa.
2341 * Note that tp can be NULL here as no transaction is used for COW fork
2342 * unwritten conversion.
2345 xfs_rmap_convert_extent(
2346 struct xfs_mount
*mp
,
2347 struct xfs_trans
*tp
,
2348 struct xfs_inode
*ip
,
2350 struct xfs_bmbt_irec
*PREV
)
2352 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2355 return __xfs_rmap_add(tp
, xfs_is_reflink_inode(ip
) ?
2356 XFS_RMAP_CONVERT_SHARED
: XFS_RMAP_CONVERT
, ip
->i_ino
,
2360 /* Schedule the creation of an rmap for non-file data. */
2362 xfs_rmap_alloc_extent(
2363 struct xfs_trans
*tp
,
2364 xfs_agnumber_t agno
,
2369 struct xfs_bmbt_irec bmap
;
2371 if (!xfs_rmap_update_is_needed(tp
->t_mountp
, XFS_DATA_FORK
))
2374 bmap
.br_startblock
= XFS_AGB_TO_FSB(tp
->t_mountp
, agno
, bno
);
2375 bmap
.br_blockcount
= len
;
2376 bmap
.br_startoff
= 0;
2377 bmap
.br_state
= XFS_EXT_NORM
;
2379 return __xfs_rmap_add(tp
, XFS_RMAP_ALLOC
, owner
, XFS_DATA_FORK
, &bmap
);
2382 /* Schedule the deletion of an rmap for non-file data. */
2384 xfs_rmap_free_extent(
2385 struct xfs_trans
*tp
,
2386 xfs_agnumber_t agno
,
2391 struct xfs_bmbt_irec bmap
;
2393 if (!xfs_rmap_update_is_needed(tp
->t_mountp
, XFS_DATA_FORK
))
2396 bmap
.br_startblock
= XFS_AGB_TO_FSB(tp
->t_mountp
, agno
, bno
);
2397 bmap
.br_blockcount
= len
;
2398 bmap
.br_startoff
= 0;
2399 bmap
.br_state
= XFS_EXT_NORM
;
2401 return __xfs_rmap_add(tp
, XFS_RMAP_FREE
, owner
, XFS_DATA_FORK
, &bmap
);
2404 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2407 const struct xfs_rmap_irec
*a
,
2408 const struct xfs_rmap_irec
*b
)
2413 oa
= xfs_rmap_irec_offset_pack(a
);
2414 ob
= xfs_rmap_irec_offset_pack(b
);
2416 if (a
->rm_startblock
< b
->rm_startblock
)
2418 else if (a
->rm_startblock
> b
->rm_startblock
)
2420 else if (a
->rm_owner
< b
->rm_owner
)
2422 else if (a
->rm_owner
> b
->rm_owner
)
2432 /* Is there a record covering a given extent? */
2434 xfs_rmap_has_record(
2435 struct xfs_btree_cur
*cur
,
2440 union xfs_btree_irec low
;
2441 union xfs_btree_irec high
;
2443 memset(&low
, 0, sizeof(low
));
2444 low
.r
.rm_startblock
= bno
;
2445 memset(&high
, 0xFF, sizeof(high
));
2446 high
.r
.rm_startblock
= bno
+ len
- 1;
2448 return xfs_btree_has_record(cur
, &low
, &high
, exists
);
2452 * Is there a record for this owner completely covering a given physical
2453 * extent? If so, *has_rmap will be set to true. If there is no record
2454 * or the record only covers part of the range, we set *has_rmap to false.
2455 * This function doesn't perform range lookups or offset checks, so it is
2456 * not suitable for checking data fork blocks.
2459 xfs_rmap_record_exists(
2460 struct xfs_btree_cur
*cur
,
2463 struct xfs_owner_info
*oinfo
,
2470 struct xfs_rmap_irec irec
;
2473 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
2474 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner
) ||
2475 (flags
& XFS_RMAP_BMBT_BLOCK
));
2477 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
,
2486 error
= xfs_rmap_get_rec(cur
, &irec
, &has_record
);
2494 *has_rmap
= (irec
.rm_owner
== owner
&& irec
.rm_startblock
<= bno
&&
2495 irec
.rm_startblock
+ irec
.rm_blockcount
>= bno
+ len
);
2499 struct xfs_rmap_key_state
{
2506 /* For each rmap given, figure out if it doesn't match the key we want. */
2508 xfs_rmap_has_other_keys_helper(
2509 struct xfs_btree_cur
*cur
,
2510 struct xfs_rmap_irec
*rec
,
2513 struct xfs_rmap_key_state
*rks
= priv
;
2515 if (rks
->owner
== rec
->rm_owner
&& rks
->offset
== rec
->rm_offset
&&
2516 ((rks
->flags
& rec
->rm_flags
) & XFS_RMAP_KEY_FLAGS
) == rks
->flags
)
2518 rks
->has_rmap
= true;
2519 return XFS_BTREE_QUERY_RANGE_ABORT
;
2523 * Given an extent and some owner info, can we find records overlapping
2524 * the extent whose owner info does not match the given owner?
2527 xfs_rmap_has_other_keys(
2528 struct xfs_btree_cur
*cur
,
2531 struct xfs_owner_info
*oinfo
,
2534 struct xfs_rmap_irec low
= {0};
2535 struct xfs_rmap_irec high
;
2536 struct xfs_rmap_key_state rks
;
2539 xfs_owner_info_unpack(oinfo
, &rks
.owner
, &rks
.offset
, &rks
.flags
);
2540 rks
.has_rmap
= false;
2542 low
.rm_startblock
= bno
;
2543 memset(&high
, 0xFF, sizeof(high
));
2544 high
.rm_startblock
= bno
+ len
- 1;
2546 error
= xfs_rmap_query_range(cur
, &low
, &high
,
2547 xfs_rmap_has_other_keys_helper
, &rks
);
2548 *has_rmap
= rks
.has_rmap
;