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
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"
38 #include "xfs_error.h"
39 #include "xfs_extent_busy.h"
41 #include "xfs_inode.h"
44 * Lookup the first record less than or equal to [bno, len, owner, offset]
45 * in the btree given by cur.
49 struct xfs_btree_cur
*cur
,
57 cur
->bc_rec
.r
.rm_startblock
= bno
;
58 cur
->bc_rec
.r
.rm_blockcount
= len
;
59 cur
->bc_rec
.r
.rm_owner
= owner
;
60 cur
->bc_rec
.r
.rm_offset
= offset
;
61 cur
->bc_rec
.r
.rm_flags
= flags
;
62 return xfs_btree_lookup(cur
, XFS_LOOKUP_LE
, stat
);
66 * Lookup the record exactly matching [bno, len, owner, offset]
67 * in the btree given by cur.
71 struct xfs_btree_cur
*cur
,
79 cur
->bc_rec
.r
.rm_startblock
= bno
;
80 cur
->bc_rec
.r
.rm_blockcount
= len
;
81 cur
->bc_rec
.r
.rm_owner
= owner
;
82 cur
->bc_rec
.r
.rm_offset
= offset
;
83 cur
->bc_rec
.r
.rm_flags
= flags
;
84 return xfs_btree_lookup(cur
, XFS_LOOKUP_EQ
, stat
);
88 * Update the record referred to by cur to the value given
89 * by [bno, len, owner, offset].
90 * This either works (return 0) or gets an EFSCORRUPTED error.
94 struct xfs_btree_cur
*cur
,
95 struct xfs_rmap_irec
*irec
)
97 union xfs_btree_rec rec
;
100 trace_xfs_rmap_update(cur
->bc_mp
, cur
->bc_private
.a
.agno
,
101 irec
->rm_startblock
, irec
->rm_blockcount
,
102 irec
->rm_owner
, irec
->rm_offset
, irec
->rm_flags
);
104 rec
.rmap
.rm_startblock
= cpu_to_be32(irec
->rm_startblock
);
105 rec
.rmap
.rm_blockcount
= cpu_to_be32(irec
->rm_blockcount
);
106 rec
.rmap
.rm_owner
= cpu_to_be64(irec
->rm_owner
);
107 rec
.rmap
.rm_offset
= cpu_to_be64(
108 xfs_rmap_irec_offset_pack(irec
));
109 error
= xfs_btree_update(cur
, &rec
);
111 trace_xfs_rmap_update_error(cur
->bc_mp
,
112 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
118 struct xfs_btree_cur
*rcur
,
128 trace_xfs_rmap_insert(rcur
->bc_mp
, rcur
->bc_private
.a
.agno
, agbno
,
129 len
, owner
, offset
, flags
);
131 error
= xfs_rmap_lookup_eq(rcur
, agbno
, len
, owner
, offset
, flags
, &i
);
134 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 0, done
);
136 rcur
->bc_rec
.r
.rm_startblock
= agbno
;
137 rcur
->bc_rec
.r
.rm_blockcount
= len
;
138 rcur
->bc_rec
.r
.rm_owner
= owner
;
139 rcur
->bc_rec
.r
.rm_offset
= offset
;
140 rcur
->bc_rec
.r
.rm_flags
= flags
;
141 error
= xfs_btree_insert(rcur
, &i
);
144 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 1, done
);
147 trace_xfs_rmap_insert_error(rcur
->bc_mp
,
148 rcur
->bc_private
.a
.agno
, error
, _RET_IP_
);
154 struct xfs_btree_cur
*rcur
,
164 trace_xfs_rmap_delete(rcur
->bc_mp
, rcur
->bc_private
.a
.agno
, agbno
,
165 len
, owner
, offset
, flags
);
167 error
= xfs_rmap_lookup_eq(rcur
, agbno
, len
, owner
, offset
, flags
, &i
);
170 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 1, done
);
172 error
= xfs_btree_delete(rcur
, &i
);
175 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 1, done
);
178 trace_xfs_rmap_delete_error(rcur
->bc_mp
,
179 rcur
->bc_private
.a
.agno
, error
, _RET_IP_
);
183 /* Convert an internal btree record to an rmap record. */
185 xfs_rmap_btrec_to_irec(
186 union xfs_btree_rec
*rec
,
187 struct xfs_rmap_irec
*irec
)
190 irec
->rm_startblock
= be32_to_cpu(rec
->rmap
.rm_startblock
);
191 irec
->rm_blockcount
= be32_to_cpu(rec
->rmap
.rm_blockcount
);
192 irec
->rm_owner
= be64_to_cpu(rec
->rmap
.rm_owner
);
193 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec
->rmap
.rm_offset
),
198 * Get the data from the pointed-to record.
202 struct xfs_btree_cur
*cur
,
203 struct xfs_rmap_irec
*irec
,
206 union xfs_btree_rec
*rec
;
209 error
= xfs_btree_get_rec(cur
, &rec
, stat
);
213 return xfs_rmap_btrec_to_irec(rec
, irec
);
216 struct xfs_find_left_neighbor_info
{
217 struct xfs_rmap_irec high
;
218 struct xfs_rmap_irec
*irec
;
222 /* For each rmap given, figure out if it matches the key we want. */
224 xfs_rmap_find_left_neighbor_helper(
225 struct xfs_btree_cur
*cur
,
226 struct xfs_rmap_irec
*rec
,
229 struct xfs_find_left_neighbor_info
*info
= priv
;
231 trace_xfs_rmap_find_left_neighbor_candidate(cur
->bc_mp
,
232 cur
->bc_private
.a
.agno
, rec
->rm_startblock
,
233 rec
->rm_blockcount
, rec
->rm_owner
, rec
->rm_offset
,
236 if (rec
->rm_owner
!= info
->high
.rm_owner
)
237 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
238 if (!XFS_RMAP_NON_INODE_OWNER(rec
->rm_owner
) &&
239 !(rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
) &&
240 rec
->rm_offset
+ rec
->rm_blockcount
- 1 != info
->high
.rm_offset
)
241 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
245 return XFS_BTREE_QUERY_RANGE_ABORT
;
249 * Find the record to the left of the given extent, being careful only to
250 * return a match with the same owner and adjacent physical and logical
254 xfs_rmap_find_left_neighbor(
255 struct xfs_btree_cur
*cur
,
260 struct xfs_rmap_irec
*irec
,
263 struct xfs_find_left_neighbor_info info
;
269 info
.high
.rm_startblock
= bno
- 1;
270 info
.high
.rm_owner
= owner
;
271 if (!XFS_RMAP_NON_INODE_OWNER(owner
) &&
272 !(flags
& XFS_RMAP_BMBT_BLOCK
)) {
275 info
.high
.rm_offset
= offset
- 1;
277 info
.high
.rm_offset
= 0;
278 info
.high
.rm_flags
= flags
;
279 info
.high
.rm_blockcount
= 0;
283 trace_xfs_rmap_find_left_neighbor_query(cur
->bc_mp
,
284 cur
->bc_private
.a
.agno
, bno
, 0, owner
, offset
, flags
);
286 error
= xfs_rmap_query_range(cur
, &info
.high
, &info
.high
,
287 xfs_rmap_find_left_neighbor_helper
, &info
);
288 if (error
== XFS_BTREE_QUERY_RANGE_ABORT
)
291 trace_xfs_rmap_find_left_neighbor_result(cur
->bc_mp
,
292 cur
->bc_private
.a
.agno
, irec
->rm_startblock
,
293 irec
->rm_blockcount
, irec
->rm_owner
,
294 irec
->rm_offset
, irec
->rm_flags
);
298 /* For each rmap given, figure out if it matches the key we want. */
300 xfs_rmap_lookup_le_range_helper(
301 struct xfs_btree_cur
*cur
,
302 struct xfs_rmap_irec
*rec
,
305 struct xfs_find_left_neighbor_info
*info
= priv
;
307 trace_xfs_rmap_lookup_le_range_candidate(cur
->bc_mp
,
308 cur
->bc_private
.a
.agno
, rec
->rm_startblock
,
309 rec
->rm_blockcount
, rec
->rm_owner
, rec
->rm_offset
,
312 if (rec
->rm_owner
!= info
->high
.rm_owner
)
313 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
314 if (!XFS_RMAP_NON_INODE_OWNER(rec
->rm_owner
) &&
315 !(rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
) &&
316 (rec
->rm_offset
> info
->high
.rm_offset
||
317 rec
->rm_offset
+ rec
->rm_blockcount
<= info
->high
.rm_offset
))
318 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
322 return XFS_BTREE_QUERY_RANGE_ABORT
;
326 * Find the record to the left of the given extent, being careful only to
327 * return a match with the same owner and overlapping physical and logical
328 * block ranges. This is the overlapping-interval version of
329 * xfs_rmap_lookup_le.
332 xfs_rmap_lookup_le_range(
333 struct xfs_btree_cur
*cur
,
338 struct xfs_rmap_irec
*irec
,
341 struct xfs_find_left_neighbor_info info
;
344 info
.high
.rm_startblock
= bno
;
345 info
.high
.rm_owner
= owner
;
346 if (!XFS_RMAP_NON_INODE_OWNER(owner
) && !(flags
& XFS_RMAP_BMBT_BLOCK
))
347 info
.high
.rm_offset
= offset
;
349 info
.high
.rm_offset
= 0;
350 info
.high
.rm_flags
= flags
;
351 info
.high
.rm_blockcount
= 0;
356 trace_xfs_rmap_lookup_le_range(cur
->bc_mp
,
357 cur
->bc_private
.a
.agno
, bno
, 0, owner
, offset
, flags
);
358 error
= xfs_rmap_query_range(cur
, &info
.high
, &info
.high
,
359 xfs_rmap_lookup_le_range_helper
, &info
);
360 if (error
== XFS_BTREE_QUERY_RANGE_ABORT
)
363 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
364 cur
->bc_private
.a
.agno
, irec
->rm_startblock
,
365 irec
->rm_blockcount
, irec
->rm_owner
,
366 irec
->rm_offset
, irec
->rm_flags
);
371 * Perform all the relevant owner checks for a removal op. If we're doing an
372 * unknown-owner removal then we have no owner information to check.
375 xfs_rmap_free_check_owner(
376 struct xfs_mount
*mp
,
378 struct xfs_rmap_irec
*rec
,
387 if (owner
== XFS_RMAP_OWN_UNKNOWN
)
390 /* Make sure the unwritten flag matches. */
391 XFS_WANT_CORRUPTED_GOTO(mp
, (flags
& XFS_RMAP_UNWRITTEN
) ==
392 (rec
->rm_flags
& XFS_RMAP_UNWRITTEN
), out
);
394 /* Make sure the owner matches what we expect to find in the tree. */
395 XFS_WANT_CORRUPTED_GOTO(mp
, owner
== rec
->rm_owner
, out
);
397 /* Check the offset, if necessary. */
398 if (XFS_RMAP_NON_INODE_OWNER(owner
))
401 if (flags
& XFS_RMAP_BMBT_BLOCK
) {
402 XFS_WANT_CORRUPTED_GOTO(mp
, rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
,
405 XFS_WANT_CORRUPTED_GOTO(mp
, rec
->rm_offset
<= offset
, out
);
406 XFS_WANT_CORRUPTED_GOTO(mp
,
407 ltoff
+ rec
->rm_blockcount
>= offset
+ len
,
416 * Find the extent in the rmap btree and remove it.
418 * The record we find should always be an exact match for the extent that we're
419 * looking for, since we insert them into the btree without modification.
421 * Special Case #1: when growing the filesystem, we "free" an extent when
422 * growing the last AG. This extent is new space and so it is not tracked as
423 * used space in the btree. The growfs code will pass in an owner of
424 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
425 * extent. We verify that - the extent lookup result in a record that does not
428 * Special Case #2: EFIs do not record the owner of the extent, so when
429 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
430 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
431 * corruption checks during log recovery.
435 struct xfs_btree_cur
*cur
,
439 struct xfs_owner_info
*oinfo
)
441 struct xfs_mount
*mp
= cur
->bc_mp
;
442 struct xfs_rmap_irec ltrec
;
451 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
452 ignore_off
= XFS_RMAP_NON_INODE_OWNER(owner
) ||
453 (flags
& XFS_RMAP_BMBT_BLOCK
);
455 flags
|= XFS_RMAP_UNWRITTEN
;
456 trace_xfs_rmap_unmap(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
460 * We should always have a left record because there's a static record
461 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
462 * will not ever be removed from the tree.
464 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
, &i
);
467 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
469 error
= xfs_rmap_get_rec(cur
, <rec
, &i
);
472 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
473 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
474 cur
->bc_private
.a
.agno
, ltrec
.rm_startblock
,
475 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
476 ltrec
.rm_offset
, ltrec
.rm_flags
);
477 ltoff
= ltrec
.rm_offset
;
480 * For growfs, the incoming extent must be beyond the left record we
481 * just found as it is new space and won't be used by anyone. This is
482 * just a corruption check as we don't actually do anything with this
483 * extent. Note that we need to use >= instead of > because it might
484 * be the case that the "left" extent goes all the way to EOFS.
486 if (owner
== XFS_RMAP_OWN_NULL
) {
487 XFS_WANT_CORRUPTED_GOTO(mp
, bno
>= ltrec
.rm_startblock
+
488 ltrec
.rm_blockcount
, out_error
);
493 * If we're doing an unknown-owner removal for EFI recovery, we expect
494 * to find the full range in the rmapbt or nothing at all. If we
495 * don't find any rmaps overlapping either end of the range, we're
496 * done. Hopefully this means that the EFI creator already queued
497 * (and finished) a RUI to remove the rmap.
499 if (owner
== XFS_RMAP_OWN_UNKNOWN
&&
500 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
<= bno
) {
501 struct xfs_rmap_irec rtrec
;
503 error
= xfs_btree_increment(cur
, 0, &i
);
508 error
= xfs_rmap_get_rec(cur
, &rtrec
, &i
);
511 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
512 if (rtrec
.rm_startblock
>= bno
+ len
)
516 /* Make sure the extent we found covers the entire freeing range. */
517 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_startblock
<= bno
&&
518 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
>=
519 bno
+ len
, out_error
);
521 /* Check owner information. */
522 error
= xfs_rmap_free_check_owner(mp
, ltoff
, <rec
, bno
, len
, owner
,
527 if (ltrec
.rm_startblock
== bno
&& ltrec
.rm_blockcount
== len
) {
528 /* exact match, simply remove the record from rmap tree */
529 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
530 ltrec
.rm_startblock
, ltrec
.rm_blockcount
,
531 ltrec
.rm_owner
, ltrec
.rm_offset
,
533 error
= xfs_btree_delete(cur
, &i
);
536 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
537 } else if (ltrec
.rm_startblock
== bno
) {
539 * overlap left hand side of extent: move the start, trim the
540 * length and update the current record.
543 * Orig: |oooooooooooooooooooo|
544 * Freeing: |fffffffff|
545 * Result: |rrrrrrrrrr|
548 ltrec
.rm_startblock
+= len
;
549 ltrec
.rm_blockcount
-= len
;
551 ltrec
.rm_offset
+= len
;
552 error
= xfs_rmap_update(cur
, <rec
);
555 } else if (ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
+ len
) {
557 * overlap right hand side of extent: trim the length and update
558 * the current record.
561 * Orig: |oooooooooooooooooooo|
562 * Freeing: |fffffffff|
563 * Result: |rrrrrrrrrr|
566 ltrec
.rm_blockcount
-= len
;
567 error
= xfs_rmap_update(cur
, <rec
);
573 * overlap middle of extent: trim the length of the existing
574 * record to the length of the new left-extent size, increment
575 * the insertion position so we can insert a new record
576 * containing the remaining right-extent space.
579 * Orig: |oooooooooooooooooooo|
580 * Freeing: |fffffffff|
581 * Result: |rrrrr| |rrrr|
584 xfs_extlen_t orig_len
= ltrec
.rm_blockcount
;
586 ltrec
.rm_blockcount
= bno
- ltrec
.rm_startblock
;
587 error
= xfs_rmap_update(cur
, <rec
);
591 error
= xfs_btree_increment(cur
, 0, &i
);
595 cur
->bc_rec
.r
.rm_startblock
= bno
+ len
;
596 cur
->bc_rec
.r
.rm_blockcount
= orig_len
- len
-
598 cur
->bc_rec
.r
.rm_owner
= ltrec
.rm_owner
;
600 cur
->bc_rec
.r
.rm_offset
= 0;
602 cur
->bc_rec
.r
.rm_offset
= offset
+ len
;
603 cur
->bc_rec
.r
.rm_flags
= flags
;
604 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
,
605 cur
->bc_rec
.r
.rm_startblock
,
606 cur
->bc_rec
.r
.rm_blockcount
,
607 cur
->bc_rec
.r
.rm_owner
,
608 cur
->bc_rec
.r
.rm_offset
,
609 cur
->bc_rec
.r
.rm_flags
);
610 error
= xfs_btree_insert(cur
, &i
);
616 trace_xfs_rmap_unmap_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
620 trace_xfs_rmap_unmap_error(mp
, cur
->bc_private
.a
.agno
,
626 * Remove a reference to an extent in the rmap btree.
630 struct xfs_trans
*tp
,
631 struct xfs_buf
*agbp
,
635 struct xfs_owner_info
*oinfo
)
637 struct xfs_mount
*mp
= tp
->t_mountp
;
638 struct xfs_btree_cur
*cur
;
641 if (!xfs_sb_version_hasrmapbt(&mp
->m_sb
))
644 cur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
646 error
= xfs_rmap_unmap(cur
, bno
, len
, false, oinfo
);
650 xfs_btree_del_cursor(cur
, XFS_BTREE_NOERROR
);
654 xfs_btree_del_cursor(cur
, XFS_BTREE_ERROR
);
659 * A mergeable rmap must have the same owner and the same values for
660 * the unwritten, attr_fork, and bmbt flags. The startblock and
661 * offset are checked separately.
664 xfs_rmap_is_mergeable(
665 struct xfs_rmap_irec
*irec
,
669 if (irec
->rm_owner
== XFS_RMAP_OWN_NULL
)
671 if (irec
->rm_owner
!= owner
)
673 if ((flags
& XFS_RMAP_UNWRITTEN
) ^
674 (irec
->rm_flags
& XFS_RMAP_UNWRITTEN
))
676 if ((flags
& XFS_RMAP_ATTR_FORK
) ^
677 (irec
->rm_flags
& XFS_RMAP_ATTR_FORK
))
679 if ((flags
& XFS_RMAP_BMBT_BLOCK
) ^
680 (irec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
))
686 * When we allocate a new block, the first thing we do is add a reference to
687 * the extent in the rmap btree. This takes the form of a [agbno, length,
688 * owner, offset] record. Flags are encoded in the high bits of the offset
693 struct xfs_btree_cur
*cur
,
697 struct xfs_owner_info
*oinfo
)
699 struct xfs_mount
*mp
= cur
->bc_mp
;
700 struct xfs_rmap_irec ltrec
;
701 struct xfs_rmap_irec gtrec
;
708 unsigned int flags
= 0;
711 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
713 ignore_off
= XFS_RMAP_NON_INODE_OWNER(owner
) ||
714 (flags
& XFS_RMAP_BMBT_BLOCK
);
716 flags
|= XFS_RMAP_UNWRITTEN
;
717 trace_xfs_rmap_map(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
719 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo
));
722 * For the initial lookup, look for an exact match or the left-adjacent
723 * record for our insertion point. This will also give us the record for
724 * start block contiguity tests.
726 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
,
730 XFS_WANT_CORRUPTED_GOTO(mp
, have_lt
== 1, out_error
);
732 error
= xfs_rmap_get_rec(cur
, <rec
, &have_lt
);
735 XFS_WANT_CORRUPTED_GOTO(mp
, have_lt
== 1, out_error
);
736 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
737 cur
->bc_private
.a
.agno
, ltrec
.rm_startblock
,
738 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
739 ltrec
.rm_offset
, ltrec
.rm_flags
);
741 if (!xfs_rmap_is_mergeable(<rec
, owner
, flags
))
744 XFS_WANT_CORRUPTED_GOTO(mp
,
746 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
<= bno
, out_error
);
749 * Increment the cursor to see if we have a right-adjacent record to our
750 * insertion point. This will give us the record for end block
753 error
= xfs_btree_increment(cur
, 0, &have_gt
);
757 error
= xfs_rmap_get_rec(cur
, >rec
, &have_gt
);
760 XFS_WANT_CORRUPTED_GOTO(mp
, have_gt
== 1, out_error
);
761 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= gtrec
.rm_startblock
,
763 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
764 cur
->bc_private
.a
.agno
, gtrec
.rm_startblock
,
765 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
766 gtrec
.rm_offset
, gtrec
.rm_flags
);
767 if (!xfs_rmap_is_mergeable(>rec
, owner
, flags
))
772 * Note: cursor currently points one record to the right of ltrec, even
773 * if there is no record in the tree to the right.
776 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
&&
777 (ignore_off
|| ltrec
.rm_offset
+ ltrec
.rm_blockcount
== offset
)) {
779 * left edge contiguous, merge into left record.
783 * adding: |aaaaaaaaa|
784 * result: |rrrrrrrrrrrrrrrrrrr|
787 ltrec
.rm_blockcount
+= len
;
789 bno
+ len
== gtrec
.rm_startblock
&&
790 (ignore_off
|| offset
+ len
== gtrec
.rm_offset
) &&
791 (unsigned long)ltrec
.rm_blockcount
+ len
+
792 gtrec
.rm_blockcount
<= XFS_RMAP_LEN_MAX
) {
794 * right edge also contiguous, delete right record
795 * and merge into left record.
797 * ltbno ltlen gtbno gtlen
798 * orig: |ooooooooo| |ooooooooo|
799 * adding: |aaaaaaaaa|
800 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
802 ltrec
.rm_blockcount
+= gtrec
.rm_blockcount
;
803 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
809 error
= xfs_btree_delete(cur
, &i
);
812 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
815 /* point the cursor back to the left record and update */
816 error
= xfs_btree_decrement(cur
, 0, &have_gt
);
819 error
= xfs_rmap_update(cur
, <rec
);
822 } else if (have_gt
&&
823 bno
+ len
== gtrec
.rm_startblock
&&
824 (ignore_off
|| offset
+ len
== gtrec
.rm_offset
)) {
826 * right edge contiguous, merge into right record.
830 * adding: |aaaaaaaaa|
831 * Result: |rrrrrrrrrrrrrrrrrrr|
834 gtrec
.rm_startblock
= bno
;
835 gtrec
.rm_blockcount
+= len
;
837 gtrec
.rm_offset
= offset
;
838 error
= xfs_rmap_update(cur
, >rec
);
843 * no contiguous edge with identical owner, insert
844 * new record at current cursor position.
846 cur
->bc_rec
.r
.rm_startblock
= bno
;
847 cur
->bc_rec
.r
.rm_blockcount
= len
;
848 cur
->bc_rec
.r
.rm_owner
= owner
;
849 cur
->bc_rec
.r
.rm_offset
= offset
;
850 cur
->bc_rec
.r
.rm_flags
= flags
;
851 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
852 owner
, offset
, flags
);
853 error
= xfs_btree_insert(cur
, &i
);
856 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
859 trace_xfs_rmap_map_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
863 trace_xfs_rmap_map_error(mp
, cur
->bc_private
.a
.agno
,
869 * Add a reference to an extent in the rmap btree.
873 struct xfs_trans
*tp
,
874 struct xfs_buf
*agbp
,
878 struct xfs_owner_info
*oinfo
)
880 struct xfs_mount
*mp
= tp
->t_mountp
;
881 struct xfs_btree_cur
*cur
;
884 if (!xfs_sb_version_hasrmapbt(&mp
->m_sb
))
887 cur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
888 error
= xfs_rmap_map(cur
, bno
, len
, false, oinfo
);
892 xfs_btree_del_cursor(cur
, XFS_BTREE_NOERROR
);
896 xfs_btree_del_cursor(cur
, XFS_BTREE_ERROR
);
900 #define RMAP_LEFT_CONTIG (1 << 0)
901 #define RMAP_RIGHT_CONTIG (1 << 1)
902 #define RMAP_LEFT_FILLING (1 << 2)
903 #define RMAP_RIGHT_FILLING (1 << 3)
904 #define RMAP_LEFT_VALID (1 << 6)
905 #define RMAP_RIGHT_VALID (1 << 7)
913 * Convert an unwritten extent to a real extent or vice versa.
914 * Does not handle overlapping extents.
918 struct xfs_btree_cur
*cur
,
922 struct xfs_owner_info
*oinfo
)
924 struct xfs_mount
*mp
= cur
->bc_mp
;
925 struct xfs_rmap_irec r
[4]; /* neighbor extent entries */
926 /* left is 0, right is 1, prev is 2 */
933 unsigned int flags
= 0;
938 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
939 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner
) ||
940 (flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
))));
941 oldext
= unwritten
? XFS_RMAP_UNWRITTEN
: 0;
942 new_endoff
= offset
+ len
;
943 trace_xfs_rmap_convert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
947 * For the initial lookup, look for an exact match or the left-adjacent
948 * record for our insertion point. This will also give us the record for
949 * start block contiguity tests.
951 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, oldext
, &i
);
954 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
956 error
= xfs_rmap_get_rec(cur
, &PREV
, &i
);
959 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
960 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
961 cur
->bc_private
.a
.agno
, PREV
.rm_startblock
,
962 PREV
.rm_blockcount
, PREV
.rm_owner
,
963 PREV
.rm_offset
, PREV
.rm_flags
);
965 ASSERT(PREV
.rm_offset
<= offset
);
966 ASSERT(PREV
.rm_offset
+ PREV
.rm_blockcount
>= new_endoff
);
967 ASSERT((PREV
.rm_flags
& XFS_RMAP_UNWRITTEN
) == oldext
);
968 newext
= ~oldext
& XFS_RMAP_UNWRITTEN
;
971 * Set flags determining what part of the previous oldext allocation
972 * extent is being replaced by a newext allocation.
974 if (PREV
.rm_offset
== offset
)
975 state
|= RMAP_LEFT_FILLING
;
976 if (PREV
.rm_offset
+ PREV
.rm_blockcount
== new_endoff
)
977 state
|= RMAP_RIGHT_FILLING
;
980 * Decrement the cursor to see if we have a left-adjacent record to our
981 * insertion point. This will give us the record for end block
984 error
= xfs_btree_decrement(cur
, 0, &i
);
988 state
|= RMAP_LEFT_VALID
;
989 error
= xfs_rmap_get_rec(cur
, &LEFT
, &i
);
992 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
993 XFS_WANT_CORRUPTED_GOTO(mp
,
994 LEFT
.rm_startblock
+ LEFT
.rm_blockcount
<= bno
,
996 trace_xfs_rmap_find_left_neighbor_result(cur
->bc_mp
,
997 cur
->bc_private
.a
.agno
, LEFT
.rm_startblock
,
998 LEFT
.rm_blockcount
, LEFT
.rm_owner
,
999 LEFT
.rm_offset
, LEFT
.rm_flags
);
1000 if (LEFT
.rm_startblock
+ LEFT
.rm_blockcount
== bno
&&
1001 LEFT
.rm_offset
+ LEFT
.rm_blockcount
== offset
&&
1002 xfs_rmap_is_mergeable(&LEFT
, owner
, newext
))
1003 state
|= RMAP_LEFT_CONTIG
;
1007 * Increment the cursor to see if we have a right-adjacent record to our
1008 * insertion point. This will give us the record for end block
1011 error
= xfs_btree_increment(cur
, 0, &i
);
1014 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1015 error
= xfs_btree_increment(cur
, 0, &i
);
1019 state
|= RMAP_RIGHT_VALID
;
1020 error
= xfs_rmap_get_rec(cur
, &RIGHT
, &i
);
1023 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1024 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= RIGHT
.rm_startblock
,
1026 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1027 cur
->bc_private
.a
.agno
, RIGHT
.rm_startblock
,
1028 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1029 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1030 if (bno
+ len
== RIGHT
.rm_startblock
&&
1031 offset
+ len
== RIGHT
.rm_offset
&&
1032 xfs_rmap_is_mergeable(&RIGHT
, owner
, newext
))
1033 state
|= RMAP_RIGHT_CONTIG
;
1036 /* check that left + prev + right is not too long */
1037 if ((state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1038 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) ==
1039 (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1040 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
) &&
1041 (unsigned long)LEFT
.rm_blockcount
+ len
+
1042 RIGHT
.rm_blockcount
> XFS_RMAP_LEN_MAX
)
1043 state
&= ~RMAP_RIGHT_CONTIG
;
1045 trace_xfs_rmap_convert_state(mp
, cur
->bc_private
.a
.agno
, state
,
1048 /* reset the cursor back to PREV */
1049 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, oldext
, &i
);
1052 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1055 * Switch out based on the FILLING and CONTIG state bits.
1057 switch (state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1058 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) {
1059 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1060 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1062 * Setting all of a previous oldext extent to newext.
1063 * The left and right neighbors are both contiguous with new.
1065 error
= xfs_btree_increment(cur
, 0, &i
);
1068 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1069 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1070 RIGHT
.rm_startblock
, RIGHT
.rm_blockcount
,
1071 RIGHT
.rm_owner
, RIGHT
.rm_offset
,
1073 error
= xfs_btree_delete(cur
, &i
);
1076 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1077 error
= xfs_btree_decrement(cur
, 0, &i
);
1080 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1081 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1082 PREV
.rm_startblock
, PREV
.rm_blockcount
,
1083 PREV
.rm_owner
, PREV
.rm_offset
,
1085 error
= xfs_btree_delete(cur
, &i
);
1088 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1089 error
= xfs_btree_decrement(cur
, 0, &i
);
1092 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1094 NEW
.rm_blockcount
+= PREV
.rm_blockcount
+ RIGHT
.rm_blockcount
;
1095 error
= xfs_rmap_update(cur
, &NEW
);
1100 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1102 * Setting all of a previous oldext extent to newext.
1103 * The left neighbor is contiguous, the right is not.
1105 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1106 PREV
.rm_startblock
, PREV
.rm_blockcount
,
1107 PREV
.rm_owner
, PREV
.rm_offset
,
1109 error
= xfs_btree_delete(cur
, &i
);
1112 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1113 error
= xfs_btree_decrement(cur
, 0, &i
);
1116 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1118 NEW
.rm_blockcount
+= PREV
.rm_blockcount
;
1119 error
= xfs_rmap_update(cur
, &NEW
);
1124 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1126 * Setting all of a previous oldext extent to newext.
1127 * The right neighbor is contiguous, the left is not.
1129 error
= xfs_btree_increment(cur
, 0, &i
);
1132 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1133 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1134 RIGHT
.rm_startblock
, RIGHT
.rm_blockcount
,
1135 RIGHT
.rm_owner
, RIGHT
.rm_offset
,
1137 error
= xfs_btree_delete(cur
, &i
);
1140 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1141 error
= xfs_btree_decrement(cur
, 0, &i
);
1144 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1146 NEW
.rm_blockcount
= len
+ RIGHT
.rm_blockcount
;
1147 NEW
.rm_flags
= newext
;
1148 error
= xfs_rmap_update(cur
, &NEW
);
1153 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
:
1155 * Setting all of a previous oldext extent to newext.
1156 * Neither the left nor right neighbors are contiguous with
1160 NEW
.rm_flags
= newext
;
1161 error
= xfs_rmap_update(cur
, &NEW
);
1166 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
:
1168 * Setting the first part of a previous oldext extent to newext.
1169 * The left neighbor is contiguous.
1172 NEW
.rm_offset
+= len
;
1173 NEW
.rm_startblock
+= len
;
1174 NEW
.rm_blockcount
-= len
;
1175 error
= xfs_rmap_update(cur
, &NEW
);
1178 error
= xfs_btree_decrement(cur
, 0, &i
);
1182 NEW
.rm_blockcount
+= len
;
1183 error
= xfs_rmap_update(cur
, &NEW
);
1188 case RMAP_LEFT_FILLING
:
1190 * Setting the first part of a previous oldext extent to newext.
1191 * The left neighbor is not contiguous.
1194 NEW
.rm_startblock
+= len
;
1195 NEW
.rm_offset
+= len
;
1196 NEW
.rm_blockcount
-= len
;
1197 error
= xfs_rmap_update(cur
, &NEW
);
1200 NEW
.rm_startblock
= bno
;
1201 NEW
.rm_owner
= owner
;
1202 NEW
.rm_offset
= offset
;
1203 NEW
.rm_blockcount
= len
;
1204 NEW
.rm_flags
= newext
;
1205 cur
->bc_rec
.r
= NEW
;
1206 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
,
1207 len
, owner
, offset
, newext
);
1208 error
= xfs_btree_insert(cur
, &i
);
1211 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1214 case RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1216 * Setting the last part of a previous oldext extent to newext.
1217 * The right neighbor is contiguous with the new allocation.
1220 NEW
.rm_blockcount
-= len
;
1221 error
= xfs_rmap_update(cur
, &NEW
);
1224 error
= xfs_btree_increment(cur
, 0, &i
);
1228 NEW
.rm_offset
= offset
;
1229 NEW
.rm_startblock
= bno
;
1230 NEW
.rm_blockcount
+= len
;
1231 error
= xfs_rmap_update(cur
, &NEW
);
1236 case RMAP_RIGHT_FILLING
:
1238 * Setting the last part of a previous oldext extent to newext.
1239 * The right neighbor is not contiguous.
1242 NEW
.rm_blockcount
-= len
;
1243 error
= xfs_rmap_update(cur
, &NEW
);
1246 error
= xfs_rmap_lookup_eq(cur
, bno
, len
, owner
, offset
,
1250 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 0, done
);
1251 NEW
.rm_startblock
= bno
;
1252 NEW
.rm_owner
= owner
;
1253 NEW
.rm_offset
= offset
;
1254 NEW
.rm_blockcount
= len
;
1255 NEW
.rm_flags
= newext
;
1256 cur
->bc_rec
.r
= NEW
;
1257 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
,
1258 len
, owner
, offset
, newext
);
1259 error
= xfs_btree_insert(cur
, &i
);
1262 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1267 * Setting the middle part of a previous oldext extent to
1268 * newext. Contiguity is impossible here.
1269 * One extent becomes three extents.
1271 /* new right extent - oldext */
1272 NEW
.rm_startblock
= bno
+ len
;
1273 NEW
.rm_owner
= owner
;
1274 NEW
.rm_offset
= new_endoff
;
1275 NEW
.rm_blockcount
= PREV
.rm_offset
+ PREV
.rm_blockcount
-
1277 NEW
.rm_flags
= PREV
.rm_flags
;
1278 error
= xfs_rmap_update(cur
, &NEW
);
1281 /* new left extent - oldext */
1283 NEW
.rm_blockcount
= offset
- PREV
.rm_offset
;
1284 cur
->bc_rec
.r
= NEW
;
1285 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
,
1286 NEW
.rm_startblock
, NEW
.rm_blockcount
,
1287 NEW
.rm_owner
, NEW
.rm_offset
,
1289 error
= xfs_btree_insert(cur
, &i
);
1292 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1294 * Reset the cursor to the position of the new extent
1295 * we are about to insert as we can't trust it after
1296 * the previous insert.
1298 error
= xfs_rmap_lookup_eq(cur
, bno
, len
, owner
, offset
,
1302 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 0, done
);
1303 /* new middle extent - newext */
1304 cur
->bc_rec
.r
.rm_flags
&= ~XFS_RMAP_UNWRITTEN
;
1305 cur
->bc_rec
.r
.rm_flags
|= newext
;
1306 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1307 owner
, offset
, newext
);
1308 error
= xfs_btree_insert(cur
, &i
);
1311 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1314 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1315 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1316 case RMAP_LEFT_FILLING
| RMAP_RIGHT_CONTIG
:
1317 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1318 case RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1319 case RMAP_LEFT_CONTIG
:
1320 case RMAP_RIGHT_CONTIG
:
1322 * These cases are all impossible.
1327 trace_xfs_rmap_convert_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1331 trace_xfs_rmap_convert_error(cur
->bc_mp
,
1332 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1337 * Convert an unwritten extent to a real extent or vice versa. If there is no
1338 * possibility of overlapping extents, delegate to the simpler convert
1342 xfs_rmap_convert_shared(
1343 struct xfs_btree_cur
*cur
,
1347 struct xfs_owner_info
*oinfo
)
1349 struct xfs_mount
*mp
= cur
->bc_mp
;
1350 struct xfs_rmap_irec r
[4]; /* neighbor extent entries */
1351 /* left is 0, right is 1, prev is 2 */
1355 uint64_t new_endoff
;
1356 unsigned int oldext
;
1357 unsigned int newext
;
1358 unsigned int flags
= 0;
1363 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1364 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner
) ||
1365 (flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
))));
1366 oldext
= unwritten
? XFS_RMAP_UNWRITTEN
: 0;
1367 new_endoff
= offset
+ len
;
1368 trace_xfs_rmap_convert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1372 * For the initial lookup, look for and exact match or the left-adjacent
1373 * record for our insertion point. This will also give us the record for
1374 * start block contiguity tests.
1376 error
= xfs_rmap_lookup_le_range(cur
, bno
, owner
, offset
, flags
,
1378 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1380 ASSERT(PREV
.rm_offset
<= offset
);
1381 ASSERT(PREV
.rm_offset
+ PREV
.rm_blockcount
>= new_endoff
);
1382 ASSERT((PREV
.rm_flags
& XFS_RMAP_UNWRITTEN
) == oldext
);
1383 newext
= ~oldext
& XFS_RMAP_UNWRITTEN
;
1386 * Set flags determining what part of the previous oldext allocation
1387 * extent is being replaced by a newext allocation.
1389 if (PREV
.rm_offset
== offset
)
1390 state
|= RMAP_LEFT_FILLING
;
1391 if (PREV
.rm_offset
+ PREV
.rm_blockcount
== new_endoff
)
1392 state
|= RMAP_RIGHT_FILLING
;
1394 /* Is there a left record that abuts our range? */
1395 error
= xfs_rmap_find_left_neighbor(cur
, bno
, owner
, offset
, newext
,
1400 state
|= RMAP_LEFT_VALID
;
1401 XFS_WANT_CORRUPTED_GOTO(mp
,
1402 LEFT
.rm_startblock
+ LEFT
.rm_blockcount
<= bno
,
1404 if (xfs_rmap_is_mergeable(&LEFT
, owner
, newext
))
1405 state
|= RMAP_LEFT_CONTIG
;
1408 /* Is there a right record that abuts our range? */
1409 error
= xfs_rmap_lookup_eq(cur
, bno
+ len
, len
, owner
, offset
+ len
,
1414 state
|= RMAP_RIGHT_VALID
;
1415 error
= xfs_rmap_get_rec(cur
, &RIGHT
, &i
);
1418 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1419 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= RIGHT
.rm_startblock
,
1421 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1422 cur
->bc_private
.a
.agno
, RIGHT
.rm_startblock
,
1423 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1424 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1425 if (xfs_rmap_is_mergeable(&RIGHT
, owner
, newext
))
1426 state
|= RMAP_RIGHT_CONTIG
;
1429 /* check that left + prev + right is not too long */
1430 if ((state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1431 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) ==
1432 (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1433 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
) &&
1434 (unsigned long)LEFT
.rm_blockcount
+ len
+
1435 RIGHT
.rm_blockcount
> XFS_RMAP_LEN_MAX
)
1436 state
&= ~RMAP_RIGHT_CONTIG
;
1438 trace_xfs_rmap_convert_state(mp
, cur
->bc_private
.a
.agno
, state
,
1441 * Switch out based on the FILLING and CONTIG state bits.
1443 switch (state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1444 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) {
1445 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1446 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1448 * Setting all of a previous oldext extent to newext.
1449 * The left and right neighbors are both contiguous with new.
1451 error
= xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1452 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1453 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1456 error
= xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1457 PREV
.rm_blockcount
, PREV
.rm_owner
,
1458 PREV
.rm_offset
, PREV
.rm_flags
);
1462 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1463 NEW
.rm_blockcount
, NEW
.rm_owner
,
1464 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1467 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1468 NEW
.rm_blockcount
+= PREV
.rm_blockcount
+ RIGHT
.rm_blockcount
;
1469 error
= xfs_rmap_update(cur
, &NEW
);
1474 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1476 * Setting all of a previous oldext extent to newext.
1477 * The left neighbor is contiguous, the right is not.
1479 error
= xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1480 PREV
.rm_blockcount
, PREV
.rm_owner
,
1481 PREV
.rm_offset
, PREV
.rm_flags
);
1485 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1486 NEW
.rm_blockcount
, NEW
.rm_owner
,
1487 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1490 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1491 NEW
.rm_blockcount
+= PREV
.rm_blockcount
;
1492 error
= xfs_rmap_update(cur
, &NEW
);
1497 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1499 * Setting all of a previous oldext extent to newext.
1500 * The right neighbor is contiguous, the left is not.
1502 error
= xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1503 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1504 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1508 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1509 NEW
.rm_blockcount
, NEW
.rm_owner
,
1510 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1513 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1514 NEW
.rm_blockcount
+= RIGHT
.rm_blockcount
;
1515 NEW
.rm_flags
= RIGHT
.rm_flags
;
1516 error
= xfs_rmap_update(cur
, &NEW
);
1521 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
:
1523 * Setting all of a previous oldext extent to newext.
1524 * Neither the left nor right neighbors are contiguous with
1528 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1529 NEW
.rm_blockcount
, NEW
.rm_owner
,
1530 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1533 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1534 NEW
.rm_flags
= newext
;
1535 error
= xfs_rmap_update(cur
, &NEW
);
1540 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
:
1542 * Setting the first part of a previous oldext extent to newext.
1543 * The left neighbor is contiguous.
1546 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1547 NEW
.rm_blockcount
, NEW
.rm_owner
,
1548 NEW
.rm_offset
, NEW
.rm_flags
);
1551 NEW
.rm_offset
+= len
;
1552 NEW
.rm_startblock
+= len
;
1553 NEW
.rm_blockcount
-= len
;
1554 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1555 NEW
.rm_blockcount
, NEW
.rm_owner
,
1556 NEW
.rm_offset
, NEW
.rm_flags
);
1560 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1561 NEW
.rm_blockcount
, NEW
.rm_owner
,
1562 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1565 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1566 NEW
.rm_blockcount
+= len
;
1567 error
= xfs_rmap_update(cur
, &NEW
);
1572 case RMAP_LEFT_FILLING
:
1574 * Setting the first part of a previous oldext extent to newext.
1575 * The left neighbor is not contiguous.
1578 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1579 NEW
.rm_blockcount
, NEW
.rm_owner
,
1580 NEW
.rm_offset
, NEW
.rm_flags
);
1583 NEW
.rm_offset
+= len
;
1584 NEW
.rm_startblock
+= len
;
1585 NEW
.rm_blockcount
-= len
;
1586 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1587 NEW
.rm_blockcount
, NEW
.rm_owner
,
1588 NEW
.rm_offset
, NEW
.rm_flags
);
1591 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1596 case RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1598 * Setting the last part of a previous oldext extent to newext.
1599 * The right neighbor is contiguous with the new allocation.
1602 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1603 NEW
.rm_blockcount
, NEW
.rm_owner
,
1604 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1607 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1608 NEW
.rm_blockcount
= offset
- NEW
.rm_offset
;
1609 error
= xfs_rmap_update(cur
, &NEW
);
1613 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1614 NEW
.rm_blockcount
, NEW
.rm_owner
,
1615 NEW
.rm_offset
, NEW
.rm_flags
);
1618 NEW
.rm_offset
= offset
;
1619 NEW
.rm_startblock
= bno
;
1620 NEW
.rm_blockcount
+= len
;
1621 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1622 NEW
.rm_blockcount
, NEW
.rm_owner
,
1623 NEW
.rm_offset
, NEW
.rm_flags
);
1628 case RMAP_RIGHT_FILLING
:
1630 * Setting the last part of a previous oldext extent to newext.
1631 * The right neighbor is not contiguous.
1634 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1635 NEW
.rm_blockcount
, NEW
.rm_owner
,
1636 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1639 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1640 NEW
.rm_blockcount
-= len
;
1641 error
= xfs_rmap_update(cur
, &NEW
);
1644 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1651 * Setting the middle part of a previous oldext extent to
1652 * newext. Contiguity is impossible here.
1653 * One extent becomes three extents.
1655 /* new right extent - oldext */
1656 NEW
.rm_startblock
= bno
+ len
;
1657 NEW
.rm_owner
= owner
;
1658 NEW
.rm_offset
= new_endoff
;
1659 NEW
.rm_blockcount
= PREV
.rm_offset
+ PREV
.rm_blockcount
-
1661 NEW
.rm_flags
= PREV
.rm_flags
;
1662 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1663 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
1667 /* new left extent - oldext */
1669 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1670 NEW
.rm_blockcount
, NEW
.rm_owner
,
1671 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1674 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1675 NEW
.rm_blockcount
= offset
- NEW
.rm_offset
;
1676 error
= xfs_rmap_update(cur
, &NEW
);
1679 /* new middle extent - newext */
1680 NEW
.rm_startblock
= bno
;
1681 NEW
.rm_blockcount
= len
;
1682 NEW
.rm_owner
= owner
;
1683 NEW
.rm_offset
= offset
;
1684 NEW
.rm_flags
= newext
;
1685 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1686 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
1692 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1693 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1694 case RMAP_LEFT_FILLING
| RMAP_RIGHT_CONTIG
:
1695 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1696 case RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1697 case RMAP_LEFT_CONTIG
:
1698 case RMAP_RIGHT_CONTIG
:
1700 * These cases are all impossible.
1705 trace_xfs_rmap_convert_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1709 trace_xfs_rmap_convert_error(cur
->bc_mp
,
1710 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1720 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1721 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1722 * that the prev/next records in the btree might belong to another owner.
1723 * Therefore we must use delete+insert to alter any of the key fields.
1725 * For every other situation there can only be one owner for a given extent,
1726 * so we can call the regular _free function.
1729 xfs_rmap_unmap_shared(
1730 struct xfs_btree_cur
*cur
,
1734 struct xfs_owner_info
*oinfo
)
1736 struct xfs_mount
*mp
= cur
->bc_mp
;
1737 struct xfs_rmap_irec ltrec
;
1745 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1747 flags
|= XFS_RMAP_UNWRITTEN
;
1748 trace_xfs_rmap_unmap(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1752 * We should always have a left record because there's a static record
1753 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1754 * will not ever be removed from the tree.
1756 error
= xfs_rmap_lookup_le_range(cur
, bno
, owner
, offset
, flags
,
1760 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1761 ltoff
= ltrec
.rm_offset
;
1763 /* Make sure the extent we found covers the entire freeing range. */
1764 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_startblock
<= bno
&&
1765 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
>=
1766 bno
+ len
, out_error
);
1768 /* Make sure the owner matches what we expect to find in the tree. */
1769 XFS_WANT_CORRUPTED_GOTO(mp
, owner
== ltrec
.rm_owner
, out_error
);
1771 /* Make sure the unwritten flag matches. */
1772 XFS_WANT_CORRUPTED_GOTO(mp
, (flags
& XFS_RMAP_UNWRITTEN
) ==
1773 (ltrec
.rm_flags
& XFS_RMAP_UNWRITTEN
), out_error
);
1775 /* Check the offset. */
1776 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_offset
<= offset
, out_error
);
1777 XFS_WANT_CORRUPTED_GOTO(mp
, offset
<= ltoff
+ ltrec
.rm_blockcount
,
1780 if (ltrec
.rm_startblock
== bno
&& ltrec
.rm_blockcount
== len
) {
1781 /* Exact match, simply remove the record from rmap tree. */
1782 error
= xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
1783 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1784 ltrec
.rm_offset
, ltrec
.rm_flags
);
1787 } else if (ltrec
.rm_startblock
== bno
) {
1789 * Overlap left hand side of extent: move the start, trim the
1790 * length and update the current record.
1793 * Orig: |oooooooooooooooooooo|
1794 * Freeing: |fffffffff|
1795 * Result: |rrrrrrrrrr|
1799 /* Delete prev rmap. */
1800 error
= xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
1801 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1802 ltrec
.rm_offset
, ltrec
.rm_flags
);
1806 /* Add an rmap at the new offset. */
1807 ltrec
.rm_startblock
+= len
;
1808 ltrec
.rm_blockcount
-= len
;
1809 ltrec
.rm_offset
+= len
;
1810 error
= xfs_rmap_insert(cur
, ltrec
.rm_startblock
,
1811 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1812 ltrec
.rm_offset
, ltrec
.rm_flags
);
1815 } else if (ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
+ len
) {
1817 * Overlap right hand side of extent: trim the length and
1818 * update the current record.
1821 * Orig: |oooooooooooooooooooo|
1822 * Freeing: |fffffffff|
1823 * Result: |rrrrrrrrrr|
1826 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1827 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1828 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1831 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1832 ltrec
.rm_blockcount
-= len
;
1833 error
= xfs_rmap_update(cur
, <rec
);
1838 * Overlap middle of extent: trim the length of the existing
1839 * record to the length of the new left-extent size, increment
1840 * the insertion position so we can insert a new record
1841 * containing the remaining right-extent space.
1844 * Orig: |oooooooooooooooooooo|
1845 * Freeing: |fffffffff|
1846 * Result: |rrrrr| |rrrr|
1849 xfs_extlen_t orig_len
= ltrec
.rm_blockcount
;
1851 /* Shrink the left side of the rmap */
1852 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1853 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1854 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1857 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1858 ltrec
.rm_blockcount
= bno
- ltrec
.rm_startblock
;
1859 error
= xfs_rmap_update(cur
, <rec
);
1863 /* Add an rmap at the new offset */
1864 error
= xfs_rmap_insert(cur
, bno
+ len
,
1865 orig_len
- len
- ltrec
.rm_blockcount
,
1866 ltrec
.rm_owner
, offset
+ len
,
1872 trace_xfs_rmap_unmap_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1876 trace_xfs_rmap_unmap_error(cur
->bc_mp
,
1877 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1882 * Find an extent in the rmap btree and map it. For rmap extent types that
1883 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1884 * that the prev/next records in the btree might belong to another owner.
1885 * Therefore we must use delete+insert to alter any of the key fields.
1887 * For every other situation there can only be one owner for a given extent,
1888 * so we can call the regular _alloc function.
1891 xfs_rmap_map_shared(
1892 struct xfs_btree_cur
*cur
,
1896 struct xfs_owner_info
*oinfo
)
1898 struct xfs_mount
*mp
= cur
->bc_mp
;
1899 struct xfs_rmap_irec ltrec
;
1900 struct xfs_rmap_irec gtrec
;
1907 unsigned int flags
= 0;
1909 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1911 flags
|= XFS_RMAP_UNWRITTEN
;
1912 trace_xfs_rmap_map(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1915 /* Is there a left record that abuts our range? */
1916 error
= xfs_rmap_find_left_neighbor(cur
, bno
, owner
, offset
, flags
,
1921 !xfs_rmap_is_mergeable(<rec
, owner
, flags
))
1924 /* Is there a right record that abuts our range? */
1925 error
= xfs_rmap_lookup_eq(cur
, bno
+ len
, len
, owner
, offset
+ len
,
1930 error
= xfs_rmap_get_rec(cur
, >rec
, &have_gt
);
1933 XFS_WANT_CORRUPTED_GOTO(mp
, have_gt
== 1, out_error
);
1934 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1935 cur
->bc_private
.a
.agno
, gtrec
.rm_startblock
,
1936 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
1937 gtrec
.rm_offset
, gtrec
.rm_flags
);
1939 if (!xfs_rmap_is_mergeable(>rec
, owner
, flags
))
1944 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
&&
1945 ltrec
.rm_offset
+ ltrec
.rm_blockcount
== offset
) {
1947 * Left edge contiguous, merge into left record.
1951 * adding: |aaaaaaaaa|
1952 * result: |rrrrrrrrrrrrrrrrrrr|
1955 ltrec
.rm_blockcount
+= len
;
1957 bno
+ len
== gtrec
.rm_startblock
&&
1958 offset
+ len
== gtrec
.rm_offset
) {
1960 * Right edge also contiguous, delete right record
1961 * and merge into left record.
1963 * ltbno ltlen gtbno gtlen
1964 * orig: |ooooooooo| |ooooooooo|
1965 * adding: |aaaaaaaaa|
1966 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1968 ltrec
.rm_blockcount
+= gtrec
.rm_blockcount
;
1969 error
= xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
1970 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
1971 gtrec
.rm_offset
, gtrec
.rm_flags
);
1976 /* Point the cursor back to the left record and update. */
1977 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1978 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1979 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1982 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1984 error
= xfs_rmap_update(cur
, <rec
);
1987 } else if (have_gt
&&
1988 bno
+ len
== gtrec
.rm_startblock
&&
1989 offset
+ len
== gtrec
.rm_offset
) {
1991 * Right edge contiguous, merge into right record.
1995 * adding: |aaaaaaaaa|
1996 * Result: |rrrrrrrrrrrrrrrrrrr|
1999 /* Delete the old record. */
2000 error
= xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
2001 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2002 gtrec
.rm_offset
, gtrec
.rm_flags
);
2006 /* Move the start and re-add it. */
2007 gtrec
.rm_startblock
= bno
;
2008 gtrec
.rm_blockcount
+= len
;
2009 gtrec
.rm_offset
= offset
;
2010 error
= xfs_rmap_insert(cur
, gtrec
.rm_startblock
,
2011 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
2012 gtrec
.rm_offset
, gtrec
.rm_flags
);
2017 * No contiguous edge with identical owner, insert
2018 * new record at current cursor position.
2020 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, flags
);
2025 trace_xfs_rmap_map_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
2029 trace_xfs_rmap_map_error(cur
->bc_mp
,
2030 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
2034 struct xfs_rmap_query_range_info
{
2035 xfs_rmap_query_range_fn fn
;
2039 /* Format btree record and pass to our callback. */
2041 xfs_rmap_query_range_helper(
2042 struct xfs_btree_cur
*cur
,
2043 union xfs_btree_rec
*rec
,
2046 struct xfs_rmap_query_range_info
*query
= priv
;
2047 struct xfs_rmap_irec irec
;
2050 error
= xfs_rmap_btrec_to_irec(rec
, &irec
);
2053 return query
->fn(cur
, &irec
, query
->priv
);
2056 /* Find all rmaps between two keys. */
2058 xfs_rmap_query_range(
2059 struct xfs_btree_cur
*cur
,
2060 struct xfs_rmap_irec
*low_rec
,
2061 struct xfs_rmap_irec
*high_rec
,
2062 xfs_rmap_query_range_fn fn
,
2065 union xfs_btree_irec low_brec
;
2066 union xfs_btree_irec high_brec
;
2067 struct xfs_rmap_query_range_info query
;
2069 low_brec
.r
= *low_rec
;
2070 high_brec
.r
= *high_rec
;
2073 return xfs_btree_query_range(cur
, &low_brec
, &high_brec
,
2074 xfs_rmap_query_range_helper
, &query
);
2077 /* Find all rmaps. */
2080 struct xfs_btree_cur
*cur
,
2081 xfs_rmap_query_range_fn fn
,
2084 struct xfs_rmap_query_range_info query
;
2088 return xfs_btree_query_all(cur
, xfs_rmap_query_range_helper
, &query
);
2091 /* Clean up after calling xfs_rmap_finish_one. */
2093 xfs_rmap_finish_one_cleanup(
2094 struct xfs_trans
*tp
,
2095 struct xfs_btree_cur
*rcur
,
2098 struct xfs_buf
*agbp
;
2102 agbp
= rcur
->bc_private
.a
.agbp
;
2103 xfs_btree_del_cursor(rcur
, error
? XFS_BTREE_ERROR
: XFS_BTREE_NOERROR
);
2105 xfs_trans_brelse(tp
, agbp
);
2109 * Process one of the deferred rmap operations. We pass back the
2110 * btree cursor to maintain our lock on the rmapbt between calls.
2111 * This saves time and eliminates a buffer deadlock between the
2112 * superblock and the AGF because we'll always grab them in the same
2116 xfs_rmap_finish_one(
2117 struct xfs_trans
*tp
,
2118 enum xfs_rmap_intent_type type
,
2121 xfs_fileoff_t startoff
,
2122 xfs_fsblock_t startblock
,
2123 xfs_filblks_t blockcount
,
2125 struct xfs_btree_cur
**pcur
)
2127 struct xfs_mount
*mp
= tp
->t_mountp
;
2128 struct xfs_btree_cur
*rcur
;
2129 struct xfs_buf
*agbp
= NULL
;
2131 xfs_agnumber_t agno
;
2132 struct xfs_owner_info oinfo
;
2136 agno
= XFS_FSB_TO_AGNO(mp
, startblock
);
2137 ASSERT(agno
!= NULLAGNUMBER
);
2138 bno
= XFS_FSB_TO_AGBNO(mp
, startblock
);
2140 trace_xfs_rmap_deferred(mp
, agno
, type
, bno
, owner
, whichfork
,
2141 startoff
, blockcount
, state
);
2143 if (XFS_TEST_ERROR(false, mp
,
2144 XFS_ERRTAG_RMAP_FINISH_ONE
))
2148 * If we haven't gotten a cursor or the cursor AG doesn't match
2149 * the startblock, get one now.
2152 if (rcur
!= NULL
&& rcur
->bc_private
.a
.agno
!= agno
) {
2153 xfs_rmap_finish_one_cleanup(tp
, rcur
, 0);
2159 * Refresh the freelist before we start changing the
2160 * rmapbt, because a shape change could cause us to
2163 error
= xfs_free_extent_fix_freelist(tp
, agno
, &agbp
);
2167 return -EFSCORRUPTED
;
2169 rcur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
2177 xfs_rmap_ino_owner(&oinfo
, owner
, whichfork
, startoff
);
2178 unwritten
= state
== XFS_EXT_UNWRITTEN
;
2179 bno
= XFS_FSB_TO_AGBNO(rcur
->bc_mp
, startblock
);
2182 case XFS_RMAP_ALLOC
:
2184 error
= xfs_rmap_map(rcur
, bno
, blockcount
, unwritten
, &oinfo
);
2186 case XFS_RMAP_MAP_SHARED
:
2187 error
= xfs_rmap_map_shared(rcur
, bno
, blockcount
, unwritten
,
2191 case XFS_RMAP_UNMAP
:
2192 error
= xfs_rmap_unmap(rcur
, bno
, blockcount
, unwritten
,
2195 case XFS_RMAP_UNMAP_SHARED
:
2196 error
= xfs_rmap_unmap_shared(rcur
, bno
, blockcount
, unwritten
,
2199 case XFS_RMAP_CONVERT
:
2200 error
= xfs_rmap_convert(rcur
, bno
, blockcount
, !unwritten
,
2203 case XFS_RMAP_CONVERT_SHARED
:
2204 error
= xfs_rmap_convert_shared(rcur
, bno
, blockcount
,
2205 !unwritten
, &oinfo
);
2209 error
= -EFSCORRUPTED
;
2214 xfs_trans_brelse(tp
, agbp
);
2220 * Don't defer an rmap if we aren't an rmap filesystem.
2223 xfs_rmap_update_is_needed(
2224 struct xfs_mount
*mp
,
2227 return xfs_sb_version_hasrmapbt(&mp
->m_sb
) && whichfork
!= XFS_COW_FORK
;
2231 * Record a rmap intent; the list is kept sorted first by AG and then by
2236 struct xfs_mount
*mp
,
2237 struct xfs_defer_ops
*dfops
,
2238 enum xfs_rmap_intent_type type
,
2241 struct xfs_bmbt_irec
*bmap
)
2243 struct xfs_rmap_intent
*ri
;
2245 trace_xfs_rmap_defer(mp
, XFS_FSB_TO_AGNO(mp
, bmap
->br_startblock
),
2247 XFS_FSB_TO_AGBNO(mp
, bmap
->br_startblock
),
2250 bmap
->br_blockcount
,
2253 ri
= kmem_alloc(sizeof(struct xfs_rmap_intent
), KM_SLEEP
| KM_NOFS
);
2254 INIT_LIST_HEAD(&ri
->ri_list
);
2256 ri
->ri_owner
= owner
;
2257 ri
->ri_whichfork
= whichfork
;
2258 ri
->ri_bmap
= *bmap
;
2260 xfs_defer_add(dfops
, XFS_DEFER_OPS_TYPE_RMAP
, &ri
->ri_list
);
2264 /* Map an extent into a file. */
2266 xfs_rmap_map_extent(
2267 struct xfs_mount
*mp
,
2268 struct xfs_defer_ops
*dfops
,
2269 struct xfs_inode
*ip
,
2271 struct xfs_bmbt_irec
*PREV
)
2273 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2276 return __xfs_rmap_add(mp
, dfops
, xfs_is_reflink_inode(ip
) ?
2277 XFS_RMAP_MAP_SHARED
: XFS_RMAP_MAP
, ip
->i_ino
,
2281 /* Unmap an extent out of a file. */
2283 xfs_rmap_unmap_extent(
2284 struct xfs_mount
*mp
,
2285 struct xfs_defer_ops
*dfops
,
2286 struct xfs_inode
*ip
,
2288 struct xfs_bmbt_irec
*PREV
)
2290 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2293 return __xfs_rmap_add(mp
, dfops
, xfs_is_reflink_inode(ip
) ?
2294 XFS_RMAP_UNMAP_SHARED
: XFS_RMAP_UNMAP
, ip
->i_ino
,
2298 /* Convert a data fork extent from unwritten to real or vice versa. */
2300 xfs_rmap_convert_extent(
2301 struct xfs_mount
*mp
,
2302 struct xfs_defer_ops
*dfops
,
2303 struct xfs_inode
*ip
,
2305 struct xfs_bmbt_irec
*PREV
)
2307 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2310 return __xfs_rmap_add(mp
, dfops
, xfs_is_reflink_inode(ip
) ?
2311 XFS_RMAP_CONVERT_SHARED
: XFS_RMAP_CONVERT
, ip
->i_ino
,
2315 /* Schedule the creation of an rmap for non-file data. */
2317 xfs_rmap_alloc_extent(
2318 struct xfs_mount
*mp
,
2319 struct xfs_defer_ops
*dfops
,
2320 xfs_agnumber_t agno
,
2325 struct xfs_bmbt_irec bmap
;
2327 if (!xfs_rmap_update_is_needed(mp
, XFS_DATA_FORK
))
2330 bmap
.br_startblock
= XFS_AGB_TO_FSB(mp
, agno
, bno
);
2331 bmap
.br_blockcount
= len
;
2332 bmap
.br_startoff
= 0;
2333 bmap
.br_state
= XFS_EXT_NORM
;
2335 return __xfs_rmap_add(mp
, dfops
, XFS_RMAP_ALLOC
, owner
,
2336 XFS_DATA_FORK
, &bmap
);
2339 /* Schedule the deletion of an rmap for non-file data. */
2341 xfs_rmap_free_extent(
2342 struct xfs_mount
*mp
,
2343 struct xfs_defer_ops
*dfops
,
2344 xfs_agnumber_t agno
,
2349 struct xfs_bmbt_irec bmap
;
2351 if (!xfs_rmap_update_is_needed(mp
, XFS_DATA_FORK
))
2354 bmap
.br_startblock
= XFS_AGB_TO_FSB(mp
, agno
, bno
);
2355 bmap
.br_blockcount
= len
;
2356 bmap
.br_startoff
= 0;
2357 bmap
.br_state
= XFS_EXT_NORM
;
2359 return __xfs_rmap_add(mp
, dfops
, XFS_RMAP_FREE
, owner
,
2360 XFS_DATA_FORK
, &bmap
);
2363 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2366 const struct xfs_rmap_irec
*a
,
2367 const struct xfs_rmap_irec
*b
)
2372 oa
= xfs_rmap_irec_offset_pack(a
);
2373 ob
= xfs_rmap_irec_offset_pack(b
);
2375 if (a
->rm_startblock
< b
->rm_startblock
)
2377 else if (a
->rm_startblock
> b
->rm_startblock
)
2379 else if (a
->rm_owner
< b
->rm_owner
)
2381 else if (a
->rm_owner
> b
->rm_owner
)
2391 /* Is there a record covering a given extent? */
2393 xfs_rmap_has_record(
2394 struct xfs_btree_cur
*cur
,
2399 union xfs_btree_irec low
;
2400 union xfs_btree_irec high
;
2402 memset(&low
, 0, sizeof(low
));
2403 low
.r
.rm_startblock
= bno
;
2404 memset(&high
, 0xFF, sizeof(high
));
2405 high
.r
.rm_startblock
= bno
+ len
- 1;
2407 return xfs_btree_has_record(cur
, &low
, &high
, exists
);
2411 * Is there a record for this owner completely covering a given physical
2412 * extent? If so, *has_rmap will be set to true. If there is no record
2413 * or the record only covers part of the range, we set *has_rmap to false.
2414 * This function doesn't perform range lookups or offset checks, so it is
2415 * not suitable for checking data fork blocks.
2418 xfs_rmap_record_exists(
2419 struct xfs_btree_cur
*cur
,
2422 struct xfs_owner_info
*oinfo
,
2429 struct xfs_rmap_irec irec
;
2432 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
2433 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner
) ||
2434 (flags
& XFS_RMAP_BMBT_BLOCK
));
2436 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
,
2445 error
= xfs_rmap_get_rec(cur
, &irec
, &has_record
);
2453 *has_rmap
= (irec
.rm_owner
== owner
&& irec
.rm_startblock
<= bno
&&
2454 irec
.rm_startblock
+ irec
.rm_blockcount
>= bno
+ len
);