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"
13 #include "xfs_mount.h"
15 #include "xfs_defer.h"
16 #include "xfs_btree.h"
17 #include "xfs_trans.h"
18 #include "xfs_alloc.h"
20 #include "xfs_rmap_btree.h"
21 #include "xfs_trace.h"
22 #include "xfs_errortag.h"
23 #include "xfs_inode.h"
25 #include "xfs_health.h"
26 #include "defer_item.h"
27 #include "xfs_rtgroup.h"
28 #include "xfs_rtrmap_btree.h"
30 struct kmem_cache
*xfs_rmap_intent_cache
;
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
,
43 struct xfs_rmap_irec
*irec
,
49 cur
->bc_rec
.r
.rm_startblock
= bno
;
50 cur
->bc_rec
.r
.rm_blockcount
= 0;
51 cur
->bc_rec
.r
.rm_owner
= owner
;
52 cur
->bc_rec
.r
.rm_offset
= offset
;
53 cur
->bc_rec
.r
.rm_flags
= flags
;
55 error
= xfs_btree_lookup(cur
, XFS_LOOKUP_LE
, stat
);
56 if (error
|| !(*stat
) || !irec
)
59 error
= xfs_rmap_get_rec(cur
, irec
, &get_stat
);
63 xfs_btree_mark_sick(cur
);
71 * Lookup the record exactly matching [bno, len, owner, offset]
72 * in the btree given by cur.
76 struct xfs_btree_cur
*cur
,
84 cur
->bc_rec
.r
.rm_startblock
= bno
;
85 cur
->bc_rec
.r
.rm_blockcount
= len
;
86 cur
->bc_rec
.r
.rm_owner
= owner
;
87 cur
->bc_rec
.r
.rm_offset
= offset
;
88 cur
->bc_rec
.r
.rm_flags
= flags
;
89 return xfs_btree_lookup(cur
, XFS_LOOKUP_EQ
, stat
);
93 * Update the record referred to by cur to the value given
94 * by [bno, len, owner, offset].
95 * This either works (return 0) or gets an EFSCORRUPTED error.
99 struct xfs_btree_cur
*cur
,
100 struct xfs_rmap_irec
*irec
)
102 union xfs_btree_rec rec
;
105 trace_xfs_rmap_update(cur
, irec
->rm_startblock
, irec
->rm_blockcount
,
106 irec
->rm_owner
, irec
->rm_offset
, irec
->rm_flags
);
108 rec
.rmap
.rm_startblock
= cpu_to_be32(irec
->rm_startblock
);
109 rec
.rmap
.rm_blockcount
= cpu_to_be32(irec
->rm_blockcount
);
110 rec
.rmap
.rm_owner
= cpu_to_be64(irec
->rm_owner
);
111 rec
.rmap
.rm_offset
= cpu_to_be64(
112 xfs_rmap_irec_offset_pack(irec
));
113 error
= xfs_btree_update(cur
, &rec
);
115 trace_xfs_rmap_update_error(cur
, error
, _RET_IP_
);
121 struct xfs_btree_cur
*rcur
,
131 trace_xfs_rmap_insert(rcur
, agbno
, len
, owner
, offset
, flags
);
133 error
= xfs_rmap_lookup_eq(rcur
, agbno
, len
, owner
, offset
, flags
, &i
);
136 if (XFS_IS_CORRUPT(rcur
->bc_mp
, i
!= 0)) {
137 xfs_btree_mark_sick(rcur
);
138 error
= -EFSCORRUPTED
;
142 rcur
->bc_rec
.r
.rm_startblock
= agbno
;
143 rcur
->bc_rec
.r
.rm_blockcount
= len
;
144 rcur
->bc_rec
.r
.rm_owner
= owner
;
145 rcur
->bc_rec
.r
.rm_offset
= offset
;
146 rcur
->bc_rec
.r
.rm_flags
= flags
;
147 error
= xfs_btree_insert(rcur
, &i
);
150 if (XFS_IS_CORRUPT(rcur
->bc_mp
, i
!= 1)) {
151 xfs_btree_mark_sick(rcur
);
152 error
= -EFSCORRUPTED
;
157 trace_xfs_rmap_insert_error(rcur
, error
, _RET_IP_
);
163 struct xfs_btree_cur
*rcur
,
173 trace_xfs_rmap_delete(rcur
, agbno
, len
, owner
, offset
, flags
);
175 error
= xfs_rmap_lookup_eq(rcur
, agbno
, len
, owner
, offset
, flags
, &i
);
178 if (XFS_IS_CORRUPT(rcur
->bc_mp
, i
!= 1)) {
179 xfs_btree_mark_sick(rcur
);
180 error
= -EFSCORRUPTED
;
184 error
= xfs_btree_delete(rcur
, &i
);
187 if (XFS_IS_CORRUPT(rcur
->bc_mp
, i
!= 1)) {
188 xfs_btree_mark_sick(rcur
);
189 error
= -EFSCORRUPTED
;
194 trace_xfs_rmap_delete_error(rcur
, error
, _RET_IP_
);
198 /* Convert an internal btree record to an rmap record. */
200 xfs_rmap_btrec_to_irec(
201 const union xfs_btree_rec
*rec
,
202 struct xfs_rmap_irec
*irec
)
204 irec
->rm_startblock
= be32_to_cpu(rec
->rmap
.rm_startblock
);
205 irec
->rm_blockcount
= be32_to_cpu(rec
->rmap
.rm_blockcount
);
206 irec
->rm_owner
= be64_to_cpu(rec
->rmap
.rm_owner
);
207 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec
->rmap
.rm_offset
),
211 /* Simple checks for rmap records. */
214 struct xfs_perag
*pag
,
215 const struct xfs_rmap_irec
*irec
)
217 struct xfs_mount
*mp
= pag_mount(pag
);
223 if (irec
->rm_blockcount
== 0)
224 return __this_address
;
225 if (irec
->rm_startblock
<= XFS_AGFL_BLOCK(mp
)) {
226 if (irec
->rm_owner
!= XFS_RMAP_OWN_FS
)
227 return __this_address
;
228 if (irec
->rm_blockcount
!= XFS_AGFL_BLOCK(mp
) + 1)
229 return __this_address
;
231 /* check for valid extent range, including overflow */
232 if (!xfs_verify_agbext(pag
, irec
->rm_startblock
,
233 irec
->rm_blockcount
))
234 return __this_address
;
237 if (!(xfs_verify_ino(mp
, irec
->rm_owner
) ||
238 (irec
->rm_owner
<= XFS_RMAP_OWN_FS
&&
239 irec
->rm_owner
>= XFS_RMAP_OWN_MIN
)))
240 return __this_address
;
243 is_inode
= !XFS_RMAP_NON_INODE_OWNER(irec
->rm_owner
);
244 is_bmbt
= irec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
;
245 is_attr
= irec
->rm_flags
& XFS_RMAP_ATTR_FORK
;
246 is_unwritten
= irec
->rm_flags
& XFS_RMAP_UNWRITTEN
;
248 if (is_bmbt
&& irec
->rm_offset
!= 0)
249 return __this_address
;
251 if (!is_inode
&& irec
->rm_offset
!= 0)
252 return __this_address
;
254 if (is_unwritten
&& (is_bmbt
|| !is_inode
|| is_attr
))
255 return __this_address
;
257 if (!is_inode
&& (is_bmbt
|| is_unwritten
|| is_attr
))
258 return __this_address
;
260 /* Check for a valid fork offset, if applicable. */
261 if (is_inode
&& !is_bmbt
&&
262 !xfs_verify_fileext(mp
, irec
->rm_offset
, irec
->rm_blockcount
))
263 return __this_address
;
268 static xfs_failaddr_t
269 xfs_rtrmap_check_meta_irec(
270 struct xfs_rtgroup
*rtg
,
271 const struct xfs_rmap_irec
*irec
)
273 struct xfs_mount
*mp
= rtg_mount(rtg
);
275 if (irec
->rm_offset
!= 0)
276 return __this_address
;
277 if (irec
->rm_flags
& XFS_RMAP_UNWRITTEN
)
278 return __this_address
;
280 switch (irec
->rm_owner
) {
281 case XFS_RMAP_OWN_FS
:
282 if (irec
->rm_startblock
!= 0)
283 return __this_address
;
284 if (irec
->rm_blockcount
!= mp
->m_sb
.sb_rextsize
)
285 return __this_address
;
287 case XFS_RMAP_OWN_COW
:
288 if (!xfs_has_rtreflink(mp
))
289 return __this_address
;
290 if (!xfs_verify_rgbext(rtg
, irec
->rm_startblock
,
291 irec
->rm_blockcount
))
292 return __this_address
;
295 return __this_address
;
301 static xfs_failaddr_t
302 xfs_rtrmap_check_inode_irec(
303 struct xfs_rtgroup
*rtg
,
304 const struct xfs_rmap_irec
*irec
)
306 struct xfs_mount
*mp
= rtg_mount(rtg
);
308 if (!xfs_verify_ino(mp
, irec
->rm_owner
))
309 return __this_address
;
310 if (!xfs_verify_rgbext(rtg
, irec
->rm_startblock
, irec
->rm_blockcount
))
311 return __this_address
;
312 if (!xfs_verify_fileext(mp
, irec
->rm_offset
, irec
->rm_blockcount
))
313 return __this_address
;
318 xfs_rtrmap_check_irec(
319 struct xfs_rtgroup
*rtg
,
320 const struct xfs_rmap_irec
*irec
)
322 if (irec
->rm_blockcount
== 0)
323 return __this_address
;
324 if (irec
->rm_flags
& (XFS_RMAP_BMBT_BLOCK
| XFS_RMAP_ATTR_FORK
))
325 return __this_address
;
326 if (XFS_RMAP_NON_INODE_OWNER(irec
->rm_owner
))
327 return xfs_rtrmap_check_meta_irec(rtg
, irec
);
328 return xfs_rtrmap_check_inode_irec(rtg
, irec
);
331 static inline xfs_failaddr_t
332 xfs_rmap_check_btrec(
333 struct xfs_btree_cur
*cur
,
334 const struct xfs_rmap_irec
*irec
)
336 if (xfs_btree_is_rtrmap(cur
->bc_ops
) ||
337 xfs_btree_is_mem_rtrmap(cur
->bc_ops
))
338 return xfs_rtrmap_check_irec(to_rtg(cur
->bc_group
), irec
);
339 return xfs_rmap_check_irec(to_perag(cur
->bc_group
), irec
);
343 xfs_rmap_complain_bad_rec(
344 struct xfs_btree_cur
*cur
,
346 const struct xfs_rmap_irec
*irec
)
348 struct xfs_mount
*mp
= cur
->bc_mp
;
350 if (xfs_btree_is_mem_rmap(cur
->bc_ops
))
352 "In-Memory Reverse Mapping BTree record corruption detected at %pS!", fa
);
353 else if (xfs_btree_is_rtrmap(cur
->bc_ops
))
355 "RT Reverse Mapping BTree record corruption in rtgroup %u detected at %pS!",
356 cur
->bc_group
->xg_gno
, fa
);
359 "Reverse Mapping BTree record corruption in AG %d detected at %pS!",
360 cur
->bc_group
->xg_gno
, fa
);
362 "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
363 irec
->rm_owner
, irec
->rm_flags
, irec
->rm_startblock
,
364 irec
->rm_blockcount
);
365 xfs_btree_mark_sick(cur
);
366 return -EFSCORRUPTED
;
370 * Get the data from the pointed-to record.
374 struct xfs_btree_cur
*cur
,
375 struct xfs_rmap_irec
*irec
,
378 union xfs_btree_rec
*rec
;
382 error
= xfs_btree_get_rec(cur
, &rec
, stat
);
386 fa
= xfs_rmap_btrec_to_irec(rec
, irec
);
388 fa
= xfs_rmap_check_btrec(cur
, irec
);
390 return xfs_rmap_complain_bad_rec(cur
, fa
, irec
);
395 struct xfs_find_left_neighbor_info
{
396 struct xfs_rmap_irec high
;
397 struct xfs_rmap_irec
*irec
;
400 /* For each rmap given, figure out if it matches the key we want. */
402 xfs_rmap_find_left_neighbor_helper(
403 struct xfs_btree_cur
*cur
,
404 const struct xfs_rmap_irec
*rec
,
407 struct xfs_find_left_neighbor_info
*info
= priv
;
409 trace_xfs_rmap_find_left_neighbor_candidate(cur
, rec
->rm_startblock
,
410 rec
->rm_blockcount
, rec
->rm_owner
, rec
->rm_offset
,
413 if (rec
->rm_owner
!= info
->high
.rm_owner
)
415 if (!XFS_RMAP_NON_INODE_OWNER(rec
->rm_owner
) &&
416 !(rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
) &&
417 rec
->rm_offset
+ rec
->rm_blockcount
- 1 != info
->high
.rm_offset
)
425 * Find the record to the left of the given extent, being careful only to
426 * return a match with the same owner and adjacent physical and logical
430 xfs_rmap_find_left_neighbor(
431 struct xfs_btree_cur
*cur
,
436 struct xfs_rmap_irec
*irec
,
439 struct xfs_find_left_neighbor_info info
;
446 info
.high
.rm_startblock
= bno
- 1;
447 info
.high
.rm_owner
= owner
;
448 if (!XFS_RMAP_NON_INODE_OWNER(owner
) &&
449 !(flags
& XFS_RMAP_BMBT_BLOCK
)) {
452 info
.high
.rm_offset
= offset
- 1;
454 info
.high
.rm_offset
= 0;
455 info
.high
.rm_flags
= flags
;
456 info
.high
.rm_blockcount
= 0;
459 trace_xfs_rmap_find_left_neighbor_query(cur
, bno
, 0, owner
, offset
,
463 * Historically, we always used the range query to walk every reverse
464 * mapping that could possibly overlap the key that the caller asked
465 * for, and filter out the ones that don't. That is very slow when
466 * there are a lot of records.
468 * However, there are two scenarios where the classic btree search can
469 * produce correct results -- if the index contains a record that is an
470 * exact match for the lookup key; and if there are no other records
471 * between the record we want and the key we supplied.
473 * As an optimization, try a non-overlapped lookup first. This makes
474 * extent conversion and remap operations run a bit faster if the
475 * physical extents aren't being shared. If we don't find what we
476 * want, we fall back to the overlapped query.
478 error
= xfs_rmap_lookup_le(cur
, bno
, owner
, offset
, flags
, irec
,
483 error
= xfs_rmap_find_left_neighbor_helper(cur
, irec
, &info
);
485 error
= xfs_rmap_query_range(cur
, &info
.high
, &info
.high
,
486 xfs_rmap_find_left_neighbor_helper
, &info
);
487 if (error
!= -ECANCELED
)
491 trace_xfs_rmap_find_left_neighbor_result(cur
, irec
->rm_startblock
,
492 irec
->rm_blockcount
, irec
->rm_owner
, irec
->rm_offset
,
497 /* For each rmap given, figure out if it matches the key we want. */
499 xfs_rmap_lookup_le_range_helper(
500 struct xfs_btree_cur
*cur
,
501 const struct xfs_rmap_irec
*rec
,
504 struct xfs_find_left_neighbor_info
*info
= priv
;
506 trace_xfs_rmap_lookup_le_range_candidate(cur
, rec
->rm_startblock
,
507 rec
->rm_blockcount
, rec
->rm_owner
, rec
->rm_offset
,
510 if (rec
->rm_owner
!= info
->high
.rm_owner
)
512 if (!XFS_RMAP_NON_INODE_OWNER(rec
->rm_owner
) &&
513 !(rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
) &&
514 (rec
->rm_offset
> info
->high
.rm_offset
||
515 rec
->rm_offset
+ rec
->rm_blockcount
<= info
->high
.rm_offset
))
523 * Find the record to the left of the given extent, being careful only to
524 * return a match with the same owner and overlapping physical and logical
525 * block ranges. This is the overlapping-interval version of
526 * xfs_rmap_lookup_le.
529 xfs_rmap_lookup_le_range(
530 struct xfs_btree_cur
*cur
,
535 struct xfs_rmap_irec
*irec
,
538 struct xfs_find_left_neighbor_info info
;
542 info
.high
.rm_startblock
= bno
;
543 info
.high
.rm_owner
= owner
;
544 if (!XFS_RMAP_NON_INODE_OWNER(owner
) && !(flags
& XFS_RMAP_BMBT_BLOCK
))
545 info
.high
.rm_offset
= offset
;
547 info
.high
.rm_offset
= 0;
548 info
.high
.rm_flags
= flags
;
549 info
.high
.rm_blockcount
= 0;
553 trace_xfs_rmap_lookup_le_range(cur
, bno
, 0, owner
, offset
, flags
);
556 * Historically, we always used the range query to walk every reverse
557 * mapping that could possibly overlap the key that the caller asked
558 * for, and filter out the ones that don't. That is very slow when
559 * there are a lot of records.
561 * However, there are two scenarios where the classic btree search can
562 * produce correct results -- if the index contains a record that is an
563 * exact match for the lookup key; and if there are no other records
564 * between the record we want and the key we supplied.
566 * As an optimization, try a non-overlapped lookup first. This makes
567 * scrub run much faster on most filesystems because bmbt records are
568 * usually an exact match for rmap records. If we don't find what we
569 * want, we fall back to the overlapped query.
571 error
= xfs_rmap_lookup_le(cur
, bno
, owner
, offset
, flags
, irec
,
576 error
= xfs_rmap_lookup_le_range_helper(cur
, irec
, &info
);
578 error
= xfs_rmap_query_range(cur
, &info
.high
, &info
.high
,
579 xfs_rmap_lookup_le_range_helper
, &info
);
580 if (error
!= -ECANCELED
)
584 trace_xfs_rmap_lookup_le_range_result(cur
, irec
->rm_startblock
,
585 irec
->rm_blockcount
, irec
->rm_owner
, irec
->rm_offset
,
591 * Perform all the relevant owner checks for a removal op. If we're doing an
592 * unknown-owner removal then we have no owner information to check.
595 xfs_rmap_free_check_owner(
596 struct xfs_btree_cur
*cur
,
598 struct xfs_rmap_irec
*rec
,
604 struct xfs_mount
*mp
= cur
->bc_mp
;
607 if (owner
== XFS_RMAP_OWN_UNKNOWN
)
610 /* Make sure the unwritten flag matches. */
611 if (XFS_IS_CORRUPT(mp
,
612 (flags
& XFS_RMAP_UNWRITTEN
) !=
613 (rec
->rm_flags
& XFS_RMAP_UNWRITTEN
))) {
614 xfs_btree_mark_sick(cur
);
615 error
= -EFSCORRUPTED
;
619 /* Make sure the owner matches what we expect to find in the tree. */
620 if (XFS_IS_CORRUPT(mp
, owner
!= rec
->rm_owner
)) {
621 xfs_btree_mark_sick(cur
);
622 error
= -EFSCORRUPTED
;
626 /* Check the offset, if necessary. */
627 if (XFS_RMAP_NON_INODE_OWNER(owner
))
630 if (flags
& XFS_RMAP_BMBT_BLOCK
) {
631 if (XFS_IS_CORRUPT(mp
,
632 !(rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
))) {
633 xfs_btree_mark_sick(cur
);
634 error
= -EFSCORRUPTED
;
638 if (XFS_IS_CORRUPT(mp
, rec
->rm_offset
> offset
)) {
639 xfs_btree_mark_sick(cur
);
640 error
= -EFSCORRUPTED
;
643 if (XFS_IS_CORRUPT(mp
,
644 offset
+ len
> ltoff
+ rec
->rm_blockcount
)) {
645 xfs_btree_mark_sick(cur
);
646 error
= -EFSCORRUPTED
;
656 * Find the extent in the rmap btree and remove it.
658 * The record we find should always be an exact match for the extent that we're
659 * looking for, since we insert them into the btree without modification.
661 * Special Case #1: when growing the filesystem, we "free" an extent when
662 * growing the last AG. This extent is new space and so it is not tracked as
663 * used space in the btree. The growfs code will pass in an owner of
664 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
665 * extent. We verify that - the extent lookup result in a record that does not
668 * Special Case #2: EFIs do not record the owner of the extent, so when
669 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
670 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
671 * corruption checks during log recovery.
675 struct xfs_btree_cur
*cur
,
679 const struct xfs_owner_info
*oinfo
)
681 struct xfs_mount
*mp
= cur
->bc_mp
;
682 struct xfs_rmap_irec ltrec
;
691 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
692 ignore_off
= XFS_RMAP_NON_INODE_OWNER(owner
) ||
693 (flags
& XFS_RMAP_BMBT_BLOCK
);
695 flags
|= XFS_RMAP_UNWRITTEN
;
696 trace_xfs_rmap_unmap(cur
, bno
, len
, unwritten
, oinfo
);
699 * We should always have a left record because there's a static record
700 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
701 * will not ever be removed from the tree.
703 error
= xfs_rmap_lookup_le(cur
, bno
, owner
, offset
, flags
, <rec
, &i
);
706 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
707 xfs_btree_mark_sick(cur
);
708 error
= -EFSCORRUPTED
;
712 trace_xfs_rmap_lookup_le_range_result(cur
, ltrec
.rm_startblock
,
713 ltrec
.rm_blockcount
, ltrec
.rm_owner
, ltrec
.rm_offset
,
715 ltoff
= ltrec
.rm_offset
;
718 * For growfs, the incoming extent must be beyond the left record we
719 * just found as it is new space and won't be used by anyone. This is
720 * just a corruption check as we don't actually do anything with this
721 * extent. Note that we need to use >= instead of > because it might
722 * be the case that the "left" extent goes all the way to EOFS.
724 if (owner
== XFS_RMAP_OWN_NULL
) {
725 if (XFS_IS_CORRUPT(mp
,
727 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
)) {
728 xfs_btree_mark_sick(cur
);
729 error
= -EFSCORRUPTED
;
736 * If we're doing an unknown-owner removal for EFI recovery, we expect
737 * to find the full range in the rmapbt or nothing at all. If we
738 * don't find any rmaps overlapping either end of the range, we're
739 * done. Hopefully this means that the EFI creator already queued
740 * (and finished) a RUI to remove the rmap.
742 if (owner
== XFS_RMAP_OWN_UNKNOWN
&&
743 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
<= bno
) {
744 struct xfs_rmap_irec rtrec
;
746 error
= xfs_btree_increment(cur
, 0, &i
);
751 error
= xfs_rmap_get_rec(cur
, &rtrec
, &i
);
754 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
755 xfs_btree_mark_sick(cur
);
756 error
= -EFSCORRUPTED
;
759 if (rtrec
.rm_startblock
>= bno
+ len
)
763 /* Make sure the extent we found covers the entire freeing range. */
764 if (XFS_IS_CORRUPT(mp
,
765 ltrec
.rm_startblock
> bno
||
766 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
<
768 xfs_btree_mark_sick(cur
);
769 error
= -EFSCORRUPTED
;
773 /* Check owner information. */
774 error
= xfs_rmap_free_check_owner(cur
, ltoff
, <rec
, len
, owner
,
779 if (ltrec
.rm_startblock
== bno
&& ltrec
.rm_blockcount
== len
) {
780 /* exact match, simply remove the record from rmap tree */
781 trace_xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
782 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
783 ltrec
.rm_offset
, ltrec
.rm_flags
);
784 error
= xfs_btree_delete(cur
, &i
);
787 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
788 xfs_btree_mark_sick(cur
);
789 error
= -EFSCORRUPTED
;
792 } else if (ltrec
.rm_startblock
== bno
) {
794 * overlap left hand side of extent: move the start, trim the
795 * length and update the current record.
798 * Orig: |oooooooooooooooooooo|
799 * Freeing: |fffffffff|
800 * Result: |rrrrrrrrrr|
803 ltrec
.rm_startblock
+= len
;
804 ltrec
.rm_blockcount
-= len
;
806 ltrec
.rm_offset
+= len
;
807 error
= xfs_rmap_update(cur
, <rec
);
810 } else if (ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
+ len
) {
812 * overlap right hand side of extent: trim the length and update
813 * the current record.
816 * Orig: |oooooooooooooooooooo|
817 * Freeing: |fffffffff|
818 * Result: |rrrrrrrrrr|
821 ltrec
.rm_blockcount
-= len
;
822 error
= xfs_rmap_update(cur
, <rec
);
828 * overlap middle of extent: trim the length of the existing
829 * record to the length of the new left-extent size, increment
830 * the insertion position so we can insert a new record
831 * containing the remaining right-extent space.
834 * Orig: |oooooooooooooooooooo|
835 * Freeing: |fffffffff|
836 * Result: |rrrrr| |rrrr|
839 xfs_extlen_t orig_len
= ltrec
.rm_blockcount
;
841 ltrec
.rm_blockcount
= bno
- ltrec
.rm_startblock
;
842 error
= xfs_rmap_update(cur
, <rec
);
846 error
= xfs_btree_increment(cur
, 0, &i
);
850 cur
->bc_rec
.r
.rm_startblock
= bno
+ len
;
851 cur
->bc_rec
.r
.rm_blockcount
= orig_len
- len
-
853 cur
->bc_rec
.r
.rm_owner
= ltrec
.rm_owner
;
855 cur
->bc_rec
.r
.rm_offset
= 0;
857 cur
->bc_rec
.r
.rm_offset
= offset
+ len
;
858 cur
->bc_rec
.r
.rm_flags
= flags
;
859 trace_xfs_rmap_insert(cur
, cur
->bc_rec
.r
.rm_startblock
,
860 cur
->bc_rec
.r
.rm_blockcount
,
861 cur
->bc_rec
.r
.rm_owner
,
862 cur
->bc_rec
.r
.rm_offset
,
863 cur
->bc_rec
.r
.rm_flags
);
864 error
= xfs_btree_insert(cur
, &i
);
870 trace_xfs_rmap_unmap_done(cur
, bno
, len
, unwritten
, oinfo
);
873 trace_xfs_rmap_unmap_error(cur
, error
, _RET_IP_
);
877 #ifdef CONFIG_XFS_LIVE_HOOKS
879 * Use a static key here to reduce the overhead of rmapbt live updates. If
880 * the compiler supports jump labels, the static branch will be replaced by a
881 * nop sled when there are no hook users. Online fsck is currently the only
882 * caller, so this is a reasonable tradeoff.
884 * Note: Patching the kernel code requires taking the cpu hotplug lock. Other
885 * parts of the kernel allocate memory with that lock held, which means that
886 * XFS callers cannot hold any locks that might be used by memory reclaim or
887 * writeback when calling the static_branch_{inc,dec} functions.
889 DEFINE_STATIC_XFS_HOOK_SWITCH(xfs_rmap_hooks_switch
);
892 xfs_rmap_hook_disable(void)
894 xfs_hooks_switch_off(&xfs_rmap_hooks_switch
);
898 xfs_rmap_hook_enable(void)
900 xfs_hooks_switch_on(&xfs_rmap_hooks_switch
);
903 /* Call downstream hooks for a reverse mapping update. */
905 xfs_rmap_update_hook(
906 struct xfs_trans
*tp
,
907 struct xfs_group
*xg
,
908 enum xfs_rmap_intent_type op
,
909 xfs_agblock_t startblock
,
910 xfs_extlen_t blockcount
,
912 const struct xfs_owner_info
*oinfo
)
914 if (xfs_hooks_switched_on(&xfs_rmap_hooks_switch
)) {
915 struct xfs_rmap_update_params p
= {
916 .startblock
= startblock
,
917 .blockcount
= blockcount
,
918 .unwritten
= unwritten
,
919 .oinfo
= *oinfo
, /* struct copy */
923 xfs_hooks_call(&xg
->xg_rmap_update_hooks
, op
, &p
);
927 /* Call the specified function during a reverse mapping update. */
930 struct xfs_group
*xg
,
931 struct xfs_rmap_hook
*hook
)
933 return xfs_hooks_add(&xg
->xg_rmap_update_hooks
, &hook
->rmap_hook
);
936 /* Stop calling the specified function during a reverse mapping update. */
939 struct xfs_group
*xg
,
940 struct xfs_rmap_hook
*hook
)
942 xfs_hooks_del(&xg
->xg_rmap_update_hooks
, &hook
->rmap_hook
);
945 /* Configure rmap update hook functions. */
948 struct xfs_rmap_hook
*hook
,
949 notifier_fn_t mod_fn
)
951 xfs_hook_setup(&hook
->rmap_hook
, mod_fn
);
954 # define xfs_rmap_update_hook(t, p, o, s, b, u, oi) do { } while (0)
955 #endif /* CONFIG_XFS_LIVE_HOOKS */
958 * Remove a reference to an extent in the rmap btree.
962 struct xfs_trans
*tp
,
963 struct xfs_buf
*agbp
,
964 struct xfs_perag
*pag
,
967 const struct xfs_owner_info
*oinfo
)
969 struct xfs_mount
*mp
= tp
->t_mountp
;
970 struct xfs_btree_cur
*cur
;
973 if (!xfs_has_rmapbt(mp
))
976 cur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, pag
);
977 xfs_rmap_update_hook(tp
, pag_group(pag
), XFS_RMAP_UNMAP
, bno
, len
,
979 error
= xfs_rmap_unmap(cur
, bno
, len
, false, oinfo
);
981 xfs_btree_del_cursor(cur
, error
);
986 * A mergeable rmap must have the same owner and the same values for
987 * the unwritten, attr_fork, and bmbt flags. The startblock and
988 * offset are checked separately.
991 xfs_rmap_is_mergeable(
992 struct xfs_rmap_irec
*irec
,
996 if (irec
->rm_owner
== XFS_RMAP_OWN_NULL
)
998 if (irec
->rm_owner
!= owner
)
1000 if ((flags
& XFS_RMAP_UNWRITTEN
) ^
1001 (irec
->rm_flags
& XFS_RMAP_UNWRITTEN
))
1003 if ((flags
& XFS_RMAP_ATTR_FORK
) ^
1004 (irec
->rm_flags
& XFS_RMAP_ATTR_FORK
))
1006 if ((flags
& XFS_RMAP_BMBT_BLOCK
) ^
1007 (irec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
))
1013 * When we allocate a new block, the first thing we do is add a reference to
1014 * the extent in the rmap btree. This takes the form of a [agbno, length,
1015 * owner, offset] record. Flags are encoded in the high bits of the offset
1020 struct xfs_btree_cur
*cur
,
1024 const struct xfs_owner_info
*oinfo
)
1026 struct xfs_mount
*mp
= cur
->bc_mp
;
1027 struct xfs_rmap_irec ltrec
;
1028 struct xfs_rmap_irec gtrec
;
1035 unsigned int flags
= 0;
1038 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1040 ignore_off
= XFS_RMAP_NON_INODE_OWNER(owner
) ||
1041 (flags
& XFS_RMAP_BMBT_BLOCK
);
1043 flags
|= XFS_RMAP_UNWRITTEN
;
1044 trace_xfs_rmap_map(cur
, bno
, len
, unwritten
, oinfo
);
1045 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo
));
1048 * For the initial lookup, look for an exact match or the left-adjacent
1049 * record for our insertion point. This will also give us the record for
1050 * start block contiguity tests.
1052 error
= xfs_rmap_lookup_le(cur
, bno
, owner
, offset
, flags
, <rec
,
1057 trace_xfs_rmap_lookup_le_range_result(cur
, ltrec
.rm_startblock
,
1058 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1059 ltrec
.rm_offset
, ltrec
.rm_flags
);
1061 if (!xfs_rmap_is_mergeable(<rec
, owner
, flags
))
1065 if (XFS_IS_CORRUPT(mp
,
1067 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
> bno
)) {
1068 xfs_btree_mark_sick(cur
);
1069 error
= -EFSCORRUPTED
;
1074 * Increment the cursor to see if we have a right-adjacent record to our
1075 * insertion point. This will give us the record for end block
1078 error
= xfs_btree_increment(cur
, 0, &have_gt
);
1082 error
= xfs_rmap_get_rec(cur
, >rec
, &have_gt
);
1085 if (XFS_IS_CORRUPT(mp
, have_gt
!= 1)) {
1086 xfs_btree_mark_sick(cur
);
1087 error
= -EFSCORRUPTED
;
1090 if (XFS_IS_CORRUPT(mp
, bno
+ len
> gtrec
.rm_startblock
)) {
1091 xfs_btree_mark_sick(cur
);
1092 error
= -EFSCORRUPTED
;
1095 trace_xfs_rmap_find_right_neighbor_result(cur
,
1096 gtrec
.rm_startblock
, gtrec
.rm_blockcount
,
1097 gtrec
.rm_owner
, gtrec
.rm_offset
,
1099 if (!xfs_rmap_is_mergeable(>rec
, owner
, flags
))
1104 * Note: cursor currently points one record to the right of ltrec, even
1105 * if there is no record in the tree to the right.
1108 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
&&
1109 (ignore_off
|| ltrec
.rm_offset
+ ltrec
.rm_blockcount
== offset
)) {
1111 * left edge contiguous, merge into left record.
1115 * adding: |aaaaaaaaa|
1116 * result: |rrrrrrrrrrrrrrrrrrr|
1119 ltrec
.rm_blockcount
+= len
;
1121 bno
+ len
== gtrec
.rm_startblock
&&
1122 (ignore_off
|| offset
+ len
== gtrec
.rm_offset
) &&
1123 (unsigned long)ltrec
.rm_blockcount
+ len
+
1124 gtrec
.rm_blockcount
<= XFS_RMAP_LEN_MAX
) {
1126 * right edge also contiguous, delete right record
1127 * and merge into left record.
1129 * ltbno ltlen gtbno gtlen
1130 * orig: |ooooooooo| |ooooooooo|
1131 * adding: |aaaaaaaaa|
1132 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1134 ltrec
.rm_blockcount
+= gtrec
.rm_blockcount
;
1135 trace_xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
1136 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
1137 gtrec
.rm_offset
, gtrec
.rm_flags
);
1138 error
= xfs_btree_delete(cur
, &i
);
1141 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1142 xfs_btree_mark_sick(cur
);
1143 error
= -EFSCORRUPTED
;
1148 /* point the cursor back to the left record and update */
1149 error
= xfs_btree_decrement(cur
, 0, &have_gt
);
1152 error
= xfs_rmap_update(cur
, <rec
);
1155 } else if (have_gt
&&
1156 bno
+ len
== gtrec
.rm_startblock
&&
1157 (ignore_off
|| offset
+ len
== gtrec
.rm_offset
)) {
1159 * right edge contiguous, merge into right record.
1163 * adding: |aaaaaaaaa|
1164 * Result: |rrrrrrrrrrrrrrrrrrr|
1167 gtrec
.rm_startblock
= bno
;
1168 gtrec
.rm_blockcount
+= len
;
1170 gtrec
.rm_offset
= offset
;
1171 error
= xfs_rmap_update(cur
, >rec
);
1176 * no contiguous edge with identical owner, insert
1177 * new record at current cursor position.
1179 cur
->bc_rec
.r
.rm_startblock
= bno
;
1180 cur
->bc_rec
.r
.rm_blockcount
= len
;
1181 cur
->bc_rec
.r
.rm_owner
= owner
;
1182 cur
->bc_rec
.r
.rm_offset
= offset
;
1183 cur
->bc_rec
.r
.rm_flags
= flags
;
1184 trace_xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, flags
);
1185 error
= xfs_btree_insert(cur
, &i
);
1188 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1189 xfs_btree_mark_sick(cur
);
1190 error
= -EFSCORRUPTED
;
1195 trace_xfs_rmap_map_done(cur
, bno
, len
, unwritten
, oinfo
);
1198 trace_xfs_rmap_map_error(cur
, error
, _RET_IP_
);
1203 * Add a reference to an extent in the rmap btree.
1207 struct xfs_trans
*tp
,
1208 struct xfs_buf
*agbp
,
1209 struct xfs_perag
*pag
,
1212 const struct xfs_owner_info
*oinfo
)
1214 struct xfs_mount
*mp
= tp
->t_mountp
;
1215 struct xfs_btree_cur
*cur
;
1218 if (!xfs_has_rmapbt(mp
))
1221 cur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, pag
);
1222 xfs_rmap_update_hook(tp
, pag_group(pag
), XFS_RMAP_MAP
, bno
, len
, false,
1224 error
= xfs_rmap_map(cur
, bno
, len
, false, oinfo
);
1226 xfs_btree_del_cursor(cur
, error
);
1230 #define RMAP_LEFT_CONTIG (1 << 0)
1231 #define RMAP_RIGHT_CONTIG (1 << 1)
1232 #define RMAP_LEFT_FILLING (1 << 2)
1233 #define RMAP_RIGHT_FILLING (1 << 3)
1234 #define RMAP_LEFT_VALID (1 << 6)
1235 #define RMAP_RIGHT_VALID (1 << 7)
1243 * Convert an unwritten extent to a real extent or vice versa.
1244 * Does not handle overlapping extents.
1248 struct xfs_btree_cur
*cur
,
1252 const struct xfs_owner_info
*oinfo
)
1254 struct xfs_mount
*mp
= cur
->bc_mp
;
1255 struct xfs_rmap_irec r
[4]; /* neighbor extent entries */
1256 /* left is 0, right is 1, */
1257 /* prev is 2, new is 3 */
1260 uint64_t new_endoff
;
1261 unsigned int oldext
;
1262 unsigned int newext
;
1263 unsigned int flags
= 0;
1268 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1269 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner
) ||
1270 (flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
))));
1271 oldext
= unwritten
? XFS_RMAP_UNWRITTEN
: 0;
1272 new_endoff
= offset
+ len
;
1273 trace_xfs_rmap_convert(cur
, bno
, len
, unwritten
, oinfo
);
1276 * For the initial lookup, look for an exact match or the left-adjacent
1277 * record for our insertion point. This will also give us the record for
1278 * start block contiguity tests.
1280 error
= xfs_rmap_lookup_le(cur
, bno
, owner
, offset
, oldext
, &PREV
, &i
);
1283 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1284 xfs_btree_mark_sick(cur
);
1285 error
= -EFSCORRUPTED
;
1289 trace_xfs_rmap_lookup_le_range_result(cur
, PREV
.rm_startblock
,
1290 PREV
.rm_blockcount
, PREV
.rm_owner
, PREV
.rm_offset
,
1293 ASSERT(PREV
.rm_offset
<= offset
);
1294 ASSERT(PREV
.rm_offset
+ PREV
.rm_blockcount
>= new_endoff
);
1295 ASSERT((PREV
.rm_flags
& XFS_RMAP_UNWRITTEN
) == oldext
);
1296 newext
= ~oldext
& XFS_RMAP_UNWRITTEN
;
1299 * Set flags determining what part of the previous oldext allocation
1300 * extent is being replaced by a newext allocation.
1302 if (PREV
.rm_offset
== offset
)
1303 state
|= RMAP_LEFT_FILLING
;
1304 if (PREV
.rm_offset
+ PREV
.rm_blockcount
== new_endoff
)
1305 state
|= RMAP_RIGHT_FILLING
;
1308 * Decrement the cursor to see if we have a left-adjacent record to our
1309 * insertion point. This will give us the record for end block
1312 error
= xfs_btree_decrement(cur
, 0, &i
);
1316 state
|= RMAP_LEFT_VALID
;
1317 error
= xfs_rmap_get_rec(cur
, &LEFT
, &i
);
1320 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1321 xfs_btree_mark_sick(cur
);
1322 error
= -EFSCORRUPTED
;
1325 if (XFS_IS_CORRUPT(mp
,
1326 LEFT
.rm_startblock
+ LEFT
.rm_blockcount
>
1328 xfs_btree_mark_sick(cur
);
1329 error
= -EFSCORRUPTED
;
1332 trace_xfs_rmap_find_left_neighbor_result(cur
,
1333 LEFT
.rm_startblock
, LEFT
.rm_blockcount
,
1334 LEFT
.rm_owner
, LEFT
.rm_offset
, LEFT
.rm_flags
);
1335 if (LEFT
.rm_startblock
+ LEFT
.rm_blockcount
== bno
&&
1336 LEFT
.rm_offset
+ LEFT
.rm_blockcount
== offset
&&
1337 xfs_rmap_is_mergeable(&LEFT
, owner
, newext
))
1338 state
|= RMAP_LEFT_CONTIG
;
1342 * Increment the cursor to see if we have a right-adjacent record to our
1343 * insertion point. This will give us the record for end block
1346 error
= xfs_btree_increment(cur
, 0, &i
);
1349 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1350 xfs_btree_mark_sick(cur
);
1351 error
= -EFSCORRUPTED
;
1354 error
= xfs_btree_increment(cur
, 0, &i
);
1358 state
|= RMAP_RIGHT_VALID
;
1359 error
= xfs_rmap_get_rec(cur
, &RIGHT
, &i
);
1362 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1363 xfs_btree_mark_sick(cur
);
1364 error
= -EFSCORRUPTED
;
1367 if (XFS_IS_CORRUPT(mp
, bno
+ len
> RIGHT
.rm_startblock
)) {
1368 xfs_btree_mark_sick(cur
);
1369 error
= -EFSCORRUPTED
;
1372 trace_xfs_rmap_find_right_neighbor_result(cur
,
1373 RIGHT
.rm_startblock
, RIGHT
.rm_blockcount
,
1374 RIGHT
.rm_owner
, RIGHT
.rm_offset
,
1376 if (bno
+ len
== RIGHT
.rm_startblock
&&
1377 offset
+ len
== RIGHT
.rm_offset
&&
1378 xfs_rmap_is_mergeable(&RIGHT
, owner
, newext
))
1379 state
|= RMAP_RIGHT_CONTIG
;
1382 /* check that left + prev + right is not too long */
1383 if ((state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1384 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) ==
1385 (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1386 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
) &&
1387 (unsigned long)LEFT
.rm_blockcount
+ len
+
1388 RIGHT
.rm_blockcount
> XFS_RMAP_LEN_MAX
)
1389 state
&= ~RMAP_RIGHT_CONTIG
;
1391 trace_xfs_rmap_convert_state(cur
, state
, _RET_IP_
);
1393 /* reset the cursor back to PREV */
1394 error
= xfs_rmap_lookup_le(cur
, bno
, owner
, offset
, oldext
, NULL
, &i
);
1397 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1398 xfs_btree_mark_sick(cur
);
1399 error
= -EFSCORRUPTED
;
1404 * Switch out based on the FILLING and CONTIG state bits.
1406 switch (state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1407 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) {
1408 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1409 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1411 * Setting all of a previous oldext extent to newext.
1412 * The left and right neighbors are both contiguous with new.
1414 error
= xfs_btree_increment(cur
, 0, &i
);
1417 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1418 xfs_btree_mark_sick(cur
);
1419 error
= -EFSCORRUPTED
;
1422 trace_xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1423 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1424 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1425 error
= xfs_btree_delete(cur
, &i
);
1428 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1429 xfs_btree_mark_sick(cur
);
1430 error
= -EFSCORRUPTED
;
1433 error
= xfs_btree_decrement(cur
, 0, &i
);
1436 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1437 xfs_btree_mark_sick(cur
);
1438 error
= -EFSCORRUPTED
;
1441 trace_xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1442 PREV
.rm_blockcount
, PREV
.rm_owner
,
1443 PREV
.rm_offset
, PREV
.rm_flags
);
1444 error
= xfs_btree_delete(cur
, &i
);
1447 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1448 xfs_btree_mark_sick(cur
);
1449 error
= -EFSCORRUPTED
;
1452 error
= xfs_btree_decrement(cur
, 0, &i
);
1455 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1456 xfs_btree_mark_sick(cur
);
1457 error
= -EFSCORRUPTED
;
1461 NEW
.rm_blockcount
+= PREV
.rm_blockcount
+ RIGHT
.rm_blockcount
;
1462 error
= xfs_rmap_update(cur
, &NEW
);
1467 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1469 * Setting all of a previous oldext extent to newext.
1470 * The left neighbor is contiguous, the right is not.
1472 trace_xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1473 PREV
.rm_blockcount
, PREV
.rm_owner
,
1474 PREV
.rm_offset
, PREV
.rm_flags
);
1475 error
= xfs_btree_delete(cur
, &i
);
1478 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1479 xfs_btree_mark_sick(cur
);
1480 error
= -EFSCORRUPTED
;
1483 error
= xfs_btree_decrement(cur
, 0, &i
);
1486 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1487 xfs_btree_mark_sick(cur
);
1488 error
= -EFSCORRUPTED
;
1492 NEW
.rm_blockcount
+= PREV
.rm_blockcount
;
1493 error
= xfs_rmap_update(cur
, &NEW
);
1498 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1500 * Setting all of a previous oldext extent to newext.
1501 * The right neighbor is contiguous, the left is not.
1503 error
= xfs_btree_increment(cur
, 0, &i
);
1506 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1507 xfs_btree_mark_sick(cur
);
1508 error
= -EFSCORRUPTED
;
1511 trace_xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1512 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1513 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1514 error
= xfs_btree_delete(cur
, &i
);
1517 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1518 xfs_btree_mark_sick(cur
);
1519 error
= -EFSCORRUPTED
;
1522 error
= xfs_btree_decrement(cur
, 0, &i
);
1525 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1526 xfs_btree_mark_sick(cur
);
1527 error
= -EFSCORRUPTED
;
1531 NEW
.rm_blockcount
= len
+ RIGHT
.rm_blockcount
;
1532 NEW
.rm_flags
= newext
;
1533 error
= xfs_rmap_update(cur
, &NEW
);
1538 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
:
1540 * Setting all of a previous oldext extent to newext.
1541 * Neither the left nor right neighbors are contiguous with
1545 NEW
.rm_flags
= newext
;
1546 error
= xfs_rmap_update(cur
, &NEW
);
1551 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
:
1553 * Setting the first part of a previous oldext extent to newext.
1554 * The left neighbor is contiguous.
1557 NEW
.rm_offset
+= len
;
1558 NEW
.rm_startblock
+= len
;
1559 NEW
.rm_blockcount
-= len
;
1560 error
= xfs_rmap_update(cur
, &NEW
);
1563 error
= xfs_btree_decrement(cur
, 0, &i
);
1567 NEW
.rm_blockcount
+= len
;
1568 error
= xfs_rmap_update(cur
, &NEW
);
1573 case RMAP_LEFT_FILLING
:
1575 * Setting the first part of a previous oldext extent to newext.
1576 * The left neighbor is not contiguous.
1579 NEW
.rm_startblock
+= len
;
1580 NEW
.rm_offset
+= len
;
1581 NEW
.rm_blockcount
-= len
;
1582 error
= xfs_rmap_update(cur
, &NEW
);
1585 NEW
.rm_startblock
= bno
;
1586 NEW
.rm_owner
= owner
;
1587 NEW
.rm_offset
= offset
;
1588 NEW
.rm_blockcount
= len
;
1589 NEW
.rm_flags
= newext
;
1590 cur
->bc_rec
.r
= NEW
;
1591 trace_xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1592 error
= xfs_btree_insert(cur
, &i
);
1595 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1596 xfs_btree_mark_sick(cur
);
1597 error
= -EFSCORRUPTED
;
1602 case RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1604 * Setting the last part of a previous oldext extent to newext.
1605 * The right neighbor is contiguous with the new allocation.
1608 NEW
.rm_blockcount
-= len
;
1609 error
= xfs_rmap_update(cur
, &NEW
);
1612 error
= xfs_btree_increment(cur
, 0, &i
);
1616 NEW
.rm_offset
= offset
;
1617 NEW
.rm_startblock
= bno
;
1618 NEW
.rm_blockcount
+= len
;
1619 error
= xfs_rmap_update(cur
, &NEW
);
1624 case RMAP_RIGHT_FILLING
:
1626 * Setting the last part of a previous oldext extent to newext.
1627 * The right neighbor is not contiguous.
1630 NEW
.rm_blockcount
-= len
;
1631 error
= xfs_rmap_update(cur
, &NEW
);
1634 error
= xfs_rmap_lookup_eq(cur
, bno
, len
, owner
, offset
,
1638 if (XFS_IS_CORRUPT(mp
, i
!= 0)) {
1639 xfs_btree_mark_sick(cur
);
1640 error
= -EFSCORRUPTED
;
1643 NEW
.rm_startblock
= bno
;
1644 NEW
.rm_owner
= owner
;
1645 NEW
.rm_offset
= offset
;
1646 NEW
.rm_blockcount
= len
;
1647 NEW
.rm_flags
= newext
;
1648 cur
->bc_rec
.r
= NEW
;
1649 trace_xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1650 error
= xfs_btree_insert(cur
, &i
);
1653 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1654 xfs_btree_mark_sick(cur
);
1655 error
= -EFSCORRUPTED
;
1662 * Setting the middle part of a previous oldext extent to
1663 * newext. Contiguity is impossible here.
1664 * One extent becomes three extents.
1666 /* new right extent - oldext */
1667 NEW
.rm_startblock
= bno
+ len
;
1668 NEW
.rm_owner
= owner
;
1669 NEW
.rm_offset
= new_endoff
;
1670 NEW
.rm_blockcount
= PREV
.rm_offset
+ PREV
.rm_blockcount
-
1672 NEW
.rm_flags
= PREV
.rm_flags
;
1673 error
= xfs_rmap_update(cur
, &NEW
);
1676 /* new left extent - oldext */
1678 NEW
.rm_blockcount
= offset
- PREV
.rm_offset
;
1679 cur
->bc_rec
.r
= NEW
;
1680 trace_xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1681 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
1683 error
= xfs_btree_insert(cur
, &i
);
1686 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1687 xfs_btree_mark_sick(cur
);
1688 error
= -EFSCORRUPTED
;
1692 * Reset the cursor to the position of the new extent
1693 * we are about to insert as we can't trust it after
1694 * the previous insert.
1696 error
= xfs_rmap_lookup_eq(cur
, bno
, len
, owner
, offset
,
1700 if (XFS_IS_CORRUPT(mp
, i
!= 0)) {
1701 xfs_btree_mark_sick(cur
);
1702 error
= -EFSCORRUPTED
;
1705 /* new middle extent - newext */
1706 cur
->bc_rec
.r
.rm_flags
&= ~XFS_RMAP_UNWRITTEN
;
1707 cur
->bc_rec
.r
.rm_flags
|= newext
;
1708 trace_xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1709 error
= xfs_btree_insert(cur
, &i
);
1712 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1713 xfs_btree_mark_sick(cur
);
1714 error
= -EFSCORRUPTED
;
1719 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1720 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1721 case RMAP_LEFT_FILLING
| RMAP_RIGHT_CONTIG
:
1722 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1723 case RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1724 case RMAP_LEFT_CONTIG
:
1725 case RMAP_RIGHT_CONTIG
:
1727 * These cases are all impossible.
1732 trace_xfs_rmap_convert_done(cur
, bno
, len
, unwritten
, oinfo
);
1735 trace_xfs_rmap_convert_error(cur
, error
, _RET_IP_
);
1740 * Convert an unwritten extent to a real extent or vice versa. If there is no
1741 * possibility of overlapping extents, delegate to the simpler convert
1745 xfs_rmap_convert_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 r
[4]; /* neighbor extent entries */
1754 /* left is 0, right is 1, */
1755 /* prev is 2, new is 3 */
1758 uint64_t new_endoff
;
1759 unsigned int oldext
;
1760 unsigned int newext
;
1761 unsigned int flags
= 0;
1766 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1767 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner
) ||
1768 (flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
))));
1769 oldext
= unwritten
? XFS_RMAP_UNWRITTEN
: 0;
1770 new_endoff
= offset
+ len
;
1771 trace_xfs_rmap_convert(cur
, bno
, len
, unwritten
, oinfo
);
1774 * For the initial lookup, look for and exact match or the left-adjacent
1775 * record for our insertion point. This will also give us the record for
1776 * start block contiguity tests.
1778 error
= xfs_rmap_lookup_le_range(cur
, bno
, owner
, offset
, oldext
,
1782 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1783 xfs_btree_mark_sick(cur
);
1784 error
= -EFSCORRUPTED
;
1788 ASSERT(PREV
.rm_offset
<= offset
);
1789 ASSERT(PREV
.rm_offset
+ PREV
.rm_blockcount
>= new_endoff
);
1790 ASSERT((PREV
.rm_flags
& XFS_RMAP_UNWRITTEN
) == oldext
);
1791 newext
= ~oldext
& XFS_RMAP_UNWRITTEN
;
1794 * Set flags determining what part of the previous oldext allocation
1795 * extent is being replaced by a newext allocation.
1797 if (PREV
.rm_offset
== offset
)
1798 state
|= RMAP_LEFT_FILLING
;
1799 if (PREV
.rm_offset
+ PREV
.rm_blockcount
== new_endoff
)
1800 state
|= RMAP_RIGHT_FILLING
;
1802 /* Is there a left record that abuts our range? */
1803 error
= xfs_rmap_find_left_neighbor(cur
, bno
, owner
, offset
, newext
,
1808 state
|= RMAP_LEFT_VALID
;
1809 if (XFS_IS_CORRUPT(mp
,
1810 LEFT
.rm_startblock
+ LEFT
.rm_blockcount
>
1812 xfs_btree_mark_sick(cur
);
1813 error
= -EFSCORRUPTED
;
1816 if (xfs_rmap_is_mergeable(&LEFT
, owner
, newext
))
1817 state
|= RMAP_LEFT_CONTIG
;
1820 /* Is there a right record that abuts our range? */
1821 error
= xfs_rmap_lookup_eq(cur
, bno
+ len
, len
, owner
, offset
+ len
,
1826 state
|= RMAP_RIGHT_VALID
;
1827 error
= xfs_rmap_get_rec(cur
, &RIGHT
, &i
);
1830 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1831 xfs_btree_mark_sick(cur
);
1832 error
= -EFSCORRUPTED
;
1835 if (XFS_IS_CORRUPT(mp
, bno
+ len
> RIGHT
.rm_startblock
)) {
1836 xfs_btree_mark_sick(cur
);
1837 error
= -EFSCORRUPTED
;
1840 trace_xfs_rmap_find_right_neighbor_result(cur
,
1841 RIGHT
.rm_startblock
, RIGHT
.rm_blockcount
,
1842 RIGHT
.rm_owner
, RIGHT
.rm_offset
,
1844 if (xfs_rmap_is_mergeable(&RIGHT
, owner
, newext
))
1845 state
|= RMAP_RIGHT_CONTIG
;
1848 /* check that left + prev + right is not too long */
1849 if ((state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1850 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) ==
1851 (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1852 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
) &&
1853 (unsigned long)LEFT
.rm_blockcount
+ len
+
1854 RIGHT
.rm_blockcount
> XFS_RMAP_LEN_MAX
)
1855 state
&= ~RMAP_RIGHT_CONTIG
;
1857 trace_xfs_rmap_convert_state(cur
, state
, _RET_IP_
);
1859 * Switch out based on the FILLING and CONTIG state bits.
1861 switch (state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1862 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) {
1863 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1864 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1866 * Setting all of a previous oldext extent to newext.
1867 * The left and right neighbors are both contiguous with new.
1869 error
= xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1870 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1871 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1874 error
= xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1875 PREV
.rm_blockcount
, PREV
.rm_owner
,
1876 PREV
.rm_offset
, PREV
.rm_flags
);
1880 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1881 NEW
.rm_blockcount
, NEW
.rm_owner
,
1882 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1885 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1886 xfs_btree_mark_sick(cur
);
1887 error
= -EFSCORRUPTED
;
1890 NEW
.rm_blockcount
+= PREV
.rm_blockcount
+ RIGHT
.rm_blockcount
;
1891 error
= xfs_rmap_update(cur
, &NEW
);
1896 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1898 * Setting all of a previous oldext extent to newext.
1899 * The left neighbor is contiguous, the right is not.
1901 error
= xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1902 PREV
.rm_blockcount
, PREV
.rm_owner
,
1903 PREV
.rm_offset
, PREV
.rm_flags
);
1907 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1908 NEW
.rm_blockcount
, NEW
.rm_owner
,
1909 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1912 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1913 xfs_btree_mark_sick(cur
);
1914 error
= -EFSCORRUPTED
;
1917 NEW
.rm_blockcount
+= PREV
.rm_blockcount
;
1918 error
= xfs_rmap_update(cur
, &NEW
);
1923 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1925 * Setting all of a previous oldext extent to newext.
1926 * The right neighbor is contiguous, the left is not.
1928 error
= xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1929 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1930 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1934 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1935 NEW
.rm_blockcount
, NEW
.rm_owner
,
1936 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1939 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1940 xfs_btree_mark_sick(cur
);
1941 error
= -EFSCORRUPTED
;
1944 NEW
.rm_blockcount
+= RIGHT
.rm_blockcount
;
1945 NEW
.rm_flags
= RIGHT
.rm_flags
;
1946 error
= xfs_rmap_update(cur
, &NEW
);
1951 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
:
1953 * Setting all of a previous oldext extent to newext.
1954 * Neither the left nor right neighbors are contiguous with
1958 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1959 NEW
.rm_blockcount
, NEW
.rm_owner
,
1960 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1963 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
1964 xfs_btree_mark_sick(cur
);
1965 error
= -EFSCORRUPTED
;
1968 NEW
.rm_flags
= newext
;
1969 error
= xfs_rmap_update(cur
, &NEW
);
1974 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
:
1976 * Setting the first part of a previous oldext extent to newext.
1977 * The left neighbor is contiguous.
1980 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1981 NEW
.rm_blockcount
, NEW
.rm_owner
,
1982 NEW
.rm_offset
, NEW
.rm_flags
);
1985 NEW
.rm_offset
+= len
;
1986 NEW
.rm_startblock
+= len
;
1987 NEW
.rm_blockcount
-= len
;
1988 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1989 NEW
.rm_blockcount
, NEW
.rm_owner
,
1990 NEW
.rm_offset
, NEW
.rm_flags
);
1994 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1995 NEW
.rm_blockcount
, NEW
.rm_owner
,
1996 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1999 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
2000 xfs_btree_mark_sick(cur
);
2001 error
= -EFSCORRUPTED
;
2004 NEW
.rm_blockcount
+= len
;
2005 error
= xfs_rmap_update(cur
, &NEW
);
2010 case RMAP_LEFT_FILLING
:
2012 * Setting the first part of a previous oldext extent to newext.
2013 * The left neighbor is not contiguous.
2016 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
2017 NEW
.rm_blockcount
, NEW
.rm_owner
,
2018 NEW
.rm_offset
, NEW
.rm_flags
);
2021 NEW
.rm_offset
+= len
;
2022 NEW
.rm_startblock
+= len
;
2023 NEW
.rm_blockcount
-= len
;
2024 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
2025 NEW
.rm_blockcount
, NEW
.rm_owner
,
2026 NEW
.rm_offset
, NEW
.rm_flags
);
2029 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
2034 case RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
2036 * Setting the last part of a previous oldext extent to newext.
2037 * The right neighbor is contiguous with the new allocation.
2040 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
2041 NEW
.rm_blockcount
, NEW
.rm_owner
,
2042 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
2045 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
2046 xfs_btree_mark_sick(cur
);
2047 error
= -EFSCORRUPTED
;
2050 NEW
.rm_blockcount
= offset
- NEW
.rm_offset
;
2051 error
= xfs_rmap_update(cur
, &NEW
);
2055 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
2056 NEW
.rm_blockcount
, NEW
.rm_owner
,
2057 NEW
.rm_offset
, NEW
.rm_flags
);
2060 NEW
.rm_offset
= offset
;
2061 NEW
.rm_startblock
= bno
;
2062 NEW
.rm_blockcount
+= len
;
2063 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
2064 NEW
.rm_blockcount
, NEW
.rm_owner
,
2065 NEW
.rm_offset
, NEW
.rm_flags
);
2070 case RMAP_RIGHT_FILLING
:
2072 * Setting the last part of a previous oldext extent to newext.
2073 * The right neighbor is not contiguous.
2076 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
2077 NEW
.rm_blockcount
, NEW
.rm_owner
,
2078 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
2081 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
2082 xfs_btree_mark_sick(cur
);
2083 error
= -EFSCORRUPTED
;
2086 NEW
.rm_blockcount
-= len
;
2087 error
= xfs_rmap_update(cur
, &NEW
);
2090 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
2097 * Setting the middle part of a previous oldext extent to
2098 * newext. Contiguity is impossible here.
2099 * One extent becomes three extents.
2101 /* new right extent - oldext */
2102 NEW
.rm_startblock
= bno
+ len
;
2103 NEW
.rm_owner
= owner
;
2104 NEW
.rm_offset
= new_endoff
;
2105 NEW
.rm_blockcount
= PREV
.rm_offset
+ PREV
.rm_blockcount
-
2107 NEW
.rm_flags
= PREV
.rm_flags
;
2108 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
2109 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
2113 /* new left extent - oldext */
2115 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
2116 NEW
.rm_blockcount
, NEW
.rm_owner
,
2117 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
2120 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
2121 xfs_btree_mark_sick(cur
);
2122 error
= -EFSCORRUPTED
;
2125 NEW
.rm_blockcount
= offset
- NEW
.rm_offset
;
2126 error
= xfs_rmap_update(cur
, &NEW
);
2129 /* new middle extent - newext */
2130 NEW
.rm_startblock
= bno
;
2131 NEW
.rm_blockcount
= len
;
2132 NEW
.rm_owner
= owner
;
2133 NEW
.rm_offset
= offset
;
2134 NEW
.rm_flags
= newext
;
2135 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
2136 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
2142 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
2143 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
2144 case RMAP_LEFT_FILLING
| RMAP_RIGHT_CONTIG
:
2145 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
2146 case RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
2147 case RMAP_LEFT_CONTIG
:
2148 case RMAP_RIGHT_CONTIG
:
2150 * These cases are all impossible.
2155 trace_xfs_rmap_convert_done(cur
, bno
, len
, unwritten
, oinfo
);
2158 trace_xfs_rmap_convert_error(cur
, error
, _RET_IP_
);
2168 * Find an extent in the rmap btree and unmap it. For rmap extent types that
2169 * can overlap (data fork rmaps on reflink filesystems) we must be careful
2170 * that the prev/next records in the btree might belong to another owner.
2171 * Therefore we must use delete+insert to alter any of the key fields.
2173 * For every other situation there can only be one owner for a given extent,
2174 * so we can call the regular _free function.
2177 xfs_rmap_unmap_shared(
2178 struct xfs_btree_cur
*cur
,
2182 const struct xfs_owner_info
*oinfo
)
2184 struct xfs_mount
*mp
= cur
->bc_mp
;
2185 struct xfs_rmap_irec ltrec
;
2193 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
2195 flags
|= XFS_RMAP_UNWRITTEN
;
2196 trace_xfs_rmap_unmap(cur
, bno
, len
, unwritten
, oinfo
);
2199 * We should always have a left record because there's a static record
2200 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
2201 * will not ever be removed from the tree.
2203 error
= xfs_rmap_lookup_le_range(cur
, bno
, owner
, offset
, flags
,
2207 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
2208 xfs_btree_mark_sick(cur
);
2209 error
= -EFSCORRUPTED
;
2212 ltoff
= ltrec
.rm_offset
;
2214 /* Make sure the extent we found covers the entire freeing range. */
2215 if (XFS_IS_CORRUPT(mp
,
2216 ltrec
.rm_startblock
> bno
||
2217 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
<
2219 xfs_btree_mark_sick(cur
);
2220 error
= -EFSCORRUPTED
;
2224 /* Make sure the owner matches what we expect to find in the tree. */
2225 if (XFS_IS_CORRUPT(mp
, owner
!= ltrec
.rm_owner
)) {
2226 xfs_btree_mark_sick(cur
);
2227 error
= -EFSCORRUPTED
;
2231 /* Make sure the unwritten flag matches. */
2232 if (XFS_IS_CORRUPT(mp
,
2233 (flags
& XFS_RMAP_UNWRITTEN
) !=
2234 (ltrec
.rm_flags
& XFS_RMAP_UNWRITTEN
))) {
2235 xfs_btree_mark_sick(cur
);
2236 error
= -EFSCORRUPTED
;
2240 /* Check the offset. */
2241 if (XFS_IS_CORRUPT(mp
, ltrec
.rm_offset
> offset
)) {
2242 xfs_btree_mark_sick(cur
);
2243 error
= -EFSCORRUPTED
;
2246 if (XFS_IS_CORRUPT(mp
, offset
> ltoff
+ ltrec
.rm_blockcount
)) {
2247 xfs_btree_mark_sick(cur
);
2248 error
= -EFSCORRUPTED
;
2252 if (ltrec
.rm_startblock
== bno
&& ltrec
.rm_blockcount
== len
) {
2253 /* Exact match, simply remove the record from rmap tree. */
2254 error
= xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
2255 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
2256 ltrec
.rm_offset
, ltrec
.rm_flags
);
2259 } else if (ltrec
.rm_startblock
== bno
) {
2261 * Overlap left hand side of extent: move the start, trim the
2262 * length and update the current record.
2265 * Orig: |oooooooooooooooooooo|
2266 * Freeing: |fffffffff|
2267 * Result: |rrrrrrrrrr|
2271 /* Delete prev rmap. */
2272 error
= xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
2273 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
2274 ltrec
.rm_offset
, ltrec
.rm_flags
);
2278 /* Add an rmap at the new offset. */
2279 ltrec
.rm_startblock
+= len
;
2280 ltrec
.rm_blockcount
-= len
;
2281 ltrec
.rm_offset
+= len
;
2282 error
= xfs_rmap_insert(cur
, ltrec
.rm_startblock
,
2283 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
2284 ltrec
.rm_offset
, ltrec
.rm_flags
);
2287 } else if (ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
+ len
) {
2289 * Overlap right hand side of extent: trim the length and
2290 * update the current record.
2293 * Orig: |oooooooooooooooooooo|
2294 * Freeing: |fffffffff|
2295 * Result: |rrrrrrrrrr|
2298 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
2299 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
2300 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
2303 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
2304 xfs_btree_mark_sick(cur
);
2305 error
= -EFSCORRUPTED
;
2308 ltrec
.rm_blockcount
-= len
;
2309 error
= xfs_rmap_update(cur
, <rec
);
2314 * Overlap middle of extent: trim the length of the existing
2315 * record to the length of the new left-extent size, increment
2316 * the insertion position so we can insert a new record
2317 * containing the remaining right-extent space.
2320 * Orig: |oooooooooooooooooooo|
2321 * Freeing: |fffffffff|
2322 * Result: |rrrrr| |rrrr|
2325 xfs_extlen_t orig_len
= ltrec
.rm_blockcount
;
2327 /* Shrink the left side of the rmap */
2328 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
2329 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
2330 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
2333 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
2334 xfs_btree_mark_sick(cur
);
2335 error
= -EFSCORRUPTED
;
2338 ltrec
.rm_blockcount
= bno
- ltrec
.rm_startblock
;
2339 error
= xfs_rmap_update(cur
, <rec
);
2343 /* Add an rmap at the new offset */
2344 error
= xfs_rmap_insert(cur
, bno
+ len
,
2345 orig_len
- len
- ltrec
.rm_blockcount
,
2346 ltrec
.rm_owner
, offset
+ len
,
2352 trace_xfs_rmap_unmap_done(cur
, bno
, len
, unwritten
, oinfo
);
2355 trace_xfs_rmap_unmap_error(cur
, error
, _RET_IP_
);
2360 * Find an extent in the rmap btree and map it. For rmap extent types that
2361 * can overlap (data fork rmaps on reflink filesystems) we must be careful
2362 * that the prev/next records in the btree might belong to another owner.
2363 * Therefore we must use delete+insert to alter any of the key fields.
2365 * For every other situation there can only be one owner for a given extent,
2366 * so we can call the regular _alloc function.
2369 xfs_rmap_map_shared(
2370 struct xfs_btree_cur
*cur
,
2374 const struct xfs_owner_info
*oinfo
)
2376 struct xfs_mount
*mp
= cur
->bc_mp
;
2377 struct xfs_rmap_irec ltrec
;
2378 struct xfs_rmap_irec gtrec
;
2385 unsigned int flags
= 0;
2387 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
2389 flags
|= XFS_RMAP_UNWRITTEN
;
2390 trace_xfs_rmap_map(cur
, bno
, len
, unwritten
, oinfo
);
2392 /* Is there a left record that abuts our range? */
2393 error
= xfs_rmap_find_left_neighbor(cur
, bno
, owner
, offset
, flags
,
2398 !xfs_rmap_is_mergeable(<rec
, owner
, flags
))
2401 /* Is there a right record that abuts our range? */
2402 error
= xfs_rmap_lookup_eq(cur
, bno
+ len
, len
, owner
, offset
+ len
,
2407 error
= xfs_rmap_get_rec(cur
, >rec
, &have_gt
);
2410 if (XFS_IS_CORRUPT(mp
, have_gt
!= 1)) {
2411 xfs_btree_mark_sick(cur
);
2412 error
= -EFSCORRUPTED
;
2415 trace_xfs_rmap_find_right_neighbor_result(cur
,
2416 gtrec
.rm_startblock
, gtrec
.rm_blockcount
,
2417 gtrec
.rm_owner
, gtrec
.rm_offset
,
2420 if (!xfs_rmap_is_mergeable(>rec
, owner
, flags
))
2425 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
&&
2426 ltrec
.rm_offset
+ ltrec
.rm_blockcount
== offset
) {
2428 * Left edge contiguous, merge into left record.
2432 * adding: |aaaaaaaaa|
2433 * result: |rrrrrrrrrrrrrrrrrrr|
2436 ltrec
.rm_blockcount
+= len
;
2438 bno
+ len
== gtrec
.rm_startblock
&&
2439 offset
+ len
== gtrec
.rm_offset
) {
2441 * Right edge also contiguous, delete right record
2442 * and merge into left record.
2444 * ltbno ltlen gtbno gtlen
2445 * orig: |ooooooooo| |ooooooooo|
2446 * adding: |aaaaaaaaa|
2447 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
2449 ltrec
.rm_blockcount
+= gtrec
.rm_blockcount
;
2450 error
= xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
2451 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2452 gtrec
.rm_offset
, gtrec
.rm_flags
);
2457 /* Point the cursor back to the left record and update. */
2458 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
2459 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
2460 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
2463 if (XFS_IS_CORRUPT(mp
, i
!= 1)) {
2464 xfs_btree_mark_sick(cur
);
2465 error
= -EFSCORRUPTED
;
2469 error
= xfs_rmap_update(cur
, <rec
);
2472 } else if (have_gt
&&
2473 bno
+ len
== gtrec
.rm_startblock
&&
2474 offset
+ len
== gtrec
.rm_offset
) {
2476 * Right edge contiguous, merge into right record.
2480 * adding: |aaaaaaaaa|
2481 * Result: |rrrrrrrrrrrrrrrrrrr|
2484 /* Delete the old record. */
2485 error
= xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
2486 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2487 gtrec
.rm_offset
, gtrec
.rm_flags
);
2491 /* Move the start and re-add it. */
2492 gtrec
.rm_startblock
= bno
;
2493 gtrec
.rm_blockcount
+= len
;
2494 gtrec
.rm_offset
= offset
;
2495 error
= xfs_rmap_insert(cur
, gtrec
.rm_startblock
,
2496 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2497 gtrec
.rm_offset
, gtrec
.rm_flags
);
2502 * No contiguous edge with identical owner, insert
2503 * new record at current cursor position.
2505 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, flags
);
2510 trace_xfs_rmap_map_done(cur
, bno
, len
, unwritten
, oinfo
);
2513 trace_xfs_rmap_map_error(cur
, error
, _RET_IP_
);
2517 /* Insert a raw rmap into the rmapbt. */
2520 struct xfs_btree_cur
*cur
,
2521 struct xfs_rmap_irec
*rmap
)
2523 struct xfs_owner_info oinfo
;
2525 xfs_owner_info_pack(&oinfo
, rmap
->rm_owner
, rmap
->rm_offset
,
2528 if ((rmap
->rm_flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
|
2529 XFS_RMAP_UNWRITTEN
)) ||
2530 XFS_RMAP_NON_INODE_OWNER(rmap
->rm_owner
))
2531 return xfs_rmap_map(cur
, rmap
->rm_startblock
,
2532 rmap
->rm_blockcount
,
2533 rmap
->rm_flags
& XFS_RMAP_UNWRITTEN
,
2536 return xfs_rmap_map_shared(cur
, rmap
->rm_startblock
,
2537 rmap
->rm_blockcount
,
2538 rmap
->rm_flags
& XFS_RMAP_UNWRITTEN
,
2542 struct xfs_rmap_query_range_info
{
2543 xfs_rmap_query_range_fn fn
;
2547 /* Format btree record and pass to our callback. */
2549 xfs_rmap_query_range_helper(
2550 struct xfs_btree_cur
*cur
,
2551 const union xfs_btree_rec
*rec
,
2554 struct xfs_rmap_query_range_info
*query
= priv
;
2555 struct xfs_rmap_irec irec
;
2558 fa
= xfs_rmap_btrec_to_irec(rec
, &irec
);
2560 fa
= xfs_rmap_check_btrec(cur
, &irec
);
2562 return xfs_rmap_complain_bad_rec(cur
, fa
, &irec
);
2564 return query
->fn(cur
, &irec
, query
->priv
);
2567 /* Find all rmaps between two keys. */
2569 xfs_rmap_query_range(
2570 struct xfs_btree_cur
*cur
,
2571 const struct xfs_rmap_irec
*low_rec
,
2572 const struct xfs_rmap_irec
*high_rec
,
2573 xfs_rmap_query_range_fn fn
,
2576 union xfs_btree_irec low_brec
= { .r
= *low_rec
};
2577 union xfs_btree_irec high_brec
= { .r
= *high_rec
};
2578 struct xfs_rmap_query_range_info query
= { .priv
= priv
, .fn
= fn
};
2580 return xfs_btree_query_range(cur
, &low_brec
, &high_brec
,
2581 xfs_rmap_query_range_helper
, &query
);
2584 /* Find all rmaps. */
2587 struct xfs_btree_cur
*cur
,
2588 xfs_rmap_query_range_fn fn
,
2591 struct xfs_rmap_query_range_info query
;
2595 return xfs_btree_query_all(cur
, xfs_rmap_query_range_helper
, &query
);
2598 /* Commit an rmap operation into the ondisk tree. */
2600 __xfs_rmap_finish_intent(
2601 struct xfs_btree_cur
*rcur
,
2602 enum xfs_rmap_intent_type op
,
2605 const struct xfs_owner_info
*oinfo
,
2609 case XFS_RMAP_ALLOC
:
2611 return xfs_rmap_map(rcur
, bno
, len
, unwritten
, oinfo
);
2612 case XFS_RMAP_MAP_SHARED
:
2613 return xfs_rmap_map_shared(rcur
, bno
, len
, unwritten
, oinfo
);
2615 case XFS_RMAP_UNMAP
:
2616 return xfs_rmap_unmap(rcur
, bno
, len
, unwritten
, oinfo
);
2617 case XFS_RMAP_UNMAP_SHARED
:
2618 return xfs_rmap_unmap_shared(rcur
, bno
, len
, unwritten
, oinfo
);
2619 case XFS_RMAP_CONVERT
:
2620 return xfs_rmap_convert(rcur
, bno
, len
, !unwritten
, oinfo
);
2621 case XFS_RMAP_CONVERT_SHARED
:
2622 return xfs_rmap_convert_shared(rcur
, bno
, len
, !unwritten
,
2626 return -EFSCORRUPTED
;
2631 xfs_rmap_finish_init_cursor(
2632 struct xfs_trans
*tp
,
2633 struct xfs_rmap_intent
*ri
,
2634 struct xfs_btree_cur
**pcur
)
2636 struct xfs_perag
*pag
= to_perag(ri
->ri_group
);
2637 struct xfs_buf
*agbp
= NULL
;
2641 * Refresh the freelist before we start changing the rmapbt, because a
2642 * shape change could cause us to allocate blocks.
2644 error
= xfs_free_extent_fix_freelist(tp
, pag
, &agbp
);
2646 xfs_ag_mark_sick(pag
, XFS_SICK_AG_AGFL
);
2649 if (XFS_IS_CORRUPT(tp
->t_mountp
, !agbp
)) {
2650 xfs_ag_mark_sick(pag
, XFS_SICK_AG_AGFL
);
2651 return -EFSCORRUPTED
;
2653 *pcur
= xfs_rmapbt_init_cursor(tp
->t_mountp
, tp
, agbp
, pag
);
2658 xfs_rtrmap_finish_init_cursor(
2659 struct xfs_trans
*tp
,
2660 struct xfs_rmap_intent
*ri
,
2661 struct xfs_btree_cur
**pcur
)
2663 struct xfs_rtgroup
*rtg
= to_rtg(ri
->ri_group
);
2665 xfs_rtgroup_lock(rtg
, XFS_RTGLOCK_RMAP
);
2666 xfs_rtgroup_trans_join(tp
, rtg
, XFS_RTGLOCK_RMAP
);
2667 *pcur
= xfs_rtrmapbt_init_cursor(tp
, rtg
);
2672 * Process one of the deferred rmap operations. We pass back the
2673 * btree cursor to maintain our lock on the rmapbt between calls.
2674 * This saves time and eliminates a buffer deadlock between the
2675 * superblock and the AGF because we'll always grab them in the same
2679 xfs_rmap_finish_one(
2680 struct xfs_trans
*tp
,
2681 struct xfs_rmap_intent
*ri
,
2682 struct xfs_btree_cur
**pcur
)
2684 struct xfs_owner_info oinfo
;
2685 struct xfs_mount
*mp
= tp
->t_mountp
;
2690 trace_xfs_rmap_deferred(mp
, ri
);
2692 if (XFS_TEST_ERROR(false, mp
, XFS_ERRTAG_RMAP_FINISH_ONE
))
2696 * If we haven't gotten a cursor or the cursor AG doesn't match
2697 * the startblock, get one now.
2699 if (*pcur
!= NULL
&& (*pcur
)->bc_group
!= ri
->ri_group
) {
2700 xfs_btree_del_cursor(*pcur
, 0);
2703 if (*pcur
== NULL
) {
2704 if (ri
->ri_group
->xg_type
== XG_TYPE_RTG
)
2705 error
= xfs_rtrmap_finish_init_cursor(tp
, ri
, pcur
);
2707 error
= xfs_rmap_finish_init_cursor(tp
, ri
, pcur
);
2712 xfs_rmap_ino_owner(&oinfo
, ri
->ri_owner
, ri
->ri_whichfork
,
2713 ri
->ri_bmap
.br_startoff
);
2714 unwritten
= ri
->ri_bmap
.br_state
== XFS_EXT_UNWRITTEN
;
2716 bno
= xfs_fsb_to_gbno(mp
, ri
->ri_bmap
.br_startblock
,
2717 ri
->ri_group
->xg_type
);
2718 error
= __xfs_rmap_finish_intent(*pcur
, ri
->ri_type
, bno
,
2719 ri
->ri_bmap
.br_blockcount
, &oinfo
, unwritten
);
2723 xfs_rmap_update_hook(tp
, ri
->ri_group
, ri
->ri_type
, bno
,
2724 ri
->ri_bmap
.br_blockcount
, unwritten
, &oinfo
);
2729 * Don't defer an rmap if we aren't an rmap filesystem.
2732 xfs_rmap_update_is_needed(
2733 struct xfs_mount
*mp
,
2736 return xfs_has_rmapbt(mp
) && whichfork
!= XFS_COW_FORK
;
2740 * Record a rmap intent; the list is kept sorted first by AG and then by
2745 struct xfs_trans
*tp
,
2746 enum xfs_rmap_intent_type type
,
2750 struct xfs_bmbt_irec
*bmap
)
2752 struct xfs_rmap_intent
*ri
;
2754 ri
= kmem_cache_alloc(xfs_rmap_intent_cache
, GFP_KERNEL
| __GFP_NOFAIL
);
2755 INIT_LIST_HEAD(&ri
->ri_list
);
2757 ri
->ri_owner
= owner
;
2758 ri
->ri_whichfork
= whichfork
;
2759 ri
->ri_bmap
= *bmap
;
2760 ri
->ri_realtime
= isrt
;
2762 xfs_rmap_defer_add(tp
, ri
);
2765 /* Map an extent into a file. */
2767 xfs_rmap_map_extent(
2768 struct xfs_trans
*tp
,
2769 struct xfs_inode
*ip
,
2771 struct xfs_bmbt_irec
*PREV
)
2773 enum xfs_rmap_intent_type type
= XFS_RMAP_MAP
;
2774 bool isrt
= xfs_ifork_is_realtime(ip
, whichfork
);
2776 if (!xfs_rmap_update_is_needed(tp
->t_mountp
, whichfork
))
2779 if (whichfork
!= XFS_ATTR_FORK
&& xfs_is_reflink_inode(ip
))
2780 type
= XFS_RMAP_MAP_SHARED
;
2782 __xfs_rmap_add(tp
, type
, ip
->i_ino
, isrt
, whichfork
, PREV
);
2785 /* Unmap an extent out of a file. */
2787 xfs_rmap_unmap_extent(
2788 struct xfs_trans
*tp
,
2789 struct xfs_inode
*ip
,
2791 struct xfs_bmbt_irec
*PREV
)
2793 enum xfs_rmap_intent_type type
= XFS_RMAP_UNMAP
;
2794 bool isrt
= xfs_ifork_is_realtime(ip
, whichfork
);
2796 if (!xfs_rmap_update_is_needed(tp
->t_mountp
, whichfork
))
2799 if (whichfork
!= XFS_ATTR_FORK
&& xfs_is_reflink_inode(ip
))
2800 type
= XFS_RMAP_UNMAP_SHARED
;
2802 __xfs_rmap_add(tp
, type
, ip
->i_ino
, isrt
, whichfork
, PREV
);
2806 * Convert a data fork extent from unwritten to real or vice versa.
2808 * Note that tp can be NULL here as no transaction is used for COW fork
2809 * unwritten conversion.
2812 xfs_rmap_convert_extent(
2813 struct xfs_mount
*mp
,
2814 struct xfs_trans
*tp
,
2815 struct xfs_inode
*ip
,
2817 struct xfs_bmbt_irec
*PREV
)
2819 enum xfs_rmap_intent_type type
= XFS_RMAP_CONVERT
;
2820 bool isrt
= xfs_ifork_is_realtime(ip
, whichfork
);
2822 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2825 if (whichfork
!= XFS_ATTR_FORK
&& xfs_is_reflink_inode(ip
))
2826 type
= XFS_RMAP_CONVERT_SHARED
;
2828 __xfs_rmap_add(tp
, type
, ip
->i_ino
, isrt
, whichfork
, PREV
);
2831 /* Schedule the creation of an rmap for non-file data. */
2833 xfs_rmap_alloc_extent(
2834 struct xfs_trans
*tp
,
2836 xfs_fsblock_t fsbno
,
2840 struct xfs_bmbt_irec bmap
;
2842 if (!xfs_rmap_update_is_needed(tp
->t_mountp
, XFS_DATA_FORK
))
2845 bmap
.br_startblock
= fsbno
;
2846 bmap
.br_blockcount
= len
;
2847 bmap
.br_startoff
= 0;
2848 bmap
.br_state
= XFS_EXT_NORM
;
2850 __xfs_rmap_add(tp
, XFS_RMAP_ALLOC
, owner
, isrt
, XFS_DATA_FORK
, &bmap
);
2853 /* Schedule the deletion of an rmap for non-file data. */
2855 xfs_rmap_free_extent(
2856 struct xfs_trans
*tp
,
2858 xfs_fsblock_t fsbno
,
2862 struct xfs_bmbt_irec bmap
;
2864 if (!xfs_rmap_update_is_needed(tp
->t_mountp
, XFS_DATA_FORK
))
2867 bmap
.br_startblock
= fsbno
;
2868 bmap
.br_blockcount
= len
;
2869 bmap
.br_startoff
= 0;
2870 bmap
.br_state
= XFS_EXT_NORM
;
2872 __xfs_rmap_add(tp
, XFS_RMAP_FREE
, owner
, isrt
, XFS_DATA_FORK
, &bmap
);
2875 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2878 const struct xfs_rmap_irec
*a
,
2879 const struct xfs_rmap_irec
*b
)
2884 oa
= xfs_rmap_irec_offset_pack(a
);
2885 ob
= xfs_rmap_irec_offset_pack(b
);
2887 if (a
->rm_startblock
< b
->rm_startblock
)
2889 else if (a
->rm_startblock
> b
->rm_startblock
)
2891 else if (a
->rm_owner
< b
->rm_owner
)
2893 else if (a
->rm_owner
> b
->rm_owner
)
2904 * Scan the physical storage part of the keyspace of the reverse mapping index
2905 * and tell us if the area has no records, is fully mapped by records, or is
2909 xfs_rmap_has_records(
2910 struct xfs_btree_cur
*cur
,
2913 enum xbtree_recpacking
*outcome
)
2915 union xfs_btree_key mask
= {
2916 .rmap
.rm_startblock
= cpu_to_be32(-1U),
2918 union xfs_btree_irec low
;
2919 union xfs_btree_irec high
;
2921 memset(&low
, 0, sizeof(low
));
2922 low
.r
.rm_startblock
= bno
;
2923 memset(&high
, 0xFF, sizeof(high
));
2924 high
.r
.rm_startblock
= bno
+ len
- 1;
2926 return xfs_btree_has_records(cur
, &low
, &high
, &mask
, outcome
);
2929 struct xfs_rmap_ownercount
{
2930 /* Owner that we're looking for. */
2931 struct xfs_rmap_irec good
;
2933 /* rmap search keys */
2934 struct xfs_rmap_irec low
;
2935 struct xfs_rmap_irec high
;
2937 struct xfs_rmap_matches
*results
;
2939 /* Stop early if we find a nonmatch? */
2940 bool stop_on_nonmatch
;
2943 /* Does this rmap represent space that can have multiple owners? */
2946 struct xfs_mount
*mp
,
2947 const struct xfs_rmap_irec
*rmap
)
2949 if (!xfs_has_reflink(mp
))
2951 if (XFS_RMAP_NON_INODE_OWNER(rmap
->rm_owner
))
2953 if (rmap
->rm_flags
& (XFS_RMAP_ATTR_FORK
|
2954 XFS_RMAP_BMBT_BLOCK
))
2960 xfs_rmap_ownercount_init(
2961 struct xfs_rmap_ownercount
*roc
,
2964 const struct xfs_owner_info
*oinfo
,
2965 struct xfs_rmap_matches
*results
)
2967 memset(roc
, 0, sizeof(*roc
));
2968 roc
->results
= results
;
2970 roc
->low
.rm_startblock
= bno
;
2971 memset(&roc
->high
, 0xFF, sizeof(roc
->high
));
2972 roc
->high
.rm_startblock
= bno
+ len
- 1;
2974 memset(results
, 0, sizeof(*results
));
2975 roc
->good
.rm_startblock
= bno
;
2976 roc
->good
.rm_blockcount
= len
;
2977 roc
->good
.rm_owner
= oinfo
->oi_owner
;
2978 roc
->good
.rm_offset
= oinfo
->oi_offset
;
2979 if (oinfo
->oi_flags
& XFS_OWNER_INFO_ATTR_FORK
)
2980 roc
->good
.rm_flags
|= XFS_RMAP_ATTR_FORK
;
2981 if (oinfo
->oi_flags
& XFS_OWNER_INFO_BMBT_BLOCK
)
2982 roc
->good
.rm_flags
|= XFS_RMAP_BMBT_BLOCK
;
2985 /* Figure out if this is a match for the owner. */
2987 xfs_rmap_count_owners_helper(
2988 struct xfs_btree_cur
*cur
,
2989 const struct xfs_rmap_irec
*rec
,
2992 struct xfs_rmap_ownercount
*roc
= priv
;
2993 struct xfs_rmap_irec check
= *rec
;
2994 unsigned int keyflags
;
2998 filedata
= !XFS_RMAP_NON_INODE_OWNER(check
.rm_owner
) &&
2999 !(check
.rm_flags
& XFS_RMAP_BMBT_BLOCK
);
3001 /* Trim the part of check that comes before the comparison range. */
3002 delta
= (int64_t)roc
->good
.rm_startblock
- check
.rm_startblock
;
3004 check
.rm_startblock
+= delta
;
3005 check
.rm_blockcount
-= delta
;
3007 check
.rm_offset
+= delta
;
3010 /* Trim the part of check that comes after the comparison range. */
3011 delta
= (check
.rm_startblock
+ check
.rm_blockcount
) -
3012 (roc
->good
.rm_startblock
+ roc
->good
.rm_blockcount
);
3014 check
.rm_blockcount
-= delta
;
3016 /* Don't care about unwritten status for establishing ownership. */
3017 keyflags
= check
.rm_flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
);
3019 if (check
.rm_startblock
== roc
->good
.rm_startblock
&&
3020 check
.rm_blockcount
== roc
->good
.rm_blockcount
&&
3021 check
.rm_owner
== roc
->good
.rm_owner
&&
3022 check
.rm_offset
== roc
->good
.rm_offset
&&
3023 keyflags
== roc
->good
.rm_flags
) {
3024 roc
->results
->matches
++;
3026 roc
->results
->non_owner_matches
++;
3027 if (xfs_rmap_shareable(cur
->bc_mp
, &roc
->good
) ^
3028 xfs_rmap_shareable(cur
->bc_mp
, &check
))
3029 roc
->results
->bad_non_owner_matches
++;
3032 if (roc
->results
->non_owner_matches
&& roc
->stop_on_nonmatch
)
3038 /* Count the number of owners and non-owners of this range of blocks. */
3040 xfs_rmap_count_owners(
3041 struct xfs_btree_cur
*cur
,
3044 const struct xfs_owner_info
*oinfo
,
3045 struct xfs_rmap_matches
*results
)
3047 struct xfs_rmap_ownercount roc
;
3050 xfs_rmap_ownercount_init(&roc
, bno
, len
, oinfo
, results
);
3051 error
= xfs_rmap_query_range(cur
, &roc
.low
, &roc
.high
,
3052 xfs_rmap_count_owners_helper
, &roc
);
3057 * There can't be any non-owner rmaps that conflict with the given
3058 * owner if we didn't find any rmaps matching the owner.
3060 if (!results
->matches
)
3061 results
->bad_non_owner_matches
= 0;
3067 * Given an extent and some owner info, can we find records overlapping
3068 * the extent whose owner info does not match the given owner?
3071 xfs_rmap_has_other_keys(
3072 struct xfs_btree_cur
*cur
,
3075 const struct xfs_owner_info
*oinfo
,
3078 struct xfs_rmap_matches res
;
3079 struct xfs_rmap_ownercount roc
;
3082 xfs_rmap_ownercount_init(&roc
, bno
, len
, oinfo
, &res
);
3083 roc
.stop_on_nonmatch
= true;
3085 error
= xfs_rmap_query_range(cur
, &roc
.low
, &roc
.high
,
3086 xfs_rmap_count_owners_helper
, &roc
);
3087 if (error
== -ECANCELED
) {
3098 const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE
= {
3099 .oi_owner
= XFS_RMAP_OWN_NULL
,
3101 const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER
= {
3102 .oi_owner
= XFS_RMAP_OWN_UNKNOWN
,
3104 const struct xfs_owner_info XFS_RMAP_OINFO_FS
= {
3105 .oi_owner
= XFS_RMAP_OWN_FS
,
3107 const struct xfs_owner_info XFS_RMAP_OINFO_LOG
= {
3108 .oi_owner
= XFS_RMAP_OWN_LOG
,
3110 const struct xfs_owner_info XFS_RMAP_OINFO_AG
= {
3111 .oi_owner
= XFS_RMAP_OWN_AG
,
3113 const struct xfs_owner_info XFS_RMAP_OINFO_INOBT
= {
3114 .oi_owner
= XFS_RMAP_OWN_INOBT
,
3116 const struct xfs_owner_info XFS_RMAP_OINFO_INODES
= {
3117 .oi_owner
= XFS_RMAP_OWN_INODES
,
3119 const struct xfs_owner_info XFS_RMAP_OINFO_REFC
= {
3120 .oi_owner
= XFS_RMAP_OWN_REFC
,
3122 const struct xfs_owner_info XFS_RMAP_OINFO_COW
= {
3123 .oi_owner
= XFS_RMAP_OWN_COW
,
3127 xfs_rmap_intent_init_cache(void)
3129 xfs_rmap_intent_cache
= kmem_cache_create("xfs_rmap_intent",
3130 sizeof(struct xfs_rmap_intent
),
3133 return xfs_rmap_intent_cache
!= NULL
? 0 : -ENOMEM
;
3137 xfs_rmap_intent_destroy_cache(void)
3139 kmem_cache_destroy(xfs_rmap_intent_cache
);
3140 xfs_rmap_intent_cache
= NULL
;