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
,
385 if (owner
== XFS_RMAP_OWN_UNKNOWN
)
388 /* Make sure the unwritten flag matches. */
389 XFS_WANT_CORRUPTED_GOTO(mp
, (flags
& XFS_RMAP_UNWRITTEN
) ==
390 (rec
->rm_flags
& XFS_RMAP_UNWRITTEN
), out
);
392 /* Make sure the owner matches what we expect to find in the tree. */
393 XFS_WANT_CORRUPTED_GOTO(mp
, owner
== rec
->rm_owner
, out
);
395 /* Check the offset, if necessary. */
396 if (XFS_RMAP_NON_INODE_OWNER(owner
))
399 if (flags
& XFS_RMAP_BMBT_BLOCK
) {
400 XFS_WANT_CORRUPTED_GOTO(mp
, rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
,
403 XFS_WANT_CORRUPTED_GOTO(mp
, rec
->rm_offset
<= offset
, out
);
404 XFS_WANT_CORRUPTED_GOTO(mp
,
405 ltoff
+ rec
->rm_blockcount
>= offset
+ len
,
414 * Find the extent in the rmap btree and remove it.
416 * The record we find should always be an exact match for the extent that we're
417 * looking for, since we insert them into the btree without modification.
419 * Special Case #1: when growing the filesystem, we "free" an extent when
420 * growing the last AG. This extent is new space and so it is not tracked as
421 * used space in the btree. The growfs code will pass in an owner of
422 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
423 * extent. We verify that - the extent lookup result in a record that does not
426 * Special Case #2: EFIs do not record the owner of the extent, so when
427 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
428 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
429 * corruption checks during log recovery.
433 struct xfs_btree_cur
*cur
,
437 struct xfs_owner_info
*oinfo
)
439 struct xfs_mount
*mp
= cur
->bc_mp
;
440 struct xfs_rmap_irec ltrec
;
449 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
450 ignore_off
= XFS_RMAP_NON_INODE_OWNER(owner
) ||
451 (flags
& XFS_RMAP_BMBT_BLOCK
);
453 flags
|= XFS_RMAP_UNWRITTEN
;
454 trace_xfs_rmap_unmap(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
458 * We should always have a left record because there's a static record
459 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
460 * will not ever be removed from the tree.
462 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
, &i
);
465 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
467 error
= xfs_rmap_get_rec(cur
, <rec
, &i
);
470 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
471 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
472 cur
->bc_private
.a
.agno
, ltrec
.rm_startblock
,
473 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
474 ltrec
.rm_offset
, ltrec
.rm_flags
);
475 ltoff
= ltrec
.rm_offset
;
478 * For growfs, the incoming extent must be beyond the left record we
479 * just found as it is new space and won't be used by anyone. This is
480 * just a corruption check as we don't actually do anything with this
481 * extent. Note that we need to use >= instead of > because it might
482 * be the case that the "left" extent goes all the way to EOFS.
484 if (owner
== XFS_RMAP_OWN_NULL
) {
485 XFS_WANT_CORRUPTED_GOTO(mp
, bno
>= ltrec
.rm_startblock
+
486 ltrec
.rm_blockcount
, out_error
);
491 * If we're doing an unknown-owner removal for EFI recovery, we expect
492 * to find the full range in the rmapbt or nothing at all. If we
493 * don't find any rmaps overlapping either end of the range, we're
494 * done. Hopefully this means that the EFI creator already queued
495 * (and finished) a RUI to remove the rmap.
497 if (owner
== XFS_RMAP_OWN_UNKNOWN
&&
498 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
<= bno
) {
499 struct xfs_rmap_irec rtrec
;
501 error
= xfs_btree_increment(cur
, 0, &i
);
506 error
= xfs_rmap_get_rec(cur
, &rtrec
, &i
);
509 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
510 if (rtrec
.rm_startblock
>= bno
+ len
)
514 /* Make sure the extent we found covers the entire freeing range. */
515 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_startblock
<= bno
&&
516 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
>=
517 bno
+ len
, out_error
);
519 /* Check owner information. */
520 error
= xfs_rmap_free_check_owner(mp
, ltoff
, <rec
, bno
, len
, owner
,
525 if (ltrec
.rm_startblock
== bno
&& ltrec
.rm_blockcount
== len
) {
526 /* exact match, simply remove the record from rmap tree */
527 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
528 ltrec
.rm_startblock
, ltrec
.rm_blockcount
,
529 ltrec
.rm_owner
, ltrec
.rm_offset
,
531 error
= xfs_btree_delete(cur
, &i
);
534 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
535 } else if (ltrec
.rm_startblock
== bno
) {
537 * overlap left hand side of extent: move the start, trim the
538 * length and update the current record.
541 * Orig: |oooooooooooooooooooo|
542 * Freeing: |fffffffff|
543 * Result: |rrrrrrrrrr|
546 ltrec
.rm_startblock
+= len
;
547 ltrec
.rm_blockcount
-= len
;
549 ltrec
.rm_offset
+= len
;
550 error
= xfs_rmap_update(cur
, <rec
);
553 } else if (ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
+ len
) {
555 * overlap right hand side of extent: trim the length and update
556 * the current record.
559 * Orig: |oooooooooooooooooooo|
560 * Freeing: |fffffffff|
561 * Result: |rrrrrrrrrr|
564 ltrec
.rm_blockcount
-= len
;
565 error
= xfs_rmap_update(cur
, <rec
);
571 * overlap middle of extent: trim the length of the existing
572 * record to the length of the new left-extent size, increment
573 * the insertion position so we can insert a new record
574 * containing the remaining right-extent space.
577 * Orig: |oooooooooooooooooooo|
578 * Freeing: |fffffffff|
579 * Result: |rrrrr| |rrrr|
582 xfs_extlen_t orig_len
= ltrec
.rm_blockcount
;
584 ltrec
.rm_blockcount
= bno
- ltrec
.rm_startblock
;
585 error
= xfs_rmap_update(cur
, <rec
);
589 error
= xfs_btree_increment(cur
, 0, &i
);
593 cur
->bc_rec
.r
.rm_startblock
= bno
+ len
;
594 cur
->bc_rec
.r
.rm_blockcount
= orig_len
- len
-
596 cur
->bc_rec
.r
.rm_owner
= ltrec
.rm_owner
;
598 cur
->bc_rec
.r
.rm_offset
= 0;
600 cur
->bc_rec
.r
.rm_offset
= offset
+ len
;
601 cur
->bc_rec
.r
.rm_flags
= flags
;
602 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
,
603 cur
->bc_rec
.r
.rm_startblock
,
604 cur
->bc_rec
.r
.rm_blockcount
,
605 cur
->bc_rec
.r
.rm_owner
,
606 cur
->bc_rec
.r
.rm_offset
,
607 cur
->bc_rec
.r
.rm_flags
);
608 error
= xfs_btree_insert(cur
, &i
);
614 trace_xfs_rmap_unmap_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
618 trace_xfs_rmap_unmap_error(mp
, cur
->bc_private
.a
.agno
,
624 * Remove a reference to an extent in the rmap btree.
628 struct xfs_trans
*tp
,
629 struct xfs_buf
*agbp
,
633 struct xfs_owner_info
*oinfo
)
635 struct xfs_mount
*mp
= tp
->t_mountp
;
636 struct xfs_btree_cur
*cur
;
639 if (!xfs_sb_version_hasrmapbt(&mp
->m_sb
))
642 cur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
644 error
= xfs_rmap_unmap(cur
, bno
, len
, false, oinfo
);
648 xfs_btree_del_cursor(cur
, XFS_BTREE_NOERROR
);
652 xfs_btree_del_cursor(cur
, XFS_BTREE_ERROR
);
657 * A mergeable rmap must have the same owner and the same values for
658 * the unwritten, attr_fork, and bmbt flags. The startblock and
659 * offset are checked separately.
662 xfs_rmap_is_mergeable(
663 struct xfs_rmap_irec
*irec
,
667 if (irec
->rm_owner
== XFS_RMAP_OWN_NULL
)
669 if (irec
->rm_owner
!= owner
)
671 if ((flags
& XFS_RMAP_UNWRITTEN
) ^
672 (irec
->rm_flags
& XFS_RMAP_UNWRITTEN
))
674 if ((flags
& XFS_RMAP_ATTR_FORK
) ^
675 (irec
->rm_flags
& XFS_RMAP_ATTR_FORK
))
677 if ((flags
& XFS_RMAP_BMBT_BLOCK
) ^
678 (irec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
))
684 * When we allocate a new block, the first thing we do is add a reference to
685 * the extent in the rmap btree. This takes the form of a [agbno, length,
686 * owner, offset] record. Flags are encoded in the high bits of the offset
691 struct xfs_btree_cur
*cur
,
695 struct xfs_owner_info
*oinfo
)
697 struct xfs_mount
*mp
= cur
->bc_mp
;
698 struct xfs_rmap_irec ltrec
;
699 struct xfs_rmap_irec gtrec
;
706 unsigned int flags
= 0;
709 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
711 ignore_off
= XFS_RMAP_NON_INODE_OWNER(owner
) ||
712 (flags
& XFS_RMAP_BMBT_BLOCK
);
714 flags
|= XFS_RMAP_UNWRITTEN
;
715 trace_xfs_rmap_map(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
717 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo
));
720 * For the initial lookup, look for an exact match or the left-adjacent
721 * record for our insertion point. This will also give us the record for
722 * start block contiguity tests.
724 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
,
728 XFS_WANT_CORRUPTED_GOTO(mp
, have_lt
== 1, out_error
);
730 error
= xfs_rmap_get_rec(cur
, <rec
, &have_lt
);
733 XFS_WANT_CORRUPTED_GOTO(mp
, have_lt
== 1, out_error
);
734 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
735 cur
->bc_private
.a
.agno
, ltrec
.rm_startblock
,
736 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
737 ltrec
.rm_offset
, ltrec
.rm_flags
);
739 if (!xfs_rmap_is_mergeable(<rec
, owner
, flags
))
742 XFS_WANT_CORRUPTED_GOTO(mp
,
744 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
<= bno
, out_error
);
747 * Increment the cursor to see if we have a right-adjacent record to our
748 * insertion point. This will give us the record for end block
751 error
= xfs_btree_increment(cur
, 0, &have_gt
);
755 error
= xfs_rmap_get_rec(cur
, >rec
, &have_gt
);
758 XFS_WANT_CORRUPTED_GOTO(mp
, have_gt
== 1, out_error
);
759 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= gtrec
.rm_startblock
,
761 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
762 cur
->bc_private
.a
.agno
, gtrec
.rm_startblock
,
763 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
764 gtrec
.rm_offset
, gtrec
.rm_flags
);
765 if (!xfs_rmap_is_mergeable(>rec
, owner
, flags
))
770 * Note: cursor currently points one record to the right of ltrec, even
771 * if there is no record in the tree to the right.
774 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
&&
775 (ignore_off
|| ltrec
.rm_offset
+ ltrec
.rm_blockcount
== offset
)) {
777 * left edge contiguous, merge into left record.
781 * adding: |aaaaaaaaa|
782 * result: |rrrrrrrrrrrrrrrrrrr|
785 ltrec
.rm_blockcount
+= len
;
787 bno
+ len
== gtrec
.rm_startblock
&&
788 (ignore_off
|| offset
+ len
== gtrec
.rm_offset
) &&
789 (unsigned long)ltrec
.rm_blockcount
+ len
+
790 gtrec
.rm_blockcount
<= XFS_RMAP_LEN_MAX
) {
792 * right edge also contiguous, delete right record
793 * and merge into left record.
795 * ltbno ltlen gtbno gtlen
796 * orig: |ooooooooo| |ooooooooo|
797 * adding: |aaaaaaaaa|
798 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
800 ltrec
.rm_blockcount
+= gtrec
.rm_blockcount
;
801 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
807 error
= xfs_btree_delete(cur
, &i
);
810 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
813 /* point the cursor back to the left record and update */
814 error
= xfs_btree_decrement(cur
, 0, &have_gt
);
817 error
= xfs_rmap_update(cur
, <rec
);
820 } else if (have_gt
&&
821 bno
+ len
== gtrec
.rm_startblock
&&
822 (ignore_off
|| offset
+ len
== gtrec
.rm_offset
)) {
824 * right edge contiguous, merge into right record.
828 * adding: |aaaaaaaaa|
829 * Result: |rrrrrrrrrrrrrrrrrrr|
832 gtrec
.rm_startblock
= bno
;
833 gtrec
.rm_blockcount
+= len
;
835 gtrec
.rm_offset
= offset
;
836 error
= xfs_rmap_update(cur
, >rec
);
841 * no contiguous edge with identical owner, insert
842 * new record at current cursor position.
844 cur
->bc_rec
.r
.rm_startblock
= bno
;
845 cur
->bc_rec
.r
.rm_blockcount
= len
;
846 cur
->bc_rec
.r
.rm_owner
= owner
;
847 cur
->bc_rec
.r
.rm_offset
= offset
;
848 cur
->bc_rec
.r
.rm_flags
= flags
;
849 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
850 owner
, offset
, flags
);
851 error
= xfs_btree_insert(cur
, &i
);
854 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
857 trace_xfs_rmap_map_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
861 trace_xfs_rmap_map_error(mp
, cur
->bc_private
.a
.agno
,
867 * Add a reference to an extent in the rmap btree.
871 struct xfs_trans
*tp
,
872 struct xfs_buf
*agbp
,
876 struct xfs_owner_info
*oinfo
)
878 struct xfs_mount
*mp
= tp
->t_mountp
;
879 struct xfs_btree_cur
*cur
;
882 if (!xfs_sb_version_hasrmapbt(&mp
->m_sb
))
885 cur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
886 error
= xfs_rmap_map(cur
, bno
, len
, false, oinfo
);
890 xfs_btree_del_cursor(cur
, XFS_BTREE_NOERROR
);
894 xfs_btree_del_cursor(cur
, XFS_BTREE_ERROR
);
898 #define RMAP_LEFT_CONTIG (1 << 0)
899 #define RMAP_RIGHT_CONTIG (1 << 1)
900 #define RMAP_LEFT_FILLING (1 << 2)
901 #define RMAP_RIGHT_FILLING (1 << 3)
902 #define RMAP_LEFT_VALID (1 << 6)
903 #define RMAP_RIGHT_VALID (1 << 7)
911 * Convert an unwritten extent to a real extent or vice versa.
912 * Does not handle overlapping extents.
916 struct xfs_btree_cur
*cur
,
920 struct xfs_owner_info
*oinfo
)
922 struct xfs_mount
*mp
= cur
->bc_mp
;
923 struct xfs_rmap_irec r
[4]; /* neighbor extent entries */
924 /* left is 0, right is 1, prev is 2 */
931 unsigned int flags
= 0;
936 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
937 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner
) ||
938 (flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
))));
939 oldext
= unwritten
? XFS_RMAP_UNWRITTEN
: 0;
940 new_endoff
= offset
+ len
;
941 trace_xfs_rmap_convert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
945 * For the initial lookup, look for an exact match or the left-adjacent
946 * record for our insertion point. This will also give us the record for
947 * start block contiguity tests.
949 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, oldext
, &i
);
952 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
954 error
= xfs_rmap_get_rec(cur
, &PREV
, &i
);
957 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
958 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
959 cur
->bc_private
.a
.agno
, PREV
.rm_startblock
,
960 PREV
.rm_blockcount
, PREV
.rm_owner
,
961 PREV
.rm_offset
, PREV
.rm_flags
);
963 ASSERT(PREV
.rm_offset
<= offset
);
964 ASSERT(PREV
.rm_offset
+ PREV
.rm_blockcount
>= new_endoff
);
965 ASSERT((PREV
.rm_flags
& XFS_RMAP_UNWRITTEN
) == oldext
);
966 newext
= ~oldext
& XFS_RMAP_UNWRITTEN
;
969 * Set flags determining what part of the previous oldext allocation
970 * extent is being replaced by a newext allocation.
972 if (PREV
.rm_offset
== offset
)
973 state
|= RMAP_LEFT_FILLING
;
974 if (PREV
.rm_offset
+ PREV
.rm_blockcount
== new_endoff
)
975 state
|= RMAP_RIGHT_FILLING
;
978 * Decrement the cursor to see if we have a left-adjacent record to our
979 * insertion point. This will give us the record for end block
982 error
= xfs_btree_decrement(cur
, 0, &i
);
986 state
|= RMAP_LEFT_VALID
;
987 error
= xfs_rmap_get_rec(cur
, &LEFT
, &i
);
990 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
991 XFS_WANT_CORRUPTED_GOTO(mp
,
992 LEFT
.rm_startblock
+ LEFT
.rm_blockcount
<= bno
,
994 trace_xfs_rmap_find_left_neighbor_result(cur
->bc_mp
,
995 cur
->bc_private
.a
.agno
, LEFT
.rm_startblock
,
996 LEFT
.rm_blockcount
, LEFT
.rm_owner
,
997 LEFT
.rm_offset
, LEFT
.rm_flags
);
998 if (LEFT
.rm_startblock
+ LEFT
.rm_blockcount
== bno
&&
999 LEFT
.rm_offset
+ LEFT
.rm_blockcount
== offset
&&
1000 xfs_rmap_is_mergeable(&LEFT
, owner
, newext
))
1001 state
|= RMAP_LEFT_CONTIG
;
1005 * Increment the cursor to see if we have a right-adjacent record to our
1006 * insertion point. This will give us the record for end block
1009 error
= xfs_btree_increment(cur
, 0, &i
);
1012 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1013 error
= xfs_btree_increment(cur
, 0, &i
);
1017 state
|= RMAP_RIGHT_VALID
;
1018 error
= xfs_rmap_get_rec(cur
, &RIGHT
, &i
);
1021 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1022 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= RIGHT
.rm_startblock
,
1024 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1025 cur
->bc_private
.a
.agno
, RIGHT
.rm_startblock
,
1026 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1027 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1028 if (bno
+ len
== RIGHT
.rm_startblock
&&
1029 offset
+ len
== RIGHT
.rm_offset
&&
1030 xfs_rmap_is_mergeable(&RIGHT
, owner
, newext
))
1031 state
|= RMAP_RIGHT_CONTIG
;
1034 /* check that left + prev + right is not too long */
1035 if ((state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1036 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) ==
1037 (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1038 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
) &&
1039 (unsigned long)LEFT
.rm_blockcount
+ len
+
1040 RIGHT
.rm_blockcount
> XFS_RMAP_LEN_MAX
)
1041 state
&= ~RMAP_RIGHT_CONTIG
;
1043 trace_xfs_rmap_convert_state(mp
, cur
->bc_private
.a
.agno
, state
,
1046 /* reset the cursor back to PREV */
1047 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, oldext
, &i
);
1050 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1053 * Switch out based on the FILLING and CONTIG state bits.
1055 switch (state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1056 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) {
1057 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1058 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1060 * Setting all of a previous oldext extent to newext.
1061 * The left and right neighbors are both contiguous with new.
1063 error
= xfs_btree_increment(cur
, 0, &i
);
1066 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1067 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1068 RIGHT
.rm_startblock
, RIGHT
.rm_blockcount
,
1069 RIGHT
.rm_owner
, RIGHT
.rm_offset
,
1071 error
= xfs_btree_delete(cur
, &i
);
1074 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1075 error
= xfs_btree_decrement(cur
, 0, &i
);
1078 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1079 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1080 PREV
.rm_startblock
, PREV
.rm_blockcount
,
1081 PREV
.rm_owner
, PREV
.rm_offset
,
1083 error
= xfs_btree_delete(cur
, &i
);
1086 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1087 error
= xfs_btree_decrement(cur
, 0, &i
);
1090 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1092 NEW
.rm_blockcount
+= PREV
.rm_blockcount
+ RIGHT
.rm_blockcount
;
1093 error
= xfs_rmap_update(cur
, &NEW
);
1098 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1100 * Setting all of a previous oldext extent to newext.
1101 * The left neighbor is contiguous, the right is not.
1103 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1104 PREV
.rm_startblock
, PREV
.rm_blockcount
,
1105 PREV
.rm_owner
, PREV
.rm_offset
,
1107 error
= xfs_btree_delete(cur
, &i
);
1110 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1111 error
= xfs_btree_decrement(cur
, 0, &i
);
1114 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1116 NEW
.rm_blockcount
+= PREV
.rm_blockcount
;
1117 error
= xfs_rmap_update(cur
, &NEW
);
1122 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1124 * Setting all of a previous oldext extent to newext.
1125 * The right neighbor is contiguous, the left is not.
1127 error
= xfs_btree_increment(cur
, 0, &i
);
1130 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1131 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1132 RIGHT
.rm_startblock
, RIGHT
.rm_blockcount
,
1133 RIGHT
.rm_owner
, RIGHT
.rm_offset
,
1135 error
= xfs_btree_delete(cur
, &i
);
1138 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1139 error
= xfs_btree_decrement(cur
, 0, &i
);
1142 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1144 NEW
.rm_blockcount
= len
+ RIGHT
.rm_blockcount
;
1145 NEW
.rm_flags
= newext
;
1146 error
= xfs_rmap_update(cur
, &NEW
);
1151 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
:
1153 * Setting all of a previous oldext extent to newext.
1154 * Neither the left nor right neighbors are contiguous with
1158 NEW
.rm_flags
= newext
;
1159 error
= xfs_rmap_update(cur
, &NEW
);
1164 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
:
1166 * Setting the first part of a previous oldext extent to newext.
1167 * The left neighbor is contiguous.
1170 NEW
.rm_offset
+= len
;
1171 NEW
.rm_startblock
+= len
;
1172 NEW
.rm_blockcount
-= len
;
1173 error
= xfs_rmap_update(cur
, &NEW
);
1176 error
= xfs_btree_decrement(cur
, 0, &i
);
1180 NEW
.rm_blockcount
+= len
;
1181 error
= xfs_rmap_update(cur
, &NEW
);
1186 case RMAP_LEFT_FILLING
:
1188 * Setting the first part of a previous oldext extent to newext.
1189 * The left neighbor is not contiguous.
1192 NEW
.rm_startblock
+= len
;
1193 NEW
.rm_offset
+= len
;
1194 NEW
.rm_blockcount
-= len
;
1195 error
= xfs_rmap_update(cur
, &NEW
);
1198 NEW
.rm_startblock
= bno
;
1199 NEW
.rm_owner
= owner
;
1200 NEW
.rm_offset
= offset
;
1201 NEW
.rm_blockcount
= len
;
1202 NEW
.rm_flags
= newext
;
1203 cur
->bc_rec
.r
= NEW
;
1204 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
,
1205 len
, owner
, offset
, newext
);
1206 error
= xfs_btree_insert(cur
, &i
);
1209 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1212 case RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1214 * Setting the last part of a previous oldext extent to newext.
1215 * The right neighbor is contiguous with the new allocation.
1218 NEW
.rm_blockcount
-= len
;
1219 error
= xfs_rmap_update(cur
, &NEW
);
1222 error
= xfs_btree_increment(cur
, 0, &i
);
1226 NEW
.rm_offset
= offset
;
1227 NEW
.rm_startblock
= bno
;
1228 NEW
.rm_blockcount
+= len
;
1229 error
= xfs_rmap_update(cur
, &NEW
);
1234 case RMAP_RIGHT_FILLING
:
1236 * Setting the last part of a previous oldext extent to newext.
1237 * The right neighbor is not contiguous.
1240 NEW
.rm_blockcount
-= len
;
1241 error
= xfs_rmap_update(cur
, &NEW
);
1244 error
= xfs_rmap_lookup_eq(cur
, bno
, len
, owner
, offset
,
1248 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 0, done
);
1249 NEW
.rm_startblock
= bno
;
1250 NEW
.rm_owner
= owner
;
1251 NEW
.rm_offset
= offset
;
1252 NEW
.rm_blockcount
= len
;
1253 NEW
.rm_flags
= newext
;
1254 cur
->bc_rec
.r
= NEW
;
1255 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
,
1256 len
, owner
, offset
, newext
);
1257 error
= xfs_btree_insert(cur
, &i
);
1260 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1265 * Setting the middle part of a previous oldext extent to
1266 * newext. Contiguity is impossible here.
1267 * One extent becomes three extents.
1269 /* new right extent - oldext */
1270 NEW
.rm_startblock
= bno
+ len
;
1271 NEW
.rm_owner
= owner
;
1272 NEW
.rm_offset
= new_endoff
;
1273 NEW
.rm_blockcount
= PREV
.rm_offset
+ PREV
.rm_blockcount
-
1275 NEW
.rm_flags
= PREV
.rm_flags
;
1276 error
= xfs_rmap_update(cur
, &NEW
);
1279 /* new left extent - oldext */
1281 NEW
.rm_blockcount
= offset
- PREV
.rm_offset
;
1282 cur
->bc_rec
.r
= NEW
;
1283 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
,
1284 NEW
.rm_startblock
, NEW
.rm_blockcount
,
1285 NEW
.rm_owner
, NEW
.rm_offset
,
1287 error
= xfs_btree_insert(cur
, &i
);
1290 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1292 * Reset the cursor to the position of the new extent
1293 * we are about to insert as we can't trust it after
1294 * the previous insert.
1296 error
= xfs_rmap_lookup_eq(cur
, bno
, len
, owner
, offset
,
1300 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 0, done
);
1301 /* new middle extent - newext */
1302 cur
->bc_rec
.r
.rm_flags
&= ~XFS_RMAP_UNWRITTEN
;
1303 cur
->bc_rec
.r
.rm_flags
|= newext
;
1304 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1305 owner
, offset
, newext
);
1306 error
= xfs_btree_insert(cur
, &i
);
1309 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1312 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1313 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1314 case RMAP_LEFT_FILLING
| RMAP_RIGHT_CONTIG
:
1315 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1316 case RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1317 case RMAP_LEFT_CONTIG
:
1318 case RMAP_RIGHT_CONTIG
:
1320 * These cases are all impossible.
1325 trace_xfs_rmap_convert_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1329 trace_xfs_rmap_convert_error(cur
->bc_mp
,
1330 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1335 * Convert an unwritten extent to a real extent or vice versa. If there is no
1336 * possibility of overlapping extents, delegate to the simpler convert
1340 xfs_rmap_convert_shared(
1341 struct xfs_btree_cur
*cur
,
1345 struct xfs_owner_info
*oinfo
)
1347 struct xfs_mount
*mp
= cur
->bc_mp
;
1348 struct xfs_rmap_irec r
[4]; /* neighbor extent entries */
1349 /* left is 0, right is 1, prev is 2 */
1353 uint64_t new_endoff
;
1354 unsigned int oldext
;
1355 unsigned int newext
;
1356 unsigned int flags
= 0;
1361 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1362 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner
) ||
1363 (flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
))));
1364 oldext
= unwritten
? XFS_RMAP_UNWRITTEN
: 0;
1365 new_endoff
= offset
+ len
;
1366 trace_xfs_rmap_convert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1370 * For the initial lookup, look for and exact match or the left-adjacent
1371 * record for our insertion point. This will also give us the record for
1372 * start block contiguity tests.
1374 error
= xfs_rmap_lookup_le_range(cur
, bno
, owner
, offset
, flags
,
1376 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1378 ASSERT(PREV
.rm_offset
<= offset
);
1379 ASSERT(PREV
.rm_offset
+ PREV
.rm_blockcount
>= new_endoff
);
1380 ASSERT((PREV
.rm_flags
& XFS_RMAP_UNWRITTEN
) == oldext
);
1381 newext
= ~oldext
& XFS_RMAP_UNWRITTEN
;
1384 * Set flags determining what part of the previous oldext allocation
1385 * extent is being replaced by a newext allocation.
1387 if (PREV
.rm_offset
== offset
)
1388 state
|= RMAP_LEFT_FILLING
;
1389 if (PREV
.rm_offset
+ PREV
.rm_blockcount
== new_endoff
)
1390 state
|= RMAP_RIGHT_FILLING
;
1392 /* Is there a left record that abuts our range? */
1393 error
= xfs_rmap_find_left_neighbor(cur
, bno
, owner
, offset
, newext
,
1398 state
|= RMAP_LEFT_VALID
;
1399 XFS_WANT_CORRUPTED_GOTO(mp
,
1400 LEFT
.rm_startblock
+ LEFT
.rm_blockcount
<= bno
,
1402 if (xfs_rmap_is_mergeable(&LEFT
, owner
, newext
))
1403 state
|= RMAP_LEFT_CONTIG
;
1406 /* Is there a right record that abuts our range? */
1407 error
= xfs_rmap_lookup_eq(cur
, bno
+ len
, len
, owner
, offset
+ len
,
1412 state
|= RMAP_RIGHT_VALID
;
1413 error
= xfs_rmap_get_rec(cur
, &RIGHT
, &i
);
1416 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1417 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= RIGHT
.rm_startblock
,
1419 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1420 cur
->bc_private
.a
.agno
, RIGHT
.rm_startblock
,
1421 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1422 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1423 if (xfs_rmap_is_mergeable(&RIGHT
, owner
, newext
))
1424 state
|= RMAP_RIGHT_CONTIG
;
1427 /* check that left + prev + right is not too long */
1428 if ((state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1429 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) ==
1430 (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1431 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
) &&
1432 (unsigned long)LEFT
.rm_blockcount
+ len
+
1433 RIGHT
.rm_blockcount
> XFS_RMAP_LEN_MAX
)
1434 state
&= ~RMAP_RIGHT_CONTIG
;
1436 trace_xfs_rmap_convert_state(mp
, cur
->bc_private
.a
.agno
, state
,
1439 * Switch out based on the FILLING and CONTIG state bits.
1441 switch (state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1442 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) {
1443 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1444 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1446 * Setting all of a previous oldext extent to newext.
1447 * The left and right neighbors are both contiguous with new.
1449 error
= xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1450 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1451 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1454 error
= xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1455 PREV
.rm_blockcount
, PREV
.rm_owner
,
1456 PREV
.rm_offset
, PREV
.rm_flags
);
1460 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1461 NEW
.rm_blockcount
, NEW
.rm_owner
,
1462 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1465 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1466 NEW
.rm_blockcount
+= PREV
.rm_blockcount
+ RIGHT
.rm_blockcount
;
1467 error
= xfs_rmap_update(cur
, &NEW
);
1472 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1474 * Setting all of a previous oldext extent to newext.
1475 * The left neighbor is contiguous, the right is not.
1477 error
= xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1478 PREV
.rm_blockcount
, PREV
.rm_owner
,
1479 PREV
.rm_offset
, PREV
.rm_flags
);
1483 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1484 NEW
.rm_blockcount
, NEW
.rm_owner
,
1485 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1488 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1489 NEW
.rm_blockcount
+= PREV
.rm_blockcount
;
1490 error
= xfs_rmap_update(cur
, &NEW
);
1495 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1497 * Setting all of a previous oldext extent to newext.
1498 * The right neighbor is contiguous, the left is not.
1500 error
= xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1501 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1502 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1506 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1507 NEW
.rm_blockcount
, NEW
.rm_owner
,
1508 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1511 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1512 NEW
.rm_blockcount
+= RIGHT
.rm_blockcount
;
1513 NEW
.rm_flags
= RIGHT
.rm_flags
;
1514 error
= xfs_rmap_update(cur
, &NEW
);
1519 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
:
1521 * Setting all of a previous oldext extent to newext.
1522 * Neither the left nor right neighbors are contiguous with
1526 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1527 NEW
.rm_blockcount
, NEW
.rm_owner
,
1528 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1531 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1532 NEW
.rm_flags
= newext
;
1533 error
= xfs_rmap_update(cur
, &NEW
);
1538 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
:
1540 * Setting the first part of a previous oldext extent to newext.
1541 * The left neighbor is contiguous.
1544 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1545 NEW
.rm_blockcount
, NEW
.rm_owner
,
1546 NEW
.rm_offset
, NEW
.rm_flags
);
1549 NEW
.rm_offset
+= len
;
1550 NEW
.rm_startblock
+= len
;
1551 NEW
.rm_blockcount
-= len
;
1552 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1553 NEW
.rm_blockcount
, NEW
.rm_owner
,
1554 NEW
.rm_offset
, NEW
.rm_flags
);
1558 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1559 NEW
.rm_blockcount
, NEW
.rm_owner
,
1560 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1563 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1564 NEW
.rm_blockcount
+= len
;
1565 error
= xfs_rmap_update(cur
, &NEW
);
1570 case RMAP_LEFT_FILLING
:
1572 * Setting the first part of a previous oldext extent to newext.
1573 * The left neighbor is not contiguous.
1576 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1577 NEW
.rm_blockcount
, NEW
.rm_owner
,
1578 NEW
.rm_offset
, NEW
.rm_flags
);
1581 NEW
.rm_offset
+= len
;
1582 NEW
.rm_startblock
+= len
;
1583 NEW
.rm_blockcount
-= len
;
1584 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1585 NEW
.rm_blockcount
, NEW
.rm_owner
,
1586 NEW
.rm_offset
, NEW
.rm_flags
);
1589 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1594 case RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1596 * Setting the last part of a previous oldext extent to newext.
1597 * The right neighbor is contiguous with the new allocation.
1600 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1601 NEW
.rm_blockcount
, NEW
.rm_owner
,
1602 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1605 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1606 NEW
.rm_blockcount
= offset
- NEW
.rm_offset
;
1607 error
= xfs_rmap_update(cur
, &NEW
);
1611 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1612 NEW
.rm_blockcount
, NEW
.rm_owner
,
1613 NEW
.rm_offset
, NEW
.rm_flags
);
1616 NEW
.rm_offset
= offset
;
1617 NEW
.rm_startblock
= bno
;
1618 NEW
.rm_blockcount
+= len
;
1619 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1620 NEW
.rm_blockcount
, NEW
.rm_owner
,
1621 NEW
.rm_offset
, NEW
.rm_flags
);
1626 case RMAP_RIGHT_FILLING
:
1628 * Setting the last part of a previous oldext extent to newext.
1629 * The right neighbor is not contiguous.
1632 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1633 NEW
.rm_blockcount
, NEW
.rm_owner
,
1634 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1637 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1638 NEW
.rm_blockcount
-= len
;
1639 error
= xfs_rmap_update(cur
, &NEW
);
1642 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1649 * Setting the middle part of a previous oldext extent to
1650 * newext. Contiguity is impossible here.
1651 * One extent becomes three extents.
1653 /* new right extent - oldext */
1654 NEW
.rm_startblock
= bno
+ len
;
1655 NEW
.rm_owner
= owner
;
1656 NEW
.rm_offset
= new_endoff
;
1657 NEW
.rm_blockcount
= PREV
.rm_offset
+ PREV
.rm_blockcount
-
1659 NEW
.rm_flags
= PREV
.rm_flags
;
1660 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1661 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
1665 /* new left extent - oldext */
1667 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1668 NEW
.rm_blockcount
, NEW
.rm_owner
,
1669 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1672 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1673 NEW
.rm_blockcount
= offset
- NEW
.rm_offset
;
1674 error
= xfs_rmap_update(cur
, &NEW
);
1677 /* new middle extent - newext */
1678 NEW
.rm_startblock
= bno
;
1679 NEW
.rm_blockcount
= len
;
1680 NEW
.rm_owner
= owner
;
1681 NEW
.rm_offset
= offset
;
1682 NEW
.rm_flags
= newext
;
1683 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1684 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
1690 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1691 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1692 case RMAP_LEFT_FILLING
| RMAP_RIGHT_CONTIG
:
1693 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1694 case RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1695 case RMAP_LEFT_CONTIG
:
1696 case RMAP_RIGHT_CONTIG
:
1698 * These cases are all impossible.
1703 trace_xfs_rmap_convert_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1707 trace_xfs_rmap_convert_error(cur
->bc_mp
,
1708 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1718 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1719 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1720 * that the prev/next records in the btree might belong to another owner.
1721 * Therefore we must use delete+insert to alter any of the key fields.
1723 * For every other situation there can only be one owner for a given extent,
1724 * so we can call the regular _free function.
1727 xfs_rmap_unmap_shared(
1728 struct xfs_btree_cur
*cur
,
1732 struct xfs_owner_info
*oinfo
)
1734 struct xfs_mount
*mp
= cur
->bc_mp
;
1735 struct xfs_rmap_irec ltrec
;
1743 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1745 flags
|= XFS_RMAP_UNWRITTEN
;
1746 trace_xfs_rmap_unmap(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1750 * We should always have a left record because there's a static record
1751 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1752 * will not ever be removed from the tree.
1754 error
= xfs_rmap_lookup_le_range(cur
, bno
, owner
, offset
, flags
,
1758 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1759 ltoff
= ltrec
.rm_offset
;
1761 /* Make sure the extent we found covers the entire freeing range. */
1762 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_startblock
<= bno
&&
1763 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
>=
1764 bno
+ len
, out_error
);
1766 /* Make sure the owner matches what we expect to find in the tree. */
1767 XFS_WANT_CORRUPTED_GOTO(mp
, owner
== ltrec
.rm_owner
, out_error
);
1769 /* Make sure the unwritten flag matches. */
1770 XFS_WANT_CORRUPTED_GOTO(mp
, (flags
& XFS_RMAP_UNWRITTEN
) ==
1771 (ltrec
.rm_flags
& XFS_RMAP_UNWRITTEN
), out_error
);
1773 /* Check the offset. */
1774 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_offset
<= offset
, out_error
);
1775 XFS_WANT_CORRUPTED_GOTO(mp
, offset
<= ltoff
+ ltrec
.rm_blockcount
,
1778 if (ltrec
.rm_startblock
== bno
&& ltrec
.rm_blockcount
== len
) {
1779 /* Exact match, simply remove the record from rmap tree. */
1780 error
= xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
1781 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1782 ltrec
.rm_offset
, ltrec
.rm_flags
);
1785 } else if (ltrec
.rm_startblock
== bno
) {
1787 * Overlap left hand side of extent: move the start, trim the
1788 * length and update the current record.
1791 * Orig: |oooooooooooooooooooo|
1792 * Freeing: |fffffffff|
1793 * Result: |rrrrrrrrrr|
1797 /* Delete prev rmap. */
1798 error
= xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
1799 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1800 ltrec
.rm_offset
, ltrec
.rm_flags
);
1804 /* Add an rmap at the new offset. */
1805 ltrec
.rm_startblock
+= len
;
1806 ltrec
.rm_blockcount
-= len
;
1807 ltrec
.rm_offset
+= len
;
1808 error
= xfs_rmap_insert(cur
, ltrec
.rm_startblock
,
1809 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1810 ltrec
.rm_offset
, ltrec
.rm_flags
);
1813 } else if (ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
+ len
) {
1815 * Overlap right hand side of extent: trim the length and
1816 * update the current record.
1819 * Orig: |oooooooooooooooooooo|
1820 * Freeing: |fffffffff|
1821 * Result: |rrrrrrrrrr|
1824 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1825 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1826 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1829 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1830 ltrec
.rm_blockcount
-= len
;
1831 error
= xfs_rmap_update(cur
, <rec
);
1836 * Overlap middle of extent: trim the length of the existing
1837 * record to the length of the new left-extent size, increment
1838 * the insertion position so we can insert a new record
1839 * containing the remaining right-extent space.
1842 * Orig: |oooooooooooooooooooo|
1843 * Freeing: |fffffffff|
1844 * Result: |rrrrr| |rrrr|
1847 xfs_extlen_t orig_len
= ltrec
.rm_blockcount
;
1849 /* Shrink the left side of the rmap */
1850 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1851 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1852 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1855 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1856 ltrec
.rm_blockcount
= bno
- ltrec
.rm_startblock
;
1857 error
= xfs_rmap_update(cur
, <rec
);
1861 /* Add an rmap at the new offset */
1862 error
= xfs_rmap_insert(cur
, bno
+ len
,
1863 orig_len
- len
- ltrec
.rm_blockcount
,
1864 ltrec
.rm_owner
, offset
+ len
,
1870 trace_xfs_rmap_unmap_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1874 trace_xfs_rmap_unmap_error(cur
->bc_mp
,
1875 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1880 * Find an extent in the rmap btree and map it. For rmap extent types that
1881 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1882 * that the prev/next records in the btree might belong to another owner.
1883 * Therefore we must use delete+insert to alter any of the key fields.
1885 * For every other situation there can only be one owner for a given extent,
1886 * so we can call the regular _alloc function.
1889 xfs_rmap_map_shared(
1890 struct xfs_btree_cur
*cur
,
1894 struct xfs_owner_info
*oinfo
)
1896 struct xfs_mount
*mp
= cur
->bc_mp
;
1897 struct xfs_rmap_irec ltrec
;
1898 struct xfs_rmap_irec gtrec
;
1905 unsigned int flags
= 0;
1907 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1909 flags
|= XFS_RMAP_UNWRITTEN
;
1910 trace_xfs_rmap_map(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1913 /* Is there a left record that abuts our range? */
1914 error
= xfs_rmap_find_left_neighbor(cur
, bno
, owner
, offset
, flags
,
1919 !xfs_rmap_is_mergeable(<rec
, owner
, flags
))
1922 /* Is there a right record that abuts our range? */
1923 error
= xfs_rmap_lookup_eq(cur
, bno
+ len
, len
, owner
, offset
+ len
,
1928 error
= xfs_rmap_get_rec(cur
, >rec
, &have_gt
);
1931 XFS_WANT_CORRUPTED_GOTO(mp
, have_gt
== 1, out_error
);
1932 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1933 cur
->bc_private
.a
.agno
, gtrec
.rm_startblock
,
1934 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
1935 gtrec
.rm_offset
, gtrec
.rm_flags
);
1937 if (!xfs_rmap_is_mergeable(>rec
, owner
, flags
))
1942 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
&&
1943 ltrec
.rm_offset
+ ltrec
.rm_blockcount
== offset
) {
1945 * Left edge contiguous, merge into left record.
1949 * adding: |aaaaaaaaa|
1950 * result: |rrrrrrrrrrrrrrrrrrr|
1953 ltrec
.rm_blockcount
+= len
;
1955 bno
+ len
== gtrec
.rm_startblock
&&
1956 offset
+ len
== gtrec
.rm_offset
) {
1958 * Right edge also contiguous, delete right record
1959 * and merge into left record.
1961 * ltbno ltlen gtbno gtlen
1962 * orig: |ooooooooo| |ooooooooo|
1963 * adding: |aaaaaaaaa|
1964 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1966 ltrec
.rm_blockcount
+= gtrec
.rm_blockcount
;
1967 error
= xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
1968 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
1969 gtrec
.rm_offset
, gtrec
.rm_flags
);
1974 /* Point the cursor back to the left record and update. */
1975 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1976 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1977 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1980 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1982 error
= xfs_rmap_update(cur
, <rec
);
1985 } else if (have_gt
&&
1986 bno
+ len
== gtrec
.rm_startblock
&&
1987 offset
+ len
== gtrec
.rm_offset
) {
1989 * Right edge contiguous, merge into right record.
1993 * adding: |aaaaaaaaa|
1994 * Result: |rrrrrrrrrrrrrrrrrrr|
1997 /* Delete the old record. */
1998 error
= xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
1999 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2000 gtrec
.rm_offset
, gtrec
.rm_flags
);
2004 /* Move the start and re-add it. */
2005 gtrec
.rm_startblock
= bno
;
2006 gtrec
.rm_blockcount
+= len
;
2007 gtrec
.rm_offset
= offset
;
2008 error
= xfs_rmap_insert(cur
, gtrec
.rm_startblock
,
2009 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2010 gtrec
.rm_offset
, gtrec
.rm_flags
);
2015 * No contiguous edge with identical owner, insert
2016 * new record at current cursor position.
2018 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, flags
);
2023 trace_xfs_rmap_map_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
2027 trace_xfs_rmap_map_error(cur
->bc_mp
,
2028 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
2032 struct xfs_rmap_query_range_info
{
2033 xfs_rmap_query_range_fn fn
;
2037 /* Format btree record and pass to our callback. */
2039 xfs_rmap_query_range_helper(
2040 struct xfs_btree_cur
*cur
,
2041 union xfs_btree_rec
*rec
,
2044 struct xfs_rmap_query_range_info
*query
= priv
;
2045 struct xfs_rmap_irec irec
;
2048 error
= xfs_rmap_btrec_to_irec(rec
, &irec
);
2051 return query
->fn(cur
, &irec
, query
->priv
);
2054 /* Find all rmaps between two keys. */
2056 xfs_rmap_query_range(
2057 struct xfs_btree_cur
*cur
,
2058 struct xfs_rmap_irec
*low_rec
,
2059 struct xfs_rmap_irec
*high_rec
,
2060 xfs_rmap_query_range_fn fn
,
2063 union xfs_btree_irec low_brec
;
2064 union xfs_btree_irec high_brec
;
2065 struct xfs_rmap_query_range_info query
;
2067 low_brec
.r
= *low_rec
;
2068 high_brec
.r
= *high_rec
;
2071 return xfs_btree_query_range(cur
, &low_brec
, &high_brec
,
2072 xfs_rmap_query_range_helper
, &query
);
2075 /* Find all rmaps. */
2078 struct xfs_btree_cur
*cur
,
2079 xfs_rmap_query_range_fn fn
,
2082 struct xfs_rmap_query_range_info query
;
2086 return xfs_btree_query_all(cur
, xfs_rmap_query_range_helper
, &query
);
2089 /* Clean up after calling xfs_rmap_finish_one. */
2091 xfs_rmap_finish_one_cleanup(
2092 struct xfs_trans
*tp
,
2093 struct xfs_btree_cur
*rcur
,
2096 struct xfs_buf
*agbp
;
2100 agbp
= rcur
->bc_private
.a
.agbp
;
2101 xfs_btree_del_cursor(rcur
, error
? XFS_BTREE_ERROR
: XFS_BTREE_NOERROR
);
2103 xfs_trans_brelse(tp
, agbp
);
2107 * Process one of the deferred rmap operations. We pass back the
2108 * btree cursor to maintain our lock on the rmapbt between calls.
2109 * This saves time and eliminates a buffer deadlock between the
2110 * superblock and the AGF because we'll always grab them in the same
2114 xfs_rmap_finish_one(
2115 struct xfs_trans
*tp
,
2116 enum xfs_rmap_intent_type type
,
2119 xfs_fileoff_t startoff
,
2120 xfs_fsblock_t startblock
,
2121 xfs_filblks_t blockcount
,
2123 struct xfs_btree_cur
**pcur
)
2125 struct xfs_mount
*mp
= tp
->t_mountp
;
2126 struct xfs_btree_cur
*rcur
;
2127 struct xfs_buf
*agbp
= NULL
;
2129 xfs_agnumber_t agno
;
2130 struct xfs_owner_info oinfo
;
2134 agno
= XFS_FSB_TO_AGNO(mp
, startblock
);
2135 ASSERT(agno
!= NULLAGNUMBER
);
2136 bno
= XFS_FSB_TO_AGBNO(mp
, startblock
);
2138 trace_xfs_rmap_deferred(mp
, agno
, type
, bno
, owner
, whichfork
,
2139 startoff
, blockcount
, state
);
2141 if (XFS_TEST_ERROR(false, mp
,
2142 XFS_ERRTAG_RMAP_FINISH_ONE
))
2146 * If we haven't gotten a cursor or the cursor AG doesn't match
2147 * the startblock, get one now.
2150 if (rcur
!= NULL
&& rcur
->bc_private
.a
.agno
!= agno
) {
2151 xfs_rmap_finish_one_cleanup(tp
, rcur
, 0);
2157 * Refresh the freelist before we start changing the
2158 * rmapbt, because a shape change could cause us to
2161 error
= xfs_free_extent_fix_freelist(tp
, agno
, &agbp
);
2165 return -EFSCORRUPTED
;
2167 rcur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
2175 xfs_rmap_ino_owner(&oinfo
, owner
, whichfork
, startoff
);
2176 unwritten
= state
== XFS_EXT_UNWRITTEN
;
2177 bno
= XFS_FSB_TO_AGBNO(rcur
->bc_mp
, startblock
);
2180 case XFS_RMAP_ALLOC
:
2182 error
= xfs_rmap_map(rcur
, bno
, blockcount
, unwritten
, &oinfo
);
2184 case XFS_RMAP_MAP_SHARED
:
2185 error
= xfs_rmap_map_shared(rcur
, bno
, blockcount
, unwritten
,
2189 case XFS_RMAP_UNMAP
:
2190 error
= xfs_rmap_unmap(rcur
, bno
, blockcount
, unwritten
,
2193 case XFS_RMAP_UNMAP_SHARED
:
2194 error
= xfs_rmap_unmap_shared(rcur
, bno
, blockcount
, unwritten
,
2197 case XFS_RMAP_CONVERT
:
2198 error
= xfs_rmap_convert(rcur
, bno
, blockcount
, !unwritten
,
2201 case XFS_RMAP_CONVERT_SHARED
:
2202 error
= xfs_rmap_convert_shared(rcur
, bno
, blockcount
,
2203 !unwritten
, &oinfo
);
2207 error
= -EFSCORRUPTED
;
2212 xfs_trans_brelse(tp
, agbp
);
2218 * Don't defer an rmap if we aren't an rmap filesystem.
2221 xfs_rmap_update_is_needed(
2222 struct xfs_mount
*mp
,
2225 return xfs_sb_version_hasrmapbt(&mp
->m_sb
) && whichfork
!= XFS_COW_FORK
;
2229 * Record a rmap intent; the list is kept sorted first by AG and then by
2234 struct xfs_mount
*mp
,
2235 struct xfs_defer_ops
*dfops
,
2236 enum xfs_rmap_intent_type type
,
2239 struct xfs_bmbt_irec
*bmap
)
2241 struct xfs_rmap_intent
*ri
;
2243 trace_xfs_rmap_defer(mp
, XFS_FSB_TO_AGNO(mp
, bmap
->br_startblock
),
2245 XFS_FSB_TO_AGBNO(mp
, bmap
->br_startblock
),
2248 bmap
->br_blockcount
,
2251 ri
= kmem_alloc(sizeof(struct xfs_rmap_intent
), KM_SLEEP
| KM_NOFS
);
2252 INIT_LIST_HEAD(&ri
->ri_list
);
2254 ri
->ri_owner
= owner
;
2255 ri
->ri_whichfork
= whichfork
;
2256 ri
->ri_bmap
= *bmap
;
2258 xfs_defer_add(dfops
, XFS_DEFER_OPS_TYPE_RMAP
, &ri
->ri_list
);
2262 /* Map an extent into a file. */
2264 xfs_rmap_map_extent(
2265 struct xfs_mount
*mp
,
2266 struct xfs_defer_ops
*dfops
,
2267 struct xfs_inode
*ip
,
2269 struct xfs_bmbt_irec
*PREV
)
2271 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2274 return __xfs_rmap_add(mp
, dfops
, xfs_is_reflink_inode(ip
) ?
2275 XFS_RMAP_MAP_SHARED
: XFS_RMAP_MAP
, ip
->i_ino
,
2279 /* Unmap an extent out of a file. */
2281 xfs_rmap_unmap_extent(
2282 struct xfs_mount
*mp
,
2283 struct xfs_defer_ops
*dfops
,
2284 struct xfs_inode
*ip
,
2286 struct xfs_bmbt_irec
*PREV
)
2288 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2291 return __xfs_rmap_add(mp
, dfops
, xfs_is_reflink_inode(ip
) ?
2292 XFS_RMAP_UNMAP_SHARED
: XFS_RMAP_UNMAP
, ip
->i_ino
,
2296 /* Convert a data fork extent from unwritten to real or vice versa. */
2298 xfs_rmap_convert_extent(
2299 struct xfs_mount
*mp
,
2300 struct xfs_defer_ops
*dfops
,
2301 struct xfs_inode
*ip
,
2303 struct xfs_bmbt_irec
*PREV
)
2305 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2308 return __xfs_rmap_add(mp
, dfops
, xfs_is_reflink_inode(ip
) ?
2309 XFS_RMAP_CONVERT_SHARED
: XFS_RMAP_CONVERT
, ip
->i_ino
,
2313 /* Schedule the creation of an rmap for non-file data. */
2315 xfs_rmap_alloc_extent(
2316 struct xfs_mount
*mp
,
2317 struct xfs_defer_ops
*dfops
,
2318 xfs_agnumber_t agno
,
2323 struct xfs_bmbt_irec bmap
;
2325 if (!xfs_rmap_update_is_needed(mp
, XFS_DATA_FORK
))
2328 bmap
.br_startblock
= XFS_AGB_TO_FSB(mp
, agno
, bno
);
2329 bmap
.br_blockcount
= len
;
2330 bmap
.br_startoff
= 0;
2331 bmap
.br_state
= XFS_EXT_NORM
;
2333 return __xfs_rmap_add(mp
, dfops
, XFS_RMAP_ALLOC
, owner
,
2334 XFS_DATA_FORK
, &bmap
);
2337 /* Schedule the deletion of an rmap for non-file data. */
2339 xfs_rmap_free_extent(
2340 struct xfs_mount
*mp
,
2341 struct xfs_defer_ops
*dfops
,
2342 xfs_agnumber_t agno
,
2347 struct xfs_bmbt_irec bmap
;
2349 if (!xfs_rmap_update_is_needed(mp
, XFS_DATA_FORK
))
2352 bmap
.br_startblock
= XFS_AGB_TO_FSB(mp
, agno
, bno
);
2353 bmap
.br_blockcount
= len
;
2354 bmap
.br_startoff
= 0;
2355 bmap
.br_state
= XFS_EXT_NORM
;
2357 return __xfs_rmap_add(mp
, dfops
, XFS_RMAP_FREE
, owner
,
2358 XFS_DATA_FORK
, &bmap
);
2361 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2364 const struct xfs_rmap_irec
*a
,
2365 const struct xfs_rmap_irec
*b
)
2370 oa
= xfs_rmap_irec_offset_pack(a
);
2371 ob
= xfs_rmap_irec_offset_pack(b
);
2373 if (a
->rm_startblock
< b
->rm_startblock
)
2375 else if (a
->rm_startblock
> b
->rm_startblock
)
2377 else if (a
->rm_owner
< b
->rm_owner
)
2379 else if (a
->rm_owner
> b
->rm_owner
)