2 * Copyright (c) 2014 Red Hat, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 #include "libxfs_priv.h"
20 #include "xfs_shared.h"
21 #include "xfs_format.h"
22 #include "xfs_log_format.h"
23 #include "xfs_trans_resv.h"
26 #include "xfs_mount.h"
27 #include "xfs_defer.h"
28 #include "xfs_da_format.h"
29 #include "xfs_da_btree.h"
30 #include "xfs_btree.h"
31 #include "xfs_trans.h"
32 #include "xfs_alloc.h"
34 #include "xfs_rmap_btree.h"
35 #include "xfs_trans_space.h"
36 #include "xfs_trace.h"
37 #include "xfs_errortag.h"
39 #include "xfs_inode.h"
42 * Lookup the first record less than or equal to [bno, len, owner, offset]
43 * in the btree given by cur.
47 struct xfs_btree_cur
*cur
,
55 cur
->bc_rec
.r
.rm_startblock
= bno
;
56 cur
->bc_rec
.r
.rm_blockcount
= len
;
57 cur
->bc_rec
.r
.rm_owner
= owner
;
58 cur
->bc_rec
.r
.rm_offset
= offset
;
59 cur
->bc_rec
.r
.rm_flags
= flags
;
60 return xfs_btree_lookup(cur
, XFS_LOOKUP_LE
, stat
);
64 * Lookup the record exactly matching [bno, len, owner, offset]
65 * in the btree given by cur.
69 struct xfs_btree_cur
*cur
,
77 cur
->bc_rec
.r
.rm_startblock
= bno
;
78 cur
->bc_rec
.r
.rm_blockcount
= len
;
79 cur
->bc_rec
.r
.rm_owner
= owner
;
80 cur
->bc_rec
.r
.rm_offset
= offset
;
81 cur
->bc_rec
.r
.rm_flags
= flags
;
82 return xfs_btree_lookup(cur
, XFS_LOOKUP_EQ
, stat
);
86 * Update the record referred to by cur to the value given
87 * by [bno, len, owner, offset].
88 * This either works (return 0) or gets an EFSCORRUPTED error.
92 struct xfs_btree_cur
*cur
,
93 struct xfs_rmap_irec
*irec
)
95 union xfs_btree_rec rec
;
98 trace_xfs_rmap_update(cur
->bc_mp
, cur
->bc_private
.a
.agno
,
99 irec
->rm_startblock
, irec
->rm_blockcount
,
100 irec
->rm_owner
, irec
->rm_offset
, irec
->rm_flags
);
102 rec
.rmap
.rm_startblock
= cpu_to_be32(irec
->rm_startblock
);
103 rec
.rmap
.rm_blockcount
= cpu_to_be32(irec
->rm_blockcount
);
104 rec
.rmap
.rm_owner
= cpu_to_be64(irec
->rm_owner
);
105 rec
.rmap
.rm_offset
= cpu_to_be64(
106 xfs_rmap_irec_offset_pack(irec
));
107 error
= xfs_btree_update(cur
, &rec
);
109 trace_xfs_rmap_update_error(cur
->bc_mp
,
110 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
116 struct xfs_btree_cur
*rcur
,
126 trace_xfs_rmap_insert(rcur
->bc_mp
, rcur
->bc_private
.a
.agno
, agbno
,
127 len
, owner
, offset
, flags
);
129 error
= xfs_rmap_lookup_eq(rcur
, agbno
, len
, owner
, offset
, flags
, &i
);
132 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 0, done
);
134 rcur
->bc_rec
.r
.rm_startblock
= agbno
;
135 rcur
->bc_rec
.r
.rm_blockcount
= len
;
136 rcur
->bc_rec
.r
.rm_owner
= owner
;
137 rcur
->bc_rec
.r
.rm_offset
= offset
;
138 rcur
->bc_rec
.r
.rm_flags
= flags
;
139 error
= xfs_btree_insert(rcur
, &i
);
142 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 1, done
);
145 trace_xfs_rmap_insert_error(rcur
->bc_mp
,
146 rcur
->bc_private
.a
.agno
, error
, _RET_IP_
);
152 struct xfs_btree_cur
*rcur
,
162 trace_xfs_rmap_delete(rcur
->bc_mp
, rcur
->bc_private
.a
.agno
, agbno
,
163 len
, owner
, offset
, flags
);
165 error
= xfs_rmap_lookup_eq(rcur
, agbno
, len
, owner
, offset
, flags
, &i
);
168 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 1, done
);
170 error
= xfs_btree_delete(rcur
, &i
);
173 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 1, done
);
176 trace_xfs_rmap_delete_error(rcur
->bc_mp
,
177 rcur
->bc_private
.a
.agno
, error
, _RET_IP_
);
181 /* Convert an internal btree record to an rmap record. */
183 xfs_rmap_btrec_to_irec(
184 union xfs_btree_rec
*rec
,
185 struct xfs_rmap_irec
*irec
)
188 irec
->rm_startblock
= be32_to_cpu(rec
->rmap
.rm_startblock
);
189 irec
->rm_blockcount
= be32_to_cpu(rec
->rmap
.rm_blockcount
);
190 irec
->rm_owner
= be64_to_cpu(rec
->rmap
.rm_owner
);
191 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec
->rmap
.rm_offset
),
196 * Get the data from the pointed-to record.
200 struct xfs_btree_cur
*cur
,
201 struct xfs_rmap_irec
*irec
,
204 union xfs_btree_rec
*rec
;
207 error
= xfs_btree_get_rec(cur
, &rec
, stat
);
211 return xfs_rmap_btrec_to_irec(rec
, irec
);
214 struct xfs_find_left_neighbor_info
{
215 struct xfs_rmap_irec high
;
216 struct xfs_rmap_irec
*irec
;
220 /* For each rmap given, figure out if it matches the key we want. */
222 xfs_rmap_find_left_neighbor_helper(
223 struct xfs_btree_cur
*cur
,
224 struct xfs_rmap_irec
*rec
,
227 struct xfs_find_left_neighbor_info
*info
= priv
;
229 trace_xfs_rmap_find_left_neighbor_candidate(cur
->bc_mp
,
230 cur
->bc_private
.a
.agno
, rec
->rm_startblock
,
231 rec
->rm_blockcount
, rec
->rm_owner
, rec
->rm_offset
,
234 if (rec
->rm_owner
!= info
->high
.rm_owner
)
235 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
236 if (!XFS_RMAP_NON_INODE_OWNER(rec
->rm_owner
) &&
237 !(rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
) &&
238 rec
->rm_offset
+ rec
->rm_blockcount
- 1 != info
->high
.rm_offset
)
239 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
243 return XFS_BTREE_QUERY_RANGE_ABORT
;
247 * Find the record to the left of the given extent, being careful only to
248 * return a match with the same owner and adjacent physical and logical
252 xfs_rmap_find_left_neighbor(
253 struct xfs_btree_cur
*cur
,
258 struct xfs_rmap_irec
*irec
,
261 struct xfs_find_left_neighbor_info info
;
267 info
.high
.rm_startblock
= bno
- 1;
268 info
.high
.rm_owner
= owner
;
269 if (!XFS_RMAP_NON_INODE_OWNER(owner
) &&
270 !(flags
& XFS_RMAP_BMBT_BLOCK
)) {
273 info
.high
.rm_offset
= offset
- 1;
275 info
.high
.rm_offset
= 0;
276 info
.high
.rm_flags
= flags
;
277 info
.high
.rm_blockcount
= 0;
281 trace_xfs_rmap_find_left_neighbor_query(cur
->bc_mp
,
282 cur
->bc_private
.a
.agno
, bno
, 0, owner
, offset
, flags
);
284 error
= xfs_rmap_query_range(cur
, &info
.high
, &info
.high
,
285 xfs_rmap_find_left_neighbor_helper
, &info
);
286 if (error
== XFS_BTREE_QUERY_RANGE_ABORT
)
289 trace_xfs_rmap_find_left_neighbor_result(cur
->bc_mp
,
290 cur
->bc_private
.a
.agno
, irec
->rm_startblock
,
291 irec
->rm_blockcount
, irec
->rm_owner
,
292 irec
->rm_offset
, irec
->rm_flags
);
296 /* For each rmap given, figure out if it matches the key we want. */
298 xfs_rmap_lookup_le_range_helper(
299 struct xfs_btree_cur
*cur
,
300 struct xfs_rmap_irec
*rec
,
303 struct xfs_find_left_neighbor_info
*info
= priv
;
305 trace_xfs_rmap_lookup_le_range_candidate(cur
->bc_mp
,
306 cur
->bc_private
.a
.agno
, rec
->rm_startblock
,
307 rec
->rm_blockcount
, rec
->rm_owner
, rec
->rm_offset
,
310 if (rec
->rm_owner
!= info
->high
.rm_owner
)
311 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
312 if (!XFS_RMAP_NON_INODE_OWNER(rec
->rm_owner
) &&
313 !(rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
) &&
314 (rec
->rm_offset
> info
->high
.rm_offset
||
315 rec
->rm_offset
+ rec
->rm_blockcount
<= info
->high
.rm_offset
))
316 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
320 return XFS_BTREE_QUERY_RANGE_ABORT
;
324 * Find the record to the left of the given extent, being careful only to
325 * return a match with the same owner and overlapping physical and logical
326 * block ranges. This is the overlapping-interval version of
327 * xfs_rmap_lookup_le.
330 xfs_rmap_lookup_le_range(
331 struct xfs_btree_cur
*cur
,
336 struct xfs_rmap_irec
*irec
,
339 struct xfs_find_left_neighbor_info info
;
342 info
.high
.rm_startblock
= bno
;
343 info
.high
.rm_owner
= owner
;
344 if (!XFS_RMAP_NON_INODE_OWNER(owner
) && !(flags
& XFS_RMAP_BMBT_BLOCK
))
345 info
.high
.rm_offset
= offset
;
347 info
.high
.rm_offset
= 0;
348 info
.high
.rm_flags
= flags
;
349 info
.high
.rm_blockcount
= 0;
354 trace_xfs_rmap_lookup_le_range(cur
->bc_mp
,
355 cur
->bc_private
.a
.agno
, bno
, 0, owner
, offset
, flags
);
356 error
= xfs_rmap_query_range(cur
, &info
.high
, &info
.high
,
357 xfs_rmap_lookup_le_range_helper
, &info
);
358 if (error
== XFS_BTREE_QUERY_RANGE_ABORT
)
361 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
362 cur
->bc_private
.a
.agno
, irec
->rm_startblock
,
363 irec
->rm_blockcount
, irec
->rm_owner
,
364 irec
->rm_offset
, irec
->rm_flags
);
369 * Perform all the relevant owner checks for a removal op. If we're doing an
370 * unknown-owner removal then we have no owner information to check.
373 xfs_rmap_free_check_owner(
374 struct xfs_mount
*mp
,
376 struct xfs_rmap_irec
*rec
,
384 if (owner
== XFS_RMAP_OWN_UNKNOWN
)
387 /* Make sure the unwritten flag matches. */
388 XFS_WANT_CORRUPTED_GOTO(mp
, (flags
& XFS_RMAP_UNWRITTEN
) ==
389 (rec
->rm_flags
& XFS_RMAP_UNWRITTEN
), out
);
391 /* Make sure the owner matches what we expect to find in the tree. */
392 XFS_WANT_CORRUPTED_GOTO(mp
, owner
== rec
->rm_owner
, out
);
394 /* Check the offset, if necessary. */
395 if (XFS_RMAP_NON_INODE_OWNER(owner
))
398 if (flags
& XFS_RMAP_BMBT_BLOCK
) {
399 XFS_WANT_CORRUPTED_GOTO(mp
, rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
,
402 XFS_WANT_CORRUPTED_GOTO(mp
, rec
->rm_offset
<= offset
, out
);
403 XFS_WANT_CORRUPTED_GOTO(mp
,
404 ltoff
+ rec
->rm_blockcount
>= offset
+ len
,
413 * Find the extent in the rmap btree and remove it.
415 * The record we find should always be an exact match for the extent that we're
416 * looking for, since we insert them into the btree without modification.
418 * Special Case #1: when growing the filesystem, we "free" an extent when
419 * growing the last AG. This extent is new space and so it is not tracked as
420 * used space in the btree. The growfs code will pass in an owner of
421 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
422 * extent. We verify that - the extent lookup result in a record that does not
425 * Special Case #2: EFIs do not record the owner of the extent, so when
426 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
427 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
428 * corruption checks during log recovery.
432 struct xfs_btree_cur
*cur
,
436 struct xfs_owner_info
*oinfo
)
438 struct xfs_mount
*mp
= cur
->bc_mp
;
439 struct xfs_rmap_irec ltrec
;
448 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
449 ignore_off
= XFS_RMAP_NON_INODE_OWNER(owner
) ||
450 (flags
& XFS_RMAP_BMBT_BLOCK
);
452 flags
|= XFS_RMAP_UNWRITTEN
;
453 trace_xfs_rmap_unmap(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
457 * We should always have a left record because there's a static record
458 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
459 * will not ever be removed from the tree.
461 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
, &i
);
464 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
466 error
= xfs_rmap_get_rec(cur
, <rec
, &i
);
469 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
470 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
471 cur
->bc_private
.a
.agno
, ltrec
.rm_startblock
,
472 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
473 ltrec
.rm_offset
, ltrec
.rm_flags
);
474 ltoff
= ltrec
.rm_offset
;
477 * For growfs, the incoming extent must be beyond the left record we
478 * just found as it is new space and won't be used by anyone. This is
479 * just a corruption check as we don't actually do anything with this
480 * extent. Note that we need to use >= instead of > because it might
481 * be the case that the "left" extent goes all the way to EOFS.
483 if (owner
== XFS_RMAP_OWN_NULL
) {
484 XFS_WANT_CORRUPTED_GOTO(mp
, bno
>= ltrec
.rm_startblock
+
485 ltrec
.rm_blockcount
, out_error
);
490 * If we're doing an unknown-owner removal for EFI recovery, we expect
491 * to find the full range in the rmapbt or nothing at all. If we
492 * don't find any rmaps overlapping either end of the range, we're
493 * done. Hopefully this means that the EFI creator already queued
494 * (and finished) a RUI to remove the rmap.
496 if (owner
== XFS_RMAP_OWN_UNKNOWN
&&
497 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
<= bno
) {
498 struct xfs_rmap_irec rtrec
;
500 error
= xfs_btree_increment(cur
, 0, &i
);
505 error
= xfs_rmap_get_rec(cur
, &rtrec
, &i
);
508 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
509 if (rtrec
.rm_startblock
>= bno
+ len
)
513 /* Make sure the extent we found covers the entire freeing range. */
514 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_startblock
<= bno
&&
515 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
>=
516 bno
+ len
, out_error
);
518 /* Check owner information. */
519 error
= xfs_rmap_free_check_owner(mp
, ltoff
, <rec
, len
, owner
,
524 if (ltrec
.rm_startblock
== bno
&& ltrec
.rm_blockcount
== len
) {
525 /* exact match, simply remove the record from rmap tree */
526 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
527 ltrec
.rm_startblock
, ltrec
.rm_blockcount
,
528 ltrec
.rm_owner
, ltrec
.rm_offset
,
530 error
= xfs_btree_delete(cur
, &i
);
533 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
534 } else if (ltrec
.rm_startblock
== bno
) {
536 * overlap left hand side of extent: move the start, trim the
537 * length and update the current record.
540 * Orig: |oooooooooooooooooooo|
541 * Freeing: |fffffffff|
542 * Result: |rrrrrrrrrr|
545 ltrec
.rm_startblock
+= len
;
546 ltrec
.rm_blockcount
-= len
;
548 ltrec
.rm_offset
+= len
;
549 error
= xfs_rmap_update(cur
, <rec
);
552 } else if (ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
+ len
) {
554 * overlap right hand side of extent: trim the length and update
555 * the current record.
558 * Orig: |oooooooooooooooooooo|
559 * Freeing: |fffffffff|
560 * Result: |rrrrrrrrrr|
563 ltrec
.rm_blockcount
-= len
;
564 error
= xfs_rmap_update(cur
, <rec
);
570 * overlap middle of extent: trim the length of the existing
571 * record to the length of the new left-extent size, increment
572 * the insertion position so we can insert a new record
573 * containing the remaining right-extent space.
576 * Orig: |oooooooooooooooooooo|
577 * Freeing: |fffffffff|
578 * Result: |rrrrr| |rrrr|
581 xfs_extlen_t orig_len
= ltrec
.rm_blockcount
;
583 ltrec
.rm_blockcount
= bno
- ltrec
.rm_startblock
;
584 error
= xfs_rmap_update(cur
, <rec
);
588 error
= xfs_btree_increment(cur
, 0, &i
);
592 cur
->bc_rec
.r
.rm_startblock
= bno
+ len
;
593 cur
->bc_rec
.r
.rm_blockcount
= orig_len
- len
-
595 cur
->bc_rec
.r
.rm_owner
= ltrec
.rm_owner
;
597 cur
->bc_rec
.r
.rm_offset
= 0;
599 cur
->bc_rec
.r
.rm_offset
= offset
+ len
;
600 cur
->bc_rec
.r
.rm_flags
= flags
;
601 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
,
602 cur
->bc_rec
.r
.rm_startblock
,
603 cur
->bc_rec
.r
.rm_blockcount
,
604 cur
->bc_rec
.r
.rm_owner
,
605 cur
->bc_rec
.r
.rm_offset
,
606 cur
->bc_rec
.r
.rm_flags
);
607 error
= xfs_btree_insert(cur
, &i
);
613 trace_xfs_rmap_unmap_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
617 trace_xfs_rmap_unmap_error(mp
, cur
->bc_private
.a
.agno
,
623 * Remove a reference to an extent in the rmap btree.
627 struct xfs_trans
*tp
,
628 struct xfs_buf
*agbp
,
632 struct xfs_owner_info
*oinfo
)
634 struct xfs_mount
*mp
= tp
->t_mountp
;
635 struct xfs_btree_cur
*cur
;
638 if (!xfs_sb_version_hasrmapbt(&mp
->m_sb
))
641 cur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
643 error
= xfs_rmap_unmap(cur
, bno
, len
, false, oinfo
);
647 xfs_btree_del_cursor(cur
, XFS_BTREE_NOERROR
);
651 xfs_btree_del_cursor(cur
, XFS_BTREE_ERROR
);
656 * A mergeable rmap must have the same owner and the same values for
657 * the unwritten, attr_fork, and bmbt flags. The startblock and
658 * offset are checked separately.
661 xfs_rmap_is_mergeable(
662 struct xfs_rmap_irec
*irec
,
666 if (irec
->rm_owner
== XFS_RMAP_OWN_NULL
)
668 if (irec
->rm_owner
!= owner
)
670 if ((flags
& XFS_RMAP_UNWRITTEN
) ^
671 (irec
->rm_flags
& XFS_RMAP_UNWRITTEN
))
673 if ((flags
& XFS_RMAP_ATTR_FORK
) ^
674 (irec
->rm_flags
& XFS_RMAP_ATTR_FORK
))
676 if ((flags
& XFS_RMAP_BMBT_BLOCK
) ^
677 (irec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
))
683 * When we allocate a new block, the first thing we do is add a reference to
684 * the extent in the rmap btree. This takes the form of a [agbno, length,
685 * owner, offset] record. Flags are encoded in the high bits of the offset
690 struct xfs_btree_cur
*cur
,
694 struct xfs_owner_info
*oinfo
)
696 struct xfs_mount
*mp
= cur
->bc_mp
;
697 struct xfs_rmap_irec ltrec
;
698 struct xfs_rmap_irec gtrec
;
705 unsigned int flags
= 0;
708 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
710 ignore_off
= XFS_RMAP_NON_INODE_OWNER(owner
) ||
711 (flags
& XFS_RMAP_BMBT_BLOCK
);
713 flags
|= XFS_RMAP_UNWRITTEN
;
714 trace_xfs_rmap_map(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
716 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo
));
719 * For the initial lookup, look for an exact match or the left-adjacent
720 * record for our insertion point. This will also give us the record for
721 * start block contiguity tests.
723 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
,
727 XFS_WANT_CORRUPTED_GOTO(mp
, have_lt
== 1, out_error
);
729 error
= xfs_rmap_get_rec(cur
, <rec
, &have_lt
);
732 XFS_WANT_CORRUPTED_GOTO(mp
, have_lt
== 1, out_error
);
733 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
734 cur
->bc_private
.a
.agno
, ltrec
.rm_startblock
,
735 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
736 ltrec
.rm_offset
, ltrec
.rm_flags
);
738 if (!xfs_rmap_is_mergeable(<rec
, owner
, flags
))
741 XFS_WANT_CORRUPTED_GOTO(mp
,
743 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
<= bno
, out_error
);
746 * Increment the cursor to see if we have a right-adjacent record to our
747 * insertion point. This will give us the record for end block
750 error
= xfs_btree_increment(cur
, 0, &have_gt
);
754 error
= xfs_rmap_get_rec(cur
, >rec
, &have_gt
);
757 XFS_WANT_CORRUPTED_GOTO(mp
, have_gt
== 1, out_error
);
758 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= gtrec
.rm_startblock
,
760 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
761 cur
->bc_private
.a
.agno
, gtrec
.rm_startblock
,
762 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
763 gtrec
.rm_offset
, gtrec
.rm_flags
);
764 if (!xfs_rmap_is_mergeable(>rec
, owner
, flags
))
769 * Note: cursor currently points one record to the right of ltrec, even
770 * if there is no record in the tree to the right.
773 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
&&
774 (ignore_off
|| ltrec
.rm_offset
+ ltrec
.rm_blockcount
== offset
)) {
776 * left edge contiguous, merge into left record.
780 * adding: |aaaaaaaaa|
781 * result: |rrrrrrrrrrrrrrrrrrr|
784 ltrec
.rm_blockcount
+= len
;
786 bno
+ len
== gtrec
.rm_startblock
&&
787 (ignore_off
|| offset
+ len
== gtrec
.rm_offset
) &&
788 (unsigned long)ltrec
.rm_blockcount
+ len
+
789 gtrec
.rm_blockcount
<= XFS_RMAP_LEN_MAX
) {
791 * right edge also contiguous, delete right record
792 * and merge into left record.
794 * ltbno ltlen gtbno gtlen
795 * orig: |ooooooooo| |ooooooooo|
796 * adding: |aaaaaaaaa|
797 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
799 ltrec
.rm_blockcount
+= gtrec
.rm_blockcount
;
800 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
806 error
= xfs_btree_delete(cur
, &i
);
809 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
812 /* point the cursor back to the left record and update */
813 error
= xfs_btree_decrement(cur
, 0, &have_gt
);
816 error
= xfs_rmap_update(cur
, <rec
);
819 } else if (have_gt
&&
820 bno
+ len
== gtrec
.rm_startblock
&&
821 (ignore_off
|| offset
+ len
== gtrec
.rm_offset
)) {
823 * right edge contiguous, merge into right record.
827 * adding: |aaaaaaaaa|
828 * Result: |rrrrrrrrrrrrrrrrrrr|
831 gtrec
.rm_startblock
= bno
;
832 gtrec
.rm_blockcount
+= len
;
834 gtrec
.rm_offset
= offset
;
835 error
= xfs_rmap_update(cur
, >rec
);
840 * no contiguous edge with identical owner, insert
841 * new record at current cursor position.
843 cur
->bc_rec
.r
.rm_startblock
= bno
;
844 cur
->bc_rec
.r
.rm_blockcount
= len
;
845 cur
->bc_rec
.r
.rm_owner
= owner
;
846 cur
->bc_rec
.r
.rm_offset
= offset
;
847 cur
->bc_rec
.r
.rm_flags
= flags
;
848 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
849 owner
, offset
, flags
);
850 error
= xfs_btree_insert(cur
, &i
);
853 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
856 trace_xfs_rmap_map_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
860 trace_xfs_rmap_map_error(mp
, cur
->bc_private
.a
.agno
,
866 * Add a reference to an extent in the rmap btree.
870 struct xfs_trans
*tp
,
871 struct xfs_buf
*agbp
,
875 struct xfs_owner_info
*oinfo
)
877 struct xfs_mount
*mp
= tp
->t_mountp
;
878 struct xfs_btree_cur
*cur
;
881 if (!xfs_sb_version_hasrmapbt(&mp
->m_sb
))
884 cur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
885 error
= xfs_rmap_map(cur
, bno
, len
, false, oinfo
);
889 xfs_btree_del_cursor(cur
, XFS_BTREE_NOERROR
);
893 xfs_btree_del_cursor(cur
, XFS_BTREE_ERROR
);
897 #define RMAP_LEFT_CONTIG (1 << 0)
898 #define RMAP_RIGHT_CONTIG (1 << 1)
899 #define RMAP_LEFT_FILLING (1 << 2)
900 #define RMAP_RIGHT_FILLING (1 << 3)
901 #define RMAP_LEFT_VALID (1 << 6)
902 #define RMAP_RIGHT_VALID (1 << 7)
910 * Convert an unwritten extent to a real extent or vice versa.
911 * Does not handle overlapping extents.
915 struct xfs_btree_cur
*cur
,
919 struct xfs_owner_info
*oinfo
)
921 struct xfs_mount
*mp
= cur
->bc_mp
;
922 struct xfs_rmap_irec r
[4]; /* neighbor extent entries */
923 /* left is 0, right is 1, prev is 2 */
930 unsigned int flags
= 0;
935 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
936 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner
) ||
937 (flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
))));
938 oldext
= unwritten
? XFS_RMAP_UNWRITTEN
: 0;
939 new_endoff
= offset
+ len
;
940 trace_xfs_rmap_convert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
944 * For the initial lookup, look for an exact match or the left-adjacent
945 * record for our insertion point. This will also give us the record for
946 * start block contiguity tests.
948 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, oldext
, &i
);
951 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
953 error
= xfs_rmap_get_rec(cur
, &PREV
, &i
);
956 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
957 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
958 cur
->bc_private
.a
.agno
, PREV
.rm_startblock
,
959 PREV
.rm_blockcount
, PREV
.rm_owner
,
960 PREV
.rm_offset
, PREV
.rm_flags
);
962 ASSERT(PREV
.rm_offset
<= offset
);
963 ASSERT(PREV
.rm_offset
+ PREV
.rm_blockcount
>= new_endoff
);
964 ASSERT((PREV
.rm_flags
& XFS_RMAP_UNWRITTEN
) == oldext
);
965 newext
= ~oldext
& XFS_RMAP_UNWRITTEN
;
968 * Set flags determining what part of the previous oldext allocation
969 * extent is being replaced by a newext allocation.
971 if (PREV
.rm_offset
== offset
)
972 state
|= RMAP_LEFT_FILLING
;
973 if (PREV
.rm_offset
+ PREV
.rm_blockcount
== new_endoff
)
974 state
|= RMAP_RIGHT_FILLING
;
977 * Decrement the cursor to see if we have a left-adjacent record to our
978 * insertion point. This will give us the record for end block
981 error
= xfs_btree_decrement(cur
, 0, &i
);
985 state
|= RMAP_LEFT_VALID
;
986 error
= xfs_rmap_get_rec(cur
, &LEFT
, &i
);
989 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
990 XFS_WANT_CORRUPTED_GOTO(mp
,
991 LEFT
.rm_startblock
+ LEFT
.rm_blockcount
<= bno
,
993 trace_xfs_rmap_find_left_neighbor_result(cur
->bc_mp
,
994 cur
->bc_private
.a
.agno
, LEFT
.rm_startblock
,
995 LEFT
.rm_blockcount
, LEFT
.rm_owner
,
996 LEFT
.rm_offset
, LEFT
.rm_flags
);
997 if (LEFT
.rm_startblock
+ LEFT
.rm_blockcount
== bno
&&
998 LEFT
.rm_offset
+ LEFT
.rm_blockcount
== offset
&&
999 xfs_rmap_is_mergeable(&LEFT
, owner
, newext
))
1000 state
|= RMAP_LEFT_CONTIG
;
1004 * Increment the cursor to see if we have a right-adjacent record to our
1005 * insertion point. This will give us the record for end block
1008 error
= xfs_btree_increment(cur
, 0, &i
);
1011 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1012 error
= xfs_btree_increment(cur
, 0, &i
);
1016 state
|= RMAP_RIGHT_VALID
;
1017 error
= xfs_rmap_get_rec(cur
, &RIGHT
, &i
);
1020 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1021 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= RIGHT
.rm_startblock
,
1023 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1024 cur
->bc_private
.a
.agno
, RIGHT
.rm_startblock
,
1025 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1026 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1027 if (bno
+ len
== RIGHT
.rm_startblock
&&
1028 offset
+ len
== RIGHT
.rm_offset
&&
1029 xfs_rmap_is_mergeable(&RIGHT
, owner
, newext
))
1030 state
|= RMAP_RIGHT_CONTIG
;
1033 /* check that left + prev + right is not too long */
1034 if ((state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1035 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) ==
1036 (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1037 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
) &&
1038 (unsigned long)LEFT
.rm_blockcount
+ len
+
1039 RIGHT
.rm_blockcount
> XFS_RMAP_LEN_MAX
)
1040 state
&= ~RMAP_RIGHT_CONTIG
;
1042 trace_xfs_rmap_convert_state(mp
, cur
->bc_private
.a
.agno
, state
,
1045 /* reset the cursor back to PREV */
1046 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, oldext
, &i
);
1049 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1052 * Switch out based on the FILLING and CONTIG state bits.
1054 switch (state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1055 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) {
1056 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1057 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1059 * Setting all of a previous oldext extent to newext.
1060 * The left and right neighbors are both contiguous with new.
1062 error
= xfs_btree_increment(cur
, 0, &i
);
1065 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1066 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1067 RIGHT
.rm_startblock
, RIGHT
.rm_blockcount
,
1068 RIGHT
.rm_owner
, RIGHT
.rm_offset
,
1070 error
= xfs_btree_delete(cur
, &i
);
1073 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1074 error
= xfs_btree_decrement(cur
, 0, &i
);
1077 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1078 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1079 PREV
.rm_startblock
, PREV
.rm_blockcount
,
1080 PREV
.rm_owner
, PREV
.rm_offset
,
1082 error
= xfs_btree_delete(cur
, &i
);
1085 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1086 error
= xfs_btree_decrement(cur
, 0, &i
);
1089 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1091 NEW
.rm_blockcount
+= PREV
.rm_blockcount
+ RIGHT
.rm_blockcount
;
1092 error
= xfs_rmap_update(cur
, &NEW
);
1097 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1099 * Setting all of a previous oldext extent to newext.
1100 * The left neighbor is contiguous, the right is not.
1102 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1103 PREV
.rm_startblock
, PREV
.rm_blockcount
,
1104 PREV
.rm_owner
, PREV
.rm_offset
,
1106 error
= xfs_btree_delete(cur
, &i
);
1109 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1110 error
= xfs_btree_decrement(cur
, 0, &i
);
1113 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1115 NEW
.rm_blockcount
+= PREV
.rm_blockcount
;
1116 error
= xfs_rmap_update(cur
, &NEW
);
1121 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1123 * Setting all of a previous oldext extent to newext.
1124 * The right neighbor is contiguous, the left is not.
1126 error
= xfs_btree_increment(cur
, 0, &i
);
1129 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1130 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1131 RIGHT
.rm_startblock
, RIGHT
.rm_blockcount
,
1132 RIGHT
.rm_owner
, RIGHT
.rm_offset
,
1134 error
= xfs_btree_delete(cur
, &i
);
1137 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1138 error
= xfs_btree_decrement(cur
, 0, &i
);
1141 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1143 NEW
.rm_blockcount
= len
+ RIGHT
.rm_blockcount
;
1144 NEW
.rm_flags
= newext
;
1145 error
= xfs_rmap_update(cur
, &NEW
);
1150 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
:
1152 * Setting all of a previous oldext extent to newext.
1153 * Neither the left nor right neighbors are contiguous with
1157 NEW
.rm_flags
= newext
;
1158 error
= xfs_rmap_update(cur
, &NEW
);
1163 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
:
1165 * Setting the first part of a previous oldext extent to newext.
1166 * The left neighbor is contiguous.
1169 NEW
.rm_offset
+= len
;
1170 NEW
.rm_startblock
+= len
;
1171 NEW
.rm_blockcount
-= len
;
1172 error
= xfs_rmap_update(cur
, &NEW
);
1175 error
= xfs_btree_decrement(cur
, 0, &i
);
1179 NEW
.rm_blockcount
+= len
;
1180 error
= xfs_rmap_update(cur
, &NEW
);
1185 case RMAP_LEFT_FILLING
:
1187 * Setting the first part of a previous oldext extent to newext.
1188 * The left neighbor is not contiguous.
1191 NEW
.rm_startblock
+= len
;
1192 NEW
.rm_offset
+= len
;
1193 NEW
.rm_blockcount
-= len
;
1194 error
= xfs_rmap_update(cur
, &NEW
);
1197 NEW
.rm_startblock
= bno
;
1198 NEW
.rm_owner
= owner
;
1199 NEW
.rm_offset
= offset
;
1200 NEW
.rm_blockcount
= len
;
1201 NEW
.rm_flags
= newext
;
1202 cur
->bc_rec
.r
= NEW
;
1203 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
,
1204 len
, owner
, offset
, newext
);
1205 error
= xfs_btree_insert(cur
, &i
);
1208 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1211 case RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1213 * Setting the last part of a previous oldext extent to newext.
1214 * The right neighbor is contiguous with the new allocation.
1217 NEW
.rm_blockcount
-= len
;
1218 error
= xfs_rmap_update(cur
, &NEW
);
1221 error
= xfs_btree_increment(cur
, 0, &i
);
1225 NEW
.rm_offset
= offset
;
1226 NEW
.rm_startblock
= bno
;
1227 NEW
.rm_blockcount
+= len
;
1228 error
= xfs_rmap_update(cur
, &NEW
);
1233 case RMAP_RIGHT_FILLING
:
1235 * Setting the last part of a previous oldext extent to newext.
1236 * The right neighbor is not contiguous.
1239 NEW
.rm_blockcount
-= len
;
1240 error
= xfs_rmap_update(cur
, &NEW
);
1243 error
= xfs_rmap_lookup_eq(cur
, bno
, len
, owner
, offset
,
1247 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 0, done
);
1248 NEW
.rm_startblock
= bno
;
1249 NEW
.rm_owner
= owner
;
1250 NEW
.rm_offset
= offset
;
1251 NEW
.rm_blockcount
= len
;
1252 NEW
.rm_flags
= newext
;
1253 cur
->bc_rec
.r
= NEW
;
1254 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
,
1255 len
, owner
, offset
, newext
);
1256 error
= xfs_btree_insert(cur
, &i
);
1259 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1264 * Setting the middle part of a previous oldext extent to
1265 * newext. Contiguity is impossible here.
1266 * One extent becomes three extents.
1268 /* new right extent - oldext */
1269 NEW
.rm_startblock
= bno
+ len
;
1270 NEW
.rm_owner
= owner
;
1271 NEW
.rm_offset
= new_endoff
;
1272 NEW
.rm_blockcount
= PREV
.rm_offset
+ PREV
.rm_blockcount
-
1274 NEW
.rm_flags
= PREV
.rm_flags
;
1275 error
= xfs_rmap_update(cur
, &NEW
);
1278 /* new left extent - oldext */
1280 NEW
.rm_blockcount
= offset
- PREV
.rm_offset
;
1281 cur
->bc_rec
.r
= NEW
;
1282 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
,
1283 NEW
.rm_startblock
, NEW
.rm_blockcount
,
1284 NEW
.rm_owner
, NEW
.rm_offset
,
1286 error
= xfs_btree_insert(cur
, &i
);
1289 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1291 * Reset the cursor to the position of the new extent
1292 * we are about to insert as we can't trust it after
1293 * the previous insert.
1295 error
= xfs_rmap_lookup_eq(cur
, bno
, len
, owner
, offset
,
1299 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 0, done
);
1300 /* new middle extent - newext */
1301 cur
->bc_rec
.r
.rm_flags
&= ~XFS_RMAP_UNWRITTEN
;
1302 cur
->bc_rec
.r
.rm_flags
|= newext
;
1303 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1304 owner
, offset
, newext
);
1305 error
= xfs_btree_insert(cur
, &i
);
1308 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1311 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1312 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1313 case RMAP_LEFT_FILLING
| RMAP_RIGHT_CONTIG
:
1314 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1315 case RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1316 case RMAP_LEFT_CONTIG
:
1317 case RMAP_RIGHT_CONTIG
:
1319 * These cases are all impossible.
1324 trace_xfs_rmap_convert_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1328 trace_xfs_rmap_convert_error(cur
->bc_mp
,
1329 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1334 * Convert an unwritten extent to a real extent or vice versa. If there is no
1335 * possibility of overlapping extents, delegate to the simpler convert
1339 xfs_rmap_convert_shared(
1340 struct xfs_btree_cur
*cur
,
1344 struct xfs_owner_info
*oinfo
)
1346 struct xfs_mount
*mp
= cur
->bc_mp
;
1347 struct xfs_rmap_irec r
[4]; /* neighbor extent entries */
1348 /* left is 0, right is 1, prev is 2 */
1352 uint64_t new_endoff
;
1353 unsigned int oldext
;
1354 unsigned int newext
;
1355 unsigned int flags
= 0;
1360 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1361 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner
) ||
1362 (flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
))));
1363 oldext
= unwritten
? XFS_RMAP_UNWRITTEN
: 0;
1364 new_endoff
= offset
+ len
;
1365 trace_xfs_rmap_convert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1369 * For the initial lookup, look for and exact match or the left-adjacent
1370 * record for our insertion point. This will also give us the record for
1371 * start block contiguity tests.
1373 error
= xfs_rmap_lookup_le_range(cur
, bno
, owner
, offset
, flags
,
1377 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1379 ASSERT(PREV
.rm_offset
<= offset
);
1380 ASSERT(PREV
.rm_offset
+ PREV
.rm_blockcount
>= new_endoff
);
1381 ASSERT((PREV
.rm_flags
& XFS_RMAP_UNWRITTEN
) == oldext
);
1382 newext
= ~oldext
& XFS_RMAP_UNWRITTEN
;
1385 * Set flags determining what part of the previous oldext allocation
1386 * extent is being replaced by a newext allocation.
1388 if (PREV
.rm_offset
== offset
)
1389 state
|= RMAP_LEFT_FILLING
;
1390 if (PREV
.rm_offset
+ PREV
.rm_blockcount
== new_endoff
)
1391 state
|= RMAP_RIGHT_FILLING
;
1393 /* Is there a left record that abuts our range? */
1394 error
= xfs_rmap_find_left_neighbor(cur
, bno
, owner
, offset
, newext
,
1399 state
|= RMAP_LEFT_VALID
;
1400 XFS_WANT_CORRUPTED_GOTO(mp
,
1401 LEFT
.rm_startblock
+ LEFT
.rm_blockcount
<= bno
,
1403 if (xfs_rmap_is_mergeable(&LEFT
, owner
, newext
))
1404 state
|= RMAP_LEFT_CONTIG
;
1407 /* Is there a right record that abuts our range? */
1408 error
= xfs_rmap_lookup_eq(cur
, bno
+ len
, len
, owner
, offset
+ len
,
1413 state
|= RMAP_RIGHT_VALID
;
1414 error
= xfs_rmap_get_rec(cur
, &RIGHT
, &i
);
1417 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1418 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= RIGHT
.rm_startblock
,
1420 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1421 cur
->bc_private
.a
.agno
, RIGHT
.rm_startblock
,
1422 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1423 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1424 if (xfs_rmap_is_mergeable(&RIGHT
, owner
, newext
))
1425 state
|= RMAP_RIGHT_CONTIG
;
1428 /* check that left + prev + right is not too long */
1429 if ((state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1430 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) ==
1431 (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1432 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
) &&
1433 (unsigned long)LEFT
.rm_blockcount
+ len
+
1434 RIGHT
.rm_blockcount
> XFS_RMAP_LEN_MAX
)
1435 state
&= ~RMAP_RIGHT_CONTIG
;
1437 trace_xfs_rmap_convert_state(mp
, cur
->bc_private
.a
.agno
, state
,
1440 * Switch out based on the FILLING and CONTIG state bits.
1442 switch (state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1443 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) {
1444 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1445 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1447 * Setting all of a previous oldext extent to newext.
1448 * The left and right neighbors are both contiguous with new.
1450 error
= xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1451 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1452 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1455 error
= xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1456 PREV
.rm_blockcount
, PREV
.rm_owner
,
1457 PREV
.rm_offset
, PREV
.rm_flags
);
1461 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1462 NEW
.rm_blockcount
, NEW
.rm_owner
,
1463 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1466 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1467 NEW
.rm_blockcount
+= PREV
.rm_blockcount
+ RIGHT
.rm_blockcount
;
1468 error
= xfs_rmap_update(cur
, &NEW
);
1473 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1475 * Setting all of a previous oldext extent to newext.
1476 * The left neighbor is contiguous, the right is not.
1478 error
= xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1479 PREV
.rm_blockcount
, PREV
.rm_owner
,
1480 PREV
.rm_offset
, PREV
.rm_flags
);
1484 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1485 NEW
.rm_blockcount
, NEW
.rm_owner
,
1486 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1489 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1490 NEW
.rm_blockcount
+= PREV
.rm_blockcount
;
1491 error
= xfs_rmap_update(cur
, &NEW
);
1496 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1498 * Setting all of a previous oldext extent to newext.
1499 * The right neighbor is contiguous, the left is not.
1501 error
= xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1502 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1503 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1507 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1508 NEW
.rm_blockcount
, NEW
.rm_owner
,
1509 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1512 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1513 NEW
.rm_blockcount
+= RIGHT
.rm_blockcount
;
1514 NEW
.rm_flags
= RIGHT
.rm_flags
;
1515 error
= xfs_rmap_update(cur
, &NEW
);
1520 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
:
1522 * Setting all of a previous oldext extent to newext.
1523 * Neither the left nor right neighbors are contiguous with
1527 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1528 NEW
.rm_blockcount
, NEW
.rm_owner
,
1529 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1532 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1533 NEW
.rm_flags
= newext
;
1534 error
= xfs_rmap_update(cur
, &NEW
);
1539 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
:
1541 * Setting the first part of a previous oldext extent to newext.
1542 * The left neighbor is contiguous.
1545 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1546 NEW
.rm_blockcount
, NEW
.rm_owner
,
1547 NEW
.rm_offset
, NEW
.rm_flags
);
1550 NEW
.rm_offset
+= len
;
1551 NEW
.rm_startblock
+= len
;
1552 NEW
.rm_blockcount
-= len
;
1553 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1554 NEW
.rm_blockcount
, NEW
.rm_owner
,
1555 NEW
.rm_offset
, NEW
.rm_flags
);
1559 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1560 NEW
.rm_blockcount
, NEW
.rm_owner
,
1561 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1564 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1565 NEW
.rm_blockcount
+= len
;
1566 error
= xfs_rmap_update(cur
, &NEW
);
1571 case RMAP_LEFT_FILLING
:
1573 * Setting the first part of a previous oldext extent to newext.
1574 * The left neighbor is not contiguous.
1577 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1578 NEW
.rm_blockcount
, NEW
.rm_owner
,
1579 NEW
.rm_offset
, NEW
.rm_flags
);
1582 NEW
.rm_offset
+= len
;
1583 NEW
.rm_startblock
+= len
;
1584 NEW
.rm_blockcount
-= len
;
1585 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1586 NEW
.rm_blockcount
, NEW
.rm_owner
,
1587 NEW
.rm_offset
, NEW
.rm_flags
);
1590 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1595 case RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1597 * Setting the last part of a previous oldext extent to newext.
1598 * The right neighbor is contiguous with the new allocation.
1601 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1602 NEW
.rm_blockcount
, NEW
.rm_owner
,
1603 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1606 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1607 NEW
.rm_blockcount
= offset
- NEW
.rm_offset
;
1608 error
= xfs_rmap_update(cur
, &NEW
);
1612 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1613 NEW
.rm_blockcount
, NEW
.rm_owner
,
1614 NEW
.rm_offset
, NEW
.rm_flags
);
1617 NEW
.rm_offset
= offset
;
1618 NEW
.rm_startblock
= bno
;
1619 NEW
.rm_blockcount
+= len
;
1620 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1621 NEW
.rm_blockcount
, NEW
.rm_owner
,
1622 NEW
.rm_offset
, NEW
.rm_flags
);
1627 case RMAP_RIGHT_FILLING
:
1629 * Setting the last part of a previous oldext extent to newext.
1630 * The right neighbor is not contiguous.
1633 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1634 NEW
.rm_blockcount
, NEW
.rm_owner
,
1635 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1638 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1639 NEW
.rm_blockcount
-= len
;
1640 error
= xfs_rmap_update(cur
, &NEW
);
1643 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1650 * Setting the middle part of a previous oldext extent to
1651 * newext. Contiguity is impossible here.
1652 * One extent becomes three extents.
1654 /* new right extent - oldext */
1655 NEW
.rm_startblock
= bno
+ len
;
1656 NEW
.rm_owner
= owner
;
1657 NEW
.rm_offset
= new_endoff
;
1658 NEW
.rm_blockcount
= PREV
.rm_offset
+ PREV
.rm_blockcount
-
1660 NEW
.rm_flags
= PREV
.rm_flags
;
1661 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1662 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
1666 /* new left extent - oldext */
1668 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1669 NEW
.rm_blockcount
, NEW
.rm_owner
,
1670 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1673 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1674 NEW
.rm_blockcount
= offset
- NEW
.rm_offset
;
1675 error
= xfs_rmap_update(cur
, &NEW
);
1678 /* new middle extent - newext */
1679 NEW
.rm_startblock
= bno
;
1680 NEW
.rm_blockcount
= len
;
1681 NEW
.rm_owner
= owner
;
1682 NEW
.rm_offset
= offset
;
1683 NEW
.rm_flags
= newext
;
1684 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1685 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
1691 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1692 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1693 case RMAP_LEFT_FILLING
| RMAP_RIGHT_CONTIG
:
1694 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1695 case RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1696 case RMAP_LEFT_CONTIG
:
1697 case RMAP_RIGHT_CONTIG
:
1699 * These cases are all impossible.
1704 trace_xfs_rmap_convert_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1708 trace_xfs_rmap_convert_error(cur
->bc_mp
,
1709 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1719 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1720 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1721 * that the prev/next records in the btree might belong to another owner.
1722 * Therefore we must use delete+insert to alter any of the key fields.
1724 * For every other situation there can only be one owner for a given extent,
1725 * so we can call the regular _free function.
1728 xfs_rmap_unmap_shared(
1729 struct xfs_btree_cur
*cur
,
1733 struct xfs_owner_info
*oinfo
)
1735 struct xfs_mount
*mp
= cur
->bc_mp
;
1736 struct xfs_rmap_irec ltrec
;
1744 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1746 flags
|= XFS_RMAP_UNWRITTEN
;
1747 trace_xfs_rmap_unmap(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1751 * We should always have a left record because there's a static record
1752 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1753 * will not ever be removed from the tree.
1755 error
= xfs_rmap_lookup_le_range(cur
, bno
, owner
, offset
, flags
,
1759 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1760 ltoff
= ltrec
.rm_offset
;
1762 /* Make sure the extent we found covers the entire freeing range. */
1763 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_startblock
<= bno
&&
1764 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
>=
1765 bno
+ len
, out_error
);
1767 /* Make sure the owner matches what we expect to find in the tree. */
1768 XFS_WANT_CORRUPTED_GOTO(mp
, owner
== ltrec
.rm_owner
, out_error
);
1770 /* Make sure the unwritten flag matches. */
1771 XFS_WANT_CORRUPTED_GOTO(mp
, (flags
& XFS_RMAP_UNWRITTEN
) ==
1772 (ltrec
.rm_flags
& XFS_RMAP_UNWRITTEN
), out_error
);
1774 /* Check the offset. */
1775 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_offset
<= offset
, out_error
);
1776 XFS_WANT_CORRUPTED_GOTO(mp
, offset
<= ltoff
+ ltrec
.rm_blockcount
,
1779 if (ltrec
.rm_startblock
== bno
&& ltrec
.rm_blockcount
== len
) {
1780 /* Exact match, simply remove the record from rmap tree. */
1781 error
= xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
1782 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1783 ltrec
.rm_offset
, ltrec
.rm_flags
);
1786 } else if (ltrec
.rm_startblock
== bno
) {
1788 * Overlap left hand side of extent: move the start, trim the
1789 * length and update the current record.
1792 * Orig: |oooooooooooooooooooo|
1793 * Freeing: |fffffffff|
1794 * Result: |rrrrrrrrrr|
1798 /* Delete prev rmap. */
1799 error
= xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
1800 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1801 ltrec
.rm_offset
, ltrec
.rm_flags
);
1805 /* Add an rmap at the new offset. */
1806 ltrec
.rm_startblock
+= len
;
1807 ltrec
.rm_blockcount
-= len
;
1808 ltrec
.rm_offset
+= len
;
1809 error
= xfs_rmap_insert(cur
, ltrec
.rm_startblock
,
1810 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1811 ltrec
.rm_offset
, ltrec
.rm_flags
);
1814 } else if (ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
+ len
) {
1816 * Overlap right hand side of extent: trim the length and
1817 * update the current record.
1820 * Orig: |oooooooooooooooooooo|
1821 * Freeing: |fffffffff|
1822 * Result: |rrrrrrrrrr|
1825 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1826 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1827 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1830 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1831 ltrec
.rm_blockcount
-= len
;
1832 error
= xfs_rmap_update(cur
, <rec
);
1837 * Overlap middle of extent: trim the length of the existing
1838 * record to the length of the new left-extent size, increment
1839 * the insertion position so we can insert a new record
1840 * containing the remaining right-extent space.
1843 * Orig: |oooooooooooooooooooo|
1844 * Freeing: |fffffffff|
1845 * Result: |rrrrr| |rrrr|
1848 xfs_extlen_t orig_len
= ltrec
.rm_blockcount
;
1850 /* Shrink the left side of the rmap */
1851 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1852 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1853 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1856 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1857 ltrec
.rm_blockcount
= bno
- ltrec
.rm_startblock
;
1858 error
= xfs_rmap_update(cur
, <rec
);
1862 /* Add an rmap at the new offset */
1863 error
= xfs_rmap_insert(cur
, bno
+ len
,
1864 orig_len
- len
- ltrec
.rm_blockcount
,
1865 ltrec
.rm_owner
, offset
+ len
,
1871 trace_xfs_rmap_unmap_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1875 trace_xfs_rmap_unmap_error(cur
->bc_mp
,
1876 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1881 * Find an extent in the rmap btree and map it. For rmap extent types that
1882 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1883 * that the prev/next records in the btree might belong to another owner.
1884 * Therefore we must use delete+insert to alter any of the key fields.
1886 * For every other situation there can only be one owner for a given extent,
1887 * so we can call the regular _alloc function.
1890 xfs_rmap_map_shared(
1891 struct xfs_btree_cur
*cur
,
1895 struct xfs_owner_info
*oinfo
)
1897 struct xfs_mount
*mp
= cur
->bc_mp
;
1898 struct xfs_rmap_irec ltrec
;
1899 struct xfs_rmap_irec gtrec
;
1906 unsigned int flags
= 0;
1908 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1910 flags
|= XFS_RMAP_UNWRITTEN
;
1911 trace_xfs_rmap_map(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1914 /* Is there a left record that abuts our range? */
1915 error
= xfs_rmap_find_left_neighbor(cur
, bno
, owner
, offset
, flags
,
1920 !xfs_rmap_is_mergeable(<rec
, owner
, flags
))
1923 /* Is there a right record that abuts our range? */
1924 error
= xfs_rmap_lookup_eq(cur
, bno
+ len
, len
, owner
, offset
+ len
,
1929 error
= xfs_rmap_get_rec(cur
, >rec
, &have_gt
);
1932 XFS_WANT_CORRUPTED_GOTO(mp
, have_gt
== 1, out_error
);
1933 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1934 cur
->bc_private
.a
.agno
, gtrec
.rm_startblock
,
1935 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
1936 gtrec
.rm_offset
, gtrec
.rm_flags
);
1938 if (!xfs_rmap_is_mergeable(>rec
, owner
, flags
))
1943 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
&&
1944 ltrec
.rm_offset
+ ltrec
.rm_blockcount
== offset
) {
1946 * Left edge contiguous, merge into left record.
1950 * adding: |aaaaaaaaa|
1951 * result: |rrrrrrrrrrrrrrrrrrr|
1954 ltrec
.rm_blockcount
+= len
;
1956 bno
+ len
== gtrec
.rm_startblock
&&
1957 offset
+ len
== gtrec
.rm_offset
) {
1959 * Right edge also contiguous, delete right record
1960 * and merge into left record.
1962 * ltbno ltlen gtbno gtlen
1963 * orig: |ooooooooo| |ooooooooo|
1964 * adding: |aaaaaaaaa|
1965 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1967 ltrec
.rm_blockcount
+= gtrec
.rm_blockcount
;
1968 error
= xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
1969 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
1970 gtrec
.rm_offset
, gtrec
.rm_flags
);
1975 /* Point the cursor back to the left record and update. */
1976 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1977 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1978 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1981 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1983 error
= xfs_rmap_update(cur
, <rec
);
1986 } else if (have_gt
&&
1987 bno
+ len
== gtrec
.rm_startblock
&&
1988 offset
+ len
== gtrec
.rm_offset
) {
1990 * Right edge contiguous, merge into right record.
1994 * adding: |aaaaaaaaa|
1995 * Result: |rrrrrrrrrrrrrrrrrrr|
1998 /* Delete the old record. */
1999 error
= xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
2000 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2001 gtrec
.rm_offset
, gtrec
.rm_flags
);
2005 /* Move the start and re-add it. */
2006 gtrec
.rm_startblock
= bno
;
2007 gtrec
.rm_blockcount
+= len
;
2008 gtrec
.rm_offset
= offset
;
2009 error
= xfs_rmap_insert(cur
, gtrec
.rm_startblock
,
2010 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2011 gtrec
.rm_offset
, gtrec
.rm_flags
);
2016 * No contiguous edge with identical owner, insert
2017 * new record at current cursor position.
2019 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, flags
);
2024 trace_xfs_rmap_map_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
2028 trace_xfs_rmap_map_error(cur
->bc_mp
,
2029 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
2033 /* Insert a raw rmap into the rmapbt. */
2036 struct xfs_btree_cur
*cur
,
2037 struct xfs_rmap_irec
*rmap
)
2039 struct xfs_owner_info oinfo
;
2041 oinfo
.oi_owner
= rmap
->rm_owner
;
2042 oinfo
.oi_offset
= rmap
->rm_offset
;
2044 if (rmap
->rm_flags
& XFS_RMAP_ATTR_FORK
)
2045 oinfo
.oi_flags
|= XFS_OWNER_INFO_ATTR_FORK
;
2046 if (rmap
->rm_flags
& XFS_RMAP_BMBT_BLOCK
)
2047 oinfo
.oi_flags
|= XFS_OWNER_INFO_BMBT_BLOCK
;
2049 if (rmap
->rm_flags
|| XFS_RMAP_NON_INODE_OWNER(rmap
->rm_owner
))
2050 return xfs_rmap_map(cur
, rmap
->rm_startblock
,
2051 rmap
->rm_blockcount
,
2052 rmap
->rm_flags
& XFS_RMAP_UNWRITTEN
,
2055 return xfs_rmap_map_shared(cur
, rmap
->rm_startblock
,
2056 rmap
->rm_blockcount
,
2057 rmap
->rm_flags
& XFS_RMAP_UNWRITTEN
,
2061 struct xfs_rmap_query_range_info
{
2062 xfs_rmap_query_range_fn fn
;
2066 /* Format btree record and pass to our callback. */
2068 xfs_rmap_query_range_helper(
2069 struct xfs_btree_cur
*cur
,
2070 union xfs_btree_rec
*rec
,
2073 struct xfs_rmap_query_range_info
*query
= priv
;
2074 struct xfs_rmap_irec irec
;
2077 error
= xfs_rmap_btrec_to_irec(rec
, &irec
);
2080 return query
->fn(cur
, &irec
, query
->priv
);
2083 /* Find all rmaps between two keys. */
2085 xfs_rmap_query_range(
2086 struct xfs_btree_cur
*cur
,
2087 struct xfs_rmap_irec
*low_rec
,
2088 struct xfs_rmap_irec
*high_rec
,
2089 xfs_rmap_query_range_fn fn
,
2092 union xfs_btree_irec low_brec
;
2093 union xfs_btree_irec high_brec
;
2094 struct xfs_rmap_query_range_info query
;
2096 low_brec
.r
= *low_rec
;
2097 high_brec
.r
= *high_rec
;
2100 return xfs_btree_query_range(cur
, &low_brec
, &high_brec
,
2101 xfs_rmap_query_range_helper
, &query
);
2104 /* Find all rmaps. */
2107 struct xfs_btree_cur
*cur
,
2108 xfs_rmap_query_range_fn fn
,
2111 struct xfs_rmap_query_range_info query
;
2115 return xfs_btree_query_all(cur
, xfs_rmap_query_range_helper
, &query
);
2118 /* Clean up after calling xfs_rmap_finish_one. */
2120 xfs_rmap_finish_one_cleanup(
2121 struct xfs_trans
*tp
,
2122 struct xfs_btree_cur
*rcur
,
2125 struct xfs_buf
*agbp
;
2129 agbp
= rcur
->bc_private
.a
.agbp
;
2130 xfs_btree_del_cursor(rcur
, error
? XFS_BTREE_ERROR
: XFS_BTREE_NOERROR
);
2132 xfs_trans_brelse(tp
, agbp
);
2136 * Process one of the deferred rmap operations. We pass back the
2137 * btree cursor to maintain our lock on the rmapbt between calls.
2138 * This saves time and eliminates a buffer deadlock between the
2139 * superblock and the AGF because we'll always grab them in the same
2143 xfs_rmap_finish_one(
2144 struct xfs_trans
*tp
,
2145 enum xfs_rmap_intent_type type
,
2148 xfs_fileoff_t startoff
,
2149 xfs_fsblock_t startblock
,
2150 xfs_filblks_t blockcount
,
2152 struct xfs_btree_cur
**pcur
)
2154 struct xfs_mount
*mp
= tp
->t_mountp
;
2155 struct xfs_btree_cur
*rcur
;
2156 struct xfs_buf
*agbp
= NULL
;
2158 xfs_agnumber_t agno
;
2159 struct xfs_owner_info oinfo
;
2163 agno
= XFS_FSB_TO_AGNO(mp
, startblock
);
2164 ASSERT(agno
!= NULLAGNUMBER
);
2165 bno
= XFS_FSB_TO_AGBNO(mp
, startblock
);
2167 trace_xfs_rmap_deferred(mp
, agno
, type
, bno
, owner
, whichfork
,
2168 startoff
, blockcount
, state
);
2170 if (XFS_TEST_ERROR(false, mp
,
2171 XFS_ERRTAG_RMAP_FINISH_ONE
))
2175 * If we haven't gotten a cursor or the cursor AG doesn't match
2176 * the startblock, get one now.
2179 if (rcur
!= NULL
&& rcur
->bc_private
.a
.agno
!= agno
) {
2180 xfs_rmap_finish_one_cleanup(tp
, rcur
, 0);
2186 * Refresh the freelist before we start changing the
2187 * rmapbt, because a shape change could cause us to
2190 error
= xfs_free_extent_fix_freelist(tp
, agno
, &agbp
);
2194 return -EFSCORRUPTED
;
2196 rcur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
2204 xfs_rmap_ino_owner(&oinfo
, owner
, whichfork
, startoff
);
2205 unwritten
= state
== XFS_EXT_UNWRITTEN
;
2206 bno
= XFS_FSB_TO_AGBNO(rcur
->bc_mp
, startblock
);
2209 case XFS_RMAP_ALLOC
:
2211 error
= xfs_rmap_map(rcur
, bno
, blockcount
, unwritten
, &oinfo
);
2213 case XFS_RMAP_MAP_SHARED
:
2214 error
= xfs_rmap_map_shared(rcur
, bno
, blockcount
, unwritten
,
2218 case XFS_RMAP_UNMAP
:
2219 error
= xfs_rmap_unmap(rcur
, bno
, blockcount
, unwritten
,
2222 case XFS_RMAP_UNMAP_SHARED
:
2223 error
= xfs_rmap_unmap_shared(rcur
, bno
, blockcount
, unwritten
,
2226 case XFS_RMAP_CONVERT
:
2227 error
= xfs_rmap_convert(rcur
, bno
, blockcount
, !unwritten
,
2230 case XFS_RMAP_CONVERT_SHARED
:
2231 error
= xfs_rmap_convert_shared(rcur
, bno
, blockcount
,
2232 !unwritten
, &oinfo
);
2236 error
= -EFSCORRUPTED
;
2241 xfs_trans_brelse(tp
, agbp
);
2247 * Don't defer an rmap if we aren't an rmap filesystem.
2250 xfs_rmap_update_is_needed(
2251 struct xfs_mount
*mp
,
2254 return xfs_sb_version_hasrmapbt(&mp
->m_sb
) && whichfork
!= XFS_COW_FORK
;
2258 * Record a rmap intent; the list is kept sorted first by AG and then by
2263 struct xfs_mount
*mp
,
2264 struct xfs_defer_ops
*dfops
,
2265 enum xfs_rmap_intent_type type
,
2268 struct xfs_bmbt_irec
*bmap
)
2270 struct xfs_rmap_intent
*ri
;
2272 trace_xfs_rmap_defer(mp
, XFS_FSB_TO_AGNO(mp
, bmap
->br_startblock
),
2274 XFS_FSB_TO_AGBNO(mp
, bmap
->br_startblock
),
2277 bmap
->br_blockcount
,
2280 ri
= kmem_alloc(sizeof(struct xfs_rmap_intent
), KM_SLEEP
| KM_NOFS
);
2281 INIT_LIST_HEAD(&ri
->ri_list
);
2283 ri
->ri_owner
= owner
;
2284 ri
->ri_whichfork
= whichfork
;
2285 ri
->ri_bmap
= *bmap
;
2287 xfs_defer_add(dfops
, XFS_DEFER_OPS_TYPE_RMAP
, &ri
->ri_list
);
2291 /* Map an extent into a file. */
2293 xfs_rmap_map_extent(
2294 struct xfs_mount
*mp
,
2295 struct xfs_defer_ops
*dfops
,
2296 struct xfs_inode
*ip
,
2298 struct xfs_bmbt_irec
*PREV
)
2300 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2303 return __xfs_rmap_add(mp
, dfops
, xfs_is_reflink_inode(ip
) ?
2304 XFS_RMAP_MAP_SHARED
: XFS_RMAP_MAP
, ip
->i_ino
,
2308 /* Unmap an extent out of a file. */
2310 xfs_rmap_unmap_extent(
2311 struct xfs_mount
*mp
,
2312 struct xfs_defer_ops
*dfops
,
2313 struct xfs_inode
*ip
,
2315 struct xfs_bmbt_irec
*PREV
)
2317 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2320 return __xfs_rmap_add(mp
, dfops
, xfs_is_reflink_inode(ip
) ?
2321 XFS_RMAP_UNMAP_SHARED
: XFS_RMAP_UNMAP
, ip
->i_ino
,
2325 /* Convert a data fork extent from unwritten to real or vice versa. */
2327 xfs_rmap_convert_extent(
2328 struct xfs_mount
*mp
,
2329 struct xfs_defer_ops
*dfops
,
2330 struct xfs_inode
*ip
,
2332 struct xfs_bmbt_irec
*PREV
)
2334 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2337 return __xfs_rmap_add(mp
, dfops
, xfs_is_reflink_inode(ip
) ?
2338 XFS_RMAP_CONVERT_SHARED
: XFS_RMAP_CONVERT
, ip
->i_ino
,
2342 /* Schedule the creation of an rmap for non-file data. */
2344 xfs_rmap_alloc_extent(
2345 struct xfs_mount
*mp
,
2346 struct xfs_defer_ops
*dfops
,
2347 xfs_agnumber_t agno
,
2352 struct xfs_bmbt_irec bmap
;
2354 if (!xfs_rmap_update_is_needed(mp
, XFS_DATA_FORK
))
2357 bmap
.br_startblock
= XFS_AGB_TO_FSB(mp
, agno
, bno
);
2358 bmap
.br_blockcount
= len
;
2359 bmap
.br_startoff
= 0;
2360 bmap
.br_state
= XFS_EXT_NORM
;
2362 return __xfs_rmap_add(mp
, dfops
, XFS_RMAP_ALLOC
, owner
,
2363 XFS_DATA_FORK
, &bmap
);
2366 /* Schedule the deletion of an rmap for non-file data. */
2368 xfs_rmap_free_extent(
2369 struct xfs_mount
*mp
,
2370 struct xfs_defer_ops
*dfops
,
2371 xfs_agnumber_t agno
,
2376 struct xfs_bmbt_irec bmap
;
2378 if (!xfs_rmap_update_is_needed(mp
, XFS_DATA_FORK
))
2381 bmap
.br_startblock
= XFS_AGB_TO_FSB(mp
, agno
, bno
);
2382 bmap
.br_blockcount
= len
;
2383 bmap
.br_startoff
= 0;
2384 bmap
.br_state
= XFS_EXT_NORM
;
2386 return __xfs_rmap_add(mp
, dfops
, XFS_RMAP_FREE
, owner
,
2387 XFS_DATA_FORK
, &bmap
);
2390 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2393 const struct xfs_rmap_irec
*a
,
2394 const struct xfs_rmap_irec
*b
)
2399 oa
= xfs_rmap_irec_offset_pack(a
);
2400 ob
= xfs_rmap_irec_offset_pack(b
);
2402 if (a
->rm_startblock
< b
->rm_startblock
)
2404 else if (a
->rm_startblock
> b
->rm_startblock
)
2406 else if (a
->rm_owner
< b
->rm_owner
)
2408 else if (a
->rm_owner
> b
->rm_owner
)
2418 /* Is there a record covering a given extent? */
2420 xfs_rmap_has_record(
2421 struct xfs_btree_cur
*cur
,
2426 union xfs_btree_irec low
;
2427 union xfs_btree_irec high
;
2429 memset(&low
, 0, sizeof(low
));
2430 low
.r
.rm_startblock
= bno
;
2431 memset(&high
, 0xFF, sizeof(high
));
2432 high
.r
.rm_startblock
= bno
+ len
- 1;
2434 return xfs_btree_has_record(cur
, &low
, &high
, exists
);
2438 * Is there a record for this owner completely covering a given physical
2439 * extent? If so, *has_rmap will be set to true. If there is no record
2440 * or the record only covers part of the range, we set *has_rmap to false.
2441 * This function doesn't perform range lookups or offset checks, so it is
2442 * not suitable for checking data fork blocks.
2445 xfs_rmap_record_exists(
2446 struct xfs_btree_cur
*cur
,
2449 struct xfs_owner_info
*oinfo
,
2456 struct xfs_rmap_irec irec
;
2459 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
2460 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner
) ||
2461 (flags
& XFS_RMAP_BMBT_BLOCK
));
2463 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
,
2472 error
= xfs_rmap_get_rec(cur
, &irec
, &has_record
);
2480 *has_rmap
= (irec
.rm_owner
== owner
&& irec
.rm_startblock
<= bno
&&
2481 irec
.rm_startblock
+ irec
.rm_blockcount
>= bno
+ len
);
2485 struct xfs_rmap_key_state
{
2492 /* For each rmap given, figure out if it doesn't match the key we want. */
2494 xfs_rmap_has_other_keys_helper(
2495 struct xfs_btree_cur
*cur
,
2496 struct xfs_rmap_irec
*rec
,
2499 struct xfs_rmap_key_state
*rks
= priv
;
2501 if (rks
->owner
== rec
->rm_owner
&& rks
->offset
== rec
->rm_offset
&&
2502 ((rks
->flags
& rec
->rm_flags
) & XFS_RMAP_KEY_FLAGS
) == rks
->flags
)
2504 rks
->has_rmap
= true;
2505 return XFS_BTREE_QUERY_RANGE_ABORT
;
2509 * Given an extent and some owner info, can we find records overlapping
2510 * the extent whose owner info does not match the given owner?
2513 xfs_rmap_has_other_keys(
2514 struct xfs_btree_cur
*cur
,
2517 struct xfs_owner_info
*oinfo
,
2520 struct xfs_rmap_irec low
= {0};
2521 struct xfs_rmap_irec high
;
2522 struct xfs_rmap_key_state rks
;
2525 xfs_owner_info_unpack(oinfo
, &rks
.owner
, &rks
.offset
, &rks
.flags
);
2526 rks
.has_rmap
= false;
2528 low
.rm_startblock
= bno
;
2529 memset(&high
, 0xFF, sizeof(high
));
2530 high
.rm_startblock
= bno
+ len
- 1;
2532 error
= xfs_rmap_query_range(cur
, &low
, &high
,
2533 xfs_rmap_has_other_keys_helper
, &rks
);
2534 *has_rmap
= rks
.has_rmap
;