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)
172 irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
173 irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
174 irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
175 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
180 * Get the data from the pointed-to record.
184 struct xfs_btree_cur *cur,
185 struct xfs_rmap_irec *irec,
188 struct xfs_mount *mp = cur->bc_mp;
189 xfs_agnumber_t agno = cur->bc_private.a.agno;
190 union xfs_btree_rec *rec;
193 error = xfs_btree_get_rec(cur, &rec, stat);
197 if (xfs_rmap_btrec_to_irec(rec, irec))
200 if (irec->rm_blockcount == 0)
202 if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
203 if (irec->rm_owner != XFS_RMAP_OWN_FS)
205 if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
208 /* check for valid extent range, including overflow */
209 if (!xfs_verify_agbno(mp, agno, irec->rm_startblock))
211 if (irec->rm_startblock >
212 irec->rm_startblock + irec->rm_blockcount)
214 if (!xfs_verify_agbno(mp, agno,
215 irec->rm_startblock + irec->rm_blockcount - 1))
219 if (!(xfs_verify_ino(mp, irec->rm_owner) ||
220 (irec->rm_owner <= XFS_RMAP_OWN_FS &&
221 irec->rm_owner >= XFS_RMAP_OWN_MIN)))
227 "Reverse Mapping BTree record corruption in AG %d detected!",
230 "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
231 irec->rm_owner, irec->rm_flags, irec->rm_startblock,
232 irec->rm_blockcount);
233 return -EFSCORRUPTED;
236 struct xfs_find_left_neighbor_info {
237 struct xfs_rmap_irec high;
238 struct xfs_rmap_irec *irec;
242 /* For each rmap given, figure out if it matches the key we want. */
244 xfs_rmap_find_left_neighbor_helper(
245 struct xfs_btree_cur *cur,
246 struct xfs_rmap_irec *rec,
249 struct xfs_find_left_neighbor_info *info = priv;
251 trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
252 cur->bc_private.a.agno, rec->rm_startblock,
253 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
256 if (rec->rm_owner != info->high.rm_owner)
257 return XFS_BTREE_QUERY_RANGE_CONTINUE;
258 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
259 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
260 rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
261 return XFS_BTREE_QUERY_RANGE_CONTINUE;
265 return XFS_BTREE_QUERY_RANGE_ABORT;
269 * Find the record to the left of the given extent, being careful only to
270 * return a match with the same owner and adjacent physical and logical
274 xfs_rmap_find_left_neighbor(
275 struct xfs_btree_cur *cur,
280 struct xfs_rmap_irec *irec,
283 struct xfs_find_left_neighbor_info info;
289 info.high.rm_startblock = bno - 1;
290 info.high.rm_owner = owner;
291 if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
292 !(flags & XFS_RMAP_BMBT_BLOCK)) {
295 info.high.rm_offset = offset - 1;
297 info.high.rm_offset = 0;
298 info.high.rm_flags = flags;
299 info.high.rm_blockcount = 0;
303 trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
304 cur->bc_private.a.agno, bno, 0, owner, offset, flags);
306 error = xfs_rmap_query_range(cur, &info.high, &info.high,
307 xfs_rmap_find_left_neighbor_helper, &info);
308 if (error == XFS_BTREE_QUERY_RANGE_ABORT)
311 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
312 cur->bc_private.a.agno, irec->rm_startblock,
313 irec->rm_blockcount, irec->rm_owner,
314 irec->rm_offset, irec->rm_flags);
318 /* For each rmap given, figure out if it matches the key we want. */
320 xfs_rmap_lookup_le_range_helper(
321 struct xfs_btree_cur *cur,
322 struct xfs_rmap_irec *rec,
325 struct xfs_find_left_neighbor_info *info = priv;
327 trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
328 cur->bc_private.a.agno, rec->rm_startblock,
329 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
332 if (rec->rm_owner != info->high.rm_owner)
333 return XFS_BTREE_QUERY_RANGE_CONTINUE;
334 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
335 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
336 (rec->rm_offset > info->high.rm_offset ||
337 rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
338 return XFS_BTREE_QUERY_RANGE_CONTINUE;
342 return XFS_BTREE_QUERY_RANGE_ABORT;
346 * Find the record to the left of the given extent, being careful only to
347 * return a match with the same owner and overlapping physical and logical
348 * block ranges. This is the overlapping-interval version of
349 * xfs_rmap_lookup_le.
352 xfs_rmap_lookup_le_range(
353 struct xfs_btree_cur *cur,
358 struct xfs_rmap_irec *irec,
361 struct xfs_find_left_neighbor_info info;
364 info.high.rm_startblock = bno;
365 info.high.rm_owner = owner;
366 if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
367 info.high.rm_offset = offset;
369 info.high.rm_offset = 0;
370 info.high.rm_flags = flags;
371 info.high.rm_blockcount = 0;
376 trace_xfs_rmap_lookup_le_range(cur->bc_mp,
377 cur->bc_private.a.agno, bno, 0, owner, offset, flags);
378 error = xfs_rmap_query_range(cur, &info.high, &info.high,
379 xfs_rmap_lookup_le_range_helper, &info);
380 if (error == XFS_BTREE_QUERY_RANGE_ABORT)
383 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
384 cur->bc_private.a.agno, irec->rm_startblock,
385 irec->rm_blockcount, irec->rm_owner,
386 irec->rm_offset, irec->rm_flags);
391 * Perform all the relevant owner checks for a removal op. If we're doing an
392 * unknown-owner removal then we have no owner information to check.
395 xfs_rmap_free_check_owner(
396 struct xfs_mount *mp,
398 struct xfs_rmap_irec *rec,
406 if (owner == XFS_RMAP_OWN_UNKNOWN)
409 /* Make sure the unwritten flag matches. */
410 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
411 (rec->rm_flags & XFS_RMAP_UNWRITTEN), out);
413 /* Make sure the owner matches what we expect to find in the tree. */
414 XFS_WANT_CORRUPTED_GOTO(mp, owner == rec->rm_owner, out);
416 /* Check the offset, if necessary. */
417 if (XFS_RMAP_NON_INODE_OWNER(owner))
420 if (flags & XFS_RMAP_BMBT_BLOCK) {
421 XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_flags & XFS_RMAP_BMBT_BLOCK,
424 XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_offset <= offset, out);
425 XFS_WANT_CORRUPTED_GOTO(mp,
426 ltoff + rec->rm_blockcount >= offset + len,
435 * Find the extent in the rmap btree and remove it.
437 * The record we find should always be an exact match for the extent that we're
438 * looking for, since we insert them into the btree without modification.
440 * Special Case #1: when growing the filesystem, we "free" an extent when
441 * growing the last AG. This extent is new space and so it is not tracked as
442 * used space in the btree. The growfs code will pass in an owner of
443 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
444 * extent. We verify that - the extent lookup result in a record that does not
447 * Special Case #2: EFIs do not record the owner of the extent, so when
448 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
449 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
450 * corruption checks during log recovery.
454 struct xfs_btree_cur *cur,
458 const struct xfs_owner_info *oinfo)
460 struct xfs_mount *mp = cur->bc_mp;
461 struct xfs_rmap_irec ltrec;
470 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
471 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
472 (flags & XFS_RMAP_BMBT_BLOCK);
474 flags |= XFS_RMAP_UNWRITTEN;
475 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
479 * We should always have a left record because there's a static record
480 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
481 * will not ever be removed from the tree.
483 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i);
486 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
488 error = xfs_rmap_get_rec(cur, <rec, &i);
491 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
492 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
493 cur->bc_private.a.agno, ltrec.rm_startblock,
494 ltrec.rm_blockcount, ltrec.rm_owner,
495 ltrec.rm_offset, ltrec.rm_flags);
496 ltoff = ltrec.rm_offset;
499 * For growfs, the incoming extent must be beyond the left record we
500 * just found as it is new space and won't be used by anyone. This is
501 * just a corruption check as we don't actually do anything with this
502 * extent. Note that we need to use >= instead of > because it might
503 * be the case that the "left" extent goes all the way to EOFS.
505 if (owner == XFS_RMAP_OWN_NULL) {
506 XFS_WANT_CORRUPTED_GOTO(mp, bno >= ltrec.rm_startblock +
507 ltrec.rm_blockcount, out_error);
512 * If we're doing an unknown-owner removal for EFI recovery, we expect
513 * to find the full range in the rmapbt or nothing at all. If we
514 * don't find any rmaps overlapping either end of the range, we're
515 * done. Hopefully this means that the EFI creator already queued
516 * (and finished) a RUI to remove the rmap.
518 if (owner == XFS_RMAP_OWN_UNKNOWN &&
519 ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
520 struct xfs_rmap_irec rtrec;
522 error = xfs_btree_increment(cur, 0, &i);
527 error = xfs_rmap_get_rec(cur, &rtrec, &i);
530 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
531 if (rtrec.rm_startblock >= bno + len)
535 /* Make sure the extent we found covers the entire freeing range. */
536 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
537 ltrec.rm_startblock + ltrec.rm_blockcount >=
538 bno + len, out_error);
540 /* Check owner information. */
541 error = xfs_rmap_free_check_owner(mp, ltoff, <rec, len, owner,
546 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
547 /* exact match, simply remove the record from rmap tree */
548 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
549 ltrec.rm_startblock, ltrec.rm_blockcount,
550 ltrec.rm_owner, ltrec.rm_offset,
552 error = xfs_btree_delete(cur, &i);
555 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
556 } else if (ltrec.rm_startblock == bno) {
558 * overlap left hand side of extent: move the start, trim the
559 * length and update the current record.
562 * Orig: |oooooooooooooooooooo|
563 * Freeing: |fffffffff|
564 * Result: |rrrrrrrrrr|
567 ltrec.rm_startblock += len;
568 ltrec.rm_blockcount -= len;
570 ltrec.rm_offset += len;
571 error = xfs_rmap_update(cur, <rec);
574 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
576 * overlap right hand side of extent: trim the length and update
577 * the current record.
580 * Orig: |oooooooooooooooooooo|
581 * Freeing: |fffffffff|
582 * Result: |rrrrrrrrrr|
585 ltrec.rm_blockcount -= len;
586 error = xfs_rmap_update(cur, <rec);
592 * overlap middle of extent: trim the length of the existing
593 * record to the length of the new left-extent size, increment
594 * the insertion position so we can insert a new record
595 * containing the remaining right-extent space.
598 * Orig: |oooooooooooooooooooo|
599 * Freeing: |fffffffff|
600 * Result: |rrrrr| |rrrr|
603 xfs_extlen_t orig_len = ltrec.rm_blockcount;
605 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
606 error = xfs_rmap_update(cur, <rec);
610 error = xfs_btree_increment(cur, 0, &i);
614 cur->bc_rec.r.rm_startblock = bno + len;
615 cur->bc_rec.r.rm_blockcount = orig_len - len -
617 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
619 cur->bc_rec.r.rm_offset = 0;
621 cur->bc_rec.r.rm_offset = offset + len;
622 cur->bc_rec.r.rm_flags = flags;
623 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
624 cur->bc_rec.r.rm_startblock,
625 cur->bc_rec.r.rm_blockcount,
626 cur->bc_rec.r.rm_owner,
627 cur->bc_rec.r.rm_offset,
628 cur->bc_rec.r.rm_flags);
629 error = xfs_btree_insert(cur, &i);
635 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
639 trace_xfs_rmap_unmap_error(mp, cur->bc_private.a.agno,
645 * Remove a reference to an extent in the rmap btree.
649 struct xfs_trans *tp,
650 struct xfs_buf *agbp,
654 const struct xfs_owner_info *oinfo)
656 struct xfs_mount *mp = tp->t_mountp;
657 struct xfs_btree_cur *cur;
660 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
663 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
665 error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
667 xfs_btree_del_cursor(cur, error);
672 * A mergeable rmap must have the same owner and the same values for
673 * the unwritten, attr_fork, and bmbt flags. The startblock and
674 * offset are checked separately.
677 xfs_rmap_is_mergeable(
678 struct xfs_rmap_irec *irec,
682 if (irec->rm_owner == XFS_RMAP_OWN_NULL)
684 if (irec->rm_owner != owner)
686 if ((flags & XFS_RMAP_UNWRITTEN) ^
687 (irec->rm_flags & XFS_RMAP_UNWRITTEN))
689 if ((flags & XFS_RMAP_ATTR_FORK) ^
690 (irec->rm_flags & XFS_RMAP_ATTR_FORK))
692 if ((flags & XFS_RMAP_BMBT_BLOCK) ^
693 (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
699 * When we allocate a new block, the first thing we do is add a reference to
700 * the extent in the rmap btree. This takes the form of a [agbno, length,
701 * owner, offset] record. Flags are encoded in the high bits of the offset
706 struct xfs_btree_cur *cur,
710 const struct xfs_owner_info *oinfo)
712 struct xfs_mount *mp = cur->bc_mp;
713 struct xfs_rmap_irec ltrec;
714 struct xfs_rmap_irec gtrec;
721 unsigned int flags = 0;
724 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
726 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
727 (flags & XFS_RMAP_BMBT_BLOCK);
729 flags |= XFS_RMAP_UNWRITTEN;
730 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
732 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
735 * For the initial lookup, look for an exact match or the left-adjacent
736 * record for our insertion point. This will also give us the record for
737 * start block contiguity tests.
739 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
744 error = xfs_rmap_get_rec(cur, <rec, &have_lt);
747 XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
748 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
749 cur->bc_private.a.agno, ltrec.rm_startblock,
750 ltrec.rm_blockcount, ltrec.rm_owner,
751 ltrec.rm_offset, ltrec.rm_flags);
753 if (!xfs_rmap_is_mergeable(<rec, owner, flags))
757 XFS_WANT_CORRUPTED_GOTO(mp,
759 ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error);
762 * Increment the cursor to see if we have a right-adjacent record to our
763 * insertion point. This will give us the record for end block
766 error = xfs_btree_increment(cur, 0, &have_gt);
770 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
773 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
774 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock,
776 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
777 cur->bc_private.a.agno, gtrec.rm_startblock,
778 gtrec.rm_blockcount, gtrec.rm_owner,
779 gtrec.rm_offset, gtrec.rm_flags);
780 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
785 * Note: cursor currently points one record to the right of ltrec, even
786 * if there is no record in the tree to the right.
789 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
790 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
792 * left edge contiguous, merge into left record.
796 * adding: |aaaaaaaaa|
797 * result: |rrrrrrrrrrrrrrrrrrr|
800 ltrec.rm_blockcount += len;
802 bno + len == gtrec.rm_startblock &&
803 (ignore_off || offset + len == gtrec.rm_offset) &&
804 (unsigned long)ltrec.rm_blockcount + len +
805 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
807 * right edge also contiguous, delete right record
808 * and merge into left record.
810 * ltbno ltlen gtbno gtlen
811 * orig: |ooooooooo| |ooooooooo|
812 * adding: |aaaaaaaaa|
813 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
815 ltrec.rm_blockcount += gtrec.rm_blockcount;
816 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
822 error = xfs_btree_delete(cur, &i);
825 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
828 /* point the cursor back to the left record and update */
829 error = xfs_btree_decrement(cur, 0, &have_gt);
832 error = xfs_rmap_update(cur, <rec);
835 } else if (have_gt &&
836 bno + len == gtrec.rm_startblock &&
837 (ignore_off || offset + len == gtrec.rm_offset)) {
839 * right edge contiguous, merge into right record.
843 * adding: |aaaaaaaaa|
844 * Result: |rrrrrrrrrrrrrrrrrrr|
847 gtrec.rm_startblock = bno;
848 gtrec.rm_blockcount += len;
850 gtrec.rm_offset = offset;
851 error = xfs_rmap_update(cur, >rec);
856 * no contiguous edge with identical owner, insert
857 * new record at current cursor position.
859 cur->bc_rec.r.rm_startblock = bno;
860 cur->bc_rec.r.rm_blockcount = len;
861 cur->bc_rec.r.rm_owner = owner;
862 cur->bc_rec.r.rm_offset = offset;
863 cur->bc_rec.r.rm_flags = flags;
864 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
865 owner, offset, flags);
866 error = xfs_btree_insert(cur, &i);
869 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
872 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
876 trace_xfs_rmap_map_error(mp, cur->bc_private.a.agno,
882 * Add a reference to an extent in the rmap btree.
886 struct xfs_trans *tp,
887 struct xfs_buf *agbp,
891 const struct xfs_owner_info *oinfo)
893 struct xfs_mount *mp = tp->t_mountp;
894 struct xfs_btree_cur *cur;
897 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
900 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
901 error = xfs_rmap_map(cur, bno, len, false, oinfo);
903 xfs_btree_del_cursor(cur, error);
907 #define RMAP_LEFT_CONTIG (1 << 0)
908 #define RMAP_RIGHT_CONTIG (1 << 1)
909 #define RMAP_LEFT_FILLING (1 << 2)
910 #define RMAP_RIGHT_FILLING (1 << 3)
911 #define RMAP_LEFT_VALID (1 << 6)
912 #define RMAP_RIGHT_VALID (1 << 7)
920 * Convert an unwritten extent to a real extent or vice versa.
921 * Does not handle overlapping extents.
925 struct xfs_btree_cur *cur,
929 const struct xfs_owner_info *oinfo)
931 struct xfs_mount *mp = cur->bc_mp;
932 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
933 /* left is 0, right is 1, */
934 /* prev is 2, new is 3 */
940 unsigned int flags = 0;
945 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
946 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
947 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
948 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
949 new_endoff = offset + len;
950 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
954 * For the initial lookup, look for an exact match or the left-adjacent
955 * record for our insertion point. This will also give us the record for
956 * start block contiguity tests.
958 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
961 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
963 error = xfs_rmap_get_rec(cur, &PREV, &i);
966 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
967 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
968 cur->bc_private.a.agno, PREV.rm_startblock,
969 PREV.rm_blockcount, PREV.rm_owner,
970 PREV.rm_offset, PREV.rm_flags);
972 ASSERT(PREV.rm_offset <= offset);
973 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
974 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
975 newext = ~oldext & XFS_RMAP_UNWRITTEN;
978 * Set flags determining what part of the previous oldext allocation
979 * extent is being replaced by a newext allocation.
981 if (PREV.rm_offset == offset)
982 state |= RMAP_LEFT_FILLING;
983 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
984 state |= RMAP_RIGHT_FILLING;
987 * Decrement the cursor to see if we have a left-adjacent record to our
988 * insertion point. This will give us the record for end block
991 error = xfs_btree_decrement(cur, 0, &i);
995 state |= RMAP_LEFT_VALID;
996 error = xfs_rmap_get_rec(cur, &LEFT, &i);
999 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1000 XFS_WANT_CORRUPTED_GOTO(mp,
1001 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
1003 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
1004 cur->bc_private.a.agno, LEFT.rm_startblock,
1005 LEFT.rm_blockcount, LEFT.rm_owner,
1006 LEFT.rm_offset, LEFT.rm_flags);
1007 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1008 LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1009 xfs_rmap_is_mergeable(&LEFT, owner, newext))
1010 state |= RMAP_LEFT_CONTIG;
1014 * Increment the cursor to see if we have a right-adjacent record to our
1015 * insertion point. This will give us the record for end block
1018 error = xfs_btree_increment(cur, 0, &i);
1021 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1022 error = xfs_btree_increment(cur, 0, &i);
1026 state |= RMAP_RIGHT_VALID;
1027 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1030 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1031 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1033 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1034 cur->bc_private.a.agno, RIGHT.rm_startblock,
1035 RIGHT.rm_blockcount, RIGHT.rm_owner,
1036 RIGHT.rm_offset, RIGHT.rm_flags);
1037 if (bno + len == RIGHT.rm_startblock &&
1038 offset + len == RIGHT.rm_offset &&
1039 xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1040 state |= RMAP_RIGHT_CONTIG;
1043 /* check that left + prev + right is not too long */
1044 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1045 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1046 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1047 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1048 (unsigned long)LEFT.rm_blockcount + len +
1049 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1050 state &= ~RMAP_RIGHT_CONTIG;
1052 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1055 /* reset the cursor back to PREV */
1056 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1059 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1062 * Switch out based on the FILLING and CONTIG state bits.
1064 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1065 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1066 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1067 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1069 * Setting all of a previous oldext extent to newext.
1070 * The left and right neighbors are both contiguous with new.
1072 error = xfs_btree_increment(cur, 0, &i);
1075 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1076 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1077 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1078 RIGHT.rm_owner, RIGHT.rm_offset,
1080 error = xfs_btree_delete(cur, &i);
1083 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1084 error = xfs_btree_decrement(cur, 0, &i);
1087 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1088 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1089 PREV.rm_startblock, PREV.rm_blockcount,
1090 PREV.rm_owner, PREV.rm_offset,
1092 error = xfs_btree_delete(cur, &i);
1095 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1096 error = xfs_btree_decrement(cur, 0, &i);
1099 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1101 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1102 error = xfs_rmap_update(cur, &NEW);
1107 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1109 * Setting all of a previous oldext extent to newext.
1110 * The left neighbor is contiguous, the right is not.
1112 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1113 PREV.rm_startblock, PREV.rm_blockcount,
1114 PREV.rm_owner, PREV.rm_offset,
1116 error = xfs_btree_delete(cur, &i);
1119 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1120 error = xfs_btree_decrement(cur, 0, &i);
1123 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1125 NEW.rm_blockcount += PREV.rm_blockcount;
1126 error = xfs_rmap_update(cur, &NEW);
1131 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1133 * Setting all of a previous oldext extent to newext.
1134 * The right neighbor is contiguous, the left is not.
1136 error = xfs_btree_increment(cur, 0, &i);
1139 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1140 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1141 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1142 RIGHT.rm_owner, RIGHT.rm_offset,
1144 error = xfs_btree_delete(cur, &i);
1147 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1148 error = xfs_btree_decrement(cur, 0, &i);
1151 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1153 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1154 NEW.rm_flags = newext;
1155 error = xfs_rmap_update(cur, &NEW);
1160 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1162 * Setting all of a previous oldext extent to newext.
1163 * Neither the left nor right neighbors are contiguous with
1167 NEW.rm_flags = newext;
1168 error = xfs_rmap_update(cur, &NEW);
1173 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1175 * Setting the first part of a previous oldext extent to newext.
1176 * The left neighbor is contiguous.
1179 NEW.rm_offset += len;
1180 NEW.rm_startblock += len;
1181 NEW.rm_blockcount -= len;
1182 error = xfs_rmap_update(cur, &NEW);
1185 error = xfs_btree_decrement(cur, 0, &i);
1189 NEW.rm_blockcount += len;
1190 error = xfs_rmap_update(cur, &NEW);
1195 case RMAP_LEFT_FILLING:
1197 * Setting the first part of a previous oldext extent to newext.
1198 * The left neighbor is not contiguous.
1201 NEW.rm_startblock += len;
1202 NEW.rm_offset += len;
1203 NEW.rm_blockcount -= len;
1204 error = xfs_rmap_update(cur, &NEW);
1207 NEW.rm_startblock = bno;
1208 NEW.rm_owner = owner;
1209 NEW.rm_offset = offset;
1210 NEW.rm_blockcount = len;
1211 NEW.rm_flags = newext;
1212 cur->bc_rec.r = NEW;
1213 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1214 len, owner, offset, newext);
1215 error = xfs_btree_insert(cur, &i);
1218 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1221 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1223 * Setting the last part of a previous oldext extent to newext.
1224 * The right neighbor is contiguous with the new allocation.
1227 NEW.rm_blockcount -= len;
1228 error = xfs_rmap_update(cur, &NEW);
1231 error = xfs_btree_increment(cur, 0, &i);
1235 NEW.rm_offset = offset;
1236 NEW.rm_startblock = bno;
1237 NEW.rm_blockcount += len;
1238 error = xfs_rmap_update(cur, &NEW);
1243 case RMAP_RIGHT_FILLING:
1245 * Setting the last part of a previous oldext extent to newext.
1246 * The right neighbor is not contiguous.
1249 NEW.rm_blockcount -= len;
1250 error = xfs_rmap_update(cur, &NEW);
1253 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1257 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1258 NEW.rm_startblock = bno;
1259 NEW.rm_owner = owner;
1260 NEW.rm_offset = offset;
1261 NEW.rm_blockcount = len;
1262 NEW.rm_flags = newext;
1263 cur->bc_rec.r = NEW;
1264 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1265 len, owner, offset, newext);
1266 error = xfs_btree_insert(cur, &i);
1269 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1274 * Setting the middle part of a previous oldext extent to
1275 * newext. Contiguity is impossible here.
1276 * One extent becomes three extents.
1278 /* new right extent - oldext */
1279 NEW.rm_startblock = bno + len;
1280 NEW.rm_owner = owner;
1281 NEW.rm_offset = new_endoff;
1282 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1284 NEW.rm_flags = PREV.rm_flags;
1285 error = xfs_rmap_update(cur, &NEW);
1288 /* new left extent - oldext */
1290 NEW.rm_blockcount = offset - PREV.rm_offset;
1291 cur->bc_rec.r = NEW;
1292 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
1293 NEW.rm_startblock, NEW.rm_blockcount,
1294 NEW.rm_owner, NEW.rm_offset,
1296 error = xfs_btree_insert(cur, &i);
1299 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1301 * Reset the cursor to the position of the new extent
1302 * we are about to insert as we can't trust it after
1303 * the previous insert.
1305 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1309 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1310 /* new middle extent - newext */
1311 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1312 cur->bc_rec.r.rm_flags |= newext;
1313 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
1314 owner, offset, newext);
1315 error = xfs_btree_insert(cur, &i);
1318 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1321 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1322 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1323 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1324 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1325 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1326 case RMAP_LEFT_CONTIG:
1327 case RMAP_RIGHT_CONTIG:
1329 * These cases are all impossible.
1334 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1338 trace_xfs_rmap_convert_error(cur->bc_mp,
1339 cur->bc_private.a.agno, error, _RET_IP_);
1344 * Convert an unwritten extent to a real extent or vice versa. If there is no
1345 * possibility of overlapping extents, delegate to the simpler convert
1349 xfs_rmap_convert_shared(
1350 struct xfs_btree_cur *cur,
1354 const struct xfs_owner_info *oinfo)
1356 struct xfs_mount *mp = cur->bc_mp;
1357 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1358 /* left is 0, right is 1, */
1359 /* prev is 2, new is 3 */
1362 uint64_t new_endoff;
1363 unsigned int oldext;
1364 unsigned int newext;
1365 unsigned int flags = 0;
1370 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1371 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1372 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1373 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1374 new_endoff = offset + len;
1375 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
1379 * For the initial lookup, look for and exact match or the left-adjacent
1380 * record for our insertion point. This will also give us the record for
1381 * start block contiguity tests.
1383 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1387 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1389 ASSERT(PREV.rm_offset <= offset);
1390 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1391 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1392 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1395 * Set flags determining what part of the previous oldext allocation
1396 * extent is being replaced by a newext allocation.
1398 if (PREV.rm_offset == offset)
1399 state |= RMAP_LEFT_FILLING;
1400 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1401 state |= RMAP_RIGHT_FILLING;
1403 /* Is there a left record that abuts our range? */
1404 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1409 state |= RMAP_LEFT_VALID;
1410 XFS_WANT_CORRUPTED_GOTO(mp,
1411 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
1413 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1414 state |= RMAP_LEFT_CONTIG;
1417 /* Is there a right record that abuts our range? */
1418 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1423 state |= RMAP_RIGHT_VALID;
1424 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1427 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1428 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1430 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1431 cur->bc_private.a.agno, RIGHT.rm_startblock,
1432 RIGHT.rm_blockcount, RIGHT.rm_owner,
1433 RIGHT.rm_offset, RIGHT.rm_flags);
1434 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1435 state |= RMAP_RIGHT_CONTIG;
1438 /* check that left + prev + right is not too long */
1439 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1440 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1441 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1442 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1443 (unsigned long)LEFT.rm_blockcount + len +
1444 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1445 state &= ~RMAP_RIGHT_CONTIG;
1447 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1450 * Switch out based on the FILLING and CONTIG state bits.
1452 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1453 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1454 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1455 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1457 * Setting all of a previous oldext extent to newext.
1458 * The left and right neighbors are both contiguous with new.
1460 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1461 RIGHT.rm_blockcount, RIGHT.rm_owner,
1462 RIGHT.rm_offset, RIGHT.rm_flags);
1465 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1466 PREV.rm_blockcount, PREV.rm_owner,
1467 PREV.rm_offset, PREV.rm_flags);
1471 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1472 NEW.rm_blockcount, NEW.rm_owner,
1473 NEW.rm_offset, NEW.rm_flags, &i);
1476 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1477 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1478 error = xfs_rmap_update(cur, &NEW);
1483 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1485 * Setting all of a previous oldext extent to newext.
1486 * The left neighbor is contiguous, the right is not.
1488 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1489 PREV.rm_blockcount, PREV.rm_owner,
1490 PREV.rm_offset, PREV.rm_flags);
1494 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1495 NEW.rm_blockcount, NEW.rm_owner,
1496 NEW.rm_offset, NEW.rm_flags, &i);
1499 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1500 NEW.rm_blockcount += PREV.rm_blockcount;
1501 error = xfs_rmap_update(cur, &NEW);
1506 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1508 * Setting all of a previous oldext extent to newext.
1509 * The right neighbor is contiguous, the left is not.
1511 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1512 RIGHT.rm_blockcount, RIGHT.rm_owner,
1513 RIGHT.rm_offset, RIGHT.rm_flags);
1517 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1518 NEW.rm_blockcount, NEW.rm_owner,
1519 NEW.rm_offset, NEW.rm_flags, &i);
1522 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1523 NEW.rm_blockcount += RIGHT.rm_blockcount;
1524 NEW.rm_flags = RIGHT.rm_flags;
1525 error = xfs_rmap_update(cur, &NEW);
1530 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1532 * Setting all of a previous oldext extent to newext.
1533 * Neither the left nor right neighbors are contiguous with
1537 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1538 NEW.rm_blockcount, NEW.rm_owner,
1539 NEW.rm_offset, NEW.rm_flags, &i);
1542 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1543 NEW.rm_flags = newext;
1544 error = xfs_rmap_update(cur, &NEW);
1549 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1551 * Setting the first part of a previous oldext extent to newext.
1552 * The left neighbor is contiguous.
1555 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1556 NEW.rm_blockcount, NEW.rm_owner,
1557 NEW.rm_offset, NEW.rm_flags);
1560 NEW.rm_offset += len;
1561 NEW.rm_startblock += len;
1562 NEW.rm_blockcount -= len;
1563 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1564 NEW.rm_blockcount, NEW.rm_owner,
1565 NEW.rm_offset, NEW.rm_flags);
1569 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1570 NEW.rm_blockcount, NEW.rm_owner,
1571 NEW.rm_offset, NEW.rm_flags, &i);
1574 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1575 NEW.rm_blockcount += len;
1576 error = xfs_rmap_update(cur, &NEW);
1581 case RMAP_LEFT_FILLING:
1583 * Setting the first part of a previous oldext extent to newext.
1584 * The left neighbor is not contiguous.
1587 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1588 NEW.rm_blockcount, NEW.rm_owner,
1589 NEW.rm_offset, NEW.rm_flags);
1592 NEW.rm_offset += len;
1593 NEW.rm_startblock += len;
1594 NEW.rm_blockcount -= len;
1595 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1596 NEW.rm_blockcount, NEW.rm_owner,
1597 NEW.rm_offset, NEW.rm_flags);
1600 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1605 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1607 * Setting the last part of a previous oldext extent to newext.
1608 * The right neighbor is contiguous with the new allocation.
1611 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1612 NEW.rm_blockcount, NEW.rm_owner,
1613 NEW.rm_offset, NEW.rm_flags, &i);
1616 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1617 NEW.rm_blockcount = offset - NEW.rm_offset;
1618 error = xfs_rmap_update(cur, &NEW);
1622 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1623 NEW.rm_blockcount, NEW.rm_owner,
1624 NEW.rm_offset, NEW.rm_flags);
1627 NEW.rm_offset = offset;
1628 NEW.rm_startblock = bno;
1629 NEW.rm_blockcount += len;
1630 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1631 NEW.rm_blockcount, NEW.rm_owner,
1632 NEW.rm_offset, NEW.rm_flags);
1637 case RMAP_RIGHT_FILLING:
1639 * Setting the last part of a previous oldext extent to newext.
1640 * The right neighbor is not contiguous.
1643 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1644 NEW.rm_blockcount, NEW.rm_owner,
1645 NEW.rm_offset, NEW.rm_flags, &i);
1648 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1649 NEW.rm_blockcount -= len;
1650 error = xfs_rmap_update(cur, &NEW);
1653 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1660 * Setting the middle part of a previous oldext extent to
1661 * newext. Contiguity is impossible here.
1662 * One extent becomes three extents.
1664 /* new right extent - oldext */
1665 NEW.rm_startblock = bno + len;
1666 NEW.rm_owner = owner;
1667 NEW.rm_offset = new_endoff;
1668 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1670 NEW.rm_flags = PREV.rm_flags;
1671 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1672 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1676 /* new left extent - oldext */
1678 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1679 NEW.rm_blockcount, NEW.rm_owner,
1680 NEW.rm_offset, NEW.rm_flags, &i);
1683 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1684 NEW.rm_blockcount = offset - NEW.rm_offset;
1685 error = xfs_rmap_update(cur, &NEW);
1688 /* new middle extent - newext */
1689 NEW.rm_startblock = bno;
1690 NEW.rm_blockcount = len;
1691 NEW.rm_owner = owner;
1692 NEW.rm_offset = offset;
1693 NEW.rm_flags = newext;
1694 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1695 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1701 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1702 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1703 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1704 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1705 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1706 case RMAP_LEFT_CONTIG:
1707 case RMAP_RIGHT_CONTIG:
1709 * These cases are all impossible.
1714 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1718 trace_xfs_rmap_convert_error(cur->bc_mp,
1719 cur->bc_private.a.agno, error, _RET_IP_);
1729 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1730 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1731 * that the prev/next records in the btree might belong to another owner.
1732 * Therefore we must use delete+insert to alter any of the key fields.
1734 * For every other situation there can only be one owner for a given extent,
1735 * so we can call the regular _free function.
1738 xfs_rmap_unmap_shared(
1739 struct xfs_btree_cur *cur,
1743 const struct xfs_owner_info *oinfo)
1745 struct xfs_mount *mp = cur->bc_mp;
1746 struct xfs_rmap_irec ltrec;
1754 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1756 flags |= XFS_RMAP_UNWRITTEN;
1757 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
1761 * We should always have a left record because there's a static record
1762 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1763 * will not ever be removed from the tree.
1765 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1769 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1770 ltoff = ltrec.rm_offset;
1772 /* Make sure the extent we found covers the entire freeing range. */
1773 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
1774 ltrec.rm_startblock + ltrec.rm_blockcount >=
1775 bno + len, out_error);
1777 /* Make sure the owner matches what we expect to find in the tree. */
1778 XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner, out_error);
1780 /* Make sure the unwritten flag matches. */
1781 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
1782 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error);
1784 /* Check the offset. */
1785 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error);
1786 XFS_WANT_CORRUPTED_GOTO(mp, offset <= ltoff + ltrec.rm_blockcount,
1789 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
1790 /* Exact match, simply remove the record from rmap tree. */
1791 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1792 ltrec.rm_blockcount, ltrec.rm_owner,
1793 ltrec.rm_offset, ltrec.rm_flags);
1796 } else if (ltrec.rm_startblock == bno) {
1798 * Overlap left hand side of extent: move the start, trim the
1799 * length and update the current record.
1802 * Orig: |oooooooooooooooooooo|
1803 * Freeing: |fffffffff|
1804 * Result: |rrrrrrrrrr|
1808 /* Delete prev rmap. */
1809 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1810 ltrec.rm_blockcount, ltrec.rm_owner,
1811 ltrec.rm_offset, ltrec.rm_flags);
1815 /* Add an rmap at the new offset. */
1816 ltrec.rm_startblock += len;
1817 ltrec.rm_blockcount -= len;
1818 ltrec.rm_offset += len;
1819 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
1820 ltrec.rm_blockcount, ltrec.rm_owner,
1821 ltrec.rm_offset, ltrec.rm_flags);
1824 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
1826 * Overlap right hand side of extent: trim the length and
1827 * update the current record.
1830 * Orig: |oooooooooooooooooooo|
1831 * Freeing: |fffffffff|
1832 * Result: |rrrrrrrrrr|
1835 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1836 ltrec.rm_blockcount, ltrec.rm_owner,
1837 ltrec.rm_offset, ltrec.rm_flags, &i);
1840 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1841 ltrec.rm_blockcount -= len;
1842 error = xfs_rmap_update(cur, <rec);
1847 * Overlap middle of extent: trim the length of the existing
1848 * record to the length of the new left-extent size, increment
1849 * the insertion position so we can insert a new record
1850 * containing the remaining right-extent space.
1853 * Orig: |oooooooooooooooooooo|
1854 * Freeing: |fffffffff|
1855 * Result: |rrrrr| |rrrr|
1858 xfs_extlen_t orig_len = ltrec.rm_blockcount;
1860 /* Shrink the left side of the rmap */
1861 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1862 ltrec.rm_blockcount, ltrec.rm_owner,
1863 ltrec.rm_offset, ltrec.rm_flags, &i);
1866 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1867 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
1868 error = xfs_rmap_update(cur, <rec);
1872 /* Add an rmap at the new offset */
1873 error = xfs_rmap_insert(cur, bno + len,
1874 orig_len - len - ltrec.rm_blockcount,
1875 ltrec.rm_owner, offset + len,
1881 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
1885 trace_xfs_rmap_unmap_error(cur->bc_mp,
1886 cur->bc_private.a.agno, error, _RET_IP_);
1891 * Find an extent in the rmap btree and map it. For rmap extent types that
1892 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1893 * that the prev/next records in the btree might belong to another owner.
1894 * Therefore we must use delete+insert to alter any of the key fields.
1896 * For every other situation there can only be one owner for a given extent,
1897 * so we can call the regular _alloc function.
1900 xfs_rmap_map_shared(
1901 struct xfs_btree_cur *cur,
1905 const struct xfs_owner_info *oinfo)
1907 struct xfs_mount *mp = cur->bc_mp;
1908 struct xfs_rmap_irec ltrec;
1909 struct xfs_rmap_irec gtrec;
1916 unsigned int flags = 0;
1918 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1920 flags |= XFS_RMAP_UNWRITTEN;
1921 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
1924 /* Is there a left record that abuts our range? */
1925 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
1930 !xfs_rmap_is_mergeable(<rec, owner, flags))
1933 /* Is there a right record that abuts our range? */
1934 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1939 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
1942 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
1943 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1944 cur->bc_private.a.agno, gtrec.rm_startblock,
1945 gtrec.rm_blockcount, gtrec.rm_owner,
1946 gtrec.rm_offset, gtrec.rm_flags);
1948 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
1953 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
1954 ltrec.rm_offset + ltrec.rm_blockcount == offset) {
1956 * Left edge contiguous, merge into left record.
1960 * adding: |aaaaaaaaa|
1961 * result: |rrrrrrrrrrrrrrrrrrr|
1964 ltrec.rm_blockcount += len;
1966 bno + len == gtrec.rm_startblock &&
1967 offset + len == gtrec.rm_offset) {
1969 * Right edge also contiguous, delete right record
1970 * and merge into left record.
1972 * ltbno ltlen gtbno gtlen
1973 * orig: |ooooooooo| |ooooooooo|
1974 * adding: |aaaaaaaaa|
1975 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1977 ltrec.rm_blockcount += gtrec.rm_blockcount;
1978 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
1979 gtrec.rm_blockcount, gtrec.rm_owner,
1980 gtrec.rm_offset, gtrec.rm_flags);
1985 /* Point the cursor back to the left record and update. */
1986 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1987 ltrec.rm_blockcount, ltrec.rm_owner,
1988 ltrec.rm_offset, ltrec.rm_flags, &i);
1991 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1993 error = xfs_rmap_update(cur, <rec);
1996 } else if (have_gt &&
1997 bno + len == gtrec.rm_startblock &&
1998 offset + len == gtrec.rm_offset) {
2000 * Right edge contiguous, merge into right record.
2004 * adding: |aaaaaaaaa|
2005 * Result: |rrrrrrrrrrrrrrrrrrr|
2008 /* Delete the old record. */
2009 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2010 gtrec.rm_blockcount, gtrec.rm_owner,
2011 gtrec.rm_offset, gtrec.rm_flags);
2015 /* Move the start and re-add it. */
2016 gtrec.rm_startblock = bno;
2017 gtrec.rm_blockcount += len;
2018 gtrec.rm_offset = offset;
2019 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2020 gtrec.rm_blockcount, gtrec.rm_owner,
2021 gtrec.rm_offset, gtrec.rm_flags);
2026 * No contiguous edge with identical owner, insert
2027 * new record at current cursor position.
2029 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2034 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
2038 trace_xfs_rmap_map_error(cur->bc_mp,
2039 cur->bc_private.a.agno, error, _RET_IP_);
2043 /* Insert a raw rmap into the rmapbt. */
2046 struct xfs_btree_cur *cur,
2047 struct xfs_rmap_irec *rmap)
2049 struct xfs_owner_info oinfo;
2051 oinfo.oi_owner = rmap->rm_owner;
2052 oinfo.oi_offset = rmap->rm_offset;
2054 if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
2055 oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
2056 if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
2057 oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
2059 if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2060 return xfs_rmap_map(cur, rmap->rm_startblock,
2061 rmap->rm_blockcount,
2062 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2065 return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2066 rmap->rm_blockcount,
2067 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2071 struct xfs_rmap_query_range_info {
2072 xfs_rmap_query_range_fn fn;
2076 /* Format btree record and pass to our callback. */
2078 xfs_rmap_query_range_helper(
2079 struct xfs_btree_cur *cur,
2080 union xfs_btree_rec *rec,
2083 struct xfs_rmap_query_range_info *query = priv;
2084 struct xfs_rmap_irec irec;
2087 error = xfs_rmap_btrec_to_irec(rec, &irec);
2090 return query->fn(cur, &irec, query->priv);
2093 /* Find all rmaps between two keys. */
2095 xfs_rmap_query_range(
2096 struct xfs_btree_cur *cur,
2097 struct xfs_rmap_irec *low_rec,
2098 struct xfs_rmap_irec *high_rec,
2099 xfs_rmap_query_range_fn fn,
2102 union xfs_btree_irec low_brec;
2103 union xfs_btree_irec high_brec;
2104 struct xfs_rmap_query_range_info query;
2106 low_brec.r = *low_rec;
2107 high_brec.r = *high_rec;
2110 return xfs_btree_query_range(cur, &low_brec, &high_brec,
2111 xfs_rmap_query_range_helper, &query);
2114 /* Find all rmaps. */
2117 struct xfs_btree_cur *cur,
2118 xfs_rmap_query_range_fn fn,
2121 struct xfs_rmap_query_range_info query;
2125 return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2128 /* Clean up after calling xfs_rmap_finish_one. */
2130 xfs_rmap_finish_one_cleanup(
2131 struct xfs_trans *tp,
2132 struct xfs_btree_cur *rcur,
2135 struct xfs_buf *agbp;
2139 agbp = rcur->bc_private.a.agbp;
2140 xfs_btree_del_cursor(rcur, error);
2142 xfs_trans_brelse(tp, agbp);
2146 * Process one of the deferred rmap operations. We pass back the
2147 * btree cursor to maintain our lock on the rmapbt between calls.
2148 * This saves time and eliminates a buffer deadlock between the
2149 * superblock and the AGF because we'll always grab them in the same
2153 xfs_rmap_finish_one(
2154 struct xfs_trans *tp,
2155 enum xfs_rmap_intent_type type,
2158 xfs_fileoff_t startoff,
2159 xfs_fsblock_t startblock,
2160 xfs_filblks_t blockcount,
2162 struct xfs_btree_cur **pcur)
2164 struct xfs_mount *mp = tp->t_mountp;
2165 struct xfs_btree_cur *rcur;
2166 struct xfs_buf *agbp = NULL;
2168 xfs_agnumber_t agno;
2169 struct xfs_owner_info oinfo;
2173 agno = XFS_FSB_TO_AGNO(mp, startblock);
2174 ASSERT(agno != NULLAGNUMBER);
2175 bno = XFS_FSB_TO_AGBNO(mp, startblock);
2177 trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork,
2178 startoff, blockcount, state);
2180 if (XFS_TEST_ERROR(false, mp,
2181 XFS_ERRTAG_RMAP_FINISH_ONE))
2185 * If we haven't gotten a cursor or the cursor AG doesn't match
2186 * the startblock, get one now.
2189 if (rcur != NULL && rcur->bc_private.a.agno != agno) {
2190 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2196 * Refresh the freelist before we start changing the
2197 * rmapbt, because a shape change could cause us to
2200 error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
2204 return -EFSCORRUPTED;
2206 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
2214 xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2215 unwritten = state == XFS_EXT_UNWRITTEN;
2216 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2219 case XFS_RMAP_ALLOC:
2221 error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2223 case XFS_RMAP_MAP_SHARED:
2224 error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2228 case XFS_RMAP_UNMAP:
2229 error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2232 case XFS_RMAP_UNMAP_SHARED:
2233 error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2236 case XFS_RMAP_CONVERT:
2237 error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2240 case XFS_RMAP_CONVERT_SHARED:
2241 error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2242 !unwritten, &oinfo);
2246 error = -EFSCORRUPTED;
2251 xfs_trans_brelse(tp, agbp);
2257 * Don't defer an rmap if we aren't an rmap filesystem.
2260 xfs_rmap_update_is_needed(
2261 struct xfs_mount *mp,
2264 return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK;
2268 * Record a rmap intent; the list is kept sorted first by AG and then by
2273 struct xfs_trans *tp,
2274 enum xfs_rmap_intent_type type,
2277 struct xfs_bmbt_irec *bmap)
2279 struct xfs_rmap_intent *ri;
2281 trace_xfs_rmap_defer(tp->t_mountp,
2282 XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock),
2284 XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock),
2287 bmap->br_blockcount,
2290 ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_SLEEP | KM_NOFS);
2291 INIT_LIST_HEAD(&ri->ri_list);
2293 ri->ri_owner = owner;
2294 ri->ri_whichfork = whichfork;
2295 ri->ri_bmap = *bmap;
2297 xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
2301 /* Map an extent into a file. */
2303 xfs_rmap_map_extent(
2304 struct xfs_trans *tp,
2305 struct xfs_inode *ip,
2307 struct xfs_bmbt_irec *PREV)
2309 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2312 return __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
2313 XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino,
2317 /* Unmap an extent out of a file. */
2319 xfs_rmap_unmap_extent(
2320 struct xfs_trans *tp,
2321 struct xfs_inode *ip,
2323 struct xfs_bmbt_irec *PREV)
2325 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2328 return __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
2329 XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino,
2334 * Convert a data fork extent from unwritten to real or vice versa.
2336 * Note that tp can be NULL here as no transaction is used for COW fork
2337 * unwritten conversion.
2340 xfs_rmap_convert_extent(
2341 struct xfs_mount *mp,
2342 struct xfs_trans *tp,
2343 struct xfs_inode *ip,
2345 struct xfs_bmbt_irec *PREV)
2347 if (!xfs_rmap_update_is_needed(mp, whichfork))
2350 return __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
2351 XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino,
2355 /* Schedule the creation of an rmap for non-file data. */
2357 xfs_rmap_alloc_extent(
2358 struct xfs_trans *tp,
2359 xfs_agnumber_t agno,
2364 struct xfs_bmbt_irec bmap;
2366 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2369 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2370 bmap.br_blockcount = len;
2371 bmap.br_startoff = 0;
2372 bmap.br_state = XFS_EXT_NORM;
2374 return __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
2377 /* Schedule the deletion of an rmap for non-file data. */
2379 xfs_rmap_free_extent(
2380 struct xfs_trans *tp,
2381 xfs_agnumber_t agno,
2386 struct xfs_bmbt_irec bmap;
2388 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2391 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2392 bmap.br_blockcount = len;
2393 bmap.br_startoff = 0;
2394 bmap.br_state = XFS_EXT_NORM;
2396 return __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
2399 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2402 const struct xfs_rmap_irec *a,
2403 const struct xfs_rmap_irec *b)
2408 oa = xfs_rmap_irec_offset_pack(a);
2409 ob = xfs_rmap_irec_offset_pack(b);
2411 if (a->rm_startblock < b->rm_startblock)
2413 else if (a->rm_startblock > b->rm_startblock)
2415 else if (a->rm_owner < b->rm_owner)
2417 else if (a->rm_owner > b->rm_owner)
2427 /* Is there a record covering a given extent? */
2429 xfs_rmap_has_record(
2430 struct xfs_btree_cur *cur,
2435 union xfs_btree_irec low;
2436 union xfs_btree_irec high;
2438 memset(&low, 0, sizeof(low));
2439 low.r.rm_startblock = bno;
2440 memset(&high, 0xFF, sizeof(high));
2441 high.r.rm_startblock = bno + len - 1;
2443 return xfs_btree_has_record(cur, &low, &high, exists);
2447 * Is there a record for this owner completely covering a given physical
2448 * extent? If so, *has_rmap will be set to true. If there is no record
2449 * or the record only covers part of the range, we set *has_rmap to false.
2450 * This function doesn't perform range lookups or offset checks, so it is
2451 * not suitable for checking data fork blocks.
2454 xfs_rmap_record_exists(
2455 struct xfs_btree_cur *cur,
2458 const struct xfs_owner_info *oinfo,
2465 struct xfs_rmap_irec irec;
2468 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2469 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
2470 (flags & XFS_RMAP_BMBT_BLOCK));
2472 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
2481 error = xfs_rmap_get_rec(cur, &irec, &has_record);
2489 *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
2490 irec.rm_startblock + irec.rm_blockcount >= bno + len);
2494 struct xfs_rmap_key_state {
2501 /* For each rmap given, figure out if it doesn't match the key we want. */
2503 xfs_rmap_has_other_keys_helper(
2504 struct xfs_btree_cur *cur,
2505 struct xfs_rmap_irec *rec,
2508 struct xfs_rmap_key_state *rks = priv;
2510 if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset &&
2511 ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags)
2513 rks->has_rmap = true;
2514 return XFS_BTREE_QUERY_RANGE_ABORT;
2518 * Given an extent and some owner info, can we find records overlapping
2519 * the extent whose owner info does not match the given owner?
2522 xfs_rmap_has_other_keys(
2523 struct xfs_btree_cur *cur,
2526 const struct xfs_owner_info *oinfo,
2529 struct xfs_rmap_irec low = {0};
2530 struct xfs_rmap_irec high;
2531 struct xfs_rmap_key_state rks;
2534 xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags);
2535 rks.has_rmap = false;
2537 low.rm_startblock = bno;
2538 memset(&high, 0xFF, sizeof(high));
2539 high.rm_startblock = bno + len - 1;
2541 error = xfs_rmap_query_range(cur, &low, &high,
2542 xfs_rmap_has_other_keys_helper, &rks);
2543 *has_rmap = rks.has_rmap;
2547 const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
2548 .oi_owner = XFS_RMAP_OWN_NULL,
2550 const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
2551 .oi_owner = XFS_RMAP_OWN_UNKNOWN,
2553 const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
2554 .oi_owner = XFS_RMAP_OWN_FS,
2556 const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
2557 .oi_owner = XFS_RMAP_OWN_LOG,
2559 const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
2560 .oi_owner = XFS_RMAP_OWN_AG,
2562 const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
2563 .oi_owner = XFS_RMAP_OWN_INOBT,
2565 const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
2566 .oi_owner = XFS_RMAP_OWN_INODES,
2568 const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
2569 .oi_owner = XFS_RMAP_OWN_REFC,
2571 const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
2572 .oi_owner = XFS_RMAP_OWN_COW,