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_private.a.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_private.a.agno, error, _RET_IP_);
100 struct xfs_btree_cur *rcur,
110 trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
111 len, owner, offset, flags);
113 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
116 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 0, done);
118 rcur->bc_rec.r.rm_startblock = agbno;
119 rcur->bc_rec.r.rm_blockcount = len;
120 rcur->bc_rec.r.rm_owner = owner;
121 rcur->bc_rec.r.rm_offset = offset;
122 rcur->bc_rec.r.rm_flags = flags;
123 error = xfs_btree_insert(rcur, &i);
126 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
129 trace_xfs_rmap_insert_error(rcur->bc_mp,
130 rcur->bc_private.a.agno, error, _RET_IP_);
136 struct xfs_btree_cur *rcur,
146 trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
147 len, owner, offset, flags);
149 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
152 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
154 error = xfs_btree_delete(rcur, &i);
157 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
160 trace_xfs_rmap_delete_error(rcur->bc_mp,
161 rcur->bc_private.a.agno, error, _RET_IP_);
165 /* Convert an internal btree record to an rmap record. */
167 xfs_rmap_btrec_to_irec(
168 union xfs_btree_rec *rec,
169 struct xfs_rmap_irec *irec)
171 irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
172 irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
173 irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
174 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
179 * Get the data from the pointed-to record.
183 struct xfs_btree_cur *cur,
184 struct xfs_rmap_irec *irec,
187 struct xfs_mount *mp = cur->bc_mp;
188 xfs_agnumber_t agno = cur->bc_private.a.agno;
189 union xfs_btree_rec *rec;
192 error = xfs_btree_get_rec(cur, &rec, stat);
196 if (xfs_rmap_btrec_to_irec(rec, irec))
199 if (irec->rm_blockcount == 0)
201 if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
202 if (irec->rm_owner != XFS_RMAP_OWN_FS)
204 if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
207 /* check for valid extent range, including overflow */
208 if (!xfs_verify_agbno(mp, agno, irec->rm_startblock))
210 if (irec->rm_startblock >
211 irec->rm_startblock + irec->rm_blockcount)
213 if (!xfs_verify_agbno(mp, agno,
214 irec->rm_startblock + irec->rm_blockcount - 1))
218 if (!(xfs_verify_ino(mp, irec->rm_owner) ||
219 (irec->rm_owner <= XFS_RMAP_OWN_FS &&
220 irec->rm_owner >= XFS_RMAP_OWN_MIN)))
226 "Reverse Mapping BTree record corruption in AG %d detected!",
229 "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
230 irec->rm_owner, irec->rm_flags, irec->rm_startblock,
231 irec->rm_blockcount);
232 return -EFSCORRUPTED;
235 struct xfs_find_left_neighbor_info {
236 struct xfs_rmap_irec high;
237 struct xfs_rmap_irec *irec;
241 /* For each rmap given, figure out if it matches the key we want. */
243 xfs_rmap_find_left_neighbor_helper(
244 struct xfs_btree_cur *cur,
245 struct xfs_rmap_irec *rec,
248 struct xfs_find_left_neighbor_info *info = priv;
250 trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
251 cur->bc_private.a.agno, rec->rm_startblock,
252 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
255 if (rec->rm_owner != info->high.rm_owner)
256 return XFS_BTREE_QUERY_RANGE_CONTINUE;
257 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
258 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
259 rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
260 return XFS_BTREE_QUERY_RANGE_CONTINUE;
264 return XFS_BTREE_QUERY_RANGE_ABORT;
268 * Find the record to the left of the given extent, being careful only to
269 * return a match with the same owner and adjacent physical and logical
273 xfs_rmap_find_left_neighbor(
274 struct xfs_btree_cur *cur,
279 struct xfs_rmap_irec *irec,
282 struct xfs_find_left_neighbor_info info;
288 info.high.rm_startblock = bno - 1;
289 info.high.rm_owner = owner;
290 if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
291 !(flags & XFS_RMAP_BMBT_BLOCK)) {
294 info.high.rm_offset = offset - 1;
296 info.high.rm_offset = 0;
297 info.high.rm_flags = flags;
298 info.high.rm_blockcount = 0;
302 trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
303 cur->bc_private.a.agno, bno, 0, owner, offset, flags);
305 error = xfs_rmap_query_range(cur, &info.high, &info.high,
306 xfs_rmap_find_left_neighbor_helper, &info);
307 if (error == XFS_BTREE_QUERY_RANGE_ABORT)
310 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
311 cur->bc_private.a.agno, irec->rm_startblock,
312 irec->rm_blockcount, irec->rm_owner,
313 irec->rm_offset, irec->rm_flags);
317 /* For each rmap given, figure out if it matches the key we want. */
319 xfs_rmap_lookup_le_range_helper(
320 struct xfs_btree_cur *cur,
321 struct xfs_rmap_irec *rec,
324 struct xfs_find_left_neighbor_info *info = priv;
326 trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
327 cur->bc_private.a.agno, rec->rm_startblock,
328 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
331 if (rec->rm_owner != info->high.rm_owner)
332 return XFS_BTREE_QUERY_RANGE_CONTINUE;
333 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
334 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
335 (rec->rm_offset > info->high.rm_offset ||
336 rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
337 return XFS_BTREE_QUERY_RANGE_CONTINUE;
341 return XFS_BTREE_QUERY_RANGE_ABORT;
345 * Find the record to the left of the given extent, being careful only to
346 * return a match with the same owner and overlapping physical and logical
347 * block ranges. This is the overlapping-interval version of
348 * xfs_rmap_lookup_le.
351 xfs_rmap_lookup_le_range(
352 struct xfs_btree_cur *cur,
357 struct xfs_rmap_irec *irec,
360 struct xfs_find_left_neighbor_info info;
363 info.high.rm_startblock = bno;
364 info.high.rm_owner = owner;
365 if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
366 info.high.rm_offset = offset;
368 info.high.rm_offset = 0;
369 info.high.rm_flags = flags;
370 info.high.rm_blockcount = 0;
375 trace_xfs_rmap_lookup_le_range(cur->bc_mp,
376 cur->bc_private.a.agno, bno, 0, owner, offset, flags);
377 error = xfs_rmap_query_range(cur, &info.high, &info.high,
378 xfs_rmap_lookup_le_range_helper, &info);
379 if (error == XFS_BTREE_QUERY_RANGE_ABORT)
382 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
383 cur->bc_private.a.agno, irec->rm_startblock,
384 irec->rm_blockcount, irec->rm_owner,
385 irec->rm_offset, irec->rm_flags);
390 * Perform all the relevant owner checks for a removal op. If we're doing an
391 * unknown-owner removal then we have no owner information to check.
394 xfs_rmap_free_check_owner(
395 struct xfs_mount *mp,
397 struct xfs_rmap_irec *rec,
405 if (owner == XFS_RMAP_OWN_UNKNOWN)
408 /* Make sure the unwritten flag matches. */
409 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
410 (rec->rm_flags & XFS_RMAP_UNWRITTEN), out);
412 /* Make sure the owner matches what we expect to find in the tree. */
413 XFS_WANT_CORRUPTED_GOTO(mp, owner == rec->rm_owner, out);
415 /* Check the offset, if necessary. */
416 if (XFS_RMAP_NON_INODE_OWNER(owner))
419 if (flags & XFS_RMAP_BMBT_BLOCK) {
420 XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_flags & XFS_RMAP_BMBT_BLOCK,
423 XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_offset <= offset, out);
424 XFS_WANT_CORRUPTED_GOTO(mp,
425 ltoff + rec->rm_blockcount >= offset + len,
434 * Find the extent in the rmap btree and remove it.
436 * The record we find should always be an exact match for the extent that we're
437 * looking for, since we insert them into the btree without modification.
439 * Special Case #1: when growing the filesystem, we "free" an extent when
440 * growing the last AG. This extent is new space and so it is not tracked as
441 * used space in the btree. The growfs code will pass in an owner of
442 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
443 * extent. We verify that - the extent lookup result in a record that does not
446 * Special Case #2: EFIs do not record the owner of the extent, so when
447 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
448 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
449 * corruption checks during log recovery.
453 struct xfs_btree_cur *cur,
457 const struct xfs_owner_info *oinfo)
459 struct xfs_mount *mp = cur->bc_mp;
460 struct xfs_rmap_irec ltrec;
469 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
470 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
471 (flags & XFS_RMAP_BMBT_BLOCK);
473 flags |= XFS_RMAP_UNWRITTEN;
474 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
478 * We should always have a left record because there's a static record
479 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
480 * will not ever be removed from the tree.
482 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i);
485 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
487 error = xfs_rmap_get_rec(cur, <rec, &i);
490 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
491 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
492 cur->bc_private.a.agno, ltrec.rm_startblock,
493 ltrec.rm_blockcount, ltrec.rm_owner,
494 ltrec.rm_offset, ltrec.rm_flags);
495 ltoff = ltrec.rm_offset;
498 * For growfs, the incoming extent must be beyond the left record we
499 * just found as it is new space and won't be used by anyone. This is
500 * just a corruption check as we don't actually do anything with this
501 * extent. Note that we need to use >= instead of > because it might
502 * be the case that the "left" extent goes all the way to EOFS.
504 if (owner == XFS_RMAP_OWN_NULL) {
505 XFS_WANT_CORRUPTED_GOTO(mp, bno >= ltrec.rm_startblock +
506 ltrec.rm_blockcount, out_error);
511 * If we're doing an unknown-owner removal for EFI recovery, we expect
512 * to find the full range in the rmapbt or nothing at all. If we
513 * don't find any rmaps overlapping either end of the range, we're
514 * done. Hopefully this means that the EFI creator already queued
515 * (and finished) a RUI to remove the rmap.
517 if (owner == XFS_RMAP_OWN_UNKNOWN &&
518 ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
519 struct xfs_rmap_irec rtrec;
521 error = xfs_btree_increment(cur, 0, &i);
526 error = xfs_rmap_get_rec(cur, &rtrec, &i);
529 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
530 if (rtrec.rm_startblock >= bno + len)
534 /* Make sure the extent we found covers the entire freeing range. */
535 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
536 ltrec.rm_startblock + ltrec.rm_blockcount >=
537 bno + len, out_error);
539 /* Check owner information. */
540 error = xfs_rmap_free_check_owner(mp, ltoff, <rec, len, owner,
545 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
546 /* exact match, simply remove the record from rmap tree */
547 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
548 ltrec.rm_startblock, ltrec.rm_blockcount,
549 ltrec.rm_owner, ltrec.rm_offset,
551 error = xfs_btree_delete(cur, &i);
554 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
555 } else if (ltrec.rm_startblock == bno) {
557 * overlap left hand side of extent: move the start, trim the
558 * length and update the current record.
561 * Orig: |oooooooooooooooooooo|
562 * Freeing: |fffffffff|
563 * Result: |rrrrrrrrrr|
566 ltrec.rm_startblock += len;
567 ltrec.rm_blockcount -= len;
569 ltrec.rm_offset += len;
570 error = xfs_rmap_update(cur, <rec);
573 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
575 * overlap right hand side of extent: trim the length and update
576 * the current record.
579 * Orig: |oooooooooooooooooooo|
580 * Freeing: |fffffffff|
581 * Result: |rrrrrrrrrr|
584 ltrec.rm_blockcount -= len;
585 error = xfs_rmap_update(cur, <rec);
591 * overlap middle of extent: trim the length of the existing
592 * record to the length of the new left-extent size, increment
593 * the insertion position so we can insert a new record
594 * containing the remaining right-extent space.
597 * Orig: |oooooooooooooooooooo|
598 * Freeing: |fffffffff|
599 * Result: |rrrrr| |rrrr|
602 xfs_extlen_t orig_len = ltrec.rm_blockcount;
604 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
605 error = xfs_rmap_update(cur, <rec);
609 error = xfs_btree_increment(cur, 0, &i);
613 cur->bc_rec.r.rm_startblock = bno + len;
614 cur->bc_rec.r.rm_blockcount = orig_len - len -
616 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
618 cur->bc_rec.r.rm_offset = 0;
620 cur->bc_rec.r.rm_offset = offset + len;
621 cur->bc_rec.r.rm_flags = flags;
622 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
623 cur->bc_rec.r.rm_startblock,
624 cur->bc_rec.r.rm_blockcount,
625 cur->bc_rec.r.rm_owner,
626 cur->bc_rec.r.rm_offset,
627 cur->bc_rec.r.rm_flags);
628 error = xfs_btree_insert(cur, &i);
634 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
638 trace_xfs_rmap_unmap_error(mp, cur->bc_private.a.agno,
644 * Remove a reference to an extent in the rmap btree.
648 struct xfs_trans *tp,
649 struct xfs_buf *agbp,
653 const struct xfs_owner_info *oinfo)
655 struct xfs_mount *mp = tp->t_mountp;
656 struct xfs_btree_cur *cur;
659 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
662 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
664 error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
666 xfs_btree_del_cursor(cur, error);
671 * A mergeable rmap must have the same owner and the same values for
672 * the unwritten, attr_fork, and bmbt flags. The startblock and
673 * offset are checked separately.
676 xfs_rmap_is_mergeable(
677 struct xfs_rmap_irec *irec,
681 if (irec->rm_owner == XFS_RMAP_OWN_NULL)
683 if (irec->rm_owner != owner)
685 if ((flags & XFS_RMAP_UNWRITTEN) ^
686 (irec->rm_flags & XFS_RMAP_UNWRITTEN))
688 if ((flags & XFS_RMAP_ATTR_FORK) ^
689 (irec->rm_flags & XFS_RMAP_ATTR_FORK))
691 if ((flags & XFS_RMAP_BMBT_BLOCK) ^
692 (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
698 * When we allocate a new block, the first thing we do is add a reference to
699 * the extent in the rmap btree. This takes the form of a [agbno, length,
700 * owner, offset] record. Flags are encoded in the high bits of the offset
705 struct xfs_btree_cur *cur,
709 const struct xfs_owner_info *oinfo)
711 struct xfs_mount *mp = cur->bc_mp;
712 struct xfs_rmap_irec ltrec;
713 struct xfs_rmap_irec gtrec;
720 unsigned int flags = 0;
723 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
725 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
726 (flags & XFS_RMAP_BMBT_BLOCK);
728 flags |= XFS_RMAP_UNWRITTEN;
729 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
731 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
734 * For the initial lookup, look for an exact match or the left-adjacent
735 * record for our insertion point. This will also give us the record for
736 * start block contiguity tests.
738 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
743 error = xfs_rmap_get_rec(cur, <rec, &have_lt);
746 XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
747 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
748 cur->bc_private.a.agno, ltrec.rm_startblock,
749 ltrec.rm_blockcount, ltrec.rm_owner,
750 ltrec.rm_offset, ltrec.rm_flags);
752 if (!xfs_rmap_is_mergeable(<rec, owner, flags))
756 XFS_WANT_CORRUPTED_GOTO(mp,
758 ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error);
761 * Increment the cursor to see if we have a right-adjacent record to our
762 * insertion point. This will give us the record for end block
765 error = xfs_btree_increment(cur, 0, &have_gt);
769 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
772 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
773 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock,
775 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
776 cur->bc_private.a.agno, gtrec.rm_startblock,
777 gtrec.rm_blockcount, gtrec.rm_owner,
778 gtrec.rm_offset, gtrec.rm_flags);
779 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
784 * Note: cursor currently points one record to the right of ltrec, even
785 * if there is no record in the tree to the right.
788 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
789 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
791 * left edge contiguous, merge into left record.
795 * adding: |aaaaaaaaa|
796 * result: |rrrrrrrrrrrrrrrrrrr|
799 ltrec.rm_blockcount += len;
801 bno + len == gtrec.rm_startblock &&
802 (ignore_off || offset + len == gtrec.rm_offset) &&
803 (unsigned long)ltrec.rm_blockcount + len +
804 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
806 * right edge also contiguous, delete right record
807 * and merge into left record.
809 * ltbno ltlen gtbno gtlen
810 * orig: |ooooooooo| |ooooooooo|
811 * adding: |aaaaaaaaa|
812 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
814 ltrec.rm_blockcount += gtrec.rm_blockcount;
815 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
821 error = xfs_btree_delete(cur, &i);
824 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
827 /* point the cursor back to the left record and update */
828 error = xfs_btree_decrement(cur, 0, &have_gt);
831 error = xfs_rmap_update(cur, <rec);
834 } else if (have_gt &&
835 bno + len == gtrec.rm_startblock &&
836 (ignore_off || offset + len == gtrec.rm_offset)) {
838 * right edge contiguous, merge into right record.
842 * adding: |aaaaaaaaa|
843 * Result: |rrrrrrrrrrrrrrrrrrr|
846 gtrec.rm_startblock = bno;
847 gtrec.rm_blockcount += len;
849 gtrec.rm_offset = offset;
850 error = xfs_rmap_update(cur, >rec);
855 * no contiguous edge with identical owner, insert
856 * new record at current cursor position.
858 cur->bc_rec.r.rm_startblock = bno;
859 cur->bc_rec.r.rm_blockcount = len;
860 cur->bc_rec.r.rm_owner = owner;
861 cur->bc_rec.r.rm_offset = offset;
862 cur->bc_rec.r.rm_flags = flags;
863 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
864 owner, offset, flags);
865 error = xfs_btree_insert(cur, &i);
868 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
871 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
875 trace_xfs_rmap_map_error(mp, cur->bc_private.a.agno,
881 * Add a reference to an extent in the rmap btree.
885 struct xfs_trans *tp,
886 struct xfs_buf *agbp,
890 const struct xfs_owner_info *oinfo)
892 struct xfs_mount *mp = tp->t_mountp;
893 struct xfs_btree_cur *cur;
896 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
899 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
900 error = xfs_rmap_map(cur, bno, len, false, oinfo);
902 xfs_btree_del_cursor(cur, error);
906 #define RMAP_LEFT_CONTIG (1 << 0)
907 #define RMAP_RIGHT_CONTIG (1 << 1)
908 #define RMAP_LEFT_FILLING (1 << 2)
909 #define RMAP_RIGHT_FILLING (1 << 3)
910 #define RMAP_LEFT_VALID (1 << 6)
911 #define RMAP_RIGHT_VALID (1 << 7)
919 * Convert an unwritten extent to a real extent or vice versa.
920 * Does not handle overlapping extents.
924 struct xfs_btree_cur *cur,
928 const struct xfs_owner_info *oinfo)
930 struct xfs_mount *mp = cur->bc_mp;
931 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
932 /* left is 0, right is 1, */
933 /* prev is 2, new is 3 */
939 unsigned int flags = 0;
944 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
945 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
946 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
947 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
948 new_endoff = offset + len;
949 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
953 * For the initial lookup, look for an exact match or the left-adjacent
954 * record for our insertion point. This will also give us the record for
955 * start block contiguity tests.
957 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
960 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
962 error = xfs_rmap_get_rec(cur, &PREV, &i);
965 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
966 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
967 cur->bc_private.a.agno, PREV.rm_startblock,
968 PREV.rm_blockcount, PREV.rm_owner,
969 PREV.rm_offset, PREV.rm_flags);
971 ASSERT(PREV.rm_offset <= offset);
972 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
973 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
974 newext = ~oldext & XFS_RMAP_UNWRITTEN;
977 * Set flags determining what part of the previous oldext allocation
978 * extent is being replaced by a newext allocation.
980 if (PREV.rm_offset == offset)
981 state |= RMAP_LEFT_FILLING;
982 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
983 state |= RMAP_RIGHT_FILLING;
986 * Decrement the cursor to see if we have a left-adjacent record to our
987 * insertion point. This will give us the record for end block
990 error = xfs_btree_decrement(cur, 0, &i);
994 state |= RMAP_LEFT_VALID;
995 error = xfs_rmap_get_rec(cur, &LEFT, &i);
998 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
999 XFS_WANT_CORRUPTED_GOTO(mp,
1000 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
1002 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
1003 cur->bc_private.a.agno, LEFT.rm_startblock,
1004 LEFT.rm_blockcount, LEFT.rm_owner,
1005 LEFT.rm_offset, LEFT.rm_flags);
1006 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1007 LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1008 xfs_rmap_is_mergeable(&LEFT, owner, newext))
1009 state |= RMAP_LEFT_CONTIG;
1013 * Increment the cursor to see if we have a right-adjacent record to our
1014 * insertion point. This will give us the record for end block
1017 error = xfs_btree_increment(cur, 0, &i);
1020 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1021 error = xfs_btree_increment(cur, 0, &i);
1025 state |= RMAP_RIGHT_VALID;
1026 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1029 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1030 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1032 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1033 cur->bc_private.a.agno, RIGHT.rm_startblock,
1034 RIGHT.rm_blockcount, RIGHT.rm_owner,
1035 RIGHT.rm_offset, RIGHT.rm_flags);
1036 if (bno + len == RIGHT.rm_startblock &&
1037 offset + len == RIGHT.rm_offset &&
1038 xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1039 state |= RMAP_RIGHT_CONTIG;
1042 /* check that left + prev + right is not too long */
1043 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1044 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1045 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1046 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1047 (unsigned long)LEFT.rm_blockcount + len +
1048 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1049 state &= ~RMAP_RIGHT_CONTIG;
1051 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1054 /* reset the cursor back to PREV */
1055 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1058 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1061 * Switch out based on the FILLING and CONTIG state bits.
1063 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1064 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1065 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1066 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1068 * Setting all of a previous oldext extent to newext.
1069 * The left and right neighbors are both contiguous with new.
1071 error = xfs_btree_increment(cur, 0, &i);
1074 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1075 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1076 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1077 RIGHT.rm_owner, RIGHT.rm_offset,
1079 error = xfs_btree_delete(cur, &i);
1082 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1083 error = xfs_btree_decrement(cur, 0, &i);
1086 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1087 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1088 PREV.rm_startblock, PREV.rm_blockcount,
1089 PREV.rm_owner, PREV.rm_offset,
1091 error = xfs_btree_delete(cur, &i);
1094 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1095 error = xfs_btree_decrement(cur, 0, &i);
1098 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1100 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1101 error = xfs_rmap_update(cur, &NEW);
1106 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1108 * Setting all of a previous oldext extent to newext.
1109 * The left neighbor is contiguous, the right is not.
1111 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1112 PREV.rm_startblock, PREV.rm_blockcount,
1113 PREV.rm_owner, PREV.rm_offset,
1115 error = xfs_btree_delete(cur, &i);
1118 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1119 error = xfs_btree_decrement(cur, 0, &i);
1122 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1124 NEW.rm_blockcount += PREV.rm_blockcount;
1125 error = xfs_rmap_update(cur, &NEW);
1130 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1132 * Setting all of a previous oldext extent to newext.
1133 * The right neighbor is contiguous, the left is not.
1135 error = xfs_btree_increment(cur, 0, &i);
1138 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1139 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1140 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1141 RIGHT.rm_owner, RIGHT.rm_offset,
1143 error = xfs_btree_delete(cur, &i);
1146 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1147 error = xfs_btree_decrement(cur, 0, &i);
1150 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1152 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1153 NEW.rm_flags = newext;
1154 error = xfs_rmap_update(cur, &NEW);
1159 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1161 * Setting all of a previous oldext extent to newext.
1162 * Neither the left nor right neighbors are contiguous with
1166 NEW.rm_flags = newext;
1167 error = xfs_rmap_update(cur, &NEW);
1172 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1174 * Setting the first part of a previous oldext extent to newext.
1175 * The left neighbor is contiguous.
1178 NEW.rm_offset += len;
1179 NEW.rm_startblock += len;
1180 NEW.rm_blockcount -= len;
1181 error = xfs_rmap_update(cur, &NEW);
1184 error = xfs_btree_decrement(cur, 0, &i);
1188 NEW.rm_blockcount += len;
1189 error = xfs_rmap_update(cur, &NEW);
1194 case RMAP_LEFT_FILLING:
1196 * Setting the first part of a previous oldext extent to newext.
1197 * The left neighbor is not contiguous.
1200 NEW.rm_startblock += len;
1201 NEW.rm_offset += len;
1202 NEW.rm_blockcount -= len;
1203 error = xfs_rmap_update(cur, &NEW);
1206 NEW.rm_startblock = bno;
1207 NEW.rm_owner = owner;
1208 NEW.rm_offset = offset;
1209 NEW.rm_blockcount = len;
1210 NEW.rm_flags = newext;
1211 cur->bc_rec.r = NEW;
1212 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1213 len, owner, offset, newext);
1214 error = xfs_btree_insert(cur, &i);
1217 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1220 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1222 * Setting the last part of a previous oldext extent to newext.
1223 * The right neighbor is contiguous with the new allocation.
1226 NEW.rm_blockcount -= len;
1227 error = xfs_rmap_update(cur, &NEW);
1230 error = xfs_btree_increment(cur, 0, &i);
1234 NEW.rm_offset = offset;
1235 NEW.rm_startblock = bno;
1236 NEW.rm_blockcount += len;
1237 error = xfs_rmap_update(cur, &NEW);
1242 case RMAP_RIGHT_FILLING:
1244 * Setting the last part of a previous oldext extent to newext.
1245 * The right neighbor is not contiguous.
1248 NEW.rm_blockcount -= len;
1249 error = xfs_rmap_update(cur, &NEW);
1252 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1256 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1257 NEW.rm_startblock = bno;
1258 NEW.rm_owner = owner;
1259 NEW.rm_offset = offset;
1260 NEW.rm_blockcount = len;
1261 NEW.rm_flags = newext;
1262 cur->bc_rec.r = NEW;
1263 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1264 len, owner, offset, newext);
1265 error = xfs_btree_insert(cur, &i);
1268 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1273 * Setting the middle part of a previous oldext extent to
1274 * newext. Contiguity is impossible here.
1275 * One extent becomes three extents.
1277 /* new right extent - oldext */
1278 NEW.rm_startblock = bno + len;
1279 NEW.rm_owner = owner;
1280 NEW.rm_offset = new_endoff;
1281 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1283 NEW.rm_flags = PREV.rm_flags;
1284 error = xfs_rmap_update(cur, &NEW);
1287 /* new left extent - oldext */
1289 NEW.rm_blockcount = offset - PREV.rm_offset;
1290 cur->bc_rec.r = NEW;
1291 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
1292 NEW.rm_startblock, NEW.rm_blockcount,
1293 NEW.rm_owner, NEW.rm_offset,
1295 error = xfs_btree_insert(cur, &i);
1298 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1300 * Reset the cursor to the position of the new extent
1301 * we are about to insert as we can't trust it after
1302 * the previous insert.
1304 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1308 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1309 /* new middle extent - newext */
1310 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1311 cur->bc_rec.r.rm_flags |= newext;
1312 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
1313 owner, offset, newext);
1314 error = xfs_btree_insert(cur, &i);
1317 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1320 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1321 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1322 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1323 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1324 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1325 case RMAP_LEFT_CONTIG:
1326 case RMAP_RIGHT_CONTIG:
1328 * These cases are all impossible.
1333 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1337 trace_xfs_rmap_convert_error(cur->bc_mp,
1338 cur->bc_private.a.agno, error, _RET_IP_);
1343 * Convert an unwritten extent to a real extent or vice versa. If there is no
1344 * possibility of overlapping extents, delegate to the simpler convert
1348 xfs_rmap_convert_shared(
1349 struct xfs_btree_cur *cur,
1353 const struct xfs_owner_info *oinfo)
1355 struct xfs_mount *mp = cur->bc_mp;
1356 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1357 /* left is 0, right is 1, */
1358 /* prev is 2, new is 3 */
1361 uint64_t new_endoff;
1362 unsigned int oldext;
1363 unsigned int newext;
1364 unsigned int flags = 0;
1369 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1370 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1371 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1372 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1373 new_endoff = offset + len;
1374 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
1378 * For the initial lookup, look for and exact match or the left-adjacent
1379 * record for our insertion point. This will also give us the record for
1380 * start block contiguity tests.
1382 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1386 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1388 ASSERT(PREV.rm_offset <= offset);
1389 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1390 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1391 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1394 * Set flags determining what part of the previous oldext allocation
1395 * extent is being replaced by a newext allocation.
1397 if (PREV.rm_offset == offset)
1398 state |= RMAP_LEFT_FILLING;
1399 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1400 state |= RMAP_RIGHT_FILLING;
1402 /* Is there a left record that abuts our range? */
1403 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1408 state |= RMAP_LEFT_VALID;
1409 XFS_WANT_CORRUPTED_GOTO(mp,
1410 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
1412 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1413 state |= RMAP_LEFT_CONTIG;
1416 /* Is there a right record that abuts our range? */
1417 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1422 state |= RMAP_RIGHT_VALID;
1423 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1426 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1427 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1429 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1430 cur->bc_private.a.agno, RIGHT.rm_startblock,
1431 RIGHT.rm_blockcount, RIGHT.rm_owner,
1432 RIGHT.rm_offset, RIGHT.rm_flags);
1433 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1434 state |= RMAP_RIGHT_CONTIG;
1437 /* check that left + prev + right is not too long */
1438 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1439 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1440 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1441 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1442 (unsigned long)LEFT.rm_blockcount + len +
1443 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1444 state &= ~RMAP_RIGHT_CONTIG;
1446 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1449 * Switch out based on the FILLING and CONTIG state bits.
1451 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1452 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1453 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1454 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1456 * Setting all of a previous oldext extent to newext.
1457 * The left and right neighbors are both contiguous with new.
1459 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1460 RIGHT.rm_blockcount, RIGHT.rm_owner,
1461 RIGHT.rm_offset, RIGHT.rm_flags);
1464 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1465 PREV.rm_blockcount, PREV.rm_owner,
1466 PREV.rm_offset, PREV.rm_flags);
1470 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1471 NEW.rm_blockcount, NEW.rm_owner,
1472 NEW.rm_offset, NEW.rm_flags, &i);
1475 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1476 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1477 error = xfs_rmap_update(cur, &NEW);
1482 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1484 * Setting all of a previous oldext extent to newext.
1485 * The left neighbor is contiguous, the right is not.
1487 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1488 PREV.rm_blockcount, PREV.rm_owner,
1489 PREV.rm_offset, PREV.rm_flags);
1493 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1494 NEW.rm_blockcount, NEW.rm_owner,
1495 NEW.rm_offset, NEW.rm_flags, &i);
1498 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1499 NEW.rm_blockcount += PREV.rm_blockcount;
1500 error = xfs_rmap_update(cur, &NEW);
1505 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1507 * Setting all of a previous oldext extent to newext.
1508 * The right neighbor is contiguous, the left is not.
1510 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1511 RIGHT.rm_blockcount, RIGHT.rm_owner,
1512 RIGHT.rm_offset, RIGHT.rm_flags);
1516 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1517 NEW.rm_blockcount, NEW.rm_owner,
1518 NEW.rm_offset, NEW.rm_flags, &i);
1521 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1522 NEW.rm_blockcount += RIGHT.rm_blockcount;
1523 NEW.rm_flags = RIGHT.rm_flags;
1524 error = xfs_rmap_update(cur, &NEW);
1529 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1531 * Setting all of a previous oldext extent to newext.
1532 * Neither the left nor right neighbors are contiguous with
1536 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1537 NEW.rm_blockcount, NEW.rm_owner,
1538 NEW.rm_offset, NEW.rm_flags, &i);
1541 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1542 NEW.rm_flags = newext;
1543 error = xfs_rmap_update(cur, &NEW);
1548 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1550 * Setting the first part of a previous oldext extent to newext.
1551 * The left neighbor is contiguous.
1554 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1555 NEW.rm_blockcount, NEW.rm_owner,
1556 NEW.rm_offset, NEW.rm_flags);
1559 NEW.rm_offset += len;
1560 NEW.rm_startblock += len;
1561 NEW.rm_blockcount -= len;
1562 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1563 NEW.rm_blockcount, NEW.rm_owner,
1564 NEW.rm_offset, NEW.rm_flags);
1568 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1569 NEW.rm_blockcount, NEW.rm_owner,
1570 NEW.rm_offset, NEW.rm_flags, &i);
1573 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1574 NEW.rm_blockcount += len;
1575 error = xfs_rmap_update(cur, &NEW);
1580 case RMAP_LEFT_FILLING:
1582 * Setting the first part of a previous oldext extent to newext.
1583 * The left neighbor is not contiguous.
1586 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1587 NEW.rm_blockcount, NEW.rm_owner,
1588 NEW.rm_offset, NEW.rm_flags);
1591 NEW.rm_offset += len;
1592 NEW.rm_startblock += len;
1593 NEW.rm_blockcount -= len;
1594 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1595 NEW.rm_blockcount, NEW.rm_owner,
1596 NEW.rm_offset, NEW.rm_flags);
1599 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1604 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1606 * Setting the last part of a previous oldext extent to newext.
1607 * The right neighbor is contiguous with the new allocation.
1610 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1611 NEW.rm_blockcount, NEW.rm_owner,
1612 NEW.rm_offset, NEW.rm_flags, &i);
1615 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1616 NEW.rm_blockcount = offset - NEW.rm_offset;
1617 error = xfs_rmap_update(cur, &NEW);
1621 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1622 NEW.rm_blockcount, NEW.rm_owner,
1623 NEW.rm_offset, NEW.rm_flags);
1626 NEW.rm_offset = offset;
1627 NEW.rm_startblock = bno;
1628 NEW.rm_blockcount += len;
1629 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1630 NEW.rm_blockcount, NEW.rm_owner,
1631 NEW.rm_offset, NEW.rm_flags);
1636 case RMAP_RIGHT_FILLING:
1638 * Setting the last part of a previous oldext extent to newext.
1639 * The right neighbor is not contiguous.
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 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1648 NEW.rm_blockcount -= len;
1649 error = xfs_rmap_update(cur, &NEW);
1652 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1659 * Setting the middle part of a previous oldext extent to
1660 * newext. Contiguity is impossible here.
1661 * One extent becomes three extents.
1663 /* new right extent - oldext */
1664 NEW.rm_startblock = bno + len;
1665 NEW.rm_owner = owner;
1666 NEW.rm_offset = new_endoff;
1667 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1669 NEW.rm_flags = PREV.rm_flags;
1670 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1671 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1675 /* new left extent - oldext */
1677 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1678 NEW.rm_blockcount, NEW.rm_owner,
1679 NEW.rm_offset, NEW.rm_flags, &i);
1682 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1683 NEW.rm_blockcount = offset - NEW.rm_offset;
1684 error = xfs_rmap_update(cur, &NEW);
1687 /* new middle extent - newext */
1688 NEW.rm_startblock = bno;
1689 NEW.rm_blockcount = len;
1690 NEW.rm_owner = owner;
1691 NEW.rm_offset = offset;
1692 NEW.rm_flags = newext;
1693 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1694 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1700 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1701 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1702 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1703 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1704 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1705 case RMAP_LEFT_CONTIG:
1706 case RMAP_RIGHT_CONTIG:
1708 * These cases are all impossible.
1713 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1717 trace_xfs_rmap_convert_error(cur->bc_mp,
1718 cur->bc_private.a.agno, error, _RET_IP_);
1728 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1729 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1730 * that the prev/next records in the btree might belong to another owner.
1731 * Therefore we must use delete+insert to alter any of the key fields.
1733 * For every other situation there can only be one owner for a given extent,
1734 * so we can call the regular _free function.
1737 xfs_rmap_unmap_shared(
1738 struct xfs_btree_cur *cur,
1742 const struct xfs_owner_info *oinfo)
1744 struct xfs_mount *mp = cur->bc_mp;
1745 struct xfs_rmap_irec ltrec;
1753 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1755 flags |= XFS_RMAP_UNWRITTEN;
1756 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
1760 * We should always have a left record because there's a static record
1761 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1762 * will not ever be removed from the tree.
1764 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1768 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1769 ltoff = ltrec.rm_offset;
1771 /* Make sure the extent we found covers the entire freeing range. */
1772 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
1773 ltrec.rm_startblock + ltrec.rm_blockcount >=
1774 bno + len, out_error);
1776 /* Make sure the owner matches what we expect to find in the tree. */
1777 XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner, out_error);
1779 /* Make sure the unwritten flag matches. */
1780 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
1781 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error);
1783 /* Check the offset. */
1784 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error);
1785 XFS_WANT_CORRUPTED_GOTO(mp, offset <= ltoff + ltrec.rm_blockcount,
1788 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
1789 /* Exact match, simply remove the record from rmap tree. */
1790 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1791 ltrec.rm_blockcount, ltrec.rm_owner,
1792 ltrec.rm_offset, ltrec.rm_flags);
1795 } else if (ltrec.rm_startblock == bno) {
1797 * Overlap left hand side of extent: move the start, trim the
1798 * length and update the current record.
1801 * Orig: |oooooooooooooooooooo|
1802 * Freeing: |fffffffff|
1803 * Result: |rrrrrrrrrr|
1807 /* Delete prev rmap. */
1808 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1809 ltrec.rm_blockcount, ltrec.rm_owner,
1810 ltrec.rm_offset, ltrec.rm_flags);
1814 /* Add an rmap at the new offset. */
1815 ltrec.rm_startblock += len;
1816 ltrec.rm_blockcount -= len;
1817 ltrec.rm_offset += len;
1818 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
1819 ltrec.rm_blockcount, ltrec.rm_owner,
1820 ltrec.rm_offset, ltrec.rm_flags);
1823 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
1825 * Overlap right hand side of extent: trim the length and
1826 * update the current record.
1829 * Orig: |oooooooooooooooooooo|
1830 * Freeing: |fffffffff|
1831 * Result: |rrrrrrrrrr|
1834 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1835 ltrec.rm_blockcount, ltrec.rm_owner,
1836 ltrec.rm_offset, ltrec.rm_flags, &i);
1839 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1840 ltrec.rm_blockcount -= len;
1841 error = xfs_rmap_update(cur, <rec);
1846 * Overlap middle of extent: trim the length of the existing
1847 * record to the length of the new left-extent size, increment
1848 * the insertion position so we can insert a new record
1849 * containing the remaining right-extent space.
1852 * Orig: |oooooooooooooooooooo|
1853 * Freeing: |fffffffff|
1854 * Result: |rrrrr| |rrrr|
1857 xfs_extlen_t orig_len = ltrec.rm_blockcount;
1859 /* Shrink the left side of the rmap */
1860 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1861 ltrec.rm_blockcount, ltrec.rm_owner,
1862 ltrec.rm_offset, ltrec.rm_flags, &i);
1865 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1866 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
1867 error = xfs_rmap_update(cur, <rec);
1871 /* Add an rmap at the new offset */
1872 error = xfs_rmap_insert(cur, bno + len,
1873 orig_len - len - ltrec.rm_blockcount,
1874 ltrec.rm_owner, offset + len,
1880 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
1884 trace_xfs_rmap_unmap_error(cur->bc_mp,
1885 cur->bc_private.a.agno, error, _RET_IP_);
1890 * Find an extent in the rmap btree and map it. For rmap extent types that
1891 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1892 * that the prev/next records in the btree might belong to another owner.
1893 * Therefore we must use delete+insert to alter any of the key fields.
1895 * For every other situation there can only be one owner for a given extent,
1896 * so we can call the regular _alloc function.
1899 xfs_rmap_map_shared(
1900 struct xfs_btree_cur *cur,
1904 const struct xfs_owner_info *oinfo)
1906 struct xfs_mount *mp = cur->bc_mp;
1907 struct xfs_rmap_irec ltrec;
1908 struct xfs_rmap_irec gtrec;
1915 unsigned int flags = 0;
1917 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1919 flags |= XFS_RMAP_UNWRITTEN;
1920 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
1923 /* Is there a left record that abuts our range? */
1924 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
1929 !xfs_rmap_is_mergeable(<rec, owner, flags))
1932 /* Is there a right record that abuts our range? */
1933 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1938 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
1941 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
1942 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1943 cur->bc_private.a.agno, gtrec.rm_startblock,
1944 gtrec.rm_blockcount, gtrec.rm_owner,
1945 gtrec.rm_offset, gtrec.rm_flags);
1947 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
1952 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
1953 ltrec.rm_offset + ltrec.rm_blockcount == offset) {
1955 * Left edge contiguous, merge into left record.
1959 * adding: |aaaaaaaaa|
1960 * result: |rrrrrrrrrrrrrrrrrrr|
1963 ltrec.rm_blockcount += len;
1965 bno + len == gtrec.rm_startblock &&
1966 offset + len == gtrec.rm_offset) {
1968 * Right edge also contiguous, delete right record
1969 * and merge into left record.
1971 * ltbno ltlen gtbno gtlen
1972 * orig: |ooooooooo| |ooooooooo|
1973 * adding: |aaaaaaaaa|
1974 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1976 ltrec.rm_blockcount += gtrec.rm_blockcount;
1977 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
1978 gtrec.rm_blockcount, gtrec.rm_owner,
1979 gtrec.rm_offset, gtrec.rm_flags);
1984 /* Point the cursor back to the left record and update. */
1985 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1986 ltrec.rm_blockcount, ltrec.rm_owner,
1987 ltrec.rm_offset, ltrec.rm_flags, &i);
1990 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1992 error = xfs_rmap_update(cur, <rec);
1995 } else if (have_gt &&
1996 bno + len == gtrec.rm_startblock &&
1997 offset + len == gtrec.rm_offset) {
1999 * Right edge contiguous, merge into right record.
2003 * adding: |aaaaaaaaa|
2004 * Result: |rrrrrrrrrrrrrrrrrrr|
2007 /* Delete the old record. */
2008 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2009 gtrec.rm_blockcount, gtrec.rm_owner,
2010 gtrec.rm_offset, gtrec.rm_flags);
2014 /* Move the start and re-add it. */
2015 gtrec.rm_startblock = bno;
2016 gtrec.rm_blockcount += len;
2017 gtrec.rm_offset = offset;
2018 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2019 gtrec.rm_blockcount, gtrec.rm_owner,
2020 gtrec.rm_offset, gtrec.rm_flags);
2025 * No contiguous edge with identical owner, insert
2026 * new record at current cursor position.
2028 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2033 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
2037 trace_xfs_rmap_map_error(cur->bc_mp,
2038 cur->bc_private.a.agno, error, _RET_IP_);
2042 /* Insert a raw rmap into the rmapbt. */
2045 struct xfs_btree_cur *cur,
2046 struct xfs_rmap_irec *rmap)
2048 struct xfs_owner_info oinfo;
2050 oinfo.oi_owner = rmap->rm_owner;
2051 oinfo.oi_offset = rmap->rm_offset;
2053 if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
2054 oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
2055 if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
2056 oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
2058 if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2059 return xfs_rmap_map(cur, rmap->rm_startblock,
2060 rmap->rm_blockcount,
2061 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2064 return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2065 rmap->rm_blockcount,
2066 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2070 struct xfs_rmap_query_range_info {
2071 xfs_rmap_query_range_fn fn;
2075 /* Format btree record and pass to our callback. */
2077 xfs_rmap_query_range_helper(
2078 struct xfs_btree_cur *cur,
2079 union xfs_btree_rec *rec,
2082 struct xfs_rmap_query_range_info *query = priv;
2083 struct xfs_rmap_irec irec;
2086 error = xfs_rmap_btrec_to_irec(rec, &irec);
2089 return query->fn(cur, &irec, query->priv);
2092 /* Find all rmaps between two keys. */
2094 xfs_rmap_query_range(
2095 struct xfs_btree_cur *cur,
2096 struct xfs_rmap_irec *low_rec,
2097 struct xfs_rmap_irec *high_rec,
2098 xfs_rmap_query_range_fn fn,
2101 union xfs_btree_irec low_brec;
2102 union xfs_btree_irec high_brec;
2103 struct xfs_rmap_query_range_info query;
2105 low_brec.r = *low_rec;
2106 high_brec.r = *high_rec;
2109 return xfs_btree_query_range(cur, &low_brec, &high_brec,
2110 xfs_rmap_query_range_helper, &query);
2113 /* Find all rmaps. */
2116 struct xfs_btree_cur *cur,
2117 xfs_rmap_query_range_fn fn,
2120 struct xfs_rmap_query_range_info query;
2124 return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2127 /* Clean up after calling xfs_rmap_finish_one. */
2129 xfs_rmap_finish_one_cleanup(
2130 struct xfs_trans *tp,
2131 struct xfs_btree_cur *rcur,
2134 struct xfs_buf *agbp;
2138 agbp = rcur->bc_private.a.agbp;
2139 xfs_btree_del_cursor(rcur, error);
2141 xfs_trans_brelse(tp, agbp);
2145 * Process one of the deferred rmap operations. We pass back the
2146 * btree cursor to maintain our lock on the rmapbt between calls.
2147 * This saves time and eliminates a buffer deadlock between the
2148 * superblock and the AGF because we'll always grab them in the same
2152 xfs_rmap_finish_one(
2153 struct xfs_trans *tp,
2154 enum xfs_rmap_intent_type type,
2157 xfs_fileoff_t startoff,
2158 xfs_fsblock_t startblock,
2159 xfs_filblks_t blockcount,
2161 struct xfs_btree_cur **pcur)
2163 struct xfs_mount *mp = tp->t_mountp;
2164 struct xfs_btree_cur *rcur;
2165 struct xfs_buf *agbp = NULL;
2167 xfs_agnumber_t agno;
2168 struct xfs_owner_info oinfo;
2172 agno = XFS_FSB_TO_AGNO(mp, startblock);
2173 ASSERT(agno != NULLAGNUMBER);
2174 bno = XFS_FSB_TO_AGBNO(mp, startblock);
2176 trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork,
2177 startoff, blockcount, state);
2179 if (XFS_TEST_ERROR(false, mp,
2180 XFS_ERRTAG_RMAP_FINISH_ONE))
2184 * If we haven't gotten a cursor or the cursor AG doesn't match
2185 * the startblock, get one now.
2188 if (rcur != NULL && rcur->bc_private.a.agno != agno) {
2189 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2195 * Refresh the freelist before we start changing the
2196 * rmapbt, because a shape change could cause us to
2199 error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
2203 return -EFSCORRUPTED;
2205 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
2213 xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2214 unwritten = state == XFS_EXT_UNWRITTEN;
2215 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2218 case XFS_RMAP_ALLOC:
2220 error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2222 case XFS_RMAP_MAP_SHARED:
2223 error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2227 case XFS_RMAP_UNMAP:
2228 error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2231 case XFS_RMAP_UNMAP_SHARED:
2232 error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2235 case XFS_RMAP_CONVERT:
2236 error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2239 case XFS_RMAP_CONVERT_SHARED:
2240 error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2241 !unwritten, &oinfo);
2245 error = -EFSCORRUPTED;
2250 xfs_trans_brelse(tp, agbp);
2256 * Don't defer an rmap if we aren't an rmap filesystem.
2259 xfs_rmap_update_is_needed(
2260 struct xfs_mount *mp,
2263 return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK;
2267 * Record a rmap intent; the list is kept sorted first by AG and then by
2272 struct xfs_trans *tp,
2273 enum xfs_rmap_intent_type type,
2276 struct xfs_bmbt_irec *bmap)
2278 struct xfs_rmap_intent *ri;
2280 trace_xfs_rmap_defer(tp->t_mountp,
2281 XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock),
2283 XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock),
2286 bmap->br_blockcount,
2289 ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_NOFS);
2290 INIT_LIST_HEAD(&ri->ri_list);
2292 ri->ri_owner = owner;
2293 ri->ri_whichfork = whichfork;
2294 ri->ri_bmap = *bmap;
2296 xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
2299 /* Map an extent into a file. */
2301 xfs_rmap_map_extent(
2302 struct xfs_trans *tp,
2303 struct xfs_inode *ip,
2305 struct xfs_bmbt_irec *PREV)
2307 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2310 __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
2311 XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino,
2315 /* Unmap an extent out of a file. */
2317 xfs_rmap_unmap_extent(
2318 struct xfs_trans *tp,
2319 struct xfs_inode *ip,
2321 struct xfs_bmbt_irec *PREV)
2323 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2326 __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
2327 XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino,
2332 * Convert a data fork extent from unwritten to real or vice versa.
2334 * Note that tp can be NULL here as no transaction is used for COW fork
2335 * unwritten conversion.
2338 xfs_rmap_convert_extent(
2339 struct xfs_mount *mp,
2340 struct xfs_trans *tp,
2341 struct xfs_inode *ip,
2343 struct xfs_bmbt_irec *PREV)
2345 if (!xfs_rmap_update_is_needed(mp, whichfork))
2348 __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
2349 XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino,
2353 /* Schedule the creation of an rmap for non-file data. */
2355 xfs_rmap_alloc_extent(
2356 struct xfs_trans *tp,
2357 xfs_agnumber_t agno,
2362 struct xfs_bmbt_irec bmap;
2364 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2367 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2368 bmap.br_blockcount = len;
2369 bmap.br_startoff = 0;
2370 bmap.br_state = XFS_EXT_NORM;
2372 __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
2375 /* Schedule the deletion of an rmap for non-file data. */
2377 xfs_rmap_free_extent(
2378 struct xfs_trans *tp,
2379 xfs_agnumber_t agno,
2384 struct xfs_bmbt_irec bmap;
2386 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2389 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2390 bmap.br_blockcount = len;
2391 bmap.br_startoff = 0;
2392 bmap.br_state = XFS_EXT_NORM;
2394 __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
2397 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2400 const struct xfs_rmap_irec *a,
2401 const struct xfs_rmap_irec *b)
2406 oa = xfs_rmap_irec_offset_pack(a);
2407 ob = xfs_rmap_irec_offset_pack(b);
2409 if (a->rm_startblock < b->rm_startblock)
2411 else if (a->rm_startblock > b->rm_startblock)
2413 else if (a->rm_owner < b->rm_owner)
2415 else if (a->rm_owner > b->rm_owner)
2425 /* Is there a record covering a given extent? */
2427 xfs_rmap_has_record(
2428 struct xfs_btree_cur *cur,
2433 union xfs_btree_irec low;
2434 union xfs_btree_irec high;
2436 memset(&low, 0, sizeof(low));
2437 low.r.rm_startblock = bno;
2438 memset(&high, 0xFF, sizeof(high));
2439 high.r.rm_startblock = bno + len - 1;
2441 return xfs_btree_has_record(cur, &low, &high, exists);
2445 * Is there a record for this owner completely covering a given physical
2446 * extent? If so, *has_rmap will be set to true. If there is no record
2447 * or the record only covers part of the range, we set *has_rmap to false.
2448 * This function doesn't perform range lookups or offset checks, so it is
2449 * not suitable for checking data fork blocks.
2452 xfs_rmap_record_exists(
2453 struct xfs_btree_cur *cur,
2456 const struct xfs_owner_info *oinfo,
2463 struct xfs_rmap_irec irec;
2466 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2467 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
2468 (flags & XFS_RMAP_BMBT_BLOCK));
2470 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
2479 error = xfs_rmap_get_rec(cur, &irec, &has_record);
2487 *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
2488 irec.rm_startblock + irec.rm_blockcount >= bno + len);
2492 struct xfs_rmap_key_state {
2499 /* For each rmap given, figure out if it doesn't match the key we want. */
2501 xfs_rmap_has_other_keys_helper(
2502 struct xfs_btree_cur *cur,
2503 struct xfs_rmap_irec *rec,
2506 struct xfs_rmap_key_state *rks = priv;
2508 if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset &&
2509 ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags)
2511 rks->has_rmap = true;
2512 return XFS_BTREE_QUERY_RANGE_ABORT;
2516 * Given an extent and some owner info, can we find records overlapping
2517 * the extent whose owner info does not match the given owner?
2520 xfs_rmap_has_other_keys(
2521 struct xfs_btree_cur *cur,
2524 const struct xfs_owner_info *oinfo,
2527 struct xfs_rmap_irec low = {0};
2528 struct xfs_rmap_irec high;
2529 struct xfs_rmap_key_state rks;
2532 xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags);
2533 rks.has_rmap = false;
2535 low.rm_startblock = bno;
2536 memset(&high, 0xFF, sizeof(high));
2537 high.rm_startblock = bno + len - 1;
2539 error = xfs_rmap_query_range(cur, &low, &high,
2540 xfs_rmap_has_other_keys_helper, &rks);
2544 *has_rmap = rks.has_rmap;
2548 const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
2549 .oi_owner = XFS_RMAP_OWN_NULL,
2551 const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
2552 .oi_owner = XFS_RMAP_OWN_UNKNOWN,
2554 const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
2555 .oi_owner = XFS_RMAP_OWN_FS,
2557 const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
2558 .oi_owner = XFS_RMAP_OWN_LOG,
2560 const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
2561 .oi_owner = XFS_RMAP_OWN_AG,
2563 const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
2564 .oi_owner = XFS_RMAP_OWN_INOBT,
2566 const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
2567 .oi_owner = XFS_RMAP_OWN_INODES,
2569 const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
2570 .oi_owner = XFS_RMAP_OWN_REFC,
2572 const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
2573 .oi_owner = XFS_RMAP_OWN_COW,