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"
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"
26 #include "xfs_error.h"
27 #include "xfs_extent_busy.h"
29 #include "xfs_inode.h"
30 #include "xfs_ialloc.h"
33 * Lookup the first record less than or equal to [bno, len, owner, offset]
34 * in the btree given by cur.
38 struct xfs_btree_cur
*cur
,
46 cur
->bc_rec
.r
.rm_startblock
= bno
;
47 cur
->bc_rec
.r
.rm_blockcount
= len
;
48 cur
->bc_rec
.r
.rm_owner
= owner
;
49 cur
->bc_rec
.r
.rm_offset
= offset
;
50 cur
->bc_rec
.r
.rm_flags
= flags
;
51 return xfs_btree_lookup(cur
, XFS_LOOKUP_LE
, stat
);
55 * Lookup the record exactly matching [bno, len, owner, offset]
56 * in the btree given by cur.
60 struct xfs_btree_cur
*cur
,
68 cur
->bc_rec
.r
.rm_startblock
= bno
;
69 cur
->bc_rec
.r
.rm_blockcount
= len
;
70 cur
->bc_rec
.r
.rm_owner
= owner
;
71 cur
->bc_rec
.r
.rm_offset
= offset
;
72 cur
->bc_rec
.r
.rm_flags
= flags
;
73 return xfs_btree_lookup(cur
, XFS_LOOKUP_EQ
, stat
);
77 * Update the record referred to by cur to the value given
78 * by [bno, len, owner, offset].
79 * This either works (return 0) or gets an EFSCORRUPTED error.
83 struct xfs_btree_cur
*cur
,
84 struct xfs_rmap_irec
*irec
)
86 union xfs_btree_rec rec
;
89 trace_xfs_rmap_update(cur
->bc_mp
, cur
->bc_private
.a
.agno
,
90 irec
->rm_startblock
, irec
->rm_blockcount
,
91 irec
->rm_owner
, irec
->rm_offset
, irec
->rm_flags
);
93 rec
.rmap
.rm_startblock
= cpu_to_be32(irec
->rm_startblock
);
94 rec
.rmap
.rm_blockcount
= cpu_to_be32(irec
->rm_blockcount
);
95 rec
.rmap
.rm_owner
= cpu_to_be64(irec
->rm_owner
);
96 rec
.rmap
.rm_offset
= cpu_to_be64(
97 xfs_rmap_irec_offset_pack(irec
));
98 error
= xfs_btree_update(cur
, &rec
);
100 trace_xfs_rmap_update_error(cur
->bc_mp
,
101 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
107 struct xfs_btree_cur
*rcur
,
117 trace_xfs_rmap_insert(rcur
->bc_mp
, rcur
->bc_private
.a
.agno
, agbno
,
118 len
, owner
, offset
, flags
);
120 error
= xfs_rmap_lookup_eq(rcur
, agbno
, len
, owner
, offset
, flags
, &i
);
123 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 0, done
);
125 rcur
->bc_rec
.r
.rm_startblock
= agbno
;
126 rcur
->bc_rec
.r
.rm_blockcount
= len
;
127 rcur
->bc_rec
.r
.rm_owner
= owner
;
128 rcur
->bc_rec
.r
.rm_offset
= offset
;
129 rcur
->bc_rec
.r
.rm_flags
= flags
;
130 error
= xfs_btree_insert(rcur
, &i
);
133 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 1, done
);
136 trace_xfs_rmap_insert_error(rcur
->bc_mp
,
137 rcur
->bc_private
.a
.agno
, error
, _RET_IP_
);
143 struct xfs_btree_cur
*rcur
,
153 trace_xfs_rmap_delete(rcur
->bc_mp
, rcur
->bc_private
.a
.agno
, agbno
,
154 len
, owner
, offset
, flags
);
156 error
= xfs_rmap_lookup_eq(rcur
, agbno
, len
, owner
, offset
, flags
, &i
);
159 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 1, done
);
161 error
= xfs_btree_delete(rcur
, &i
);
164 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 1, done
);
167 trace_xfs_rmap_delete_error(rcur
->bc_mp
,
168 rcur
->bc_private
.a
.agno
, error
, _RET_IP_
);
172 /* Convert an internal btree record to an rmap record. */
174 xfs_rmap_btrec_to_irec(
175 union xfs_btree_rec
*rec
,
176 struct xfs_rmap_irec
*irec
)
179 irec
->rm_startblock
= be32_to_cpu(rec
->rmap
.rm_startblock
);
180 irec
->rm_blockcount
= be32_to_cpu(rec
->rmap
.rm_blockcount
);
181 irec
->rm_owner
= be64_to_cpu(rec
->rmap
.rm_owner
);
182 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec
->rmap
.rm_offset
),
187 * Get the data from the pointed-to record.
191 struct xfs_btree_cur
*cur
,
192 struct xfs_rmap_irec
*irec
,
195 struct xfs_mount
*mp
= cur
->bc_mp
;
196 xfs_agnumber_t agno
= cur
->bc_private
.a
.agno
;
197 union xfs_btree_rec
*rec
;
200 error
= xfs_btree_get_rec(cur
, &rec
, stat
);
204 if (xfs_rmap_btrec_to_irec(rec
, irec
))
207 if (irec
->rm_blockcount
== 0)
209 if (irec
->rm_startblock
<= XFS_AGFL_BLOCK(mp
)) {
210 if (irec
->rm_owner
!= XFS_RMAP_OWN_FS
)
212 if (irec
->rm_blockcount
!= XFS_AGFL_BLOCK(mp
) + 1)
215 /* check for valid extent range, including overflow */
216 if (!xfs_verify_agbno(mp
, agno
, irec
->rm_startblock
))
218 if (irec
->rm_startblock
>
219 irec
->rm_startblock
+ irec
->rm_blockcount
)
221 if (!xfs_verify_agbno(mp
, agno
,
222 irec
->rm_startblock
+ irec
->rm_blockcount
- 1))
226 if (!(xfs_verify_ino(mp
, irec
->rm_owner
) ||
227 (irec
->rm_owner
<= XFS_RMAP_OWN_FS
&&
228 irec
->rm_owner
>= XFS_RMAP_OWN_MIN
)))
234 "Reverse Mapping BTree record corruption in AG %d detected!",
237 "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
238 irec
->rm_owner
, irec
->rm_flags
, irec
->rm_startblock
,
239 irec
->rm_blockcount
);
240 return -EFSCORRUPTED
;
243 struct xfs_find_left_neighbor_info
{
244 struct xfs_rmap_irec high
;
245 struct xfs_rmap_irec
*irec
;
249 /* For each rmap given, figure out if it matches the key we want. */
251 xfs_rmap_find_left_neighbor_helper(
252 struct xfs_btree_cur
*cur
,
253 struct xfs_rmap_irec
*rec
,
256 struct xfs_find_left_neighbor_info
*info
= priv
;
258 trace_xfs_rmap_find_left_neighbor_candidate(cur
->bc_mp
,
259 cur
->bc_private
.a
.agno
, rec
->rm_startblock
,
260 rec
->rm_blockcount
, rec
->rm_owner
, rec
->rm_offset
,
263 if (rec
->rm_owner
!= info
->high
.rm_owner
)
264 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
265 if (!XFS_RMAP_NON_INODE_OWNER(rec
->rm_owner
) &&
266 !(rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
) &&
267 rec
->rm_offset
+ rec
->rm_blockcount
- 1 != info
->high
.rm_offset
)
268 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
272 return XFS_BTREE_QUERY_RANGE_ABORT
;
276 * Find the record to the left of the given extent, being careful only to
277 * return a match with the same owner and adjacent physical and logical
281 xfs_rmap_find_left_neighbor(
282 struct xfs_btree_cur
*cur
,
287 struct xfs_rmap_irec
*irec
,
290 struct xfs_find_left_neighbor_info info
;
296 info
.high
.rm_startblock
= bno
- 1;
297 info
.high
.rm_owner
= owner
;
298 if (!XFS_RMAP_NON_INODE_OWNER(owner
) &&
299 !(flags
& XFS_RMAP_BMBT_BLOCK
)) {
302 info
.high
.rm_offset
= offset
- 1;
304 info
.high
.rm_offset
= 0;
305 info
.high
.rm_flags
= flags
;
306 info
.high
.rm_blockcount
= 0;
310 trace_xfs_rmap_find_left_neighbor_query(cur
->bc_mp
,
311 cur
->bc_private
.a
.agno
, bno
, 0, owner
, offset
, flags
);
313 error
= xfs_rmap_query_range(cur
, &info
.high
, &info
.high
,
314 xfs_rmap_find_left_neighbor_helper
, &info
);
315 if (error
== XFS_BTREE_QUERY_RANGE_ABORT
)
318 trace_xfs_rmap_find_left_neighbor_result(cur
->bc_mp
,
319 cur
->bc_private
.a
.agno
, irec
->rm_startblock
,
320 irec
->rm_blockcount
, irec
->rm_owner
,
321 irec
->rm_offset
, irec
->rm_flags
);
325 /* For each rmap given, figure out if it matches the key we want. */
327 xfs_rmap_lookup_le_range_helper(
328 struct xfs_btree_cur
*cur
,
329 struct xfs_rmap_irec
*rec
,
332 struct xfs_find_left_neighbor_info
*info
= priv
;
334 trace_xfs_rmap_lookup_le_range_candidate(cur
->bc_mp
,
335 cur
->bc_private
.a
.agno
, rec
->rm_startblock
,
336 rec
->rm_blockcount
, rec
->rm_owner
, rec
->rm_offset
,
339 if (rec
->rm_owner
!= info
->high
.rm_owner
)
340 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
341 if (!XFS_RMAP_NON_INODE_OWNER(rec
->rm_owner
) &&
342 !(rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
) &&
343 (rec
->rm_offset
> info
->high
.rm_offset
||
344 rec
->rm_offset
+ rec
->rm_blockcount
<= info
->high
.rm_offset
))
345 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
349 return XFS_BTREE_QUERY_RANGE_ABORT
;
353 * Find the record to the left of the given extent, being careful only to
354 * return a match with the same owner and overlapping physical and logical
355 * block ranges. This is the overlapping-interval version of
356 * xfs_rmap_lookup_le.
359 xfs_rmap_lookup_le_range(
360 struct xfs_btree_cur
*cur
,
365 struct xfs_rmap_irec
*irec
,
368 struct xfs_find_left_neighbor_info info
;
371 info
.high
.rm_startblock
= bno
;
372 info
.high
.rm_owner
= owner
;
373 if (!XFS_RMAP_NON_INODE_OWNER(owner
) && !(flags
& XFS_RMAP_BMBT_BLOCK
))
374 info
.high
.rm_offset
= offset
;
376 info
.high
.rm_offset
= 0;
377 info
.high
.rm_flags
= flags
;
378 info
.high
.rm_blockcount
= 0;
383 trace_xfs_rmap_lookup_le_range(cur
->bc_mp
,
384 cur
->bc_private
.a
.agno
, bno
, 0, owner
, offset
, flags
);
385 error
= xfs_rmap_query_range(cur
, &info
.high
, &info
.high
,
386 xfs_rmap_lookup_le_range_helper
, &info
);
387 if (error
== XFS_BTREE_QUERY_RANGE_ABORT
)
390 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
391 cur
->bc_private
.a
.agno
, irec
->rm_startblock
,
392 irec
->rm_blockcount
, irec
->rm_owner
,
393 irec
->rm_offset
, irec
->rm_flags
);
398 * Perform all the relevant owner checks for a removal op. If we're doing an
399 * unknown-owner removal then we have no owner information to check.
402 xfs_rmap_free_check_owner(
403 struct xfs_mount
*mp
,
405 struct xfs_rmap_irec
*rec
,
413 if (owner
== XFS_RMAP_OWN_UNKNOWN
)
416 /* Make sure the unwritten flag matches. */
417 XFS_WANT_CORRUPTED_GOTO(mp
, (flags
& XFS_RMAP_UNWRITTEN
) ==
418 (rec
->rm_flags
& XFS_RMAP_UNWRITTEN
), out
);
420 /* Make sure the owner matches what we expect to find in the tree. */
421 XFS_WANT_CORRUPTED_GOTO(mp
, owner
== rec
->rm_owner
, out
);
423 /* Check the offset, if necessary. */
424 if (XFS_RMAP_NON_INODE_OWNER(owner
))
427 if (flags
& XFS_RMAP_BMBT_BLOCK
) {
428 XFS_WANT_CORRUPTED_GOTO(mp
, rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
,
431 XFS_WANT_CORRUPTED_GOTO(mp
, rec
->rm_offset
<= offset
, out
);
432 XFS_WANT_CORRUPTED_GOTO(mp
,
433 ltoff
+ rec
->rm_blockcount
>= offset
+ len
,
442 * Find the extent in the rmap btree and remove it.
444 * The record we find should always be an exact match for the extent that we're
445 * looking for, since we insert them into the btree without modification.
447 * Special Case #1: when growing the filesystem, we "free" an extent when
448 * growing the last AG. This extent is new space and so it is not tracked as
449 * used space in the btree. The growfs code will pass in an owner of
450 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
451 * extent. We verify that - the extent lookup result in a record that does not
454 * Special Case #2: EFIs do not record the owner of the extent, so when
455 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
456 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
457 * corruption checks during log recovery.
461 struct xfs_btree_cur
*cur
,
465 const struct xfs_owner_info
*oinfo
)
467 struct xfs_mount
*mp
= cur
->bc_mp
;
468 struct xfs_rmap_irec ltrec
;
477 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
478 ignore_off
= XFS_RMAP_NON_INODE_OWNER(owner
) ||
479 (flags
& XFS_RMAP_BMBT_BLOCK
);
481 flags
|= XFS_RMAP_UNWRITTEN
;
482 trace_xfs_rmap_unmap(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
486 * We should always have a left record because there's a static record
487 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
488 * will not ever be removed from the tree.
490 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
, &i
);
493 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
495 error
= xfs_rmap_get_rec(cur
, <rec
, &i
);
498 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
499 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
500 cur
->bc_private
.a
.agno
, ltrec
.rm_startblock
,
501 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
502 ltrec
.rm_offset
, ltrec
.rm_flags
);
503 ltoff
= ltrec
.rm_offset
;
506 * For growfs, the incoming extent must be beyond the left record we
507 * just found as it is new space and won't be used by anyone. This is
508 * just a corruption check as we don't actually do anything with this
509 * extent. Note that we need to use >= instead of > because it might
510 * be the case that the "left" extent goes all the way to EOFS.
512 if (owner
== XFS_RMAP_OWN_NULL
) {
513 XFS_WANT_CORRUPTED_GOTO(mp
, bno
>= ltrec
.rm_startblock
+
514 ltrec
.rm_blockcount
, out_error
);
519 * If we're doing an unknown-owner removal for EFI recovery, we expect
520 * to find the full range in the rmapbt or nothing at all. If we
521 * don't find any rmaps overlapping either end of the range, we're
522 * done. Hopefully this means that the EFI creator already queued
523 * (and finished) a RUI to remove the rmap.
525 if (owner
== XFS_RMAP_OWN_UNKNOWN
&&
526 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
<= bno
) {
527 struct xfs_rmap_irec rtrec
;
529 error
= xfs_btree_increment(cur
, 0, &i
);
534 error
= xfs_rmap_get_rec(cur
, &rtrec
, &i
);
537 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
538 if (rtrec
.rm_startblock
>= bno
+ len
)
542 /* Make sure the extent we found covers the entire freeing range. */
543 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_startblock
<= bno
&&
544 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
>=
545 bno
+ len
, out_error
);
547 /* Check owner information. */
548 error
= xfs_rmap_free_check_owner(mp
, ltoff
, <rec
, len
, owner
,
553 if (ltrec
.rm_startblock
== bno
&& ltrec
.rm_blockcount
== len
) {
554 /* exact match, simply remove the record from rmap tree */
555 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
556 ltrec
.rm_startblock
, ltrec
.rm_blockcount
,
557 ltrec
.rm_owner
, ltrec
.rm_offset
,
559 error
= xfs_btree_delete(cur
, &i
);
562 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
563 } else if (ltrec
.rm_startblock
== bno
) {
565 * overlap left hand side of extent: move the start, trim the
566 * length and update the current record.
569 * Orig: |oooooooooooooooooooo|
570 * Freeing: |fffffffff|
571 * Result: |rrrrrrrrrr|
574 ltrec
.rm_startblock
+= len
;
575 ltrec
.rm_blockcount
-= len
;
577 ltrec
.rm_offset
+= len
;
578 error
= xfs_rmap_update(cur
, <rec
);
581 } else if (ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
+ len
) {
583 * overlap right hand side of extent: trim the length and update
584 * the current record.
587 * Orig: |oooooooooooooooooooo|
588 * Freeing: |fffffffff|
589 * Result: |rrrrrrrrrr|
592 ltrec
.rm_blockcount
-= len
;
593 error
= xfs_rmap_update(cur
, <rec
);
599 * overlap middle of extent: trim the length of the existing
600 * record to the length of the new left-extent size, increment
601 * the insertion position so we can insert a new record
602 * containing the remaining right-extent space.
605 * Orig: |oooooooooooooooooooo|
606 * Freeing: |fffffffff|
607 * Result: |rrrrr| |rrrr|
610 xfs_extlen_t orig_len
= ltrec
.rm_blockcount
;
612 ltrec
.rm_blockcount
= bno
- ltrec
.rm_startblock
;
613 error
= xfs_rmap_update(cur
, <rec
);
617 error
= xfs_btree_increment(cur
, 0, &i
);
621 cur
->bc_rec
.r
.rm_startblock
= bno
+ len
;
622 cur
->bc_rec
.r
.rm_blockcount
= orig_len
- len
-
624 cur
->bc_rec
.r
.rm_owner
= ltrec
.rm_owner
;
626 cur
->bc_rec
.r
.rm_offset
= 0;
628 cur
->bc_rec
.r
.rm_offset
= offset
+ len
;
629 cur
->bc_rec
.r
.rm_flags
= flags
;
630 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
,
631 cur
->bc_rec
.r
.rm_startblock
,
632 cur
->bc_rec
.r
.rm_blockcount
,
633 cur
->bc_rec
.r
.rm_owner
,
634 cur
->bc_rec
.r
.rm_offset
,
635 cur
->bc_rec
.r
.rm_flags
);
636 error
= xfs_btree_insert(cur
, &i
);
642 trace_xfs_rmap_unmap_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
646 trace_xfs_rmap_unmap_error(mp
, cur
->bc_private
.a
.agno
,
652 * Remove a reference to an extent in the rmap btree.
656 struct xfs_trans
*tp
,
657 struct xfs_buf
*agbp
,
661 const struct xfs_owner_info
*oinfo
)
663 struct xfs_mount
*mp
= tp
->t_mountp
;
664 struct xfs_btree_cur
*cur
;
667 if (!xfs_sb_version_hasrmapbt(&mp
->m_sb
))
670 cur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
672 error
= xfs_rmap_unmap(cur
, bno
, len
, false, oinfo
);
674 xfs_btree_del_cursor(cur
, error
);
679 * A mergeable rmap must have the same owner and the same values for
680 * the unwritten, attr_fork, and bmbt flags. The startblock and
681 * offset are checked separately.
684 xfs_rmap_is_mergeable(
685 struct xfs_rmap_irec
*irec
,
689 if (irec
->rm_owner
== XFS_RMAP_OWN_NULL
)
691 if (irec
->rm_owner
!= owner
)
693 if ((flags
& XFS_RMAP_UNWRITTEN
) ^
694 (irec
->rm_flags
& XFS_RMAP_UNWRITTEN
))
696 if ((flags
& XFS_RMAP_ATTR_FORK
) ^
697 (irec
->rm_flags
& XFS_RMAP_ATTR_FORK
))
699 if ((flags
& XFS_RMAP_BMBT_BLOCK
) ^
700 (irec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
))
706 * When we allocate a new block, the first thing we do is add a reference to
707 * the extent in the rmap btree. This takes the form of a [agbno, length,
708 * owner, offset] record. Flags are encoded in the high bits of the offset
713 struct xfs_btree_cur
*cur
,
717 const struct xfs_owner_info
*oinfo
)
719 struct xfs_mount
*mp
= cur
->bc_mp
;
720 struct xfs_rmap_irec ltrec
;
721 struct xfs_rmap_irec gtrec
;
728 unsigned int flags
= 0;
731 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
733 ignore_off
= XFS_RMAP_NON_INODE_OWNER(owner
) ||
734 (flags
& XFS_RMAP_BMBT_BLOCK
);
736 flags
|= XFS_RMAP_UNWRITTEN
;
737 trace_xfs_rmap_map(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
739 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo
));
742 * For the initial lookup, look for an exact match or the left-adjacent
743 * record for our insertion point. This will also give us the record for
744 * start block contiguity tests.
746 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
,
751 error
= xfs_rmap_get_rec(cur
, <rec
, &have_lt
);
754 XFS_WANT_CORRUPTED_GOTO(mp
, have_lt
== 1, out_error
);
755 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
756 cur
->bc_private
.a
.agno
, ltrec
.rm_startblock
,
757 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
758 ltrec
.rm_offset
, ltrec
.rm_flags
);
760 if (!xfs_rmap_is_mergeable(<rec
, owner
, flags
))
764 XFS_WANT_CORRUPTED_GOTO(mp
,
766 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
<= bno
, out_error
);
769 * Increment the cursor to see if we have a right-adjacent record to our
770 * insertion point. This will give us the record for end block
773 error
= xfs_btree_increment(cur
, 0, &have_gt
);
777 error
= xfs_rmap_get_rec(cur
, >rec
, &have_gt
);
780 XFS_WANT_CORRUPTED_GOTO(mp
, have_gt
== 1, out_error
);
781 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= gtrec
.rm_startblock
,
783 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
784 cur
->bc_private
.a
.agno
, gtrec
.rm_startblock
,
785 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
786 gtrec
.rm_offset
, gtrec
.rm_flags
);
787 if (!xfs_rmap_is_mergeable(>rec
, owner
, flags
))
792 * Note: cursor currently points one record to the right of ltrec, even
793 * if there is no record in the tree to the right.
796 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
&&
797 (ignore_off
|| ltrec
.rm_offset
+ ltrec
.rm_blockcount
== offset
)) {
799 * left edge contiguous, merge into left record.
803 * adding: |aaaaaaaaa|
804 * result: |rrrrrrrrrrrrrrrrrrr|
807 ltrec
.rm_blockcount
+= len
;
809 bno
+ len
== gtrec
.rm_startblock
&&
810 (ignore_off
|| offset
+ len
== gtrec
.rm_offset
) &&
811 (unsigned long)ltrec
.rm_blockcount
+ len
+
812 gtrec
.rm_blockcount
<= XFS_RMAP_LEN_MAX
) {
814 * right edge also contiguous, delete right record
815 * and merge into left record.
817 * ltbno ltlen gtbno gtlen
818 * orig: |ooooooooo| |ooooooooo|
819 * adding: |aaaaaaaaa|
820 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
822 ltrec
.rm_blockcount
+= gtrec
.rm_blockcount
;
823 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
829 error
= xfs_btree_delete(cur
, &i
);
832 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
835 /* point the cursor back to the left record and update */
836 error
= xfs_btree_decrement(cur
, 0, &have_gt
);
839 error
= xfs_rmap_update(cur
, <rec
);
842 } else if (have_gt
&&
843 bno
+ len
== gtrec
.rm_startblock
&&
844 (ignore_off
|| offset
+ len
== gtrec
.rm_offset
)) {
846 * right edge contiguous, merge into right record.
850 * adding: |aaaaaaaaa|
851 * Result: |rrrrrrrrrrrrrrrrrrr|
854 gtrec
.rm_startblock
= bno
;
855 gtrec
.rm_blockcount
+= len
;
857 gtrec
.rm_offset
= offset
;
858 error
= xfs_rmap_update(cur
, >rec
);
863 * no contiguous edge with identical owner, insert
864 * new record at current cursor position.
866 cur
->bc_rec
.r
.rm_startblock
= bno
;
867 cur
->bc_rec
.r
.rm_blockcount
= len
;
868 cur
->bc_rec
.r
.rm_owner
= owner
;
869 cur
->bc_rec
.r
.rm_offset
= offset
;
870 cur
->bc_rec
.r
.rm_flags
= flags
;
871 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
872 owner
, offset
, flags
);
873 error
= xfs_btree_insert(cur
, &i
);
876 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
879 trace_xfs_rmap_map_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
883 trace_xfs_rmap_map_error(mp
, cur
->bc_private
.a
.agno
,
889 * Add a reference to an extent in the rmap btree.
893 struct xfs_trans
*tp
,
894 struct xfs_buf
*agbp
,
898 const struct xfs_owner_info
*oinfo
)
900 struct xfs_mount
*mp
= tp
->t_mountp
;
901 struct xfs_btree_cur
*cur
;
904 if (!xfs_sb_version_hasrmapbt(&mp
->m_sb
))
907 cur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
908 error
= xfs_rmap_map(cur
, bno
, len
, false, oinfo
);
910 xfs_btree_del_cursor(cur
, error
);
914 #define RMAP_LEFT_CONTIG (1 << 0)
915 #define RMAP_RIGHT_CONTIG (1 << 1)
916 #define RMAP_LEFT_FILLING (1 << 2)
917 #define RMAP_RIGHT_FILLING (1 << 3)
918 #define RMAP_LEFT_VALID (1 << 6)
919 #define RMAP_RIGHT_VALID (1 << 7)
927 * Convert an unwritten extent to a real extent or vice versa.
928 * Does not handle overlapping extents.
932 struct xfs_btree_cur
*cur
,
936 const struct xfs_owner_info
*oinfo
)
938 struct xfs_mount
*mp
= cur
->bc_mp
;
939 struct xfs_rmap_irec r
[4]; /* neighbor extent entries */
940 /* left is 0, right is 1, */
941 /* prev is 2, new is 3 */
947 unsigned int flags
= 0;
952 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
953 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner
) ||
954 (flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
))));
955 oldext
= unwritten
? XFS_RMAP_UNWRITTEN
: 0;
956 new_endoff
= offset
+ len
;
957 trace_xfs_rmap_convert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
961 * For the initial lookup, look for an exact match or the left-adjacent
962 * record for our insertion point. This will also give us the record for
963 * start block contiguity tests.
965 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, oldext
, &i
);
968 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
970 error
= xfs_rmap_get_rec(cur
, &PREV
, &i
);
973 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
974 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
975 cur
->bc_private
.a
.agno
, PREV
.rm_startblock
,
976 PREV
.rm_blockcount
, PREV
.rm_owner
,
977 PREV
.rm_offset
, PREV
.rm_flags
);
979 ASSERT(PREV
.rm_offset
<= offset
);
980 ASSERT(PREV
.rm_offset
+ PREV
.rm_blockcount
>= new_endoff
);
981 ASSERT((PREV
.rm_flags
& XFS_RMAP_UNWRITTEN
) == oldext
);
982 newext
= ~oldext
& XFS_RMAP_UNWRITTEN
;
985 * Set flags determining what part of the previous oldext allocation
986 * extent is being replaced by a newext allocation.
988 if (PREV
.rm_offset
== offset
)
989 state
|= RMAP_LEFT_FILLING
;
990 if (PREV
.rm_offset
+ PREV
.rm_blockcount
== new_endoff
)
991 state
|= RMAP_RIGHT_FILLING
;
994 * Decrement the cursor to see if we have a left-adjacent record to our
995 * insertion point. This will give us the record for end block
998 error
= xfs_btree_decrement(cur
, 0, &i
);
1002 state
|= RMAP_LEFT_VALID
;
1003 error
= xfs_rmap_get_rec(cur
, &LEFT
, &i
);
1006 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1007 XFS_WANT_CORRUPTED_GOTO(mp
,
1008 LEFT
.rm_startblock
+ LEFT
.rm_blockcount
<= bno
,
1010 trace_xfs_rmap_find_left_neighbor_result(cur
->bc_mp
,
1011 cur
->bc_private
.a
.agno
, LEFT
.rm_startblock
,
1012 LEFT
.rm_blockcount
, LEFT
.rm_owner
,
1013 LEFT
.rm_offset
, LEFT
.rm_flags
);
1014 if (LEFT
.rm_startblock
+ LEFT
.rm_blockcount
== bno
&&
1015 LEFT
.rm_offset
+ LEFT
.rm_blockcount
== offset
&&
1016 xfs_rmap_is_mergeable(&LEFT
, owner
, newext
))
1017 state
|= RMAP_LEFT_CONTIG
;
1021 * Increment the cursor to see if we have a right-adjacent record to our
1022 * insertion point. This will give us the record for end block
1025 error
= xfs_btree_increment(cur
, 0, &i
);
1028 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1029 error
= xfs_btree_increment(cur
, 0, &i
);
1033 state
|= RMAP_RIGHT_VALID
;
1034 error
= xfs_rmap_get_rec(cur
, &RIGHT
, &i
);
1037 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1038 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= RIGHT
.rm_startblock
,
1040 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1041 cur
->bc_private
.a
.agno
, RIGHT
.rm_startblock
,
1042 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1043 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1044 if (bno
+ len
== RIGHT
.rm_startblock
&&
1045 offset
+ len
== RIGHT
.rm_offset
&&
1046 xfs_rmap_is_mergeable(&RIGHT
, owner
, newext
))
1047 state
|= RMAP_RIGHT_CONTIG
;
1050 /* check that left + prev + right is not too long */
1051 if ((state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1052 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) ==
1053 (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1054 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
) &&
1055 (unsigned long)LEFT
.rm_blockcount
+ len
+
1056 RIGHT
.rm_blockcount
> XFS_RMAP_LEN_MAX
)
1057 state
&= ~RMAP_RIGHT_CONTIG
;
1059 trace_xfs_rmap_convert_state(mp
, cur
->bc_private
.a
.agno
, state
,
1062 /* reset the cursor back to PREV */
1063 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, oldext
, &i
);
1066 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1069 * Switch out based on the FILLING and CONTIG state bits.
1071 switch (state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1072 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) {
1073 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1074 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1076 * Setting all of a previous oldext extent to newext.
1077 * The left and right neighbors are both contiguous with new.
1079 error
= xfs_btree_increment(cur
, 0, &i
);
1082 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1083 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1084 RIGHT
.rm_startblock
, RIGHT
.rm_blockcount
,
1085 RIGHT
.rm_owner
, RIGHT
.rm_offset
,
1087 error
= xfs_btree_delete(cur
, &i
);
1090 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1091 error
= xfs_btree_decrement(cur
, 0, &i
);
1094 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1095 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1096 PREV
.rm_startblock
, PREV
.rm_blockcount
,
1097 PREV
.rm_owner
, PREV
.rm_offset
,
1099 error
= xfs_btree_delete(cur
, &i
);
1102 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1103 error
= xfs_btree_decrement(cur
, 0, &i
);
1106 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1108 NEW
.rm_blockcount
+= PREV
.rm_blockcount
+ RIGHT
.rm_blockcount
;
1109 error
= xfs_rmap_update(cur
, &NEW
);
1114 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1116 * Setting all of a previous oldext extent to newext.
1117 * The left neighbor is contiguous, the right is not.
1119 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1120 PREV
.rm_startblock
, PREV
.rm_blockcount
,
1121 PREV
.rm_owner
, PREV
.rm_offset
,
1123 error
= xfs_btree_delete(cur
, &i
);
1126 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1127 error
= xfs_btree_decrement(cur
, 0, &i
);
1130 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1132 NEW
.rm_blockcount
+= PREV
.rm_blockcount
;
1133 error
= xfs_rmap_update(cur
, &NEW
);
1138 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1140 * Setting all of a previous oldext extent to newext.
1141 * The right neighbor is contiguous, the left is not.
1143 error
= xfs_btree_increment(cur
, 0, &i
);
1146 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1147 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1148 RIGHT
.rm_startblock
, RIGHT
.rm_blockcount
,
1149 RIGHT
.rm_owner
, RIGHT
.rm_offset
,
1151 error
= xfs_btree_delete(cur
, &i
);
1154 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1155 error
= xfs_btree_decrement(cur
, 0, &i
);
1158 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1160 NEW
.rm_blockcount
= len
+ RIGHT
.rm_blockcount
;
1161 NEW
.rm_flags
= newext
;
1162 error
= xfs_rmap_update(cur
, &NEW
);
1167 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
:
1169 * Setting all of a previous oldext extent to newext.
1170 * Neither the left nor right neighbors are contiguous with
1174 NEW
.rm_flags
= newext
;
1175 error
= xfs_rmap_update(cur
, &NEW
);
1180 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
:
1182 * Setting the first part of a previous oldext extent to newext.
1183 * The left neighbor is contiguous.
1186 NEW
.rm_offset
+= len
;
1187 NEW
.rm_startblock
+= len
;
1188 NEW
.rm_blockcount
-= len
;
1189 error
= xfs_rmap_update(cur
, &NEW
);
1192 error
= xfs_btree_decrement(cur
, 0, &i
);
1196 NEW
.rm_blockcount
+= len
;
1197 error
= xfs_rmap_update(cur
, &NEW
);
1202 case RMAP_LEFT_FILLING
:
1204 * Setting the first part of a previous oldext extent to newext.
1205 * The left neighbor is not contiguous.
1208 NEW
.rm_startblock
+= len
;
1209 NEW
.rm_offset
+= len
;
1210 NEW
.rm_blockcount
-= len
;
1211 error
= xfs_rmap_update(cur
, &NEW
);
1214 NEW
.rm_startblock
= bno
;
1215 NEW
.rm_owner
= owner
;
1216 NEW
.rm_offset
= offset
;
1217 NEW
.rm_blockcount
= len
;
1218 NEW
.rm_flags
= newext
;
1219 cur
->bc_rec
.r
= NEW
;
1220 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
,
1221 len
, owner
, offset
, newext
);
1222 error
= xfs_btree_insert(cur
, &i
);
1225 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1228 case RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1230 * Setting the last part of a previous oldext extent to newext.
1231 * The right neighbor is contiguous with the new allocation.
1234 NEW
.rm_blockcount
-= len
;
1235 error
= xfs_rmap_update(cur
, &NEW
);
1238 error
= xfs_btree_increment(cur
, 0, &i
);
1242 NEW
.rm_offset
= offset
;
1243 NEW
.rm_startblock
= bno
;
1244 NEW
.rm_blockcount
+= len
;
1245 error
= xfs_rmap_update(cur
, &NEW
);
1250 case RMAP_RIGHT_FILLING
:
1252 * Setting the last part of a previous oldext extent to newext.
1253 * The right neighbor is not contiguous.
1256 NEW
.rm_blockcount
-= len
;
1257 error
= xfs_rmap_update(cur
, &NEW
);
1260 error
= xfs_rmap_lookup_eq(cur
, bno
, len
, owner
, offset
,
1264 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 0, done
);
1265 NEW
.rm_startblock
= bno
;
1266 NEW
.rm_owner
= owner
;
1267 NEW
.rm_offset
= offset
;
1268 NEW
.rm_blockcount
= len
;
1269 NEW
.rm_flags
= newext
;
1270 cur
->bc_rec
.r
= NEW
;
1271 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
,
1272 len
, owner
, offset
, newext
);
1273 error
= xfs_btree_insert(cur
, &i
);
1276 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1281 * Setting the middle part of a previous oldext extent to
1282 * newext. Contiguity is impossible here.
1283 * One extent becomes three extents.
1285 /* new right extent - oldext */
1286 NEW
.rm_startblock
= bno
+ len
;
1287 NEW
.rm_owner
= owner
;
1288 NEW
.rm_offset
= new_endoff
;
1289 NEW
.rm_blockcount
= PREV
.rm_offset
+ PREV
.rm_blockcount
-
1291 NEW
.rm_flags
= PREV
.rm_flags
;
1292 error
= xfs_rmap_update(cur
, &NEW
);
1295 /* new left extent - oldext */
1297 NEW
.rm_blockcount
= offset
- PREV
.rm_offset
;
1298 cur
->bc_rec
.r
= NEW
;
1299 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
,
1300 NEW
.rm_startblock
, NEW
.rm_blockcount
,
1301 NEW
.rm_owner
, NEW
.rm_offset
,
1303 error
= xfs_btree_insert(cur
, &i
);
1306 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1308 * Reset the cursor to the position of the new extent
1309 * we are about to insert as we can't trust it after
1310 * the previous insert.
1312 error
= xfs_rmap_lookup_eq(cur
, bno
, len
, owner
, offset
,
1316 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 0, done
);
1317 /* new middle extent - newext */
1318 cur
->bc_rec
.r
.rm_flags
&= ~XFS_RMAP_UNWRITTEN
;
1319 cur
->bc_rec
.r
.rm_flags
|= newext
;
1320 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1321 owner
, offset
, newext
);
1322 error
= xfs_btree_insert(cur
, &i
);
1325 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1328 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1329 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1330 case RMAP_LEFT_FILLING
| RMAP_RIGHT_CONTIG
:
1331 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1332 case RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1333 case RMAP_LEFT_CONTIG
:
1334 case RMAP_RIGHT_CONTIG
:
1336 * These cases are all impossible.
1341 trace_xfs_rmap_convert_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1345 trace_xfs_rmap_convert_error(cur
->bc_mp
,
1346 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1351 * Convert an unwritten extent to a real extent or vice versa. If there is no
1352 * possibility of overlapping extents, delegate to the simpler convert
1356 xfs_rmap_convert_shared(
1357 struct xfs_btree_cur
*cur
,
1361 const struct xfs_owner_info
*oinfo
)
1363 struct xfs_mount
*mp
= cur
->bc_mp
;
1364 struct xfs_rmap_irec r
[4]; /* neighbor extent entries */
1365 /* left is 0, right is 1, */
1366 /* prev is 2, new is 3 */
1369 uint64_t new_endoff
;
1370 unsigned int oldext
;
1371 unsigned int newext
;
1372 unsigned int flags
= 0;
1377 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1378 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner
) ||
1379 (flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
))));
1380 oldext
= unwritten
? XFS_RMAP_UNWRITTEN
: 0;
1381 new_endoff
= offset
+ len
;
1382 trace_xfs_rmap_convert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1386 * For the initial lookup, look for and exact match or the left-adjacent
1387 * record for our insertion point. This will also give us the record for
1388 * start block contiguity tests.
1390 error
= xfs_rmap_lookup_le_range(cur
, bno
, owner
, offset
, flags
,
1394 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1396 ASSERT(PREV
.rm_offset
<= offset
);
1397 ASSERT(PREV
.rm_offset
+ PREV
.rm_blockcount
>= new_endoff
);
1398 ASSERT((PREV
.rm_flags
& XFS_RMAP_UNWRITTEN
) == oldext
);
1399 newext
= ~oldext
& XFS_RMAP_UNWRITTEN
;
1402 * Set flags determining what part of the previous oldext allocation
1403 * extent is being replaced by a newext allocation.
1405 if (PREV
.rm_offset
== offset
)
1406 state
|= RMAP_LEFT_FILLING
;
1407 if (PREV
.rm_offset
+ PREV
.rm_blockcount
== new_endoff
)
1408 state
|= RMAP_RIGHT_FILLING
;
1410 /* Is there a left record that abuts our range? */
1411 error
= xfs_rmap_find_left_neighbor(cur
, bno
, owner
, offset
, newext
,
1416 state
|= RMAP_LEFT_VALID
;
1417 XFS_WANT_CORRUPTED_GOTO(mp
,
1418 LEFT
.rm_startblock
+ LEFT
.rm_blockcount
<= bno
,
1420 if (xfs_rmap_is_mergeable(&LEFT
, owner
, newext
))
1421 state
|= RMAP_LEFT_CONTIG
;
1424 /* Is there a right record that abuts our range? */
1425 error
= xfs_rmap_lookup_eq(cur
, bno
+ len
, len
, owner
, offset
+ len
,
1430 state
|= RMAP_RIGHT_VALID
;
1431 error
= xfs_rmap_get_rec(cur
, &RIGHT
, &i
);
1434 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1435 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= RIGHT
.rm_startblock
,
1437 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1438 cur
->bc_private
.a
.agno
, RIGHT
.rm_startblock
,
1439 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1440 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1441 if (xfs_rmap_is_mergeable(&RIGHT
, owner
, newext
))
1442 state
|= RMAP_RIGHT_CONTIG
;
1445 /* check that left + prev + right is not too long */
1446 if ((state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1447 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) ==
1448 (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1449 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
) &&
1450 (unsigned long)LEFT
.rm_blockcount
+ len
+
1451 RIGHT
.rm_blockcount
> XFS_RMAP_LEN_MAX
)
1452 state
&= ~RMAP_RIGHT_CONTIG
;
1454 trace_xfs_rmap_convert_state(mp
, cur
->bc_private
.a
.agno
, state
,
1457 * Switch out based on the FILLING and CONTIG state bits.
1459 switch (state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1460 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) {
1461 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1462 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1464 * Setting all of a previous oldext extent to newext.
1465 * The left and right neighbors are both contiguous with new.
1467 error
= xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1468 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1469 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1472 error
= xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1473 PREV
.rm_blockcount
, PREV
.rm_owner
,
1474 PREV
.rm_offset
, PREV
.rm_flags
);
1478 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1479 NEW
.rm_blockcount
, NEW
.rm_owner
,
1480 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1483 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1484 NEW
.rm_blockcount
+= PREV
.rm_blockcount
+ RIGHT
.rm_blockcount
;
1485 error
= xfs_rmap_update(cur
, &NEW
);
1490 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1492 * Setting all of a previous oldext extent to newext.
1493 * The left neighbor is contiguous, the right is not.
1495 error
= xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1496 PREV
.rm_blockcount
, PREV
.rm_owner
,
1497 PREV
.rm_offset
, PREV
.rm_flags
);
1501 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1502 NEW
.rm_blockcount
, NEW
.rm_owner
,
1503 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1506 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1507 NEW
.rm_blockcount
+= PREV
.rm_blockcount
;
1508 error
= xfs_rmap_update(cur
, &NEW
);
1513 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1515 * Setting all of a previous oldext extent to newext.
1516 * The right neighbor is contiguous, the left is not.
1518 error
= xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1519 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1520 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1524 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1525 NEW
.rm_blockcount
, NEW
.rm_owner
,
1526 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1529 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1530 NEW
.rm_blockcount
+= RIGHT
.rm_blockcount
;
1531 NEW
.rm_flags
= RIGHT
.rm_flags
;
1532 error
= xfs_rmap_update(cur
, &NEW
);
1537 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
:
1539 * Setting all of a previous oldext extent to newext.
1540 * Neither the left nor right neighbors are contiguous with
1544 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1545 NEW
.rm_blockcount
, NEW
.rm_owner
,
1546 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1549 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1550 NEW
.rm_flags
= newext
;
1551 error
= xfs_rmap_update(cur
, &NEW
);
1556 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
:
1558 * Setting the first part of a previous oldext extent to newext.
1559 * The left neighbor is contiguous.
1562 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1563 NEW
.rm_blockcount
, NEW
.rm_owner
,
1564 NEW
.rm_offset
, NEW
.rm_flags
);
1567 NEW
.rm_offset
+= len
;
1568 NEW
.rm_startblock
+= len
;
1569 NEW
.rm_blockcount
-= len
;
1570 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1571 NEW
.rm_blockcount
, NEW
.rm_owner
,
1572 NEW
.rm_offset
, NEW
.rm_flags
);
1576 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1577 NEW
.rm_blockcount
, NEW
.rm_owner
,
1578 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1581 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1582 NEW
.rm_blockcount
+= len
;
1583 error
= xfs_rmap_update(cur
, &NEW
);
1588 case RMAP_LEFT_FILLING
:
1590 * Setting the first part of a previous oldext extent to newext.
1591 * The left neighbor is not contiguous.
1594 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1595 NEW
.rm_blockcount
, NEW
.rm_owner
,
1596 NEW
.rm_offset
, NEW
.rm_flags
);
1599 NEW
.rm_offset
+= len
;
1600 NEW
.rm_startblock
+= len
;
1601 NEW
.rm_blockcount
-= len
;
1602 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1603 NEW
.rm_blockcount
, NEW
.rm_owner
,
1604 NEW
.rm_offset
, NEW
.rm_flags
);
1607 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1612 case RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1614 * Setting the last part of a previous oldext extent to newext.
1615 * The right neighbor is contiguous with the new allocation.
1618 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1619 NEW
.rm_blockcount
, NEW
.rm_owner
,
1620 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1623 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1624 NEW
.rm_blockcount
= offset
- NEW
.rm_offset
;
1625 error
= xfs_rmap_update(cur
, &NEW
);
1629 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1630 NEW
.rm_blockcount
, NEW
.rm_owner
,
1631 NEW
.rm_offset
, NEW
.rm_flags
);
1634 NEW
.rm_offset
= offset
;
1635 NEW
.rm_startblock
= bno
;
1636 NEW
.rm_blockcount
+= len
;
1637 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1638 NEW
.rm_blockcount
, NEW
.rm_owner
,
1639 NEW
.rm_offset
, NEW
.rm_flags
);
1644 case RMAP_RIGHT_FILLING
:
1646 * Setting the last part of a previous oldext extent to newext.
1647 * The right neighbor is not contiguous.
1650 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1651 NEW
.rm_blockcount
, NEW
.rm_owner
,
1652 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1655 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1656 NEW
.rm_blockcount
-= len
;
1657 error
= xfs_rmap_update(cur
, &NEW
);
1660 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1667 * Setting the middle part of a previous oldext extent to
1668 * newext. Contiguity is impossible here.
1669 * One extent becomes three extents.
1671 /* new right extent - oldext */
1672 NEW
.rm_startblock
= bno
+ len
;
1673 NEW
.rm_owner
= owner
;
1674 NEW
.rm_offset
= new_endoff
;
1675 NEW
.rm_blockcount
= PREV
.rm_offset
+ PREV
.rm_blockcount
-
1677 NEW
.rm_flags
= PREV
.rm_flags
;
1678 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1679 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
1683 /* new left extent - oldext */
1685 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1686 NEW
.rm_blockcount
, NEW
.rm_owner
,
1687 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1690 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1691 NEW
.rm_blockcount
= offset
- NEW
.rm_offset
;
1692 error
= xfs_rmap_update(cur
, &NEW
);
1695 /* new middle extent - newext */
1696 NEW
.rm_startblock
= bno
;
1697 NEW
.rm_blockcount
= len
;
1698 NEW
.rm_owner
= owner
;
1699 NEW
.rm_offset
= offset
;
1700 NEW
.rm_flags
= newext
;
1701 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1702 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
1708 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1709 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1710 case RMAP_LEFT_FILLING
| RMAP_RIGHT_CONTIG
:
1711 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1712 case RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1713 case RMAP_LEFT_CONTIG
:
1714 case RMAP_RIGHT_CONTIG
:
1716 * These cases are all impossible.
1721 trace_xfs_rmap_convert_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1725 trace_xfs_rmap_convert_error(cur
->bc_mp
,
1726 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1736 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1737 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1738 * that the prev/next records in the btree might belong to another owner.
1739 * Therefore we must use delete+insert to alter any of the key fields.
1741 * For every other situation there can only be one owner for a given extent,
1742 * so we can call the regular _free function.
1745 xfs_rmap_unmap_shared(
1746 struct xfs_btree_cur
*cur
,
1750 const struct xfs_owner_info
*oinfo
)
1752 struct xfs_mount
*mp
= cur
->bc_mp
;
1753 struct xfs_rmap_irec ltrec
;
1761 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1763 flags
|= XFS_RMAP_UNWRITTEN
;
1764 trace_xfs_rmap_unmap(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1768 * We should always have a left record because there's a static record
1769 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1770 * will not ever be removed from the tree.
1772 error
= xfs_rmap_lookup_le_range(cur
, bno
, owner
, offset
, flags
,
1776 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1777 ltoff
= ltrec
.rm_offset
;
1779 /* Make sure the extent we found covers the entire freeing range. */
1780 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_startblock
<= bno
&&
1781 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
>=
1782 bno
+ len
, out_error
);
1784 /* Make sure the owner matches what we expect to find in the tree. */
1785 XFS_WANT_CORRUPTED_GOTO(mp
, owner
== ltrec
.rm_owner
, out_error
);
1787 /* Make sure the unwritten flag matches. */
1788 XFS_WANT_CORRUPTED_GOTO(mp
, (flags
& XFS_RMAP_UNWRITTEN
) ==
1789 (ltrec
.rm_flags
& XFS_RMAP_UNWRITTEN
), out_error
);
1791 /* Check the offset. */
1792 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_offset
<= offset
, out_error
);
1793 XFS_WANT_CORRUPTED_GOTO(mp
, offset
<= ltoff
+ ltrec
.rm_blockcount
,
1796 if (ltrec
.rm_startblock
== bno
&& ltrec
.rm_blockcount
== len
) {
1797 /* Exact match, simply remove the record from rmap tree. */
1798 error
= xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
1799 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1800 ltrec
.rm_offset
, ltrec
.rm_flags
);
1803 } else if (ltrec
.rm_startblock
== bno
) {
1805 * Overlap left hand side of extent: move the start, trim the
1806 * length and update the current record.
1809 * Orig: |oooooooooooooooooooo|
1810 * Freeing: |fffffffff|
1811 * Result: |rrrrrrrrrr|
1815 /* Delete prev rmap. */
1816 error
= xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
1817 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1818 ltrec
.rm_offset
, ltrec
.rm_flags
);
1822 /* Add an rmap at the new offset. */
1823 ltrec
.rm_startblock
+= len
;
1824 ltrec
.rm_blockcount
-= len
;
1825 ltrec
.rm_offset
+= len
;
1826 error
= xfs_rmap_insert(cur
, ltrec
.rm_startblock
,
1827 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1828 ltrec
.rm_offset
, ltrec
.rm_flags
);
1831 } else if (ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
+ len
) {
1833 * Overlap right hand side of extent: trim the length and
1834 * update the current record.
1837 * Orig: |oooooooooooooooooooo|
1838 * Freeing: |fffffffff|
1839 * Result: |rrrrrrrrrr|
1842 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1843 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1844 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1847 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1848 ltrec
.rm_blockcount
-= len
;
1849 error
= xfs_rmap_update(cur
, <rec
);
1854 * Overlap middle of extent: trim the length of the existing
1855 * record to the length of the new left-extent size, increment
1856 * the insertion position so we can insert a new record
1857 * containing the remaining right-extent space.
1860 * Orig: |oooooooooooooooooooo|
1861 * Freeing: |fffffffff|
1862 * Result: |rrrrr| |rrrr|
1865 xfs_extlen_t orig_len
= ltrec
.rm_blockcount
;
1867 /* Shrink the left side of the rmap */
1868 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1869 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1870 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1873 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1874 ltrec
.rm_blockcount
= bno
- ltrec
.rm_startblock
;
1875 error
= xfs_rmap_update(cur
, <rec
);
1879 /* Add an rmap at the new offset */
1880 error
= xfs_rmap_insert(cur
, bno
+ len
,
1881 orig_len
- len
- ltrec
.rm_blockcount
,
1882 ltrec
.rm_owner
, offset
+ len
,
1888 trace_xfs_rmap_unmap_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1892 trace_xfs_rmap_unmap_error(cur
->bc_mp
,
1893 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1898 * Find an extent in the rmap btree and map 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 _alloc function.
1907 xfs_rmap_map_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
;
1916 struct xfs_rmap_irec gtrec
;
1923 unsigned int flags
= 0;
1925 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1927 flags
|= XFS_RMAP_UNWRITTEN
;
1928 trace_xfs_rmap_map(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1931 /* Is there a left record that abuts our range? */
1932 error
= xfs_rmap_find_left_neighbor(cur
, bno
, owner
, offset
, flags
,
1937 !xfs_rmap_is_mergeable(<rec
, owner
, flags
))
1940 /* Is there a right record that abuts our range? */
1941 error
= xfs_rmap_lookup_eq(cur
, bno
+ len
, len
, owner
, offset
+ len
,
1946 error
= xfs_rmap_get_rec(cur
, >rec
, &have_gt
);
1949 XFS_WANT_CORRUPTED_GOTO(mp
, have_gt
== 1, out_error
);
1950 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1951 cur
->bc_private
.a
.agno
, gtrec
.rm_startblock
,
1952 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
1953 gtrec
.rm_offset
, gtrec
.rm_flags
);
1955 if (!xfs_rmap_is_mergeable(>rec
, owner
, flags
))
1960 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
&&
1961 ltrec
.rm_offset
+ ltrec
.rm_blockcount
== offset
) {
1963 * Left edge contiguous, merge into left record.
1967 * adding: |aaaaaaaaa|
1968 * result: |rrrrrrrrrrrrrrrrrrr|
1971 ltrec
.rm_blockcount
+= len
;
1973 bno
+ len
== gtrec
.rm_startblock
&&
1974 offset
+ len
== gtrec
.rm_offset
) {
1976 * Right edge also contiguous, delete right record
1977 * and merge into left record.
1979 * ltbno ltlen gtbno gtlen
1980 * orig: |ooooooooo| |ooooooooo|
1981 * adding: |aaaaaaaaa|
1982 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1984 ltrec
.rm_blockcount
+= gtrec
.rm_blockcount
;
1985 error
= xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
1986 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
1987 gtrec
.rm_offset
, gtrec
.rm_flags
);
1992 /* Point the cursor back to the left record and update. */
1993 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1994 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1995 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1998 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
2000 error
= xfs_rmap_update(cur
, <rec
);
2003 } else if (have_gt
&&
2004 bno
+ len
== gtrec
.rm_startblock
&&
2005 offset
+ len
== gtrec
.rm_offset
) {
2007 * Right edge contiguous, merge into right record.
2011 * adding: |aaaaaaaaa|
2012 * Result: |rrrrrrrrrrrrrrrrrrr|
2015 /* Delete the old record. */
2016 error
= xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
2017 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2018 gtrec
.rm_offset
, gtrec
.rm_flags
);
2022 /* Move the start and re-add it. */
2023 gtrec
.rm_startblock
= bno
;
2024 gtrec
.rm_blockcount
+= len
;
2025 gtrec
.rm_offset
= offset
;
2026 error
= xfs_rmap_insert(cur
, gtrec
.rm_startblock
,
2027 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2028 gtrec
.rm_offset
, gtrec
.rm_flags
);
2033 * No contiguous edge with identical owner, insert
2034 * new record at current cursor position.
2036 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, flags
);
2041 trace_xfs_rmap_map_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
2045 trace_xfs_rmap_map_error(cur
->bc_mp
,
2046 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
2050 /* Insert a raw rmap into the rmapbt. */
2053 struct xfs_btree_cur
*cur
,
2054 struct xfs_rmap_irec
*rmap
)
2056 struct xfs_owner_info oinfo
;
2058 oinfo
.oi_owner
= rmap
->rm_owner
;
2059 oinfo
.oi_offset
= rmap
->rm_offset
;
2061 if (rmap
->rm_flags
& XFS_RMAP_ATTR_FORK
)
2062 oinfo
.oi_flags
|= XFS_OWNER_INFO_ATTR_FORK
;
2063 if (rmap
->rm_flags
& XFS_RMAP_BMBT_BLOCK
)
2064 oinfo
.oi_flags
|= XFS_OWNER_INFO_BMBT_BLOCK
;
2066 if (rmap
->rm_flags
|| XFS_RMAP_NON_INODE_OWNER(rmap
->rm_owner
))
2067 return xfs_rmap_map(cur
, rmap
->rm_startblock
,
2068 rmap
->rm_blockcount
,
2069 rmap
->rm_flags
& XFS_RMAP_UNWRITTEN
,
2072 return xfs_rmap_map_shared(cur
, rmap
->rm_startblock
,
2073 rmap
->rm_blockcount
,
2074 rmap
->rm_flags
& XFS_RMAP_UNWRITTEN
,
2078 struct xfs_rmap_query_range_info
{
2079 xfs_rmap_query_range_fn fn
;
2083 /* Format btree record and pass to our callback. */
2085 xfs_rmap_query_range_helper(
2086 struct xfs_btree_cur
*cur
,
2087 union xfs_btree_rec
*rec
,
2090 struct xfs_rmap_query_range_info
*query
= priv
;
2091 struct xfs_rmap_irec irec
;
2094 error
= xfs_rmap_btrec_to_irec(rec
, &irec
);
2097 return query
->fn(cur
, &irec
, query
->priv
);
2100 /* Find all rmaps between two keys. */
2102 xfs_rmap_query_range(
2103 struct xfs_btree_cur
*cur
,
2104 struct xfs_rmap_irec
*low_rec
,
2105 struct xfs_rmap_irec
*high_rec
,
2106 xfs_rmap_query_range_fn fn
,
2109 union xfs_btree_irec low_brec
;
2110 union xfs_btree_irec high_brec
;
2111 struct xfs_rmap_query_range_info query
;
2113 low_brec
.r
= *low_rec
;
2114 high_brec
.r
= *high_rec
;
2117 return xfs_btree_query_range(cur
, &low_brec
, &high_brec
,
2118 xfs_rmap_query_range_helper
, &query
);
2121 /* Find all rmaps. */
2124 struct xfs_btree_cur
*cur
,
2125 xfs_rmap_query_range_fn fn
,
2128 struct xfs_rmap_query_range_info query
;
2132 return xfs_btree_query_all(cur
, xfs_rmap_query_range_helper
, &query
);
2135 /* Clean up after calling xfs_rmap_finish_one. */
2137 xfs_rmap_finish_one_cleanup(
2138 struct xfs_trans
*tp
,
2139 struct xfs_btree_cur
*rcur
,
2142 struct xfs_buf
*agbp
;
2146 agbp
= rcur
->bc_private
.a
.agbp
;
2147 xfs_btree_del_cursor(rcur
, error
);
2149 xfs_trans_brelse(tp
, agbp
);
2153 * Process one of the deferred rmap operations. We pass back the
2154 * btree cursor to maintain our lock on the rmapbt between calls.
2155 * This saves time and eliminates a buffer deadlock between the
2156 * superblock and the AGF because we'll always grab them in the same
2160 xfs_rmap_finish_one(
2161 struct xfs_trans
*tp
,
2162 enum xfs_rmap_intent_type type
,
2165 xfs_fileoff_t startoff
,
2166 xfs_fsblock_t startblock
,
2167 xfs_filblks_t blockcount
,
2169 struct xfs_btree_cur
**pcur
)
2171 struct xfs_mount
*mp
= tp
->t_mountp
;
2172 struct xfs_btree_cur
*rcur
;
2173 struct xfs_buf
*agbp
= NULL
;
2175 xfs_agnumber_t agno
;
2176 struct xfs_owner_info oinfo
;
2180 agno
= XFS_FSB_TO_AGNO(mp
, startblock
);
2181 ASSERT(agno
!= NULLAGNUMBER
);
2182 bno
= XFS_FSB_TO_AGBNO(mp
, startblock
);
2184 trace_xfs_rmap_deferred(mp
, agno
, type
, bno
, owner
, whichfork
,
2185 startoff
, blockcount
, state
);
2187 if (XFS_TEST_ERROR(false, mp
,
2188 XFS_ERRTAG_RMAP_FINISH_ONE
))
2192 * If we haven't gotten a cursor or the cursor AG doesn't match
2193 * the startblock, get one now.
2196 if (rcur
!= NULL
&& rcur
->bc_private
.a
.agno
!= agno
) {
2197 xfs_rmap_finish_one_cleanup(tp
, rcur
, 0);
2203 * Refresh the freelist before we start changing the
2204 * rmapbt, because a shape change could cause us to
2207 error
= xfs_free_extent_fix_freelist(tp
, agno
, &agbp
);
2211 return -EFSCORRUPTED
;
2213 rcur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
2221 xfs_rmap_ino_owner(&oinfo
, owner
, whichfork
, startoff
);
2222 unwritten
= state
== XFS_EXT_UNWRITTEN
;
2223 bno
= XFS_FSB_TO_AGBNO(rcur
->bc_mp
, startblock
);
2226 case XFS_RMAP_ALLOC
:
2228 error
= xfs_rmap_map(rcur
, bno
, blockcount
, unwritten
, &oinfo
);
2230 case XFS_RMAP_MAP_SHARED
:
2231 error
= xfs_rmap_map_shared(rcur
, bno
, blockcount
, unwritten
,
2235 case XFS_RMAP_UNMAP
:
2236 error
= xfs_rmap_unmap(rcur
, bno
, blockcount
, unwritten
,
2239 case XFS_RMAP_UNMAP_SHARED
:
2240 error
= xfs_rmap_unmap_shared(rcur
, bno
, blockcount
, unwritten
,
2243 case XFS_RMAP_CONVERT
:
2244 error
= xfs_rmap_convert(rcur
, bno
, blockcount
, !unwritten
,
2247 case XFS_RMAP_CONVERT_SHARED
:
2248 error
= xfs_rmap_convert_shared(rcur
, bno
, blockcount
,
2249 !unwritten
, &oinfo
);
2253 error
= -EFSCORRUPTED
;
2258 xfs_trans_brelse(tp
, agbp
);
2264 * Don't defer an rmap if we aren't an rmap filesystem.
2267 xfs_rmap_update_is_needed(
2268 struct xfs_mount
*mp
,
2271 return xfs_sb_version_hasrmapbt(&mp
->m_sb
) && whichfork
!= XFS_COW_FORK
;
2275 * Record a rmap intent; the list is kept sorted first by AG and then by
2280 struct xfs_trans
*tp
,
2281 enum xfs_rmap_intent_type type
,
2284 struct xfs_bmbt_irec
*bmap
)
2286 struct xfs_rmap_intent
*ri
;
2288 trace_xfs_rmap_defer(tp
->t_mountp
,
2289 XFS_FSB_TO_AGNO(tp
->t_mountp
, bmap
->br_startblock
),
2291 XFS_FSB_TO_AGBNO(tp
->t_mountp
, bmap
->br_startblock
),
2294 bmap
->br_blockcount
,
2297 ri
= kmem_alloc(sizeof(struct xfs_rmap_intent
), KM_SLEEP
| KM_NOFS
);
2298 INIT_LIST_HEAD(&ri
->ri_list
);
2300 ri
->ri_owner
= owner
;
2301 ri
->ri_whichfork
= whichfork
;
2302 ri
->ri_bmap
= *bmap
;
2304 xfs_defer_add(tp
, XFS_DEFER_OPS_TYPE_RMAP
, &ri
->ri_list
);
2308 /* Map an extent into a file. */
2310 xfs_rmap_map_extent(
2311 struct xfs_trans
*tp
,
2312 struct xfs_inode
*ip
,
2314 struct xfs_bmbt_irec
*PREV
)
2316 if (!xfs_rmap_update_is_needed(tp
->t_mountp
, whichfork
))
2319 return __xfs_rmap_add(tp
, xfs_is_reflink_inode(ip
) ?
2320 XFS_RMAP_MAP_SHARED
: XFS_RMAP_MAP
, ip
->i_ino
,
2324 /* Unmap an extent out of a file. */
2326 xfs_rmap_unmap_extent(
2327 struct xfs_trans
*tp
,
2328 struct xfs_inode
*ip
,
2330 struct xfs_bmbt_irec
*PREV
)
2332 if (!xfs_rmap_update_is_needed(tp
->t_mountp
, whichfork
))
2335 return __xfs_rmap_add(tp
, xfs_is_reflink_inode(ip
) ?
2336 XFS_RMAP_UNMAP_SHARED
: XFS_RMAP_UNMAP
, ip
->i_ino
,
2341 * Convert a data fork extent from unwritten to real or vice versa.
2343 * Note that tp can be NULL here as no transaction is used for COW fork
2344 * unwritten conversion.
2347 xfs_rmap_convert_extent(
2348 struct xfs_mount
*mp
,
2349 struct xfs_trans
*tp
,
2350 struct xfs_inode
*ip
,
2352 struct xfs_bmbt_irec
*PREV
)
2354 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2357 return __xfs_rmap_add(tp
, xfs_is_reflink_inode(ip
) ?
2358 XFS_RMAP_CONVERT_SHARED
: XFS_RMAP_CONVERT
, ip
->i_ino
,
2362 /* Schedule the creation of an rmap for non-file data. */
2364 xfs_rmap_alloc_extent(
2365 struct xfs_trans
*tp
,
2366 xfs_agnumber_t agno
,
2371 struct xfs_bmbt_irec bmap
;
2373 if (!xfs_rmap_update_is_needed(tp
->t_mountp
, XFS_DATA_FORK
))
2376 bmap
.br_startblock
= XFS_AGB_TO_FSB(tp
->t_mountp
, agno
, bno
);
2377 bmap
.br_blockcount
= len
;
2378 bmap
.br_startoff
= 0;
2379 bmap
.br_state
= XFS_EXT_NORM
;
2381 return __xfs_rmap_add(tp
, XFS_RMAP_ALLOC
, owner
, XFS_DATA_FORK
, &bmap
);
2384 /* Schedule the deletion of an rmap for non-file data. */
2386 xfs_rmap_free_extent(
2387 struct xfs_trans
*tp
,
2388 xfs_agnumber_t agno
,
2393 struct xfs_bmbt_irec bmap
;
2395 if (!xfs_rmap_update_is_needed(tp
->t_mountp
, XFS_DATA_FORK
))
2398 bmap
.br_startblock
= XFS_AGB_TO_FSB(tp
->t_mountp
, agno
, bno
);
2399 bmap
.br_blockcount
= len
;
2400 bmap
.br_startoff
= 0;
2401 bmap
.br_state
= XFS_EXT_NORM
;
2403 return __xfs_rmap_add(tp
, XFS_RMAP_FREE
, owner
, XFS_DATA_FORK
, &bmap
);
2406 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2409 const struct xfs_rmap_irec
*a
,
2410 const struct xfs_rmap_irec
*b
)
2415 oa
= xfs_rmap_irec_offset_pack(a
);
2416 ob
= xfs_rmap_irec_offset_pack(b
);
2418 if (a
->rm_startblock
< b
->rm_startblock
)
2420 else if (a
->rm_startblock
> b
->rm_startblock
)
2422 else if (a
->rm_owner
< b
->rm_owner
)
2424 else if (a
->rm_owner
> b
->rm_owner
)
2434 /* Is there a record covering a given extent? */
2436 xfs_rmap_has_record(
2437 struct xfs_btree_cur
*cur
,
2442 union xfs_btree_irec low
;
2443 union xfs_btree_irec high
;
2445 memset(&low
, 0, sizeof(low
));
2446 low
.r
.rm_startblock
= bno
;
2447 memset(&high
, 0xFF, sizeof(high
));
2448 high
.r
.rm_startblock
= bno
+ len
- 1;
2450 return xfs_btree_has_record(cur
, &low
, &high
, exists
);
2454 * Is there a record for this owner completely covering a given physical
2455 * extent? If so, *has_rmap will be set to true. If there is no record
2456 * or the record only covers part of the range, we set *has_rmap to false.
2457 * This function doesn't perform range lookups or offset checks, so it is
2458 * not suitable for checking data fork blocks.
2461 xfs_rmap_record_exists(
2462 struct xfs_btree_cur
*cur
,
2465 const struct xfs_owner_info
*oinfo
,
2472 struct xfs_rmap_irec irec
;
2475 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
2476 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner
) ||
2477 (flags
& XFS_RMAP_BMBT_BLOCK
));
2479 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
,
2488 error
= xfs_rmap_get_rec(cur
, &irec
, &has_record
);
2496 *has_rmap
= (irec
.rm_owner
== owner
&& irec
.rm_startblock
<= bno
&&
2497 irec
.rm_startblock
+ irec
.rm_blockcount
>= bno
+ len
);
2501 struct xfs_rmap_key_state
{
2508 /* For each rmap given, figure out if it doesn't match the key we want. */
2510 xfs_rmap_has_other_keys_helper(
2511 struct xfs_btree_cur
*cur
,
2512 struct xfs_rmap_irec
*rec
,
2515 struct xfs_rmap_key_state
*rks
= priv
;
2517 if (rks
->owner
== rec
->rm_owner
&& rks
->offset
== rec
->rm_offset
&&
2518 ((rks
->flags
& rec
->rm_flags
) & XFS_RMAP_KEY_FLAGS
) == rks
->flags
)
2520 rks
->has_rmap
= true;
2521 return XFS_BTREE_QUERY_RANGE_ABORT
;
2525 * Given an extent and some owner info, can we find records overlapping
2526 * the extent whose owner info does not match the given owner?
2529 xfs_rmap_has_other_keys(
2530 struct xfs_btree_cur
*cur
,
2533 const struct xfs_owner_info
*oinfo
,
2536 struct xfs_rmap_irec low
= {0};
2537 struct xfs_rmap_irec high
;
2538 struct xfs_rmap_key_state rks
;
2541 xfs_owner_info_unpack(oinfo
, &rks
.owner
, &rks
.offset
, &rks
.flags
);
2542 rks
.has_rmap
= false;
2544 low
.rm_startblock
= bno
;
2545 memset(&high
, 0xFF, sizeof(high
));
2546 high
.rm_startblock
= bno
+ len
- 1;
2548 error
= xfs_rmap_query_range(cur
, &low
, &high
,
2549 xfs_rmap_has_other_keys_helper
, &rks
);
2550 *has_rmap
= rks
.has_rmap
;
2554 const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE
= {
2555 .oi_owner
= XFS_RMAP_OWN_NULL
,
2557 const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER
= {
2558 .oi_owner
= XFS_RMAP_OWN_UNKNOWN
,
2560 const struct xfs_owner_info XFS_RMAP_OINFO_FS
= {
2561 .oi_owner
= XFS_RMAP_OWN_FS
,
2563 const struct xfs_owner_info XFS_RMAP_OINFO_LOG
= {
2564 .oi_owner
= XFS_RMAP_OWN_LOG
,
2566 const struct xfs_owner_info XFS_RMAP_OINFO_AG
= {
2567 .oi_owner
= XFS_RMAP_OWN_AG
,
2569 const struct xfs_owner_info XFS_RMAP_OINFO_INOBT
= {
2570 .oi_owner
= XFS_RMAP_OWN_INOBT
,
2572 const struct xfs_owner_info XFS_RMAP_OINFO_INODES
= {
2573 .oi_owner
= XFS_RMAP_OWN_INODES
,
2575 const struct xfs_owner_info XFS_RMAP_OINFO_REFC
= {
2576 .oi_owner
= XFS_RMAP_OWN_REFC
,
2578 const struct xfs_owner_info XFS_RMAP_OINFO_COW
= {
2579 .oi_owner
= XFS_RMAP_OWN_COW
,