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"
15 #include "xfs_defer.h"
16 #include "xfs_btree.h"
17 #include "xfs_trans.h"
18 #include "xfs_alloc.h"
20 #include "xfs_rmap_btree.h"
21 #include "xfs_trace.h"
22 #include "xfs_errortag.h"
23 #include "xfs_error.h"
24 #include "xfs_inode.h"
27 struct kmem_cache *xfs_rmap_intent_cache;
30 * Lookup the first record less than or equal to [bno, len, owner, offset]
31 * in the btree given by cur.
35 struct xfs_btree_cur *cur,
40 struct xfs_rmap_irec *irec,
46 cur->bc_rec.r.rm_startblock = bno;
47 cur->bc_rec.r.rm_blockcount = 0;
48 cur->bc_rec.r.rm_owner = owner;
49 cur->bc_rec.r.rm_offset = offset;
50 cur->bc_rec.r.rm_flags = flags;
52 error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
53 if (error || !(*stat) || !irec)
56 error = xfs_rmap_get_rec(cur, irec, &get_stat);
66 * Lookup the record exactly matching [bno, len, owner, offset]
67 * in the btree given by cur.
71 struct xfs_btree_cur *cur,
79 cur->bc_rec.r.rm_startblock = bno;
80 cur->bc_rec.r.rm_blockcount = len;
81 cur->bc_rec.r.rm_owner = owner;
82 cur->bc_rec.r.rm_offset = offset;
83 cur->bc_rec.r.rm_flags = flags;
84 return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
88 * Update the record referred to by cur to the value given
89 * by [bno, len, owner, offset].
90 * This either works (return 0) or gets an EFSCORRUPTED error.
94 struct xfs_btree_cur *cur,
95 struct xfs_rmap_irec *irec)
97 union xfs_btree_rec rec;
100 trace_xfs_rmap_update(cur->bc_mp, cur->bc_ag.pag->pag_agno,
101 irec->rm_startblock, irec->rm_blockcount,
102 irec->rm_owner, irec->rm_offset, irec->rm_flags);
104 rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
105 rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
106 rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
107 rec.rmap.rm_offset = cpu_to_be64(
108 xfs_rmap_irec_offset_pack(irec));
109 error = xfs_btree_update(cur, &rec);
111 trace_xfs_rmap_update_error(cur->bc_mp,
112 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
118 struct xfs_btree_cur *rcur,
128 trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno,
129 len, owner, offset, flags);
131 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
134 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 0)) {
135 error = -EFSCORRUPTED;
139 rcur->bc_rec.r.rm_startblock = agbno;
140 rcur->bc_rec.r.rm_blockcount = len;
141 rcur->bc_rec.r.rm_owner = owner;
142 rcur->bc_rec.r.rm_offset = offset;
143 rcur->bc_rec.r.rm_flags = flags;
144 error = xfs_btree_insert(rcur, &i);
147 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
148 error = -EFSCORRUPTED;
153 trace_xfs_rmap_insert_error(rcur->bc_mp,
154 rcur->bc_ag.pag->pag_agno, error, _RET_IP_);
160 struct xfs_btree_cur *rcur,
170 trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno,
171 len, owner, offset, flags);
173 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
176 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
177 error = -EFSCORRUPTED;
181 error = xfs_btree_delete(rcur, &i);
184 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
185 error = -EFSCORRUPTED;
190 trace_xfs_rmap_delete_error(rcur->bc_mp,
191 rcur->bc_ag.pag->pag_agno, error, _RET_IP_);
195 /* Convert an internal btree record to an rmap record. */
197 xfs_rmap_btrec_to_irec(
198 const union xfs_btree_rec *rec,
199 struct xfs_rmap_irec *irec)
201 irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
202 irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
203 irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
204 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
208 /* Simple checks for rmap records. */
211 struct xfs_btree_cur *cur,
212 const struct xfs_rmap_irec *irec)
214 struct xfs_mount *mp = cur->bc_mp;
220 if (irec->rm_blockcount == 0)
221 return __this_address;
222 if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
223 if (irec->rm_owner != XFS_RMAP_OWN_FS)
224 return __this_address;
225 if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
226 return __this_address;
228 /* check for valid extent range, including overflow */
229 if (!xfs_verify_agbext(cur->bc_ag.pag, irec->rm_startblock,
230 irec->rm_blockcount))
231 return __this_address;
234 if (!(xfs_verify_ino(mp, irec->rm_owner) ||
235 (irec->rm_owner <= XFS_RMAP_OWN_FS &&
236 irec->rm_owner >= XFS_RMAP_OWN_MIN)))
237 return __this_address;
240 is_inode = !XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
241 is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
242 is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
243 is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
245 if (is_bmbt && irec->rm_offset != 0)
246 return __this_address;
248 if (!is_inode && irec->rm_offset != 0)
249 return __this_address;
251 if (is_unwritten && (is_bmbt || !is_inode || is_attr))
252 return __this_address;
254 if (!is_inode && (is_bmbt || is_unwritten || is_attr))
255 return __this_address;
257 /* Check for a valid fork offset, if applicable. */
258 if (is_inode && !is_bmbt &&
259 !xfs_verify_fileext(mp, irec->rm_offset, irec->rm_blockcount))
260 return __this_address;
266 xfs_rmap_complain_bad_rec(
267 struct xfs_btree_cur *cur,
269 const struct xfs_rmap_irec *irec)
271 struct xfs_mount *mp = cur->bc_mp;
274 "Reverse Mapping BTree record corruption in AG %d detected at %pS!",
275 cur->bc_ag.pag->pag_agno, fa);
277 "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
278 irec->rm_owner, irec->rm_flags, irec->rm_startblock,
279 irec->rm_blockcount);
280 return -EFSCORRUPTED;
284 * Get the data from the pointed-to record.
288 struct xfs_btree_cur *cur,
289 struct xfs_rmap_irec *irec,
292 union xfs_btree_rec *rec;
296 error = xfs_btree_get_rec(cur, &rec, stat);
300 fa = xfs_rmap_btrec_to_irec(rec, irec);
302 fa = xfs_rmap_check_irec(cur, irec);
304 return xfs_rmap_complain_bad_rec(cur, fa, irec);
309 struct xfs_find_left_neighbor_info {
310 struct xfs_rmap_irec high;
311 struct xfs_rmap_irec *irec;
314 /* For each rmap given, figure out if it matches the key we want. */
316 xfs_rmap_find_left_neighbor_helper(
317 struct xfs_btree_cur *cur,
318 const struct xfs_rmap_irec *rec,
321 struct xfs_find_left_neighbor_info *info = priv;
323 trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
324 cur->bc_ag.pag->pag_agno, rec->rm_startblock,
325 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
328 if (rec->rm_owner != info->high.rm_owner)
330 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
331 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
332 rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
340 * Find the record to the left of the given extent, being careful only to
341 * return a match with the same owner and adjacent physical and logical
345 xfs_rmap_find_left_neighbor(
346 struct xfs_btree_cur *cur,
351 struct xfs_rmap_irec *irec,
354 struct xfs_find_left_neighbor_info info;
361 info.high.rm_startblock = bno - 1;
362 info.high.rm_owner = owner;
363 if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
364 !(flags & XFS_RMAP_BMBT_BLOCK)) {
367 info.high.rm_offset = offset - 1;
369 info.high.rm_offset = 0;
370 info.high.rm_flags = flags;
371 info.high.rm_blockcount = 0;
374 trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
375 cur->bc_ag.pag->pag_agno, bno, 0, owner, offset, flags);
378 * Historically, we always used the range query to walk every reverse
379 * mapping that could possibly overlap the key that the caller asked
380 * for, and filter out the ones that don't. That is very slow when
381 * there are a lot of records.
383 * However, there are two scenarios where the classic btree search can
384 * produce correct results -- if the index contains a record that is an
385 * exact match for the lookup key; and if there are no other records
386 * between the record we want and the key we supplied.
388 * As an optimization, try a non-overlapped lookup first. This makes
389 * extent conversion and remap operations run a bit faster if the
390 * physical extents aren't being shared. If we don't find what we
391 * want, we fall back to the overlapped query.
393 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
398 error = xfs_rmap_find_left_neighbor_helper(cur, irec, &info);
400 error = xfs_rmap_query_range(cur, &info.high, &info.high,
401 xfs_rmap_find_left_neighbor_helper, &info);
402 if (error != -ECANCELED)
406 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
407 cur->bc_ag.pag->pag_agno, irec->rm_startblock,
408 irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
413 /* For each rmap given, figure out if it matches the key we want. */
415 xfs_rmap_lookup_le_range_helper(
416 struct xfs_btree_cur *cur,
417 const struct xfs_rmap_irec *rec,
420 struct xfs_find_left_neighbor_info *info = priv;
422 trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
423 cur->bc_ag.pag->pag_agno, rec->rm_startblock,
424 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
427 if (rec->rm_owner != info->high.rm_owner)
429 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
430 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
431 (rec->rm_offset > info->high.rm_offset ||
432 rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
440 * Find the record to the left of the given extent, being careful only to
441 * return a match with the same owner and overlapping physical and logical
442 * block ranges. This is the overlapping-interval version of
443 * xfs_rmap_lookup_le.
446 xfs_rmap_lookup_le_range(
447 struct xfs_btree_cur *cur,
452 struct xfs_rmap_irec *irec,
455 struct xfs_find_left_neighbor_info info;
459 info.high.rm_startblock = bno;
460 info.high.rm_owner = owner;
461 if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
462 info.high.rm_offset = offset;
464 info.high.rm_offset = 0;
465 info.high.rm_flags = flags;
466 info.high.rm_blockcount = 0;
470 trace_xfs_rmap_lookup_le_range(cur->bc_mp, cur->bc_ag.pag->pag_agno,
471 bno, 0, owner, offset, flags);
474 * Historically, we always used the range query to walk every reverse
475 * mapping that could possibly overlap the key that the caller asked
476 * for, and filter out the ones that don't. That is very slow when
477 * there are a lot of records.
479 * However, there are two scenarios where the classic btree search can
480 * produce correct results -- if the index contains a record that is an
481 * exact match for the lookup key; and if there are no other records
482 * between the record we want and the key we supplied.
484 * As an optimization, try a non-overlapped lookup first. This makes
485 * scrub run much faster on most filesystems because bmbt records are
486 * usually an exact match for rmap records. If we don't find what we
487 * want, we fall back to the overlapped query.
489 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
494 error = xfs_rmap_lookup_le_range_helper(cur, irec, &info);
496 error = xfs_rmap_query_range(cur, &info.high, &info.high,
497 xfs_rmap_lookup_le_range_helper, &info);
498 if (error != -ECANCELED)
502 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
503 cur->bc_ag.pag->pag_agno, irec->rm_startblock,
504 irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
510 * Perform all the relevant owner checks for a removal op. If we're doing an
511 * unknown-owner removal then we have no owner information to check.
514 xfs_rmap_free_check_owner(
515 struct xfs_mount *mp,
517 struct xfs_rmap_irec *rec,
525 if (owner == XFS_RMAP_OWN_UNKNOWN)
528 /* Make sure the unwritten flag matches. */
529 if (XFS_IS_CORRUPT(mp,
530 (flags & XFS_RMAP_UNWRITTEN) !=
531 (rec->rm_flags & XFS_RMAP_UNWRITTEN))) {
532 error = -EFSCORRUPTED;
536 /* Make sure the owner matches what we expect to find in the tree. */
537 if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) {
538 error = -EFSCORRUPTED;
542 /* Check the offset, if necessary. */
543 if (XFS_RMAP_NON_INODE_OWNER(owner))
546 if (flags & XFS_RMAP_BMBT_BLOCK) {
547 if (XFS_IS_CORRUPT(mp,
548 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) {
549 error = -EFSCORRUPTED;
553 if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) {
554 error = -EFSCORRUPTED;
557 if (XFS_IS_CORRUPT(mp,
558 offset + len > ltoff + rec->rm_blockcount)) {
559 error = -EFSCORRUPTED;
569 * Find the extent in the rmap btree and remove it.
571 * The record we find should always be an exact match for the extent that we're
572 * looking for, since we insert them into the btree without modification.
574 * Special Case #1: when growing the filesystem, we "free" an extent when
575 * growing the last AG. This extent is new space and so it is not tracked as
576 * used space in the btree. The growfs code will pass in an owner of
577 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
578 * extent. We verify that - the extent lookup result in a record that does not
581 * Special Case #2: EFIs do not record the owner of the extent, so when
582 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
583 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
584 * corruption checks during log recovery.
588 struct xfs_btree_cur *cur,
592 const struct xfs_owner_info *oinfo)
594 struct xfs_mount *mp = cur->bc_mp;
595 struct xfs_rmap_irec ltrec;
604 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
605 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
606 (flags & XFS_RMAP_BMBT_BLOCK);
608 flags |= XFS_RMAP_UNWRITTEN;
609 trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
613 * We should always have a left record because there's a static record
614 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
615 * will not ever be removed from the tree.
617 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, <rec, &i);
620 if (XFS_IS_CORRUPT(mp, i != 1)) {
621 error = -EFSCORRUPTED;
625 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
626 cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
627 ltrec.rm_blockcount, ltrec.rm_owner,
628 ltrec.rm_offset, ltrec.rm_flags);
629 ltoff = ltrec.rm_offset;
632 * For growfs, the incoming extent must be beyond the left record we
633 * just found as it is new space and won't be used by anyone. This is
634 * just a corruption check as we don't actually do anything with this
635 * extent. Note that we need to use >= instead of > because it might
636 * be the case that the "left" extent goes all the way to EOFS.
638 if (owner == XFS_RMAP_OWN_NULL) {
639 if (XFS_IS_CORRUPT(mp,
641 ltrec.rm_startblock + ltrec.rm_blockcount)) {
642 error = -EFSCORRUPTED;
649 * If we're doing an unknown-owner removal for EFI recovery, we expect
650 * to find the full range in the rmapbt or nothing at all. If we
651 * don't find any rmaps overlapping either end of the range, we're
652 * done. Hopefully this means that the EFI creator already queued
653 * (and finished) a RUI to remove the rmap.
655 if (owner == XFS_RMAP_OWN_UNKNOWN &&
656 ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
657 struct xfs_rmap_irec rtrec;
659 error = xfs_btree_increment(cur, 0, &i);
664 error = xfs_rmap_get_rec(cur, &rtrec, &i);
667 if (XFS_IS_CORRUPT(mp, i != 1)) {
668 error = -EFSCORRUPTED;
671 if (rtrec.rm_startblock >= bno + len)
675 /* Make sure the extent we found covers the entire freeing range. */
676 if (XFS_IS_CORRUPT(mp,
677 ltrec.rm_startblock > bno ||
678 ltrec.rm_startblock + ltrec.rm_blockcount <
680 error = -EFSCORRUPTED;
684 /* Check owner information. */
685 error = xfs_rmap_free_check_owner(mp, ltoff, <rec, len, owner,
690 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
691 /* exact match, simply remove the record from rmap tree */
692 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
693 ltrec.rm_startblock, ltrec.rm_blockcount,
694 ltrec.rm_owner, ltrec.rm_offset,
696 error = xfs_btree_delete(cur, &i);
699 if (XFS_IS_CORRUPT(mp, i != 1)) {
700 error = -EFSCORRUPTED;
703 } else if (ltrec.rm_startblock == bno) {
705 * overlap left hand side of extent: move the start, trim the
706 * length and update the current record.
709 * Orig: |oooooooooooooooooooo|
710 * Freeing: |fffffffff|
711 * Result: |rrrrrrrrrr|
714 ltrec.rm_startblock += len;
715 ltrec.rm_blockcount -= len;
717 ltrec.rm_offset += len;
718 error = xfs_rmap_update(cur, <rec);
721 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
723 * overlap right hand side of extent: trim the length and update
724 * the current record.
727 * Orig: |oooooooooooooooooooo|
728 * Freeing: |fffffffff|
729 * Result: |rrrrrrrrrr|
732 ltrec.rm_blockcount -= len;
733 error = xfs_rmap_update(cur, <rec);
739 * overlap middle of extent: trim the length of the existing
740 * record to the length of the new left-extent size, increment
741 * the insertion position so we can insert a new record
742 * containing the remaining right-extent space.
745 * Orig: |oooooooooooooooooooo|
746 * Freeing: |fffffffff|
747 * Result: |rrrrr| |rrrr|
750 xfs_extlen_t orig_len = ltrec.rm_blockcount;
752 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
753 error = xfs_rmap_update(cur, <rec);
757 error = xfs_btree_increment(cur, 0, &i);
761 cur->bc_rec.r.rm_startblock = bno + len;
762 cur->bc_rec.r.rm_blockcount = orig_len - len -
764 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
766 cur->bc_rec.r.rm_offset = 0;
768 cur->bc_rec.r.rm_offset = offset + len;
769 cur->bc_rec.r.rm_flags = flags;
770 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
771 cur->bc_rec.r.rm_startblock,
772 cur->bc_rec.r.rm_blockcount,
773 cur->bc_rec.r.rm_owner,
774 cur->bc_rec.r.rm_offset,
775 cur->bc_rec.r.rm_flags);
776 error = xfs_btree_insert(cur, &i);
782 trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
786 trace_xfs_rmap_unmap_error(mp, cur->bc_ag.pag->pag_agno,
792 * Remove a reference to an extent in the rmap btree.
796 struct xfs_trans *tp,
797 struct xfs_buf *agbp,
798 struct xfs_perag *pag,
801 const struct xfs_owner_info *oinfo)
803 struct xfs_mount *mp = tp->t_mountp;
804 struct xfs_btree_cur *cur;
807 if (!xfs_has_rmapbt(mp))
810 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
812 error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
814 xfs_btree_del_cursor(cur, error);
819 * A mergeable rmap must have the same owner and the same values for
820 * the unwritten, attr_fork, and bmbt flags. The startblock and
821 * offset are checked separately.
824 xfs_rmap_is_mergeable(
825 struct xfs_rmap_irec *irec,
829 if (irec->rm_owner == XFS_RMAP_OWN_NULL)
831 if (irec->rm_owner != owner)
833 if ((flags & XFS_RMAP_UNWRITTEN) ^
834 (irec->rm_flags & XFS_RMAP_UNWRITTEN))
836 if ((flags & XFS_RMAP_ATTR_FORK) ^
837 (irec->rm_flags & XFS_RMAP_ATTR_FORK))
839 if ((flags & XFS_RMAP_BMBT_BLOCK) ^
840 (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
846 * When we allocate a new block, the first thing we do is add a reference to
847 * the extent in the rmap btree. This takes the form of a [agbno, length,
848 * owner, offset] record. Flags are encoded in the high bits of the offset
853 struct xfs_btree_cur *cur,
857 const struct xfs_owner_info *oinfo)
859 struct xfs_mount *mp = cur->bc_mp;
860 struct xfs_rmap_irec ltrec;
861 struct xfs_rmap_irec gtrec;
868 unsigned int flags = 0;
871 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
873 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
874 (flags & XFS_RMAP_BMBT_BLOCK);
876 flags |= XFS_RMAP_UNWRITTEN;
877 trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
879 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
882 * For the initial lookup, look for an exact match or the left-adjacent
883 * record for our insertion point. This will also give us the record for
884 * start block contiguity tests.
886 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, <rec,
891 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
892 cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
893 ltrec.rm_blockcount, ltrec.rm_owner,
894 ltrec.rm_offset, ltrec.rm_flags);
896 if (!xfs_rmap_is_mergeable(<rec, owner, flags))
900 if (XFS_IS_CORRUPT(mp,
902 ltrec.rm_startblock + ltrec.rm_blockcount > bno)) {
903 error = -EFSCORRUPTED;
908 * Increment the cursor to see if we have a right-adjacent record to our
909 * insertion point. This will give us the record for end block
912 error = xfs_btree_increment(cur, 0, &have_gt);
916 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
919 if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
920 error = -EFSCORRUPTED;
923 if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) {
924 error = -EFSCORRUPTED;
927 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
928 cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
929 gtrec.rm_blockcount, gtrec.rm_owner,
930 gtrec.rm_offset, gtrec.rm_flags);
931 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
936 * Note: cursor currently points one record to the right of ltrec, even
937 * if there is no record in the tree to the right.
940 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
941 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
943 * left edge contiguous, merge into left record.
947 * adding: |aaaaaaaaa|
948 * result: |rrrrrrrrrrrrrrrrrrr|
951 ltrec.rm_blockcount += len;
953 bno + len == gtrec.rm_startblock &&
954 (ignore_off || offset + len == gtrec.rm_offset) &&
955 (unsigned long)ltrec.rm_blockcount + len +
956 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
958 * right edge also contiguous, delete right record
959 * and merge into left record.
961 * ltbno ltlen gtbno gtlen
962 * orig: |ooooooooo| |ooooooooo|
963 * adding: |aaaaaaaaa|
964 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
966 ltrec.rm_blockcount += gtrec.rm_blockcount;
967 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
973 error = xfs_btree_delete(cur, &i);
976 if (XFS_IS_CORRUPT(mp, i != 1)) {
977 error = -EFSCORRUPTED;
982 /* point the cursor back to the left record and update */
983 error = xfs_btree_decrement(cur, 0, &have_gt);
986 error = xfs_rmap_update(cur, <rec);
989 } else if (have_gt &&
990 bno + len == gtrec.rm_startblock &&
991 (ignore_off || offset + len == gtrec.rm_offset)) {
993 * right edge contiguous, merge into right record.
997 * adding: |aaaaaaaaa|
998 * Result: |rrrrrrrrrrrrrrrrrrr|
1001 gtrec.rm_startblock = bno;
1002 gtrec.rm_blockcount += len;
1004 gtrec.rm_offset = offset;
1005 error = xfs_rmap_update(cur, >rec);
1010 * no contiguous edge with identical owner, insert
1011 * new record at current cursor position.
1013 cur->bc_rec.r.rm_startblock = bno;
1014 cur->bc_rec.r.rm_blockcount = len;
1015 cur->bc_rec.r.rm_owner = owner;
1016 cur->bc_rec.r.rm_offset = offset;
1017 cur->bc_rec.r.rm_flags = flags;
1018 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1019 owner, offset, flags);
1020 error = xfs_btree_insert(cur, &i);
1023 if (XFS_IS_CORRUPT(mp, i != 1)) {
1024 error = -EFSCORRUPTED;
1029 trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1033 trace_xfs_rmap_map_error(mp, cur->bc_ag.pag->pag_agno,
1039 * Add a reference to an extent in the rmap btree.
1043 struct xfs_trans *tp,
1044 struct xfs_buf *agbp,
1045 struct xfs_perag *pag,
1048 const struct xfs_owner_info *oinfo)
1050 struct xfs_mount *mp = tp->t_mountp;
1051 struct xfs_btree_cur *cur;
1054 if (!xfs_has_rmapbt(mp))
1057 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
1058 error = xfs_rmap_map(cur, bno, len, false, oinfo);
1060 xfs_btree_del_cursor(cur, error);
1064 #define RMAP_LEFT_CONTIG (1 << 0)
1065 #define RMAP_RIGHT_CONTIG (1 << 1)
1066 #define RMAP_LEFT_FILLING (1 << 2)
1067 #define RMAP_RIGHT_FILLING (1 << 3)
1068 #define RMAP_LEFT_VALID (1 << 6)
1069 #define RMAP_RIGHT_VALID (1 << 7)
1077 * Convert an unwritten extent to a real extent or vice versa.
1078 * Does not handle overlapping extents.
1082 struct xfs_btree_cur *cur,
1086 const struct xfs_owner_info *oinfo)
1088 struct xfs_mount *mp = cur->bc_mp;
1089 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1090 /* left is 0, right is 1, */
1091 /* prev is 2, new is 3 */
1094 uint64_t new_endoff;
1095 unsigned int oldext;
1096 unsigned int newext;
1097 unsigned int flags = 0;
1102 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1103 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1104 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1105 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1106 new_endoff = offset + len;
1107 trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1111 * For the initial lookup, look for an exact match or the left-adjacent
1112 * record for our insertion point. This will also give us the record for
1113 * start block contiguity tests.
1115 error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, &PREV, &i);
1118 if (XFS_IS_CORRUPT(mp, i != 1)) {
1119 error = -EFSCORRUPTED;
1123 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
1124 cur->bc_ag.pag->pag_agno, PREV.rm_startblock,
1125 PREV.rm_blockcount, PREV.rm_owner,
1126 PREV.rm_offset, PREV.rm_flags);
1128 ASSERT(PREV.rm_offset <= offset);
1129 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1130 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1131 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1134 * Set flags determining what part of the previous oldext allocation
1135 * extent is being replaced by a newext allocation.
1137 if (PREV.rm_offset == offset)
1138 state |= RMAP_LEFT_FILLING;
1139 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1140 state |= RMAP_RIGHT_FILLING;
1143 * Decrement the cursor to see if we have a left-adjacent record to our
1144 * insertion point. This will give us the record for end block
1147 error = xfs_btree_decrement(cur, 0, &i);
1151 state |= RMAP_LEFT_VALID;
1152 error = xfs_rmap_get_rec(cur, &LEFT, &i);
1155 if (XFS_IS_CORRUPT(mp, i != 1)) {
1156 error = -EFSCORRUPTED;
1159 if (XFS_IS_CORRUPT(mp,
1160 LEFT.rm_startblock + LEFT.rm_blockcount >
1162 error = -EFSCORRUPTED;
1165 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
1166 cur->bc_ag.pag->pag_agno, LEFT.rm_startblock,
1167 LEFT.rm_blockcount, LEFT.rm_owner,
1168 LEFT.rm_offset, LEFT.rm_flags);
1169 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1170 LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1171 xfs_rmap_is_mergeable(&LEFT, owner, newext))
1172 state |= RMAP_LEFT_CONTIG;
1176 * Increment the cursor to see if we have a right-adjacent record to our
1177 * insertion point. This will give us the record for end block
1180 error = xfs_btree_increment(cur, 0, &i);
1183 if (XFS_IS_CORRUPT(mp, i != 1)) {
1184 error = -EFSCORRUPTED;
1187 error = xfs_btree_increment(cur, 0, &i);
1191 state |= RMAP_RIGHT_VALID;
1192 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1195 if (XFS_IS_CORRUPT(mp, i != 1)) {
1196 error = -EFSCORRUPTED;
1199 if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1200 error = -EFSCORRUPTED;
1203 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1204 cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
1205 RIGHT.rm_blockcount, RIGHT.rm_owner,
1206 RIGHT.rm_offset, RIGHT.rm_flags);
1207 if (bno + len == RIGHT.rm_startblock &&
1208 offset + len == RIGHT.rm_offset &&
1209 xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1210 state |= RMAP_RIGHT_CONTIG;
1213 /* check that left + prev + right is not too long */
1214 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1215 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1216 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1217 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1218 (unsigned long)LEFT.rm_blockcount + len +
1219 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1220 state &= ~RMAP_RIGHT_CONTIG;
1222 trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
1225 /* reset the cursor back to PREV */
1226 error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, NULL, &i);
1229 if (XFS_IS_CORRUPT(mp, i != 1)) {
1230 error = -EFSCORRUPTED;
1235 * Switch out based on the FILLING and CONTIG state bits.
1237 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1238 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1239 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1240 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1242 * Setting all of a previous oldext extent to newext.
1243 * The left and right neighbors are both contiguous with new.
1245 error = xfs_btree_increment(cur, 0, &i);
1248 if (XFS_IS_CORRUPT(mp, i != 1)) {
1249 error = -EFSCORRUPTED;
1252 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1253 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1254 RIGHT.rm_owner, RIGHT.rm_offset,
1256 error = xfs_btree_delete(cur, &i);
1259 if (XFS_IS_CORRUPT(mp, i != 1)) {
1260 error = -EFSCORRUPTED;
1263 error = xfs_btree_decrement(cur, 0, &i);
1266 if (XFS_IS_CORRUPT(mp, i != 1)) {
1267 error = -EFSCORRUPTED;
1270 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1271 PREV.rm_startblock, PREV.rm_blockcount,
1272 PREV.rm_owner, PREV.rm_offset,
1274 error = xfs_btree_delete(cur, &i);
1277 if (XFS_IS_CORRUPT(mp, i != 1)) {
1278 error = -EFSCORRUPTED;
1281 error = xfs_btree_decrement(cur, 0, &i);
1284 if (XFS_IS_CORRUPT(mp, i != 1)) {
1285 error = -EFSCORRUPTED;
1289 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1290 error = xfs_rmap_update(cur, &NEW);
1295 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1297 * Setting all of a previous oldext extent to newext.
1298 * The left neighbor is contiguous, the right is not.
1300 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1301 PREV.rm_startblock, PREV.rm_blockcount,
1302 PREV.rm_owner, PREV.rm_offset,
1304 error = xfs_btree_delete(cur, &i);
1307 if (XFS_IS_CORRUPT(mp, i != 1)) {
1308 error = -EFSCORRUPTED;
1311 error = xfs_btree_decrement(cur, 0, &i);
1314 if (XFS_IS_CORRUPT(mp, i != 1)) {
1315 error = -EFSCORRUPTED;
1319 NEW.rm_blockcount += PREV.rm_blockcount;
1320 error = xfs_rmap_update(cur, &NEW);
1325 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1327 * Setting all of a previous oldext extent to newext.
1328 * The right neighbor is contiguous, the left is not.
1330 error = xfs_btree_increment(cur, 0, &i);
1333 if (XFS_IS_CORRUPT(mp, i != 1)) {
1334 error = -EFSCORRUPTED;
1337 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1338 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1339 RIGHT.rm_owner, RIGHT.rm_offset,
1341 error = xfs_btree_delete(cur, &i);
1344 if (XFS_IS_CORRUPT(mp, i != 1)) {
1345 error = -EFSCORRUPTED;
1348 error = xfs_btree_decrement(cur, 0, &i);
1351 if (XFS_IS_CORRUPT(mp, i != 1)) {
1352 error = -EFSCORRUPTED;
1356 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1357 NEW.rm_flags = newext;
1358 error = xfs_rmap_update(cur, &NEW);
1363 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1365 * Setting all of a previous oldext extent to newext.
1366 * Neither the left nor right neighbors are contiguous with
1370 NEW.rm_flags = newext;
1371 error = xfs_rmap_update(cur, &NEW);
1376 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1378 * Setting the first part of a previous oldext extent to newext.
1379 * The left neighbor is contiguous.
1382 NEW.rm_offset += len;
1383 NEW.rm_startblock += len;
1384 NEW.rm_blockcount -= len;
1385 error = xfs_rmap_update(cur, &NEW);
1388 error = xfs_btree_decrement(cur, 0, &i);
1392 NEW.rm_blockcount += len;
1393 error = xfs_rmap_update(cur, &NEW);
1398 case RMAP_LEFT_FILLING:
1400 * Setting the first part of a previous oldext extent to newext.
1401 * The left neighbor is not contiguous.
1404 NEW.rm_startblock += len;
1405 NEW.rm_offset += len;
1406 NEW.rm_blockcount -= len;
1407 error = xfs_rmap_update(cur, &NEW);
1410 NEW.rm_startblock = bno;
1411 NEW.rm_owner = owner;
1412 NEW.rm_offset = offset;
1413 NEW.rm_blockcount = len;
1414 NEW.rm_flags = newext;
1415 cur->bc_rec.r = NEW;
1416 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
1417 len, owner, offset, newext);
1418 error = xfs_btree_insert(cur, &i);
1421 if (XFS_IS_CORRUPT(mp, i != 1)) {
1422 error = -EFSCORRUPTED;
1427 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1429 * Setting the last part of a previous oldext extent to newext.
1430 * The right neighbor is contiguous with the new allocation.
1433 NEW.rm_blockcount -= len;
1434 error = xfs_rmap_update(cur, &NEW);
1437 error = xfs_btree_increment(cur, 0, &i);
1441 NEW.rm_offset = offset;
1442 NEW.rm_startblock = bno;
1443 NEW.rm_blockcount += len;
1444 error = xfs_rmap_update(cur, &NEW);
1449 case RMAP_RIGHT_FILLING:
1451 * Setting the last part of a previous oldext extent to newext.
1452 * The right neighbor is not contiguous.
1455 NEW.rm_blockcount -= len;
1456 error = xfs_rmap_update(cur, &NEW);
1459 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1463 if (XFS_IS_CORRUPT(mp, i != 0)) {
1464 error = -EFSCORRUPTED;
1467 NEW.rm_startblock = bno;
1468 NEW.rm_owner = owner;
1469 NEW.rm_offset = offset;
1470 NEW.rm_blockcount = len;
1471 NEW.rm_flags = newext;
1472 cur->bc_rec.r = NEW;
1473 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
1474 len, owner, offset, newext);
1475 error = xfs_btree_insert(cur, &i);
1478 if (XFS_IS_CORRUPT(mp, i != 1)) {
1479 error = -EFSCORRUPTED;
1486 * Setting the middle part of a previous oldext extent to
1487 * newext. Contiguity is impossible here.
1488 * One extent becomes three extents.
1490 /* new right extent - oldext */
1491 NEW.rm_startblock = bno + len;
1492 NEW.rm_owner = owner;
1493 NEW.rm_offset = new_endoff;
1494 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1496 NEW.rm_flags = PREV.rm_flags;
1497 error = xfs_rmap_update(cur, &NEW);
1500 /* new left extent - oldext */
1502 NEW.rm_blockcount = offset - PREV.rm_offset;
1503 cur->bc_rec.r = NEW;
1504 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
1505 NEW.rm_startblock, NEW.rm_blockcount,
1506 NEW.rm_owner, NEW.rm_offset,
1508 error = xfs_btree_insert(cur, &i);
1511 if (XFS_IS_CORRUPT(mp, i != 1)) {
1512 error = -EFSCORRUPTED;
1516 * Reset the cursor to the position of the new extent
1517 * we are about to insert as we can't trust it after
1518 * the previous insert.
1520 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1524 if (XFS_IS_CORRUPT(mp, i != 0)) {
1525 error = -EFSCORRUPTED;
1528 /* new middle extent - newext */
1529 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1530 cur->bc_rec.r.rm_flags |= newext;
1531 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1532 owner, offset, newext);
1533 error = xfs_btree_insert(cur, &i);
1536 if (XFS_IS_CORRUPT(mp, i != 1)) {
1537 error = -EFSCORRUPTED;
1542 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1543 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1544 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1545 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1546 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1547 case RMAP_LEFT_CONTIG:
1548 case RMAP_RIGHT_CONTIG:
1550 * These cases are all impossible.
1555 trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1559 trace_xfs_rmap_convert_error(cur->bc_mp,
1560 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
1565 * Convert an unwritten extent to a real extent or vice versa. If there is no
1566 * possibility of overlapping extents, delegate to the simpler convert
1570 xfs_rmap_convert_shared(
1571 struct xfs_btree_cur *cur,
1575 const struct xfs_owner_info *oinfo)
1577 struct xfs_mount *mp = cur->bc_mp;
1578 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1579 /* left is 0, right is 1, */
1580 /* prev is 2, new is 3 */
1583 uint64_t new_endoff;
1584 unsigned int oldext;
1585 unsigned int newext;
1586 unsigned int flags = 0;
1591 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1592 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1593 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1594 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1595 new_endoff = offset + len;
1596 trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1600 * For the initial lookup, look for and exact match or the left-adjacent
1601 * record for our insertion point. This will also give us the record for
1602 * start block contiguity tests.
1604 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, oldext,
1608 if (XFS_IS_CORRUPT(mp, i != 1)) {
1609 error = -EFSCORRUPTED;
1613 ASSERT(PREV.rm_offset <= offset);
1614 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1615 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1616 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1619 * Set flags determining what part of the previous oldext allocation
1620 * extent is being replaced by a newext allocation.
1622 if (PREV.rm_offset == offset)
1623 state |= RMAP_LEFT_FILLING;
1624 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1625 state |= RMAP_RIGHT_FILLING;
1627 /* Is there a left record that abuts our range? */
1628 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1633 state |= RMAP_LEFT_VALID;
1634 if (XFS_IS_CORRUPT(mp,
1635 LEFT.rm_startblock + LEFT.rm_blockcount >
1637 error = -EFSCORRUPTED;
1640 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1641 state |= RMAP_LEFT_CONTIG;
1644 /* Is there a right record that abuts our range? */
1645 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1650 state |= RMAP_RIGHT_VALID;
1651 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1654 if (XFS_IS_CORRUPT(mp, i != 1)) {
1655 error = -EFSCORRUPTED;
1658 if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1659 error = -EFSCORRUPTED;
1662 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1663 cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
1664 RIGHT.rm_blockcount, RIGHT.rm_owner,
1665 RIGHT.rm_offset, RIGHT.rm_flags);
1666 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1667 state |= RMAP_RIGHT_CONTIG;
1670 /* check that left + prev + right is not too long */
1671 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1672 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1673 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1674 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1675 (unsigned long)LEFT.rm_blockcount + len +
1676 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1677 state &= ~RMAP_RIGHT_CONTIG;
1679 trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
1682 * Switch out based on the FILLING and CONTIG state bits.
1684 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1685 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1686 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1687 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1689 * Setting all of a previous oldext extent to newext.
1690 * The left and right neighbors are both contiguous with new.
1692 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1693 RIGHT.rm_blockcount, RIGHT.rm_owner,
1694 RIGHT.rm_offset, RIGHT.rm_flags);
1697 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1698 PREV.rm_blockcount, PREV.rm_owner,
1699 PREV.rm_offset, PREV.rm_flags);
1703 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1704 NEW.rm_blockcount, NEW.rm_owner,
1705 NEW.rm_offset, NEW.rm_flags, &i);
1708 if (XFS_IS_CORRUPT(mp, i != 1)) {
1709 error = -EFSCORRUPTED;
1712 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1713 error = xfs_rmap_update(cur, &NEW);
1718 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1720 * Setting all of a previous oldext extent to newext.
1721 * The left neighbor is contiguous, the right is not.
1723 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1724 PREV.rm_blockcount, PREV.rm_owner,
1725 PREV.rm_offset, PREV.rm_flags);
1729 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1730 NEW.rm_blockcount, NEW.rm_owner,
1731 NEW.rm_offset, NEW.rm_flags, &i);
1734 if (XFS_IS_CORRUPT(mp, i != 1)) {
1735 error = -EFSCORRUPTED;
1738 NEW.rm_blockcount += PREV.rm_blockcount;
1739 error = xfs_rmap_update(cur, &NEW);
1744 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1746 * Setting all of a previous oldext extent to newext.
1747 * The right neighbor is contiguous, the left is not.
1749 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1750 RIGHT.rm_blockcount, RIGHT.rm_owner,
1751 RIGHT.rm_offset, RIGHT.rm_flags);
1755 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1756 NEW.rm_blockcount, NEW.rm_owner,
1757 NEW.rm_offset, NEW.rm_flags, &i);
1760 if (XFS_IS_CORRUPT(mp, i != 1)) {
1761 error = -EFSCORRUPTED;
1764 NEW.rm_blockcount += RIGHT.rm_blockcount;
1765 NEW.rm_flags = RIGHT.rm_flags;
1766 error = xfs_rmap_update(cur, &NEW);
1771 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1773 * Setting all of a previous oldext extent to newext.
1774 * Neither the left nor right neighbors are contiguous with
1778 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1779 NEW.rm_blockcount, NEW.rm_owner,
1780 NEW.rm_offset, NEW.rm_flags, &i);
1783 if (XFS_IS_CORRUPT(mp, i != 1)) {
1784 error = -EFSCORRUPTED;
1787 NEW.rm_flags = newext;
1788 error = xfs_rmap_update(cur, &NEW);
1793 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1795 * Setting the first part of a previous oldext extent to newext.
1796 * The left neighbor is contiguous.
1799 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1800 NEW.rm_blockcount, NEW.rm_owner,
1801 NEW.rm_offset, NEW.rm_flags);
1804 NEW.rm_offset += len;
1805 NEW.rm_startblock += len;
1806 NEW.rm_blockcount -= len;
1807 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1808 NEW.rm_blockcount, NEW.rm_owner,
1809 NEW.rm_offset, NEW.rm_flags);
1813 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1814 NEW.rm_blockcount, NEW.rm_owner,
1815 NEW.rm_offset, NEW.rm_flags, &i);
1818 if (XFS_IS_CORRUPT(mp, i != 1)) {
1819 error = -EFSCORRUPTED;
1822 NEW.rm_blockcount += len;
1823 error = xfs_rmap_update(cur, &NEW);
1828 case RMAP_LEFT_FILLING:
1830 * Setting the first part of a previous oldext extent to newext.
1831 * The left neighbor is not contiguous.
1834 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1835 NEW.rm_blockcount, NEW.rm_owner,
1836 NEW.rm_offset, NEW.rm_flags);
1839 NEW.rm_offset += len;
1840 NEW.rm_startblock += len;
1841 NEW.rm_blockcount -= len;
1842 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1843 NEW.rm_blockcount, NEW.rm_owner,
1844 NEW.rm_offset, NEW.rm_flags);
1847 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1852 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1854 * Setting the last part of a previous oldext extent to newext.
1855 * The right neighbor is contiguous with the new allocation.
1858 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1859 NEW.rm_blockcount, NEW.rm_owner,
1860 NEW.rm_offset, NEW.rm_flags, &i);
1863 if (XFS_IS_CORRUPT(mp, i != 1)) {
1864 error = -EFSCORRUPTED;
1867 NEW.rm_blockcount = offset - NEW.rm_offset;
1868 error = xfs_rmap_update(cur, &NEW);
1872 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1873 NEW.rm_blockcount, NEW.rm_owner,
1874 NEW.rm_offset, NEW.rm_flags);
1877 NEW.rm_offset = offset;
1878 NEW.rm_startblock = bno;
1879 NEW.rm_blockcount += len;
1880 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1881 NEW.rm_blockcount, NEW.rm_owner,
1882 NEW.rm_offset, NEW.rm_flags);
1887 case RMAP_RIGHT_FILLING:
1889 * Setting the last part of a previous oldext extent to newext.
1890 * The right neighbor is not contiguous.
1893 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1894 NEW.rm_blockcount, NEW.rm_owner,
1895 NEW.rm_offset, NEW.rm_flags, &i);
1898 if (XFS_IS_CORRUPT(mp, i != 1)) {
1899 error = -EFSCORRUPTED;
1902 NEW.rm_blockcount -= len;
1903 error = xfs_rmap_update(cur, &NEW);
1906 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1913 * Setting the middle part of a previous oldext extent to
1914 * newext. Contiguity is impossible here.
1915 * One extent becomes three extents.
1917 /* new right extent - oldext */
1918 NEW.rm_startblock = bno + len;
1919 NEW.rm_owner = owner;
1920 NEW.rm_offset = new_endoff;
1921 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1923 NEW.rm_flags = PREV.rm_flags;
1924 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1925 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1929 /* new left extent - oldext */
1931 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1932 NEW.rm_blockcount, NEW.rm_owner,
1933 NEW.rm_offset, NEW.rm_flags, &i);
1936 if (XFS_IS_CORRUPT(mp, i != 1)) {
1937 error = -EFSCORRUPTED;
1940 NEW.rm_blockcount = offset - NEW.rm_offset;
1941 error = xfs_rmap_update(cur, &NEW);
1944 /* new middle extent - newext */
1945 NEW.rm_startblock = bno;
1946 NEW.rm_blockcount = len;
1947 NEW.rm_owner = owner;
1948 NEW.rm_offset = offset;
1949 NEW.rm_flags = newext;
1950 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1951 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1957 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1958 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1959 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1960 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1961 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1962 case RMAP_LEFT_CONTIG:
1963 case RMAP_RIGHT_CONTIG:
1965 * These cases are all impossible.
1970 trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1974 trace_xfs_rmap_convert_error(cur->bc_mp,
1975 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
1985 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1986 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1987 * that the prev/next records in the btree might belong to another owner.
1988 * Therefore we must use delete+insert to alter any of the key fields.
1990 * For every other situation there can only be one owner for a given extent,
1991 * so we can call the regular _free function.
1994 xfs_rmap_unmap_shared(
1995 struct xfs_btree_cur *cur,
1999 const struct xfs_owner_info *oinfo)
2001 struct xfs_mount *mp = cur->bc_mp;
2002 struct xfs_rmap_irec ltrec;
2010 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2012 flags |= XFS_RMAP_UNWRITTEN;
2013 trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
2017 * We should always have a left record because there's a static record
2018 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
2019 * will not ever be removed from the tree.
2021 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
2025 if (XFS_IS_CORRUPT(mp, i != 1)) {
2026 error = -EFSCORRUPTED;
2029 ltoff = ltrec.rm_offset;
2031 /* Make sure the extent we found covers the entire freeing range. */
2032 if (XFS_IS_CORRUPT(mp,
2033 ltrec.rm_startblock > bno ||
2034 ltrec.rm_startblock + ltrec.rm_blockcount <
2036 error = -EFSCORRUPTED;
2040 /* Make sure the owner matches what we expect to find in the tree. */
2041 if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) {
2042 error = -EFSCORRUPTED;
2046 /* Make sure the unwritten flag matches. */
2047 if (XFS_IS_CORRUPT(mp,
2048 (flags & XFS_RMAP_UNWRITTEN) !=
2049 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) {
2050 error = -EFSCORRUPTED;
2054 /* Check the offset. */
2055 if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) {
2056 error = -EFSCORRUPTED;
2059 if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) {
2060 error = -EFSCORRUPTED;
2064 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
2065 /* Exact match, simply remove the record from rmap tree. */
2066 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2067 ltrec.rm_blockcount, ltrec.rm_owner,
2068 ltrec.rm_offset, ltrec.rm_flags);
2071 } else if (ltrec.rm_startblock == bno) {
2073 * Overlap left hand side of extent: move the start, trim the
2074 * length and update the current record.
2077 * Orig: |oooooooooooooooooooo|
2078 * Freeing: |fffffffff|
2079 * Result: |rrrrrrrrrr|
2083 /* Delete prev rmap. */
2084 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2085 ltrec.rm_blockcount, ltrec.rm_owner,
2086 ltrec.rm_offset, ltrec.rm_flags);
2090 /* Add an rmap at the new offset. */
2091 ltrec.rm_startblock += len;
2092 ltrec.rm_blockcount -= len;
2093 ltrec.rm_offset += len;
2094 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
2095 ltrec.rm_blockcount, ltrec.rm_owner,
2096 ltrec.rm_offset, ltrec.rm_flags);
2099 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
2101 * Overlap right hand side of extent: trim the length and
2102 * update the current record.
2105 * Orig: |oooooooooooooooooooo|
2106 * Freeing: |fffffffff|
2107 * Result: |rrrrrrrrrr|
2110 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2111 ltrec.rm_blockcount, ltrec.rm_owner,
2112 ltrec.rm_offset, ltrec.rm_flags, &i);
2115 if (XFS_IS_CORRUPT(mp, i != 1)) {
2116 error = -EFSCORRUPTED;
2119 ltrec.rm_blockcount -= len;
2120 error = xfs_rmap_update(cur, <rec);
2125 * Overlap middle of extent: trim the length of the existing
2126 * record to the length of the new left-extent size, increment
2127 * the insertion position so we can insert a new record
2128 * containing the remaining right-extent space.
2131 * Orig: |oooooooooooooooooooo|
2132 * Freeing: |fffffffff|
2133 * Result: |rrrrr| |rrrr|
2136 xfs_extlen_t orig_len = ltrec.rm_blockcount;
2138 /* Shrink the left side of the rmap */
2139 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2140 ltrec.rm_blockcount, ltrec.rm_owner,
2141 ltrec.rm_offset, ltrec.rm_flags, &i);
2144 if (XFS_IS_CORRUPT(mp, i != 1)) {
2145 error = -EFSCORRUPTED;
2148 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
2149 error = xfs_rmap_update(cur, <rec);
2153 /* Add an rmap at the new offset */
2154 error = xfs_rmap_insert(cur, bno + len,
2155 orig_len - len - ltrec.rm_blockcount,
2156 ltrec.rm_owner, offset + len,
2162 trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2166 trace_xfs_rmap_unmap_error(cur->bc_mp,
2167 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2172 * Find an extent in the rmap btree and map it. For rmap extent types that
2173 * can overlap (data fork rmaps on reflink filesystems) we must be careful
2174 * that the prev/next records in the btree might belong to another owner.
2175 * Therefore we must use delete+insert to alter any of the key fields.
2177 * For every other situation there can only be one owner for a given extent,
2178 * so we can call the regular _alloc function.
2181 xfs_rmap_map_shared(
2182 struct xfs_btree_cur *cur,
2186 const struct xfs_owner_info *oinfo)
2188 struct xfs_mount *mp = cur->bc_mp;
2189 struct xfs_rmap_irec ltrec;
2190 struct xfs_rmap_irec gtrec;
2197 unsigned int flags = 0;
2199 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2201 flags |= XFS_RMAP_UNWRITTEN;
2202 trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
2205 /* Is there a left record that abuts our range? */
2206 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
2211 !xfs_rmap_is_mergeable(<rec, owner, flags))
2214 /* Is there a right record that abuts our range? */
2215 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
2220 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
2223 if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
2224 error = -EFSCORRUPTED;
2227 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
2228 cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
2229 gtrec.rm_blockcount, gtrec.rm_owner,
2230 gtrec.rm_offset, gtrec.rm_flags);
2232 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
2237 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
2238 ltrec.rm_offset + ltrec.rm_blockcount == offset) {
2240 * Left edge contiguous, merge into left record.
2244 * adding: |aaaaaaaaa|
2245 * result: |rrrrrrrrrrrrrrrrrrr|
2248 ltrec.rm_blockcount += len;
2250 bno + len == gtrec.rm_startblock &&
2251 offset + len == gtrec.rm_offset) {
2253 * Right edge also contiguous, delete right record
2254 * and merge into left record.
2256 * ltbno ltlen gtbno gtlen
2257 * orig: |ooooooooo| |ooooooooo|
2258 * adding: |aaaaaaaaa|
2259 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
2261 ltrec.rm_blockcount += gtrec.rm_blockcount;
2262 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2263 gtrec.rm_blockcount, gtrec.rm_owner,
2264 gtrec.rm_offset, gtrec.rm_flags);
2269 /* Point the cursor back to the left record and update. */
2270 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2271 ltrec.rm_blockcount, ltrec.rm_owner,
2272 ltrec.rm_offset, ltrec.rm_flags, &i);
2275 if (XFS_IS_CORRUPT(mp, i != 1)) {
2276 error = -EFSCORRUPTED;
2280 error = xfs_rmap_update(cur, <rec);
2283 } else if (have_gt &&
2284 bno + len == gtrec.rm_startblock &&
2285 offset + len == gtrec.rm_offset) {
2287 * Right edge contiguous, merge into right record.
2291 * adding: |aaaaaaaaa|
2292 * Result: |rrrrrrrrrrrrrrrrrrr|
2295 /* Delete the old record. */
2296 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2297 gtrec.rm_blockcount, gtrec.rm_owner,
2298 gtrec.rm_offset, gtrec.rm_flags);
2302 /* Move the start and re-add it. */
2303 gtrec.rm_startblock = bno;
2304 gtrec.rm_blockcount += len;
2305 gtrec.rm_offset = offset;
2306 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2307 gtrec.rm_blockcount, gtrec.rm_owner,
2308 gtrec.rm_offset, gtrec.rm_flags);
2313 * No contiguous edge with identical owner, insert
2314 * new record at current cursor position.
2316 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2321 trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2325 trace_xfs_rmap_map_error(cur->bc_mp,
2326 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2330 /* Insert a raw rmap into the rmapbt. */
2333 struct xfs_btree_cur *cur,
2334 struct xfs_rmap_irec *rmap)
2336 struct xfs_owner_info oinfo;
2338 oinfo.oi_owner = rmap->rm_owner;
2339 oinfo.oi_offset = rmap->rm_offset;
2341 if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
2342 oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
2343 if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
2344 oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
2346 if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2347 return xfs_rmap_map(cur, rmap->rm_startblock,
2348 rmap->rm_blockcount,
2349 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2352 return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2353 rmap->rm_blockcount,
2354 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2358 struct xfs_rmap_query_range_info {
2359 xfs_rmap_query_range_fn fn;
2363 /* Format btree record and pass to our callback. */
2365 xfs_rmap_query_range_helper(
2366 struct xfs_btree_cur *cur,
2367 const union xfs_btree_rec *rec,
2370 struct xfs_rmap_query_range_info *query = priv;
2371 struct xfs_rmap_irec irec;
2374 fa = xfs_rmap_btrec_to_irec(rec, &irec);
2376 fa = xfs_rmap_check_irec(cur, &irec);
2378 return xfs_rmap_complain_bad_rec(cur, fa, &irec);
2380 return query->fn(cur, &irec, query->priv);
2383 /* Find all rmaps between two keys. */
2385 xfs_rmap_query_range(
2386 struct xfs_btree_cur *cur,
2387 const struct xfs_rmap_irec *low_rec,
2388 const struct xfs_rmap_irec *high_rec,
2389 xfs_rmap_query_range_fn fn,
2392 union xfs_btree_irec low_brec = { .r = *low_rec };
2393 union xfs_btree_irec high_brec = { .r = *high_rec };
2394 struct xfs_rmap_query_range_info query = { .priv = priv, .fn = fn };
2396 return xfs_btree_query_range(cur, &low_brec, &high_brec,
2397 xfs_rmap_query_range_helper, &query);
2400 /* Find all rmaps. */
2403 struct xfs_btree_cur *cur,
2404 xfs_rmap_query_range_fn fn,
2407 struct xfs_rmap_query_range_info query;
2411 return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2414 /* Clean up after calling xfs_rmap_finish_one. */
2416 xfs_rmap_finish_one_cleanup(
2417 struct xfs_trans *tp,
2418 struct xfs_btree_cur *rcur,
2421 struct xfs_buf *agbp;
2425 agbp = rcur->bc_ag.agbp;
2426 xfs_btree_del_cursor(rcur, error);
2428 xfs_trans_brelse(tp, agbp);
2432 * Process one of the deferred rmap operations. We pass back the
2433 * btree cursor to maintain our lock on the rmapbt between calls.
2434 * This saves time and eliminates a buffer deadlock between the
2435 * superblock and the AGF because we'll always grab them in the same
2439 xfs_rmap_finish_one(
2440 struct xfs_trans *tp,
2441 struct xfs_rmap_intent *ri,
2442 struct xfs_btree_cur **pcur)
2444 struct xfs_mount *mp = tp->t_mountp;
2445 struct xfs_btree_cur *rcur;
2446 struct xfs_buf *agbp = NULL;
2448 struct xfs_owner_info oinfo;
2452 bno = XFS_FSB_TO_AGBNO(mp, ri->ri_bmap.br_startblock);
2454 trace_xfs_rmap_deferred(mp, ri->ri_pag->pag_agno, ri->ri_type, bno,
2455 ri->ri_owner, ri->ri_whichfork,
2456 ri->ri_bmap.br_startoff, ri->ri_bmap.br_blockcount,
2457 ri->ri_bmap.br_state);
2459 if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE))
2463 * If we haven't gotten a cursor or the cursor AG doesn't match
2464 * the startblock, get one now.
2467 if (rcur != NULL && rcur->bc_ag.pag != ri->ri_pag) {
2468 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2474 * Refresh the freelist before we start changing the
2475 * rmapbt, because a shape change could cause us to
2478 error = xfs_free_extent_fix_freelist(tp, ri->ri_pag, &agbp);
2481 if (XFS_IS_CORRUPT(tp->t_mountp, !agbp))
2482 return -EFSCORRUPTED;
2484 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, ri->ri_pag);
2488 xfs_rmap_ino_owner(&oinfo, ri->ri_owner, ri->ri_whichfork,
2489 ri->ri_bmap.br_startoff);
2490 unwritten = ri->ri_bmap.br_state == XFS_EXT_UNWRITTEN;
2491 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, ri->ri_bmap.br_startblock);
2493 switch (ri->ri_type) {
2494 case XFS_RMAP_ALLOC:
2496 error = xfs_rmap_map(rcur, bno, ri->ri_bmap.br_blockcount,
2499 case XFS_RMAP_MAP_SHARED:
2500 error = xfs_rmap_map_shared(rcur, bno,
2501 ri->ri_bmap.br_blockcount, unwritten, &oinfo);
2504 case XFS_RMAP_UNMAP:
2505 error = xfs_rmap_unmap(rcur, bno, ri->ri_bmap.br_blockcount,
2508 case XFS_RMAP_UNMAP_SHARED:
2509 error = xfs_rmap_unmap_shared(rcur, bno,
2510 ri->ri_bmap.br_blockcount, unwritten, &oinfo);
2512 case XFS_RMAP_CONVERT:
2513 error = xfs_rmap_convert(rcur, bno, ri->ri_bmap.br_blockcount,
2514 !unwritten, &oinfo);
2516 case XFS_RMAP_CONVERT_SHARED:
2517 error = xfs_rmap_convert_shared(rcur, bno,
2518 ri->ri_bmap.br_blockcount, !unwritten, &oinfo);
2522 error = -EFSCORRUPTED;
2529 * Don't defer an rmap if we aren't an rmap filesystem.
2532 xfs_rmap_update_is_needed(
2533 struct xfs_mount *mp,
2536 return xfs_has_rmapbt(mp) && whichfork != XFS_COW_FORK;
2540 * Record a rmap intent; the list is kept sorted first by AG and then by
2545 struct xfs_trans *tp,
2546 enum xfs_rmap_intent_type type,
2549 struct xfs_bmbt_irec *bmap)
2551 struct xfs_rmap_intent *ri;
2553 trace_xfs_rmap_defer(tp->t_mountp,
2554 XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock),
2556 XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock),
2559 bmap->br_blockcount,
2562 ri = kmem_cache_alloc(xfs_rmap_intent_cache, GFP_NOFS | __GFP_NOFAIL);
2563 INIT_LIST_HEAD(&ri->ri_list);
2565 ri->ri_owner = owner;
2566 ri->ri_whichfork = whichfork;
2567 ri->ri_bmap = *bmap;
2569 xfs_rmap_update_get_group(tp->t_mountp, ri);
2570 xfs_defer_add(tp, &ri->ri_list, &xfs_rmap_update_defer_type);
2573 /* Map an extent into a file. */
2575 xfs_rmap_map_extent(
2576 struct xfs_trans *tp,
2577 struct xfs_inode *ip,
2579 struct xfs_bmbt_irec *PREV)
2581 enum xfs_rmap_intent_type type = XFS_RMAP_MAP;
2583 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2586 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2587 type = XFS_RMAP_MAP_SHARED;
2589 __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2592 /* Unmap an extent out of a file. */
2594 xfs_rmap_unmap_extent(
2595 struct xfs_trans *tp,
2596 struct xfs_inode *ip,
2598 struct xfs_bmbt_irec *PREV)
2600 enum xfs_rmap_intent_type type = XFS_RMAP_UNMAP;
2602 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2605 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2606 type = XFS_RMAP_UNMAP_SHARED;
2608 __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2612 * Convert a data fork extent from unwritten to real or vice versa.
2614 * Note that tp can be NULL here as no transaction is used for COW fork
2615 * unwritten conversion.
2618 xfs_rmap_convert_extent(
2619 struct xfs_mount *mp,
2620 struct xfs_trans *tp,
2621 struct xfs_inode *ip,
2623 struct xfs_bmbt_irec *PREV)
2625 enum xfs_rmap_intent_type type = XFS_RMAP_CONVERT;
2627 if (!xfs_rmap_update_is_needed(mp, whichfork))
2630 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2631 type = XFS_RMAP_CONVERT_SHARED;
2633 __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2636 /* Schedule the creation of an rmap for non-file data. */
2638 xfs_rmap_alloc_extent(
2639 struct xfs_trans *tp,
2640 xfs_agnumber_t agno,
2645 struct xfs_bmbt_irec bmap;
2647 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2650 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2651 bmap.br_blockcount = len;
2652 bmap.br_startoff = 0;
2653 bmap.br_state = XFS_EXT_NORM;
2655 __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
2658 /* Schedule the deletion of an rmap for non-file data. */
2660 xfs_rmap_free_extent(
2661 struct xfs_trans *tp,
2662 xfs_agnumber_t agno,
2667 struct xfs_bmbt_irec bmap;
2669 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2672 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2673 bmap.br_blockcount = len;
2674 bmap.br_startoff = 0;
2675 bmap.br_state = XFS_EXT_NORM;
2677 __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
2680 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2683 const struct xfs_rmap_irec *a,
2684 const struct xfs_rmap_irec *b)
2689 oa = xfs_rmap_irec_offset_pack(a);
2690 ob = xfs_rmap_irec_offset_pack(b);
2692 if (a->rm_startblock < b->rm_startblock)
2694 else if (a->rm_startblock > b->rm_startblock)
2696 else if (a->rm_owner < b->rm_owner)
2698 else if (a->rm_owner > b->rm_owner)
2709 * Scan the physical storage part of the keyspace of the reverse mapping index
2710 * and tell us if the area has no records, is fully mapped by records, or is
2714 xfs_rmap_has_records(
2715 struct xfs_btree_cur *cur,
2718 enum xbtree_recpacking *outcome)
2720 union xfs_btree_key mask = {
2721 .rmap.rm_startblock = cpu_to_be32(-1U),
2723 union xfs_btree_irec low;
2724 union xfs_btree_irec high;
2726 memset(&low, 0, sizeof(low));
2727 low.r.rm_startblock = bno;
2728 memset(&high, 0xFF, sizeof(high));
2729 high.r.rm_startblock = bno + len - 1;
2731 return xfs_btree_has_records(cur, &low, &high, &mask, outcome);
2734 struct xfs_rmap_ownercount {
2735 /* Owner that we're looking for. */
2736 struct xfs_rmap_irec good;
2738 /* rmap search keys */
2739 struct xfs_rmap_irec low;
2740 struct xfs_rmap_irec high;
2742 struct xfs_rmap_matches *results;
2744 /* Stop early if we find a nonmatch? */
2745 bool stop_on_nonmatch;
2748 /* Does this rmap represent space that can have multiple owners? */
2751 struct xfs_mount *mp,
2752 const struct xfs_rmap_irec *rmap)
2754 if (!xfs_has_reflink(mp))
2756 if (XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2758 if (rmap->rm_flags & (XFS_RMAP_ATTR_FORK |
2759 XFS_RMAP_BMBT_BLOCK))
2765 xfs_rmap_ownercount_init(
2766 struct xfs_rmap_ownercount *roc,
2769 const struct xfs_owner_info *oinfo,
2770 struct xfs_rmap_matches *results)
2772 memset(roc, 0, sizeof(*roc));
2773 roc->results = results;
2775 roc->low.rm_startblock = bno;
2776 memset(&roc->high, 0xFF, sizeof(roc->high));
2777 roc->high.rm_startblock = bno + len - 1;
2779 memset(results, 0, sizeof(*results));
2780 roc->good.rm_startblock = bno;
2781 roc->good.rm_blockcount = len;
2782 roc->good.rm_owner = oinfo->oi_owner;
2783 roc->good.rm_offset = oinfo->oi_offset;
2784 if (oinfo->oi_flags & XFS_OWNER_INFO_ATTR_FORK)
2785 roc->good.rm_flags |= XFS_RMAP_ATTR_FORK;
2786 if (oinfo->oi_flags & XFS_OWNER_INFO_BMBT_BLOCK)
2787 roc->good.rm_flags |= XFS_RMAP_BMBT_BLOCK;
2790 /* Figure out if this is a match for the owner. */
2792 xfs_rmap_count_owners_helper(
2793 struct xfs_btree_cur *cur,
2794 const struct xfs_rmap_irec *rec,
2797 struct xfs_rmap_ownercount *roc = priv;
2798 struct xfs_rmap_irec check = *rec;
2799 unsigned int keyflags;
2803 filedata = !XFS_RMAP_NON_INODE_OWNER(check.rm_owner) &&
2804 !(check.rm_flags & XFS_RMAP_BMBT_BLOCK);
2806 /* Trim the part of check that comes before the comparison range. */
2807 delta = (int64_t)roc->good.rm_startblock - check.rm_startblock;
2809 check.rm_startblock += delta;
2810 check.rm_blockcount -= delta;
2812 check.rm_offset += delta;
2815 /* Trim the part of check that comes after the comparison range. */
2816 delta = (check.rm_startblock + check.rm_blockcount) -
2817 (roc->good.rm_startblock + roc->good.rm_blockcount);
2819 check.rm_blockcount -= delta;
2821 /* Don't care about unwritten status for establishing ownership. */
2822 keyflags = check.rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK);
2824 if (check.rm_startblock == roc->good.rm_startblock &&
2825 check.rm_blockcount == roc->good.rm_blockcount &&
2826 check.rm_owner == roc->good.rm_owner &&
2827 check.rm_offset == roc->good.rm_offset &&
2828 keyflags == roc->good.rm_flags) {
2829 roc->results->matches++;
2831 roc->results->non_owner_matches++;
2832 if (xfs_rmap_shareable(cur->bc_mp, &roc->good) ^
2833 xfs_rmap_shareable(cur->bc_mp, &check))
2834 roc->results->bad_non_owner_matches++;
2837 if (roc->results->non_owner_matches && roc->stop_on_nonmatch)
2843 /* Count the number of owners and non-owners of this range of blocks. */
2845 xfs_rmap_count_owners(
2846 struct xfs_btree_cur *cur,
2849 const struct xfs_owner_info *oinfo,
2850 struct xfs_rmap_matches *results)
2852 struct xfs_rmap_ownercount roc;
2855 xfs_rmap_ownercount_init(&roc, bno, len, oinfo, results);
2856 error = xfs_rmap_query_range(cur, &roc.low, &roc.high,
2857 xfs_rmap_count_owners_helper, &roc);
2862 * There can't be any non-owner rmaps that conflict with the given
2863 * owner if we didn't find any rmaps matching the owner.
2865 if (!results->matches)
2866 results->bad_non_owner_matches = 0;
2872 * Given an extent and some owner info, can we find records overlapping
2873 * the extent whose owner info does not match the given owner?
2876 xfs_rmap_has_other_keys(
2877 struct xfs_btree_cur *cur,
2880 const struct xfs_owner_info *oinfo,
2883 struct xfs_rmap_matches res;
2884 struct xfs_rmap_ownercount roc;
2887 xfs_rmap_ownercount_init(&roc, bno, len, oinfo, &res);
2888 roc.stop_on_nonmatch = true;
2890 error = xfs_rmap_query_range(cur, &roc.low, &roc.high,
2891 xfs_rmap_count_owners_helper, &roc);
2892 if (error == -ECANCELED) {
2903 const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
2904 .oi_owner = XFS_RMAP_OWN_NULL,
2906 const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
2907 .oi_owner = XFS_RMAP_OWN_UNKNOWN,
2909 const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
2910 .oi_owner = XFS_RMAP_OWN_FS,
2912 const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
2913 .oi_owner = XFS_RMAP_OWN_LOG,
2915 const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
2916 .oi_owner = XFS_RMAP_OWN_AG,
2918 const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
2919 .oi_owner = XFS_RMAP_OWN_INOBT,
2921 const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
2922 .oi_owner = XFS_RMAP_OWN_INODES,
2924 const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
2925 .oi_owner = XFS_RMAP_OWN_REFC,
2927 const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
2928 .oi_owner = XFS_RMAP_OWN_COW,
2932 xfs_rmap_intent_init_cache(void)
2934 xfs_rmap_intent_cache = kmem_cache_create("xfs_rmap_intent",
2935 sizeof(struct xfs_rmap_intent),
2938 return xfs_rmap_intent_cache != NULL ? 0 : -ENOMEM;
2942 xfs_rmap_intent_destroy_cache(void)
2944 kmem_cache_destroy(xfs_rmap_intent_cache);
2945 xfs_rmap_intent_cache = NULL;