1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2014 Red Hat, Inc.
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_log_format.h"
11 #include "xfs_trans_resv.h"
13 #include "xfs_mount.h"
14 #include "xfs_defer.h"
15 #include "xfs_btree.h"
16 #include "xfs_trans.h"
17 #include "xfs_alloc.h"
19 #include "xfs_rmap_btree.h"
20 #include "xfs_trace.h"
21 #include "xfs_errortag.h"
22 #include "xfs_error.h"
23 #include "xfs_inode.h"
26 * Lookup the first record less than or equal to [bno, len, owner, offset]
27 * in the btree given by cur.
31 struct xfs_btree_cur *cur,
39 cur->bc_rec.r.rm_startblock = bno;
40 cur->bc_rec.r.rm_blockcount = len;
41 cur->bc_rec.r.rm_owner = owner;
42 cur->bc_rec.r.rm_offset = offset;
43 cur->bc_rec.r.rm_flags = flags;
44 return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
48 * Lookup the record exactly matching [bno, len, owner, offset]
49 * in the btree given by cur.
53 struct xfs_btree_cur *cur,
61 cur->bc_rec.r.rm_startblock = bno;
62 cur->bc_rec.r.rm_blockcount = len;
63 cur->bc_rec.r.rm_owner = owner;
64 cur->bc_rec.r.rm_offset = offset;
65 cur->bc_rec.r.rm_flags = flags;
66 return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
70 * Update the record referred to by cur to the value given
71 * by [bno, len, owner, offset].
72 * This either works (return 0) or gets an EFSCORRUPTED error.
76 struct xfs_btree_cur *cur,
77 struct xfs_rmap_irec *irec)
79 union xfs_btree_rec rec;
82 trace_xfs_rmap_update(cur->bc_mp, cur->bc_ag.agno,
83 irec->rm_startblock, irec->rm_blockcount,
84 irec->rm_owner, irec->rm_offset, irec->rm_flags);
86 rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
87 rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
88 rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
89 rec.rmap.rm_offset = cpu_to_be64(
90 xfs_rmap_irec_offset_pack(irec));
91 error = xfs_btree_update(cur, &rec);
93 trace_xfs_rmap_update_error(cur->bc_mp,
94 cur->bc_ag.agno, error, _RET_IP_);
100 struct xfs_btree_cur *rcur,
110 trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_ag.agno, agbno,
111 len, owner, offset, flags);
113 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
116 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 0)) {
117 error = -EFSCORRUPTED;
121 rcur->bc_rec.r.rm_startblock = agbno;
122 rcur->bc_rec.r.rm_blockcount = len;
123 rcur->bc_rec.r.rm_owner = owner;
124 rcur->bc_rec.r.rm_offset = offset;
125 rcur->bc_rec.r.rm_flags = flags;
126 error = xfs_btree_insert(rcur, &i);
129 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
130 error = -EFSCORRUPTED;
135 trace_xfs_rmap_insert_error(rcur->bc_mp,
136 rcur->bc_ag.agno, error, _RET_IP_);
142 struct xfs_btree_cur *rcur,
152 trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_ag.agno, agbno,
153 len, owner, offset, flags);
155 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
158 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
159 error = -EFSCORRUPTED;
163 error = xfs_btree_delete(rcur, &i);
166 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
167 error = -EFSCORRUPTED;
172 trace_xfs_rmap_delete_error(rcur->bc_mp,
173 rcur->bc_ag.agno, error, _RET_IP_);
177 /* Convert an internal btree record to an rmap record. */
179 xfs_rmap_btrec_to_irec(
180 union xfs_btree_rec *rec,
181 struct xfs_rmap_irec *irec)
183 irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
184 irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
185 irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
186 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
191 * Get the data from the pointed-to record.
195 struct xfs_btree_cur *cur,
196 struct xfs_rmap_irec *irec,
199 struct xfs_mount *mp = cur->bc_mp;
200 xfs_agnumber_t agno = cur->bc_ag.agno;
201 union xfs_btree_rec *rec;
204 error = xfs_btree_get_rec(cur, &rec, stat);
208 if (xfs_rmap_btrec_to_irec(rec, irec))
211 if (irec->rm_blockcount == 0)
213 if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
214 if (irec->rm_owner != XFS_RMAP_OWN_FS)
216 if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
219 /* check for valid extent range, including overflow */
220 if (!xfs_verify_agbno(mp, agno, irec->rm_startblock))
222 if (irec->rm_startblock >
223 irec->rm_startblock + irec->rm_blockcount)
225 if (!xfs_verify_agbno(mp, agno,
226 irec->rm_startblock + irec->rm_blockcount - 1))
230 if (!(xfs_verify_ino(mp, irec->rm_owner) ||
231 (irec->rm_owner <= XFS_RMAP_OWN_FS &&
232 irec->rm_owner >= XFS_RMAP_OWN_MIN)))
238 "Reverse Mapping BTree record corruption in AG %d detected!",
241 "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
242 irec->rm_owner, irec->rm_flags, irec->rm_startblock,
243 irec->rm_blockcount);
244 return -EFSCORRUPTED;
247 struct xfs_find_left_neighbor_info {
248 struct xfs_rmap_irec high;
249 struct xfs_rmap_irec *irec;
253 /* For each rmap given, figure out if it matches the key we want. */
255 xfs_rmap_find_left_neighbor_helper(
256 struct xfs_btree_cur *cur,
257 struct xfs_rmap_irec *rec,
260 struct xfs_find_left_neighbor_info *info = priv;
262 trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
263 cur->bc_ag.agno, rec->rm_startblock,
264 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
267 if (rec->rm_owner != info->high.rm_owner)
269 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
270 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
271 rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
280 * Find the record to the left of the given extent, being careful only to
281 * return a match with the same owner and adjacent physical and logical
285 xfs_rmap_find_left_neighbor(
286 struct xfs_btree_cur *cur,
291 struct xfs_rmap_irec *irec,
294 struct xfs_find_left_neighbor_info info;
300 info.high.rm_startblock = bno - 1;
301 info.high.rm_owner = owner;
302 if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
303 !(flags & XFS_RMAP_BMBT_BLOCK)) {
306 info.high.rm_offset = offset - 1;
308 info.high.rm_offset = 0;
309 info.high.rm_flags = flags;
310 info.high.rm_blockcount = 0;
314 trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
315 cur->bc_ag.agno, bno, 0, owner, offset, flags);
317 error = xfs_rmap_query_range(cur, &info.high, &info.high,
318 xfs_rmap_find_left_neighbor_helper, &info);
319 if (error == -ECANCELED)
322 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
323 cur->bc_ag.agno, irec->rm_startblock,
324 irec->rm_blockcount, irec->rm_owner,
325 irec->rm_offset, irec->rm_flags);
329 /* For each rmap given, figure out if it matches the key we want. */
331 xfs_rmap_lookup_le_range_helper(
332 struct xfs_btree_cur *cur,
333 struct xfs_rmap_irec *rec,
336 struct xfs_find_left_neighbor_info *info = priv;
338 trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
339 cur->bc_ag.agno, rec->rm_startblock,
340 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
343 if (rec->rm_owner != info->high.rm_owner)
345 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
346 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
347 (rec->rm_offset > info->high.rm_offset ||
348 rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
357 * Find the record to the left of the given extent, being careful only to
358 * return a match with the same owner and overlapping physical and logical
359 * block ranges. This is the overlapping-interval version of
360 * xfs_rmap_lookup_le.
363 xfs_rmap_lookup_le_range(
364 struct xfs_btree_cur *cur,
369 struct xfs_rmap_irec *irec,
372 struct xfs_find_left_neighbor_info info;
375 info.high.rm_startblock = bno;
376 info.high.rm_owner = owner;
377 if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
378 info.high.rm_offset = offset;
380 info.high.rm_offset = 0;
381 info.high.rm_flags = flags;
382 info.high.rm_blockcount = 0;
387 trace_xfs_rmap_lookup_le_range(cur->bc_mp,
388 cur->bc_ag.agno, bno, 0, owner, offset, flags);
389 error = xfs_rmap_query_range(cur, &info.high, &info.high,
390 xfs_rmap_lookup_le_range_helper, &info);
391 if (error == -ECANCELED)
394 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
395 cur->bc_ag.agno, irec->rm_startblock,
396 irec->rm_blockcount, irec->rm_owner,
397 irec->rm_offset, irec->rm_flags);
402 * Perform all the relevant owner checks for a removal op. If we're doing an
403 * unknown-owner removal then we have no owner information to check.
406 xfs_rmap_free_check_owner(
407 struct xfs_mount *mp,
409 struct xfs_rmap_irec *rec,
417 if (owner == XFS_RMAP_OWN_UNKNOWN)
420 /* Make sure the unwritten flag matches. */
421 if (XFS_IS_CORRUPT(mp,
422 (flags & XFS_RMAP_UNWRITTEN) !=
423 (rec->rm_flags & XFS_RMAP_UNWRITTEN))) {
424 error = -EFSCORRUPTED;
428 /* Make sure the owner matches what we expect to find in the tree. */
429 if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) {
430 error = -EFSCORRUPTED;
434 /* Check the offset, if necessary. */
435 if (XFS_RMAP_NON_INODE_OWNER(owner))
438 if (flags & XFS_RMAP_BMBT_BLOCK) {
439 if (XFS_IS_CORRUPT(mp,
440 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) {
441 error = -EFSCORRUPTED;
445 if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) {
446 error = -EFSCORRUPTED;
449 if (XFS_IS_CORRUPT(mp,
450 offset + len > ltoff + rec->rm_blockcount)) {
451 error = -EFSCORRUPTED;
461 * Find the extent in the rmap btree and remove it.
463 * The record we find should always be an exact match for the extent that we're
464 * looking for, since we insert them into the btree without modification.
466 * Special Case #1: when growing the filesystem, we "free" an extent when
467 * growing the last AG. This extent is new space and so it is not tracked as
468 * used space in the btree. The growfs code will pass in an owner of
469 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
470 * extent. We verify that - the extent lookup result in a record that does not
473 * Special Case #2: EFIs do not record the owner of the extent, so when
474 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
475 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
476 * corruption checks during log recovery.
480 struct xfs_btree_cur *cur,
484 const struct xfs_owner_info *oinfo)
486 struct xfs_mount *mp = cur->bc_mp;
487 struct xfs_rmap_irec ltrec;
496 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
497 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
498 (flags & XFS_RMAP_BMBT_BLOCK);
500 flags |= XFS_RMAP_UNWRITTEN;
501 trace_xfs_rmap_unmap(mp, cur->bc_ag.agno, bno, len,
505 * We should always have a left record because there's a static record
506 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
507 * will not ever be removed from the tree.
509 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i);
512 if (XFS_IS_CORRUPT(mp, i != 1)) {
513 error = -EFSCORRUPTED;
517 error = xfs_rmap_get_rec(cur, <rec, &i);
520 if (XFS_IS_CORRUPT(mp, i != 1)) {
521 error = -EFSCORRUPTED;
524 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
525 cur->bc_ag.agno, ltrec.rm_startblock,
526 ltrec.rm_blockcount, ltrec.rm_owner,
527 ltrec.rm_offset, ltrec.rm_flags);
528 ltoff = ltrec.rm_offset;
531 * For growfs, the incoming extent must be beyond the left record we
532 * just found as it is new space and won't be used by anyone. This is
533 * just a corruption check as we don't actually do anything with this
534 * extent. Note that we need to use >= instead of > because it might
535 * be the case that the "left" extent goes all the way to EOFS.
537 if (owner == XFS_RMAP_OWN_NULL) {
538 if (XFS_IS_CORRUPT(mp,
540 ltrec.rm_startblock + ltrec.rm_blockcount)) {
541 error = -EFSCORRUPTED;
548 * If we're doing an unknown-owner removal for EFI recovery, we expect
549 * to find the full range in the rmapbt or nothing at all. If we
550 * don't find any rmaps overlapping either end of the range, we're
551 * done. Hopefully this means that the EFI creator already queued
552 * (and finished) a RUI to remove the rmap.
554 if (owner == XFS_RMAP_OWN_UNKNOWN &&
555 ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
556 struct xfs_rmap_irec rtrec;
558 error = xfs_btree_increment(cur, 0, &i);
563 error = xfs_rmap_get_rec(cur, &rtrec, &i);
566 if (XFS_IS_CORRUPT(mp, i != 1)) {
567 error = -EFSCORRUPTED;
570 if (rtrec.rm_startblock >= bno + len)
574 /* Make sure the extent we found covers the entire freeing range. */
575 if (XFS_IS_CORRUPT(mp,
576 ltrec.rm_startblock > bno ||
577 ltrec.rm_startblock + ltrec.rm_blockcount <
579 error = -EFSCORRUPTED;
583 /* Check owner information. */
584 error = xfs_rmap_free_check_owner(mp, ltoff, <rec, len, owner,
589 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
590 /* exact match, simply remove the record from rmap tree */
591 trace_xfs_rmap_delete(mp, cur->bc_ag.agno,
592 ltrec.rm_startblock, ltrec.rm_blockcount,
593 ltrec.rm_owner, ltrec.rm_offset,
595 error = xfs_btree_delete(cur, &i);
598 if (XFS_IS_CORRUPT(mp, i != 1)) {
599 error = -EFSCORRUPTED;
602 } else if (ltrec.rm_startblock == bno) {
604 * overlap left hand side of extent: move the start, trim the
605 * length and update the current record.
608 * Orig: |oooooooooooooooooooo|
609 * Freeing: |fffffffff|
610 * Result: |rrrrrrrrrr|
613 ltrec.rm_startblock += len;
614 ltrec.rm_blockcount -= len;
616 ltrec.rm_offset += len;
617 error = xfs_rmap_update(cur, <rec);
620 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
622 * overlap right hand side of extent: trim the length and update
623 * the current record.
626 * Orig: |oooooooooooooooooooo|
627 * Freeing: |fffffffff|
628 * Result: |rrrrrrrrrr|
631 ltrec.rm_blockcount -= len;
632 error = xfs_rmap_update(cur, <rec);
638 * overlap middle of extent: trim the length of the existing
639 * record to the length of the new left-extent size, increment
640 * the insertion position so we can insert a new record
641 * containing the remaining right-extent space.
644 * Orig: |oooooooooooooooooooo|
645 * Freeing: |fffffffff|
646 * Result: |rrrrr| |rrrr|
649 xfs_extlen_t orig_len = ltrec.rm_blockcount;
651 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
652 error = xfs_rmap_update(cur, <rec);
656 error = xfs_btree_increment(cur, 0, &i);
660 cur->bc_rec.r.rm_startblock = bno + len;
661 cur->bc_rec.r.rm_blockcount = orig_len - len -
663 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
665 cur->bc_rec.r.rm_offset = 0;
667 cur->bc_rec.r.rm_offset = offset + len;
668 cur->bc_rec.r.rm_flags = flags;
669 trace_xfs_rmap_insert(mp, cur->bc_ag.agno,
670 cur->bc_rec.r.rm_startblock,
671 cur->bc_rec.r.rm_blockcount,
672 cur->bc_rec.r.rm_owner,
673 cur->bc_rec.r.rm_offset,
674 cur->bc_rec.r.rm_flags);
675 error = xfs_btree_insert(cur, &i);
681 trace_xfs_rmap_unmap_done(mp, cur->bc_ag.agno, bno, len,
685 trace_xfs_rmap_unmap_error(mp, cur->bc_ag.agno,
691 * Remove a reference to an extent in the rmap btree.
695 struct xfs_trans *tp,
696 struct xfs_buf *agbp,
700 const struct xfs_owner_info *oinfo)
702 struct xfs_mount *mp = tp->t_mountp;
703 struct xfs_btree_cur *cur;
706 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
709 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
711 error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
713 xfs_btree_del_cursor(cur, error);
718 * A mergeable rmap must have the same owner and the same values for
719 * the unwritten, attr_fork, and bmbt flags. The startblock and
720 * offset are checked separately.
723 xfs_rmap_is_mergeable(
724 struct xfs_rmap_irec *irec,
728 if (irec->rm_owner == XFS_RMAP_OWN_NULL)
730 if (irec->rm_owner != owner)
732 if ((flags & XFS_RMAP_UNWRITTEN) ^
733 (irec->rm_flags & XFS_RMAP_UNWRITTEN))
735 if ((flags & XFS_RMAP_ATTR_FORK) ^
736 (irec->rm_flags & XFS_RMAP_ATTR_FORK))
738 if ((flags & XFS_RMAP_BMBT_BLOCK) ^
739 (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
745 * When we allocate a new block, the first thing we do is add a reference to
746 * the extent in the rmap btree. This takes the form of a [agbno, length,
747 * owner, offset] record. Flags are encoded in the high bits of the offset
752 struct xfs_btree_cur *cur,
756 const struct xfs_owner_info *oinfo)
758 struct xfs_mount *mp = cur->bc_mp;
759 struct xfs_rmap_irec ltrec;
760 struct xfs_rmap_irec gtrec;
767 unsigned int flags = 0;
770 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
772 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
773 (flags & XFS_RMAP_BMBT_BLOCK);
775 flags |= XFS_RMAP_UNWRITTEN;
776 trace_xfs_rmap_map(mp, cur->bc_ag.agno, bno, len,
778 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
781 * For the initial lookup, look for an exact match or the left-adjacent
782 * record for our insertion point. This will also give us the record for
783 * start block contiguity tests.
785 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
790 error = xfs_rmap_get_rec(cur, <rec, &have_lt);
793 if (XFS_IS_CORRUPT(mp, have_lt != 1)) {
794 error = -EFSCORRUPTED;
797 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
798 cur->bc_ag.agno, ltrec.rm_startblock,
799 ltrec.rm_blockcount, ltrec.rm_owner,
800 ltrec.rm_offset, ltrec.rm_flags);
802 if (!xfs_rmap_is_mergeable(<rec, owner, flags))
806 if (XFS_IS_CORRUPT(mp,
808 ltrec.rm_startblock + ltrec.rm_blockcount > bno)) {
809 error = -EFSCORRUPTED;
814 * Increment the cursor to see if we have a right-adjacent record to our
815 * insertion point. This will give us the record for end block
818 error = xfs_btree_increment(cur, 0, &have_gt);
822 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
825 if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
826 error = -EFSCORRUPTED;
829 if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) {
830 error = -EFSCORRUPTED;
833 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
834 cur->bc_ag.agno, gtrec.rm_startblock,
835 gtrec.rm_blockcount, gtrec.rm_owner,
836 gtrec.rm_offset, gtrec.rm_flags);
837 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
842 * Note: cursor currently points one record to the right of ltrec, even
843 * if there is no record in the tree to the right.
846 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
847 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
849 * left edge contiguous, merge into left record.
853 * adding: |aaaaaaaaa|
854 * result: |rrrrrrrrrrrrrrrrrrr|
857 ltrec.rm_blockcount += len;
859 bno + len == gtrec.rm_startblock &&
860 (ignore_off || offset + len == gtrec.rm_offset) &&
861 (unsigned long)ltrec.rm_blockcount + len +
862 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
864 * right edge also contiguous, delete right record
865 * and merge into left record.
867 * ltbno ltlen gtbno gtlen
868 * orig: |ooooooooo| |ooooooooo|
869 * adding: |aaaaaaaaa|
870 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
872 ltrec.rm_blockcount += gtrec.rm_blockcount;
873 trace_xfs_rmap_delete(mp, cur->bc_ag.agno,
879 error = xfs_btree_delete(cur, &i);
882 if (XFS_IS_CORRUPT(mp, i != 1)) {
883 error = -EFSCORRUPTED;
888 /* point the cursor back to the left record and update */
889 error = xfs_btree_decrement(cur, 0, &have_gt);
892 error = xfs_rmap_update(cur, <rec);
895 } else if (have_gt &&
896 bno + len == gtrec.rm_startblock &&
897 (ignore_off || offset + len == gtrec.rm_offset)) {
899 * right edge contiguous, merge into right record.
903 * adding: |aaaaaaaaa|
904 * Result: |rrrrrrrrrrrrrrrrrrr|
907 gtrec.rm_startblock = bno;
908 gtrec.rm_blockcount += len;
910 gtrec.rm_offset = offset;
911 error = xfs_rmap_update(cur, >rec);
916 * no contiguous edge with identical owner, insert
917 * new record at current cursor position.
919 cur->bc_rec.r.rm_startblock = bno;
920 cur->bc_rec.r.rm_blockcount = len;
921 cur->bc_rec.r.rm_owner = owner;
922 cur->bc_rec.r.rm_offset = offset;
923 cur->bc_rec.r.rm_flags = flags;
924 trace_xfs_rmap_insert(mp, cur->bc_ag.agno, bno, len,
925 owner, offset, flags);
926 error = xfs_btree_insert(cur, &i);
929 if (XFS_IS_CORRUPT(mp, i != 1)) {
930 error = -EFSCORRUPTED;
935 trace_xfs_rmap_map_done(mp, cur->bc_ag.agno, bno, len,
939 trace_xfs_rmap_map_error(mp, cur->bc_ag.agno,
945 * Add a reference to an extent in the rmap btree.
949 struct xfs_trans *tp,
950 struct xfs_buf *agbp,
954 const struct xfs_owner_info *oinfo)
956 struct xfs_mount *mp = tp->t_mountp;
957 struct xfs_btree_cur *cur;
960 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
963 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
964 error = xfs_rmap_map(cur, bno, len, false, oinfo);
966 xfs_btree_del_cursor(cur, error);
970 #define RMAP_LEFT_CONTIG (1 << 0)
971 #define RMAP_RIGHT_CONTIG (1 << 1)
972 #define RMAP_LEFT_FILLING (1 << 2)
973 #define RMAP_RIGHT_FILLING (1 << 3)
974 #define RMAP_LEFT_VALID (1 << 6)
975 #define RMAP_RIGHT_VALID (1 << 7)
983 * Convert an unwritten extent to a real extent or vice versa.
984 * Does not handle overlapping extents.
988 struct xfs_btree_cur *cur,
992 const struct xfs_owner_info *oinfo)
994 struct xfs_mount *mp = cur->bc_mp;
995 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
996 /* left is 0, right is 1, */
997 /* prev is 2, new is 3 */
1000 uint64_t new_endoff;
1001 unsigned int oldext;
1002 unsigned int newext;
1003 unsigned int flags = 0;
1008 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1009 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1010 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1011 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1012 new_endoff = offset + len;
1013 trace_xfs_rmap_convert(mp, cur->bc_ag.agno, bno, len,
1017 * For the initial lookup, look for an exact match or the left-adjacent
1018 * record for our insertion point. This will also give us the record for
1019 * start block contiguity tests.
1021 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1024 if (XFS_IS_CORRUPT(mp, i != 1)) {
1025 error = -EFSCORRUPTED;
1029 error = xfs_rmap_get_rec(cur, &PREV, &i);
1032 if (XFS_IS_CORRUPT(mp, i != 1)) {
1033 error = -EFSCORRUPTED;
1036 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
1037 cur->bc_ag.agno, PREV.rm_startblock,
1038 PREV.rm_blockcount, PREV.rm_owner,
1039 PREV.rm_offset, PREV.rm_flags);
1041 ASSERT(PREV.rm_offset <= offset);
1042 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1043 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1044 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1047 * Set flags determining what part of the previous oldext allocation
1048 * extent is being replaced by a newext allocation.
1050 if (PREV.rm_offset == offset)
1051 state |= RMAP_LEFT_FILLING;
1052 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1053 state |= RMAP_RIGHT_FILLING;
1056 * Decrement the cursor to see if we have a left-adjacent record to our
1057 * insertion point. This will give us the record for end block
1060 error = xfs_btree_decrement(cur, 0, &i);
1064 state |= RMAP_LEFT_VALID;
1065 error = xfs_rmap_get_rec(cur, &LEFT, &i);
1068 if (XFS_IS_CORRUPT(mp, i != 1)) {
1069 error = -EFSCORRUPTED;
1072 if (XFS_IS_CORRUPT(mp,
1073 LEFT.rm_startblock + LEFT.rm_blockcount >
1075 error = -EFSCORRUPTED;
1078 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
1079 cur->bc_ag.agno, LEFT.rm_startblock,
1080 LEFT.rm_blockcount, LEFT.rm_owner,
1081 LEFT.rm_offset, LEFT.rm_flags);
1082 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1083 LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1084 xfs_rmap_is_mergeable(&LEFT, owner, newext))
1085 state |= RMAP_LEFT_CONTIG;
1089 * Increment the cursor to see if we have a right-adjacent record to our
1090 * insertion point. This will give us the record for end block
1093 error = xfs_btree_increment(cur, 0, &i);
1096 if (XFS_IS_CORRUPT(mp, i != 1)) {
1097 error = -EFSCORRUPTED;
1100 error = xfs_btree_increment(cur, 0, &i);
1104 state |= RMAP_RIGHT_VALID;
1105 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1108 if (XFS_IS_CORRUPT(mp, i != 1)) {
1109 error = -EFSCORRUPTED;
1112 if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1113 error = -EFSCORRUPTED;
1116 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1117 cur->bc_ag.agno, RIGHT.rm_startblock,
1118 RIGHT.rm_blockcount, RIGHT.rm_owner,
1119 RIGHT.rm_offset, RIGHT.rm_flags);
1120 if (bno + len == RIGHT.rm_startblock &&
1121 offset + len == RIGHT.rm_offset &&
1122 xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1123 state |= RMAP_RIGHT_CONTIG;
1126 /* check that left + prev + right is not too long */
1127 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1128 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1129 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1130 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1131 (unsigned long)LEFT.rm_blockcount + len +
1132 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1133 state &= ~RMAP_RIGHT_CONTIG;
1135 trace_xfs_rmap_convert_state(mp, cur->bc_ag.agno, state,
1138 /* reset the cursor back to PREV */
1139 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1142 if (XFS_IS_CORRUPT(mp, i != 1)) {
1143 error = -EFSCORRUPTED;
1148 * Switch out based on the FILLING and CONTIG state bits.
1150 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1151 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1152 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1153 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1155 * Setting all of a previous oldext extent to newext.
1156 * The left and right neighbors are both contiguous with new.
1158 error = xfs_btree_increment(cur, 0, &i);
1161 if (XFS_IS_CORRUPT(mp, i != 1)) {
1162 error = -EFSCORRUPTED;
1165 trace_xfs_rmap_delete(mp, cur->bc_ag.agno,
1166 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1167 RIGHT.rm_owner, RIGHT.rm_offset,
1169 error = xfs_btree_delete(cur, &i);
1172 if (XFS_IS_CORRUPT(mp, i != 1)) {
1173 error = -EFSCORRUPTED;
1176 error = xfs_btree_decrement(cur, 0, &i);
1179 if (XFS_IS_CORRUPT(mp, i != 1)) {
1180 error = -EFSCORRUPTED;
1183 trace_xfs_rmap_delete(mp, cur->bc_ag.agno,
1184 PREV.rm_startblock, PREV.rm_blockcount,
1185 PREV.rm_owner, PREV.rm_offset,
1187 error = xfs_btree_delete(cur, &i);
1190 if (XFS_IS_CORRUPT(mp, i != 1)) {
1191 error = -EFSCORRUPTED;
1194 error = xfs_btree_decrement(cur, 0, &i);
1197 if (XFS_IS_CORRUPT(mp, i != 1)) {
1198 error = -EFSCORRUPTED;
1202 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1203 error = xfs_rmap_update(cur, &NEW);
1208 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1210 * Setting all of a previous oldext extent to newext.
1211 * The left neighbor is contiguous, the right is not.
1213 trace_xfs_rmap_delete(mp, cur->bc_ag.agno,
1214 PREV.rm_startblock, PREV.rm_blockcount,
1215 PREV.rm_owner, PREV.rm_offset,
1217 error = xfs_btree_delete(cur, &i);
1220 if (XFS_IS_CORRUPT(mp, i != 1)) {
1221 error = -EFSCORRUPTED;
1224 error = xfs_btree_decrement(cur, 0, &i);
1227 if (XFS_IS_CORRUPT(mp, i != 1)) {
1228 error = -EFSCORRUPTED;
1232 NEW.rm_blockcount += PREV.rm_blockcount;
1233 error = xfs_rmap_update(cur, &NEW);
1238 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1240 * Setting all of a previous oldext extent to newext.
1241 * The right neighbor is contiguous, the left is not.
1243 error = xfs_btree_increment(cur, 0, &i);
1246 if (XFS_IS_CORRUPT(mp, i != 1)) {
1247 error = -EFSCORRUPTED;
1250 trace_xfs_rmap_delete(mp, cur->bc_ag.agno,
1251 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1252 RIGHT.rm_owner, RIGHT.rm_offset,
1254 error = xfs_btree_delete(cur, &i);
1257 if (XFS_IS_CORRUPT(mp, i != 1)) {
1258 error = -EFSCORRUPTED;
1261 error = xfs_btree_decrement(cur, 0, &i);
1264 if (XFS_IS_CORRUPT(mp, i != 1)) {
1265 error = -EFSCORRUPTED;
1269 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1270 NEW.rm_flags = newext;
1271 error = xfs_rmap_update(cur, &NEW);
1276 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1278 * Setting all of a previous oldext extent to newext.
1279 * Neither the left nor right neighbors are contiguous with
1283 NEW.rm_flags = newext;
1284 error = xfs_rmap_update(cur, &NEW);
1289 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1291 * Setting the first part of a previous oldext extent to newext.
1292 * The left neighbor is contiguous.
1295 NEW.rm_offset += len;
1296 NEW.rm_startblock += len;
1297 NEW.rm_blockcount -= len;
1298 error = xfs_rmap_update(cur, &NEW);
1301 error = xfs_btree_decrement(cur, 0, &i);
1305 NEW.rm_blockcount += len;
1306 error = xfs_rmap_update(cur, &NEW);
1311 case RMAP_LEFT_FILLING:
1313 * Setting the first part of a previous oldext extent to newext.
1314 * The left neighbor is not contiguous.
1317 NEW.rm_startblock += len;
1318 NEW.rm_offset += len;
1319 NEW.rm_blockcount -= len;
1320 error = xfs_rmap_update(cur, &NEW);
1323 NEW.rm_startblock = bno;
1324 NEW.rm_owner = owner;
1325 NEW.rm_offset = offset;
1326 NEW.rm_blockcount = len;
1327 NEW.rm_flags = newext;
1328 cur->bc_rec.r = NEW;
1329 trace_xfs_rmap_insert(mp, cur->bc_ag.agno, bno,
1330 len, owner, offset, newext);
1331 error = xfs_btree_insert(cur, &i);
1334 if (XFS_IS_CORRUPT(mp, i != 1)) {
1335 error = -EFSCORRUPTED;
1340 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1342 * Setting the last part of a previous oldext extent to newext.
1343 * The right neighbor is contiguous with the new allocation.
1346 NEW.rm_blockcount -= len;
1347 error = xfs_rmap_update(cur, &NEW);
1350 error = xfs_btree_increment(cur, 0, &i);
1354 NEW.rm_offset = offset;
1355 NEW.rm_startblock = bno;
1356 NEW.rm_blockcount += len;
1357 error = xfs_rmap_update(cur, &NEW);
1362 case RMAP_RIGHT_FILLING:
1364 * Setting the last part of a previous oldext extent to newext.
1365 * The right neighbor is not contiguous.
1368 NEW.rm_blockcount -= len;
1369 error = xfs_rmap_update(cur, &NEW);
1372 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1376 if (XFS_IS_CORRUPT(mp, i != 0)) {
1377 error = -EFSCORRUPTED;
1380 NEW.rm_startblock = bno;
1381 NEW.rm_owner = owner;
1382 NEW.rm_offset = offset;
1383 NEW.rm_blockcount = len;
1384 NEW.rm_flags = newext;
1385 cur->bc_rec.r = NEW;
1386 trace_xfs_rmap_insert(mp, cur->bc_ag.agno, bno,
1387 len, owner, offset, newext);
1388 error = xfs_btree_insert(cur, &i);
1391 if (XFS_IS_CORRUPT(mp, i != 1)) {
1392 error = -EFSCORRUPTED;
1399 * Setting the middle part of a previous oldext extent to
1400 * newext. Contiguity is impossible here.
1401 * One extent becomes three extents.
1403 /* new right extent - oldext */
1404 NEW.rm_startblock = bno + len;
1405 NEW.rm_owner = owner;
1406 NEW.rm_offset = new_endoff;
1407 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1409 NEW.rm_flags = PREV.rm_flags;
1410 error = xfs_rmap_update(cur, &NEW);
1413 /* new left extent - oldext */
1415 NEW.rm_blockcount = offset - PREV.rm_offset;
1416 cur->bc_rec.r = NEW;
1417 trace_xfs_rmap_insert(mp, cur->bc_ag.agno,
1418 NEW.rm_startblock, NEW.rm_blockcount,
1419 NEW.rm_owner, NEW.rm_offset,
1421 error = xfs_btree_insert(cur, &i);
1424 if (XFS_IS_CORRUPT(mp, i != 1)) {
1425 error = -EFSCORRUPTED;
1429 * Reset the cursor to the position of the new extent
1430 * we are about to insert as we can't trust it after
1431 * the previous insert.
1433 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1437 if (XFS_IS_CORRUPT(mp, i != 0)) {
1438 error = -EFSCORRUPTED;
1441 /* new middle extent - newext */
1442 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1443 cur->bc_rec.r.rm_flags |= newext;
1444 trace_xfs_rmap_insert(mp, cur->bc_ag.agno, bno, len,
1445 owner, offset, newext);
1446 error = xfs_btree_insert(cur, &i);
1449 if (XFS_IS_CORRUPT(mp, i != 1)) {
1450 error = -EFSCORRUPTED;
1455 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1456 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1457 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1458 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1459 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1460 case RMAP_LEFT_CONTIG:
1461 case RMAP_RIGHT_CONTIG:
1463 * These cases are all impossible.
1468 trace_xfs_rmap_convert_done(mp, cur->bc_ag.agno, bno, len,
1472 trace_xfs_rmap_convert_error(cur->bc_mp,
1473 cur->bc_ag.agno, error, _RET_IP_);
1478 * Convert an unwritten extent to a real extent or vice versa. If there is no
1479 * possibility of overlapping extents, delegate to the simpler convert
1483 xfs_rmap_convert_shared(
1484 struct xfs_btree_cur *cur,
1488 const struct xfs_owner_info *oinfo)
1490 struct xfs_mount *mp = cur->bc_mp;
1491 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1492 /* left is 0, right is 1, */
1493 /* prev is 2, new is 3 */
1496 uint64_t new_endoff;
1497 unsigned int oldext;
1498 unsigned int newext;
1499 unsigned int flags = 0;
1504 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1505 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1506 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1507 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1508 new_endoff = offset + len;
1509 trace_xfs_rmap_convert(mp, cur->bc_ag.agno, bno, len,
1513 * For the initial lookup, look for and exact match or the left-adjacent
1514 * record for our insertion point. This will also give us the record for
1515 * start block contiguity tests.
1517 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, oldext,
1521 if (XFS_IS_CORRUPT(mp, i != 1)) {
1522 error = -EFSCORRUPTED;
1526 ASSERT(PREV.rm_offset <= offset);
1527 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1528 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1529 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1532 * Set flags determining what part of the previous oldext allocation
1533 * extent is being replaced by a newext allocation.
1535 if (PREV.rm_offset == offset)
1536 state |= RMAP_LEFT_FILLING;
1537 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1538 state |= RMAP_RIGHT_FILLING;
1540 /* Is there a left record that abuts our range? */
1541 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1546 state |= RMAP_LEFT_VALID;
1547 if (XFS_IS_CORRUPT(mp,
1548 LEFT.rm_startblock + LEFT.rm_blockcount >
1550 error = -EFSCORRUPTED;
1553 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1554 state |= RMAP_LEFT_CONTIG;
1557 /* Is there a right record that abuts our range? */
1558 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1563 state |= RMAP_RIGHT_VALID;
1564 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1567 if (XFS_IS_CORRUPT(mp, i != 1)) {
1568 error = -EFSCORRUPTED;
1571 if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1572 error = -EFSCORRUPTED;
1575 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1576 cur->bc_ag.agno, RIGHT.rm_startblock,
1577 RIGHT.rm_blockcount, RIGHT.rm_owner,
1578 RIGHT.rm_offset, RIGHT.rm_flags);
1579 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1580 state |= RMAP_RIGHT_CONTIG;
1583 /* check that left + prev + right is not too long */
1584 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1585 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1586 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1587 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1588 (unsigned long)LEFT.rm_blockcount + len +
1589 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1590 state &= ~RMAP_RIGHT_CONTIG;
1592 trace_xfs_rmap_convert_state(mp, cur->bc_ag.agno, state,
1595 * Switch out based on the FILLING and CONTIG state bits.
1597 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1598 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1599 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1600 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1602 * Setting all of a previous oldext extent to newext.
1603 * The left and right neighbors are both contiguous with new.
1605 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1606 RIGHT.rm_blockcount, RIGHT.rm_owner,
1607 RIGHT.rm_offset, RIGHT.rm_flags);
1610 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1611 PREV.rm_blockcount, PREV.rm_owner,
1612 PREV.rm_offset, PREV.rm_flags);
1616 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1617 NEW.rm_blockcount, NEW.rm_owner,
1618 NEW.rm_offset, NEW.rm_flags, &i);
1621 if (XFS_IS_CORRUPT(mp, i != 1)) {
1622 error = -EFSCORRUPTED;
1625 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1626 error = xfs_rmap_update(cur, &NEW);
1631 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1633 * Setting all of a previous oldext extent to newext.
1634 * The left neighbor is contiguous, the right is not.
1636 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1637 PREV.rm_blockcount, PREV.rm_owner,
1638 PREV.rm_offset, PREV.rm_flags);
1642 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1643 NEW.rm_blockcount, NEW.rm_owner,
1644 NEW.rm_offset, NEW.rm_flags, &i);
1647 if (XFS_IS_CORRUPT(mp, i != 1)) {
1648 error = -EFSCORRUPTED;
1651 NEW.rm_blockcount += PREV.rm_blockcount;
1652 error = xfs_rmap_update(cur, &NEW);
1657 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1659 * Setting all of a previous oldext extent to newext.
1660 * The right neighbor is contiguous, the left is not.
1662 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1663 RIGHT.rm_blockcount, RIGHT.rm_owner,
1664 RIGHT.rm_offset, RIGHT.rm_flags);
1668 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1669 NEW.rm_blockcount, NEW.rm_owner,
1670 NEW.rm_offset, NEW.rm_flags, &i);
1673 if (XFS_IS_CORRUPT(mp, i != 1)) {
1674 error = -EFSCORRUPTED;
1677 NEW.rm_blockcount += RIGHT.rm_blockcount;
1678 NEW.rm_flags = RIGHT.rm_flags;
1679 error = xfs_rmap_update(cur, &NEW);
1684 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1686 * Setting all of a previous oldext extent to newext.
1687 * Neither the left nor right neighbors are contiguous with
1691 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1692 NEW.rm_blockcount, NEW.rm_owner,
1693 NEW.rm_offset, NEW.rm_flags, &i);
1696 if (XFS_IS_CORRUPT(mp, i != 1)) {
1697 error = -EFSCORRUPTED;
1700 NEW.rm_flags = newext;
1701 error = xfs_rmap_update(cur, &NEW);
1706 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1708 * Setting the first part of a previous oldext extent to newext.
1709 * The left neighbor is contiguous.
1712 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1713 NEW.rm_blockcount, NEW.rm_owner,
1714 NEW.rm_offset, NEW.rm_flags);
1717 NEW.rm_offset += len;
1718 NEW.rm_startblock += len;
1719 NEW.rm_blockcount -= len;
1720 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1721 NEW.rm_blockcount, NEW.rm_owner,
1722 NEW.rm_offset, NEW.rm_flags);
1726 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1727 NEW.rm_blockcount, NEW.rm_owner,
1728 NEW.rm_offset, NEW.rm_flags, &i);
1731 if (XFS_IS_CORRUPT(mp, i != 1)) {
1732 error = -EFSCORRUPTED;
1735 NEW.rm_blockcount += len;
1736 error = xfs_rmap_update(cur, &NEW);
1741 case RMAP_LEFT_FILLING:
1743 * Setting the first part of a previous oldext extent to newext.
1744 * The left neighbor is not contiguous.
1747 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1748 NEW.rm_blockcount, NEW.rm_owner,
1749 NEW.rm_offset, NEW.rm_flags);
1752 NEW.rm_offset += len;
1753 NEW.rm_startblock += len;
1754 NEW.rm_blockcount -= len;
1755 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1756 NEW.rm_blockcount, NEW.rm_owner,
1757 NEW.rm_offset, NEW.rm_flags);
1760 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1765 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1767 * Setting the last part of a previous oldext extent to newext.
1768 * The right neighbor is contiguous with the new allocation.
1771 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1772 NEW.rm_blockcount, NEW.rm_owner,
1773 NEW.rm_offset, NEW.rm_flags, &i);
1776 if (XFS_IS_CORRUPT(mp, i != 1)) {
1777 error = -EFSCORRUPTED;
1780 NEW.rm_blockcount = offset - NEW.rm_offset;
1781 error = xfs_rmap_update(cur, &NEW);
1785 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1786 NEW.rm_blockcount, NEW.rm_owner,
1787 NEW.rm_offset, NEW.rm_flags);
1790 NEW.rm_offset = offset;
1791 NEW.rm_startblock = bno;
1792 NEW.rm_blockcount += len;
1793 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1794 NEW.rm_blockcount, NEW.rm_owner,
1795 NEW.rm_offset, NEW.rm_flags);
1800 case RMAP_RIGHT_FILLING:
1802 * Setting the last part of a previous oldext extent to newext.
1803 * The right neighbor is not contiguous.
1806 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1807 NEW.rm_blockcount, NEW.rm_owner,
1808 NEW.rm_offset, NEW.rm_flags, &i);
1811 if (XFS_IS_CORRUPT(mp, i != 1)) {
1812 error = -EFSCORRUPTED;
1815 NEW.rm_blockcount -= len;
1816 error = xfs_rmap_update(cur, &NEW);
1819 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1826 * Setting the middle part of a previous oldext extent to
1827 * newext. Contiguity is impossible here.
1828 * One extent becomes three extents.
1830 /* new right extent - oldext */
1831 NEW.rm_startblock = bno + len;
1832 NEW.rm_owner = owner;
1833 NEW.rm_offset = new_endoff;
1834 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1836 NEW.rm_flags = PREV.rm_flags;
1837 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1838 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1842 /* new left extent - oldext */
1844 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1845 NEW.rm_blockcount, NEW.rm_owner,
1846 NEW.rm_offset, NEW.rm_flags, &i);
1849 if (XFS_IS_CORRUPT(mp, i != 1)) {
1850 error = -EFSCORRUPTED;
1853 NEW.rm_blockcount = offset - NEW.rm_offset;
1854 error = xfs_rmap_update(cur, &NEW);
1857 /* new middle extent - newext */
1858 NEW.rm_startblock = bno;
1859 NEW.rm_blockcount = len;
1860 NEW.rm_owner = owner;
1861 NEW.rm_offset = offset;
1862 NEW.rm_flags = newext;
1863 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1864 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1870 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1871 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1872 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1873 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1874 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1875 case RMAP_LEFT_CONTIG:
1876 case RMAP_RIGHT_CONTIG:
1878 * These cases are all impossible.
1883 trace_xfs_rmap_convert_done(mp, cur->bc_ag.agno, bno, len,
1887 trace_xfs_rmap_convert_error(cur->bc_mp,
1888 cur->bc_ag.agno, error, _RET_IP_);
1898 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1899 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1900 * that the prev/next records in the btree might belong to another owner.
1901 * Therefore we must use delete+insert to alter any of the key fields.
1903 * For every other situation there can only be one owner for a given extent,
1904 * so we can call the regular _free function.
1907 xfs_rmap_unmap_shared(
1908 struct xfs_btree_cur *cur,
1912 const struct xfs_owner_info *oinfo)
1914 struct xfs_mount *mp = cur->bc_mp;
1915 struct xfs_rmap_irec ltrec;
1923 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1925 flags |= XFS_RMAP_UNWRITTEN;
1926 trace_xfs_rmap_unmap(mp, cur->bc_ag.agno, bno, len,
1930 * We should always have a left record because there's a static record
1931 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1932 * will not ever be removed from the tree.
1934 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1938 if (XFS_IS_CORRUPT(mp, i != 1)) {
1939 error = -EFSCORRUPTED;
1942 ltoff = ltrec.rm_offset;
1944 /* Make sure the extent we found covers the entire freeing range. */
1945 if (XFS_IS_CORRUPT(mp,
1946 ltrec.rm_startblock > bno ||
1947 ltrec.rm_startblock + ltrec.rm_blockcount <
1949 error = -EFSCORRUPTED;
1953 /* Make sure the owner matches what we expect to find in the tree. */
1954 if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) {
1955 error = -EFSCORRUPTED;
1959 /* Make sure the unwritten flag matches. */
1960 if (XFS_IS_CORRUPT(mp,
1961 (flags & XFS_RMAP_UNWRITTEN) !=
1962 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) {
1963 error = -EFSCORRUPTED;
1967 /* Check the offset. */
1968 if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) {
1969 error = -EFSCORRUPTED;
1972 if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) {
1973 error = -EFSCORRUPTED;
1977 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
1978 /* Exact match, simply remove the record from rmap tree. */
1979 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1980 ltrec.rm_blockcount, ltrec.rm_owner,
1981 ltrec.rm_offset, ltrec.rm_flags);
1984 } else if (ltrec.rm_startblock == bno) {
1986 * Overlap left hand side of extent: move the start, trim the
1987 * length and update the current record.
1990 * Orig: |oooooooooooooooooooo|
1991 * Freeing: |fffffffff|
1992 * Result: |rrrrrrrrrr|
1996 /* Delete prev rmap. */
1997 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1998 ltrec.rm_blockcount, ltrec.rm_owner,
1999 ltrec.rm_offset, ltrec.rm_flags);
2003 /* Add an rmap at the new offset. */
2004 ltrec.rm_startblock += len;
2005 ltrec.rm_blockcount -= len;
2006 ltrec.rm_offset += len;
2007 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
2008 ltrec.rm_blockcount, ltrec.rm_owner,
2009 ltrec.rm_offset, ltrec.rm_flags);
2012 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
2014 * Overlap right hand side of extent: trim the length and
2015 * update the current record.
2018 * Orig: |oooooooooooooooooooo|
2019 * Freeing: |fffffffff|
2020 * Result: |rrrrrrrrrr|
2023 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2024 ltrec.rm_blockcount, ltrec.rm_owner,
2025 ltrec.rm_offset, ltrec.rm_flags, &i);
2028 if (XFS_IS_CORRUPT(mp, i != 1)) {
2029 error = -EFSCORRUPTED;
2032 ltrec.rm_blockcount -= len;
2033 error = xfs_rmap_update(cur, <rec);
2038 * Overlap middle of extent: trim the length of the existing
2039 * record to the length of the new left-extent size, increment
2040 * the insertion position so we can insert a new record
2041 * containing the remaining right-extent space.
2044 * Orig: |oooooooooooooooooooo|
2045 * Freeing: |fffffffff|
2046 * Result: |rrrrr| |rrrr|
2049 xfs_extlen_t orig_len = ltrec.rm_blockcount;
2051 /* Shrink the left side of the rmap */
2052 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2053 ltrec.rm_blockcount, ltrec.rm_owner,
2054 ltrec.rm_offset, ltrec.rm_flags, &i);
2057 if (XFS_IS_CORRUPT(mp, i != 1)) {
2058 error = -EFSCORRUPTED;
2061 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
2062 error = xfs_rmap_update(cur, <rec);
2066 /* Add an rmap at the new offset */
2067 error = xfs_rmap_insert(cur, bno + len,
2068 orig_len - len - ltrec.rm_blockcount,
2069 ltrec.rm_owner, offset + len,
2075 trace_xfs_rmap_unmap_done(mp, cur->bc_ag.agno, bno, len,
2079 trace_xfs_rmap_unmap_error(cur->bc_mp,
2080 cur->bc_ag.agno, error, _RET_IP_);
2085 * Find an extent in the rmap btree and map it. For rmap extent types that
2086 * can overlap (data fork rmaps on reflink filesystems) we must be careful
2087 * that the prev/next records in the btree might belong to another owner.
2088 * Therefore we must use delete+insert to alter any of the key fields.
2090 * For every other situation there can only be one owner for a given extent,
2091 * so we can call the regular _alloc function.
2094 xfs_rmap_map_shared(
2095 struct xfs_btree_cur *cur,
2099 const struct xfs_owner_info *oinfo)
2101 struct xfs_mount *mp = cur->bc_mp;
2102 struct xfs_rmap_irec ltrec;
2103 struct xfs_rmap_irec gtrec;
2110 unsigned int flags = 0;
2112 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2114 flags |= XFS_RMAP_UNWRITTEN;
2115 trace_xfs_rmap_map(mp, cur->bc_ag.agno, bno, len,
2118 /* Is there a left record that abuts our range? */
2119 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
2124 !xfs_rmap_is_mergeable(<rec, owner, flags))
2127 /* Is there a right record that abuts our range? */
2128 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
2133 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
2136 if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
2137 error = -EFSCORRUPTED;
2140 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
2141 cur->bc_ag.agno, gtrec.rm_startblock,
2142 gtrec.rm_blockcount, gtrec.rm_owner,
2143 gtrec.rm_offset, gtrec.rm_flags);
2145 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
2150 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
2151 ltrec.rm_offset + ltrec.rm_blockcount == offset) {
2153 * Left edge contiguous, merge into left record.
2157 * adding: |aaaaaaaaa|
2158 * result: |rrrrrrrrrrrrrrrrrrr|
2161 ltrec.rm_blockcount += len;
2163 bno + len == gtrec.rm_startblock &&
2164 offset + len == gtrec.rm_offset) {
2166 * Right edge also contiguous, delete right record
2167 * and merge into left record.
2169 * ltbno ltlen gtbno gtlen
2170 * orig: |ooooooooo| |ooooooooo|
2171 * adding: |aaaaaaaaa|
2172 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
2174 ltrec.rm_blockcount += gtrec.rm_blockcount;
2175 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2176 gtrec.rm_blockcount, gtrec.rm_owner,
2177 gtrec.rm_offset, gtrec.rm_flags);
2182 /* Point the cursor back to the left record and update. */
2183 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2184 ltrec.rm_blockcount, ltrec.rm_owner,
2185 ltrec.rm_offset, ltrec.rm_flags, &i);
2188 if (XFS_IS_CORRUPT(mp, i != 1)) {
2189 error = -EFSCORRUPTED;
2193 error = xfs_rmap_update(cur, <rec);
2196 } else if (have_gt &&
2197 bno + len == gtrec.rm_startblock &&
2198 offset + len == gtrec.rm_offset) {
2200 * Right edge contiguous, merge into right record.
2204 * adding: |aaaaaaaaa|
2205 * Result: |rrrrrrrrrrrrrrrrrrr|
2208 /* Delete the old record. */
2209 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2210 gtrec.rm_blockcount, gtrec.rm_owner,
2211 gtrec.rm_offset, gtrec.rm_flags);
2215 /* Move the start and re-add it. */
2216 gtrec.rm_startblock = bno;
2217 gtrec.rm_blockcount += len;
2218 gtrec.rm_offset = offset;
2219 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2220 gtrec.rm_blockcount, gtrec.rm_owner,
2221 gtrec.rm_offset, gtrec.rm_flags);
2226 * No contiguous edge with identical owner, insert
2227 * new record at current cursor position.
2229 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2234 trace_xfs_rmap_map_done(mp, cur->bc_ag.agno, bno, len,
2238 trace_xfs_rmap_map_error(cur->bc_mp,
2239 cur->bc_ag.agno, error, _RET_IP_);
2243 /* Insert a raw rmap into the rmapbt. */
2246 struct xfs_btree_cur *cur,
2247 struct xfs_rmap_irec *rmap)
2249 struct xfs_owner_info oinfo;
2251 oinfo.oi_owner = rmap->rm_owner;
2252 oinfo.oi_offset = rmap->rm_offset;
2254 if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
2255 oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
2256 if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
2257 oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
2259 if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2260 return xfs_rmap_map(cur, rmap->rm_startblock,
2261 rmap->rm_blockcount,
2262 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2265 return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2266 rmap->rm_blockcount,
2267 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2271 struct xfs_rmap_query_range_info {
2272 xfs_rmap_query_range_fn fn;
2276 /* Format btree record and pass to our callback. */
2278 xfs_rmap_query_range_helper(
2279 struct xfs_btree_cur *cur,
2280 union xfs_btree_rec *rec,
2283 struct xfs_rmap_query_range_info *query = priv;
2284 struct xfs_rmap_irec irec;
2287 error = xfs_rmap_btrec_to_irec(rec, &irec);
2290 return query->fn(cur, &irec, query->priv);
2293 /* Find all rmaps between two keys. */
2295 xfs_rmap_query_range(
2296 struct xfs_btree_cur *cur,
2297 struct xfs_rmap_irec *low_rec,
2298 struct xfs_rmap_irec *high_rec,
2299 xfs_rmap_query_range_fn fn,
2302 union xfs_btree_irec low_brec;
2303 union xfs_btree_irec high_brec;
2304 struct xfs_rmap_query_range_info query;
2306 low_brec.r = *low_rec;
2307 high_brec.r = *high_rec;
2310 return xfs_btree_query_range(cur, &low_brec, &high_brec,
2311 xfs_rmap_query_range_helper, &query);
2314 /* Find all rmaps. */
2317 struct xfs_btree_cur *cur,
2318 xfs_rmap_query_range_fn fn,
2321 struct xfs_rmap_query_range_info query;
2325 return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2328 /* Clean up after calling xfs_rmap_finish_one. */
2330 xfs_rmap_finish_one_cleanup(
2331 struct xfs_trans *tp,
2332 struct xfs_btree_cur *rcur,
2335 struct xfs_buf *agbp;
2339 agbp = rcur->bc_ag.agbp;
2340 xfs_btree_del_cursor(rcur, error);
2342 xfs_trans_brelse(tp, agbp);
2346 * Process one of the deferred rmap operations. We pass back the
2347 * btree cursor to maintain our lock on the rmapbt between calls.
2348 * This saves time and eliminates a buffer deadlock between the
2349 * superblock and the AGF because we'll always grab them in the same
2353 xfs_rmap_finish_one(
2354 struct xfs_trans *tp,
2355 enum xfs_rmap_intent_type type,
2358 xfs_fileoff_t startoff,
2359 xfs_fsblock_t startblock,
2360 xfs_filblks_t blockcount,
2362 struct xfs_btree_cur **pcur)
2364 struct xfs_mount *mp = tp->t_mountp;
2365 struct xfs_btree_cur *rcur;
2366 struct xfs_buf *agbp = NULL;
2368 xfs_agnumber_t agno;
2369 struct xfs_owner_info oinfo;
2373 agno = XFS_FSB_TO_AGNO(mp, startblock);
2374 ASSERT(agno != NULLAGNUMBER);
2375 bno = XFS_FSB_TO_AGBNO(mp, startblock);
2377 trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork,
2378 startoff, blockcount, state);
2380 if (XFS_TEST_ERROR(false, mp,
2381 XFS_ERRTAG_RMAP_FINISH_ONE))
2385 * If we haven't gotten a cursor or the cursor AG doesn't match
2386 * the startblock, get one now.
2389 if (rcur != NULL && rcur->bc_ag.agno != agno) {
2390 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2396 * Refresh the freelist before we start changing the
2397 * rmapbt, because a shape change could cause us to
2400 error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
2403 if (XFS_IS_CORRUPT(tp->t_mountp, !agbp))
2404 return -EFSCORRUPTED;
2406 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
2414 xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2415 unwritten = state == XFS_EXT_UNWRITTEN;
2416 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2419 case XFS_RMAP_ALLOC:
2421 error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2423 case XFS_RMAP_MAP_SHARED:
2424 error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2428 case XFS_RMAP_UNMAP:
2429 error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2432 case XFS_RMAP_UNMAP_SHARED:
2433 error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2436 case XFS_RMAP_CONVERT:
2437 error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2440 case XFS_RMAP_CONVERT_SHARED:
2441 error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2442 !unwritten, &oinfo);
2446 error = -EFSCORRUPTED;
2451 xfs_trans_brelse(tp, agbp);
2457 * Don't defer an rmap if we aren't an rmap filesystem.
2460 xfs_rmap_update_is_needed(
2461 struct xfs_mount *mp,
2464 return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK;
2468 * Record a rmap intent; the list is kept sorted first by AG and then by
2473 struct xfs_trans *tp,
2474 enum xfs_rmap_intent_type type,
2477 struct xfs_bmbt_irec *bmap)
2479 struct xfs_rmap_intent *ri;
2481 trace_xfs_rmap_defer(tp->t_mountp,
2482 XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock),
2484 XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock),
2487 bmap->br_blockcount,
2490 ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_NOFS);
2491 INIT_LIST_HEAD(&ri->ri_list);
2493 ri->ri_owner = owner;
2494 ri->ri_whichfork = whichfork;
2495 ri->ri_bmap = *bmap;
2497 xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
2500 /* Map an extent into a file. */
2502 xfs_rmap_map_extent(
2503 struct xfs_trans *tp,
2504 struct xfs_inode *ip,
2506 struct xfs_bmbt_irec *PREV)
2508 enum xfs_rmap_intent_type type = XFS_RMAP_MAP;
2510 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2513 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2514 type = XFS_RMAP_MAP_SHARED;
2516 __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2519 /* Unmap an extent out of a file. */
2521 xfs_rmap_unmap_extent(
2522 struct xfs_trans *tp,
2523 struct xfs_inode *ip,
2525 struct xfs_bmbt_irec *PREV)
2527 enum xfs_rmap_intent_type type = XFS_RMAP_UNMAP;
2529 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2532 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2533 type = XFS_RMAP_UNMAP_SHARED;
2535 __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2539 * Convert a data fork extent from unwritten to real or vice versa.
2541 * Note that tp can be NULL here as no transaction is used for COW fork
2542 * unwritten conversion.
2545 xfs_rmap_convert_extent(
2546 struct xfs_mount *mp,
2547 struct xfs_trans *tp,
2548 struct xfs_inode *ip,
2550 struct xfs_bmbt_irec *PREV)
2552 enum xfs_rmap_intent_type type = XFS_RMAP_CONVERT;
2554 if (!xfs_rmap_update_is_needed(mp, whichfork))
2557 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2558 type = XFS_RMAP_CONVERT_SHARED;
2560 __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2563 /* Schedule the creation of an rmap for non-file data. */
2565 xfs_rmap_alloc_extent(
2566 struct xfs_trans *tp,
2567 xfs_agnumber_t agno,
2572 struct xfs_bmbt_irec bmap;
2574 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2577 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2578 bmap.br_blockcount = len;
2579 bmap.br_startoff = 0;
2580 bmap.br_state = XFS_EXT_NORM;
2582 __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
2585 /* Schedule the deletion of an rmap for non-file data. */
2587 xfs_rmap_free_extent(
2588 struct xfs_trans *tp,
2589 xfs_agnumber_t agno,
2594 struct xfs_bmbt_irec bmap;
2596 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2599 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2600 bmap.br_blockcount = len;
2601 bmap.br_startoff = 0;
2602 bmap.br_state = XFS_EXT_NORM;
2604 __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
2607 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2610 const struct xfs_rmap_irec *a,
2611 const struct xfs_rmap_irec *b)
2616 oa = xfs_rmap_irec_offset_pack(a);
2617 ob = xfs_rmap_irec_offset_pack(b);
2619 if (a->rm_startblock < b->rm_startblock)
2621 else if (a->rm_startblock > b->rm_startblock)
2623 else if (a->rm_owner < b->rm_owner)
2625 else if (a->rm_owner > b->rm_owner)
2635 /* Is there a record covering a given extent? */
2637 xfs_rmap_has_record(
2638 struct xfs_btree_cur *cur,
2643 union xfs_btree_irec low;
2644 union xfs_btree_irec high;
2646 memset(&low, 0, sizeof(low));
2647 low.r.rm_startblock = bno;
2648 memset(&high, 0xFF, sizeof(high));
2649 high.r.rm_startblock = bno + len - 1;
2651 return xfs_btree_has_record(cur, &low, &high, exists);
2655 * Is there a record for this owner completely covering a given physical
2656 * extent? If so, *has_rmap will be set to true. If there is no record
2657 * or the record only covers part of the range, we set *has_rmap to false.
2658 * This function doesn't perform range lookups or offset checks, so it is
2659 * not suitable for checking data fork blocks.
2662 xfs_rmap_record_exists(
2663 struct xfs_btree_cur *cur,
2666 const struct xfs_owner_info *oinfo,
2673 struct xfs_rmap_irec irec;
2676 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2677 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
2678 (flags & XFS_RMAP_BMBT_BLOCK));
2680 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
2689 error = xfs_rmap_get_rec(cur, &irec, &has_record);
2697 *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
2698 irec.rm_startblock + irec.rm_blockcount >= bno + len);
2702 struct xfs_rmap_key_state {
2708 /* For each rmap given, figure out if it doesn't match the key we want. */
2710 xfs_rmap_has_other_keys_helper(
2711 struct xfs_btree_cur *cur,
2712 struct xfs_rmap_irec *rec,
2715 struct xfs_rmap_key_state *rks = priv;
2717 if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset &&
2718 ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags)
2724 * Given an extent and some owner info, can we find records overlapping
2725 * the extent whose owner info does not match the given owner?
2728 xfs_rmap_has_other_keys(
2729 struct xfs_btree_cur *cur,
2732 const struct xfs_owner_info *oinfo,
2735 struct xfs_rmap_irec low = {0};
2736 struct xfs_rmap_irec high;
2737 struct xfs_rmap_key_state rks;
2740 xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags);
2743 low.rm_startblock = bno;
2744 memset(&high, 0xFF, sizeof(high));
2745 high.rm_startblock = bno + len - 1;
2747 error = xfs_rmap_query_range(cur, &low, &high,
2748 xfs_rmap_has_other_keys_helper, &rks);
2749 if (error == -ECANCELED) {
2757 const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
2758 .oi_owner = XFS_RMAP_OWN_NULL,
2760 const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
2761 .oi_owner = XFS_RMAP_OWN_UNKNOWN,
2763 const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
2764 .oi_owner = XFS_RMAP_OWN_FS,
2766 const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
2767 .oi_owner = XFS_RMAP_OWN_LOG,
2769 const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
2770 .oi_owner = XFS_RMAP_OWN_AG,
2772 const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
2773 .oi_owner = XFS_RMAP_OWN_INOBT,
2775 const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
2776 .oi_owner = XFS_RMAP_OWN_INODES,
2778 const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
2779 .oi_owner = XFS_RMAP_OWN_REFC,
2781 const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
2782 .oi_owner = XFS_RMAP_OWN_COW,