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),
209 * Get the data from the pointed-to record.
213 struct xfs_btree_cur *cur,
214 struct xfs_rmap_irec *irec,
217 struct xfs_mount *mp = cur->bc_mp;
218 struct xfs_perag *pag = cur->bc_ag.pag;
219 union xfs_btree_rec *rec;
222 error = xfs_btree_get_rec(cur, &rec, stat);
226 if (xfs_rmap_btrec_to_irec(rec, irec))
229 if (irec->rm_blockcount == 0)
231 if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
232 if (irec->rm_owner != XFS_RMAP_OWN_FS)
234 if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
237 /* check for valid extent range, including overflow */
238 if (!xfs_verify_agbext(pag, irec->rm_startblock,
239 irec->rm_blockcount))
243 if (!(xfs_verify_ino(mp, irec->rm_owner) ||
244 (irec->rm_owner <= XFS_RMAP_OWN_FS &&
245 irec->rm_owner >= XFS_RMAP_OWN_MIN)))
251 "Reverse Mapping BTree record corruption in AG %d detected!",
254 "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
255 irec->rm_owner, irec->rm_flags, irec->rm_startblock,
256 irec->rm_blockcount);
257 return -EFSCORRUPTED;
260 struct xfs_find_left_neighbor_info {
261 struct xfs_rmap_irec high;
262 struct xfs_rmap_irec *irec;
265 /* For each rmap given, figure out if it matches the key we want. */
267 xfs_rmap_find_left_neighbor_helper(
268 struct xfs_btree_cur *cur,
269 const struct xfs_rmap_irec *rec,
272 struct xfs_find_left_neighbor_info *info = priv;
274 trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
275 cur->bc_ag.pag->pag_agno, rec->rm_startblock,
276 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
279 if (rec->rm_owner != info->high.rm_owner)
281 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
282 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
283 rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
291 * Find the record to the left of the given extent, being careful only to
292 * return a match with the same owner and adjacent physical and logical
296 xfs_rmap_find_left_neighbor(
297 struct xfs_btree_cur *cur,
302 struct xfs_rmap_irec *irec,
305 struct xfs_find_left_neighbor_info info;
312 info.high.rm_startblock = bno - 1;
313 info.high.rm_owner = owner;
314 if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
315 !(flags & XFS_RMAP_BMBT_BLOCK)) {
318 info.high.rm_offset = offset - 1;
320 info.high.rm_offset = 0;
321 info.high.rm_flags = flags;
322 info.high.rm_blockcount = 0;
325 trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
326 cur->bc_ag.pag->pag_agno, bno, 0, owner, offset, flags);
329 * Historically, we always used the range query to walk every reverse
330 * mapping that could possibly overlap the key that the caller asked
331 * for, and filter out the ones that don't. That is very slow when
332 * there are a lot of records.
334 * However, there are two scenarios where the classic btree search can
335 * produce correct results -- if the index contains a record that is an
336 * exact match for the lookup key; and if there are no other records
337 * between the record we want and the key we supplied.
339 * As an optimization, try a non-overlapped lookup first. This makes
340 * extent conversion and remap operations run a bit faster if the
341 * physical extents aren't being shared. If we don't find what we
342 * want, we fall back to the overlapped query.
344 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
349 error = xfs_rmap_find_left_neighbor_helper(cur, irec, &info);
351 error = xfs_rmap_query_range(cur, &info.high, &info.high,
352 xfs_rmap_find_left_neighbor_helper, &info);
353 if (error != -ECANCELED)
357 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
358 cur->bc_ag.pag->pag_agno, irec->rm_startblock,
359 irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
364 /* For each rmap given, figure out if it matches the key we want. */
366 xfs_rmap_lookup_le_range_helper(
367 struct xfs_btree_cur *cur,
368 const struct xfs_rmap_irec *rec,
371 struct xfs_find_left_neighbor_info *info = priv;
373 trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
374 cur->bc_ag.pag->pag_agno, rec->rm_startblock,
375 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
378 if (rec->rm_owner != info->high.rm_owner)
380 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
381 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
382 (rec->rm_offset > info->high.rm_offset ||
383 rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
391 * Find the record to the left of the given extent, being careful only to
392 * return a match with the same owner and overlapping physical and logical
393 * block ranges. This is the overlapping-interval version of
394 * xfs_rmap_lookup_le.
397 xfs_rmap_lookup_le_range(
398 struct xfs_btree_cur *cur,
403 struct xfs_rmap_irec *irec,
406 struct xfs_find_left_neighbor_info info;
410 info.high.rm_startblock = bno;
411 info.high.rm_owner = owner;
412 if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
413 info.high.rm_offset = offset;
415 info.high.rm_offset = 0;
416 info.high.rm_flags = flags;
417 info.high.rm_blockcount = 0;
421 trace_xfs_rmap_lookup_le_range(cur->bc_mp, cur->bc_ag.pag->pag_agno,
422 bno, 0, owner, offset, flags);
425 * Historically, we always used the range query to walk every reverse
426 * mapping that could possibly overlap the key that the caller asked
427 * for, and filter out the ones that don't. That is very slow when
428 * there are a lot of records.
430 * However, there are two scenarios where the classic btree search can
431 * produce correct results -- if the index contains a record that is an
432 * exact match for the lookup key; and if there are no other records
433 * between the record we want and the key we supplied.
435 * As an optimization, try a non-overlapped lookup first. This makes
436 * scrub run much faster on most filesystems because bmbt records are
437 * usually an exact match for rmap records. If we don't find what we
438 * want, we fall back to the overlapped query.
440 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
445 error = xfs_rmap_lookup_le_range_helper(cur, irec, &info);
447 error = xfs_rmap_query_range(cur, &info.high, &info.high,
448 xfs_rmap_lookup_le_range_helper, &info);
449 if (error != -ECANCELED)
453 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
454 cur->bc_ag.pag->pag_agno, irec->rm_startblock,
455 irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
461 * Perform all the relevant owner checks for a removal op. If we're doing an
462 * unknown-owner removal then we have no owner information to check.
465 xfs_rmap_free_check_owner(
466 struct xfs_mount *mp,
468 struct xfs_rmap_irec *rec,
476 if (owner == XFS_RMAP_OWN_UNKNOWN)
479 /* Make sure the unwritten flag matches. */
480 if (XFS_IS_CORRUPT(mp,
481 (flags & XFS_RMAP_UNWRITTEN) !=
482 (rec->rm_flags & XFS_RMAP_UNWRITTEN))) {
483 error = -EFSCORRUPTED;
487 /* Make sure the owner matches what we expect to find in the tree. */
488 if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) {
489 error = -EFSCORRUPTED;
493 /* Check the offset, if necessary. */
494 if (XFS_RMAP_NON_INODE_OWNER(owner))
497 if (flags & XFS_RMAP_BMBT_BLOCK) {
498 if (XFS_IS_CORRUPT(mp,
499 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) {
500 error = -EFSCORRUPTED;
504 if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) {
505 error = -EFSCORRUPTED;
508 if (XFS_IS_CORRUPT(mp,
509 offset + len > ltoff + rec->rm_blockcount)) {
510 error = -EFSCORRUPTED;
520 * Find the extent in the rmap btree and remove it.
522 * The record we find should always be an exact match for the extent that we're
523 * looking for, since we insert them into the btree without modification.
525 * Special Case #1: when growing the filesystem, we "free" an extent when
526 * growing the last AG. This extent is new space and so it is not tracked as
527 * used space in the btree. The growfs code will pass in an owner of
528 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
529 * extent. We verify that - the extent lookup result in a record that does not
532 * Special Case #2: EFIs do not record the owner of the extent, so when
533 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
534 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
535 * corruption checks during log recovery.
539 struct xfs_btree_cur *cur,
543 const struct xfs_owner_info *oinfo)
545 struct xfs_mount *mp = cur->bc_mp;
546 struct xfs_rmap_irec ltrec;
555 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
556 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
557 (flags & XFS_RMAP_BMBT_BLOCK);
559 flags |= XFS_RMAP_UNWRITTEN;
560 trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
564 * We should always have a left record because there's a static record
565 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
566 * will not ever be removed from the tree.
568 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, <rec, &i);
571 if (XFS_IS_CORRUPT(mp, i != 1)) {
572 error = -EFSCORRUPTED;
576 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
577 cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
578 ltrec.rm_blockcount, ltrec.rm_owner,
579 ltrec.rm_offset, ltrec.rm_flags);
580 ltoff = ltrec.rm_offset;
583 * For growfs, the incoming extent must be beyond the left record we
584 * just found as it is new space and won't be used by anyone. This is
585 * just a corruption check as we don't actually do anything with this
586 * extent. Note that we need to use >= instead of > because it might
587 * be the case that the "left" extent goes all the way to EOFS.
589 if (owner == XFS_RMAP_OWN_NULL) {
590 if (XFS_IS_CORRUPT(mp,
592 ltrec.rm_startblock + ltrec.rm_blockcount)) {
593 error = -EFSCORRUPTED;
600 * If we're doing an unknown-owner removal for EFI recovery, we expect
601 * to find the full range in the rmapbt or nothing at all. If we
602 * don't find any rmaps overlapping either end of the range, we're
603 * done. Hopefully this means that the EFI creator already queued
604 * (and finished) a RUI to remove the rmap.
606 if (owner == XFS_RMAP_OWN_UNKNOWN &&
607 ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
608 struct xfs_rmap_irec rtrec;
610 error = xfs_btree_increment(cur, 0, &i);
615 error = xfs_rmap_get_rec(cur, &rtrec, &i);
618 if (XFS_IS_CORRUPT(mp, i != 1)) {
619 error = -EFSCORRUPTED;
622 if (rtrec.rm_startblock >= bno + len)
626 /* Make sure the extent we found covers the entire freeing range. */
627 if (XFS_IS_CORRUPT(mp,
628 ltrec.rm_startblock > bno ||
629 ltrec.rm_startblock + ltrec.rm_blockcount <
631 error = -EFSCORRUPTED;
635 /* Check owner information. */
636 error = xfs_rmap_free_check_owner(mp, ltoff, <rec, len, owner,
641 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
642 /* exact match, simply remove the record from rmap tree */
643 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
644 ltrec.rm_startblock, ltrec.rm_blockcount,
645 ltrec.rm_owner, ltrec.rm_offset,
647 error = xfs_btree_delete(cur, &i);
650 if (XFS_IS_CORRUPT(mp, i != 1)) {
651 error = -EFSCORRUPTED;
654 } else if (ltrec.rm_startblock == bno) {
656 * overlap left hand side of extent: move the start, trim the
657 * length and update the current record.
660 * Orig: |oooooooooooooooooooo|
661 * Freeing: |fffffffff|
662 * Result: |rrrrrrrrrr|
665 ltrec.rm_startblock += len;
666 ltrec.rm_blockcount -= len;
668 ltrec.rm_offset += len;
669 error = xfs_rmap_update(cur, <rec);
672 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
674 * overlap right hand side of extent: trim the length and update
675 * the current record.
678 * Orig: |oooooooooooooooooooo|
679 * Freeing: |fffffffff|
680 * Result: |rrrrrrrrrr|
683 ltrec.rm_blockcount -= len;
684 error = xfs_rmap_update(cur, <rec);
690 * overlap middle of extent: trim the length of the existing
691 * record to the length of the new left-extent size, increment
692 * the insertion position so we can insert a new record
693 * containing the remaining right-extent space.
696 * Orig: |oooooooooooooooooooo|
697 * Freeing: |fffffffff|
698 * Result: |rrrrr| |rrrr|
701 xfs_extlen_t orig_len = ltrec.rm_blockcount;
703 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
704 error = xfs_rmap_update(cur, <rec);
708 error = xfs_btree_increment(cur, 0, &i);
712 cur->bc_rec.r.rm_startblock = bno + len;
713 cur->bc_rec.r.rm_blockcount = orig_len - len -
715 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
717 cur->bc_rec.r.rm_offset = 0;
719 cur->bc_rec.r.rm_offset = offset + len;
720 cur->bc_rec.r.rm_flags = flags;
721 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
722 cur->bc_rec.r.rm_startblock,
723 cur->bc_rec.r.rm_blockcount,
724 cur->bc_rec.r.rm_owner,
725 cur->bc_rec.r.rm_offset,
726 cur->bc_rec.r.rm_flags);
727 error = xfs_btree_insert(cur, &i);
733 trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
737 trace_xfs_rmap_unmap_error(mp, cur->bc_ag.pag->pag_agno,
743 * Remove a reference to an extent in the rmap btree.
747 struct xfs_trans *tp,
748 struct xfs_buf *agbp,
749 struct xfs_perag *pag,
752 const struct xfs_owner_info *oinfo)
754 struct xfs_mount *mp = tp->t_mountp;
755 struct xfs_btree_cur *cur;
758 if (!xfs_has_rmapbt(mp))
761 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
763 error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
765 xfs_btree_del_cursor(cur, error);
770 * A mergeable rmap must have the same owner and the same values for
771 * the unwritten, attr_fork, and bmbt flags. The startblock and
772 * offset are checked separately.
775 xfs_rmap_is_mergeable(
776 struct xfs_rmap_irec *irec,
780 if (irec->rm_owner == XFS_RMAP_OWN_NULL)
782 if (irec->rm_owner != owner)
784 if ((flags & XFS_RMAP_UNWRITTEN) ^
785 (irec->rm_flags & XFS_RMAP_UNWRITTEN))
787 if ((flags & XFS_RMAP_ATTR_FORK) ^
788 (irec->rm_flags & XFS_RMAP_ATTR_FORK))
790 if ((flags & XFS_RMAP_BMBT_BLOCK) ^
791 (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
797 * When we allocate a new block, the first thing we do is add a reference to
798 * the extent in the rmap btree. This takes the form of a [agbno, length,
799 * owner, offset] record. Flags are encoded in the high bits of the offset
804 struct xfs_btree_cur *cur,
808 const struct xfs_owner_info *oinfo)
810 struct xfs_mount *mp = cur->bc_mp;
811 struct xfs_rmap_irec ltrec;
812 struct xfs_rmap_irec gtrec;
819 unsigned int flags = 0;
822 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
824 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
825 (flags & XFS_RMAP_BMBT_BLOCK);
827 flags |= XFS_RMAP_UNWRITTEN;
828 trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
830 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
833 * For the initial lookup, look for an exact match or the left-adjacent
834 * record for our insertion point. This will also give us the record for
835 * start block contiguity tests.
837 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, <rec,
842 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
843 cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
844 ltrec.rm_blockcount, ltrec.rm_owner,
845 ltrec.rm_offset, ltrec.rm_flags);
847 if (!xfs_rmap_is_mergeable(<rec, owner, flags))
851 if (XFS_IS_CORRUPT(mp,
853 ltrec.rm_startblock + ltrec.rm_blockcount > bno)) {
854 error = -EFSCORRUPTED;
859 * Increment the cursor to see if we have a right-adjacent record to our
860 * insertion point. This will give us the record for end block
863 error = xfs_btree_increment(cur, 0, &have_gt);
867 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
870 if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
871 error = -EFSCORRUPTED;
874 if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) {
875 error = -EFSCORRUPTED;
878 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
879 cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
880 gtrec.rm_blockcount, gtrec.rm_owner,
881 gtrec.rm_offset, gtrec.rm_flags);
882 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
887 * Note: cursor currently points one record to the right of ltrec, even
888 * if there is no record in the tree to the right.
891 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
892 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
894 * left edge contiguous, merge into left record.
898 * adding: |aaaaaaaaa|
899 * result: |rrrrrrrrrrrrrrrrrrr|
902 ltrec.rm_blockcount += len;
904 bno + len == gtrec.rm_startblock &&
905 (ignore_off || offset + len == gtrec.rm_offset) &&
906 (unsigned long)ltrec.rm_blockcount + len +
907 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
909 * right edge also contiguous, delete right record
910 * and merge into left record.
912 * ltbno ltlen gtbno gtlen
913 * orig: |ooooooooo| |ooooooooo|
914 * adding: |aaaaaaaaa|
915 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
917 ltrec.rm_blockcount += gtrec.rm_blockcount;
918 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
924 error = xfs_btree_delete(cur, &i);
927 if (XFS_IS_CORRUPT(mp, i != 1)) {
928 error = -EFSCORRUPTED;
933 /* point the cursor back to the left record and update */
934 error = xfs_btree_decrement(cur, 0, &have_gt);
937 error = xfs_rmap_update(cur, <rec);
940 } else if (have_gt &&
941 bno + len == gtrec.rm_startblock &&
942 (ignore_off || offset + len == gtrec.rm_offset)) {
944 * right edge contiguous, merge into right record.
948 * adding: |aaaaaaaaa|
949 * Result: |rrrrrrrrrrrrrrrrrrr|
952 gtrec.rm_startblock = bno;
953 gtrec.rm_blockcount += len;
955 gtrec.rm_offset = offset;
956 error = xfs_rmap_update(cur, >rec);
961 * no contiguous edge with identical owner, insert
962 * new record at current cursor position.
964 cur->bc_rec.r.rm_startblock = bno;
965 cur->bc_rec.r.rm_blockcount = len;
966 cur->bc_rec.r.rm_owner = owner;
967 cur->bc_rec.r.rm_offset = offset;
968 cur->bc_rec.r.rm_flags = flags;
969 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
970 owner, offset, flags);
971 error = xfs_btree_insert(cur, &i);
974 if (XFS_IS_CORRUPT(mp, i != 1)) {
975 error = -EFSCORRUPTED;
980 trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
984 trace_xfs_rmap_map_error(mp, cur->bc_ag.pag->pag_agno,
990 * Add a reference to an extent in the rmap btree.
994 struct xfs_trans *tp,
995 struct xfs_buf *agbp,
996 struct xfs_perag *pag,
999 const struct xfs_owner_info *oinfo)
1001 struct xfs_mount *mp = tp->t_mountp;
1002 struct xfs_btree_cur *cur;
1005 if (!xfs_has_rmapbt(mp))
1008 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
1009 error = xfs_rmap_map(cur, bno, len, false, oinfo);
1011 xfs_btree_del_cursor(cur, error);
1015 #define RMAP_LEFT_CONTIG (1 << 0)
1016 #define RMAP_RIGHT_CONTIG (1 << 1)
1017 #define RMAP_LEFT_FILLING (1 << 2)
1018 #define RMAP_RIGHT_FILLING (1 << 3)
1019 #define RMAP_LEFT_VALID (1 << 6)
1020 #define RMAP_RIGHT_VALID (1 << 7)
1028 * Convert an unwritten extent to a real extent or vice versa.
1029 * Does not handle overlapping extents.
1033 struct xfs_btree_cur *cur,
1037 const struct xfs_owner_info *oinfo)
1039 struct xfs_mount *mp = cur->bc_mp;
1040 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1041 /* left is 0, right is 1, */
1042 /* prev is 2, new is 3 */
1045 uint64_t new_endoff;
1046 unsigned int oldext;
1047 unsigned int newext;
1048 unsigned int flags = 0;
1053 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1054 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1055 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1056 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1057 new_endoff = offset + len;
1058 trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1062 * For the initial lookup, look for an exact match or the left-adjacent
1063 * record for our insertion point. This will also give us the record for
1064 * start block contiguity tests.
1066 error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, &PREV, &i);
1069 if (XFS_IS_CORRUPT(mp, i != 1)) {
1070 error = -EFSCORRUPTED;
1074 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
1075 cur->bc_ag.pag->pag_agno, PREV.rm_startblock,
1076 PREV.rm_blockcount, PREV.rm_owner,
1077 PREV.rm_offset, PREV.rm_flags);
1079 ASSERT(PREV.rm_offset <= offset);
1080 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1081 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1082 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1085 * Set flags determining what part of the previous oldext allocation
1086 * extent is being replaced by a newext allocation.
1088 if (PREV.rm_offset == offset)
1089 state |= RMAP_LEFT_FILLING;
1090 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1091 state |= RMAP_RIGHT_FILLING;
1094 * Decrement the cursor to see if we have a left-adjacent record to our
1095 * insertion point. This will give us the record for end block
1098 error = xfs_btree_decrement(cur, 0, &i);
1102 state |= RMAP_LEFT_VALID;
1103 error = xfs_rmap_get_rec(cur, &LEFT, &i);
1106 if (XFS_IS_CORRUPT(mp, i != 1)) {
1107 error = -EFSCORRUPTED;
1110 if (XFS_IS_CORRUPT(mp,
1111 LEFT.rm_startblock + LEFT.rm_blockcount >
1113 error = -EFSCORRUPTED;
1116 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
1117 cur->bc_ag.pag->pag_agno, LEFT.rm_startblock,
1118 LEFT.rm_blockcount, LEFT.rm_owner,
1119 LEFT.rm_offset, LEFT.rm_flags);
1120 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1121 LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1122 xfs_rmap_is_mergeable(&LEFT, owner, newext))
1123 state |= RMAP_LEFT_CONTIG;
1127 * Increment the cursor to see if we have a right-adjacent record to our
1128 * insertion point. This will give us the record for end block
1131 error = xfs_btree_increment(cur, 0, &i);
1134 if (XFS_IS_CORRUPT(mp, i != 1)) {
1135 error = -EFSCORRUPTED;
1138 error = xfs_btree_increment(cur, 0, &i);
1142 state |= RMAP_RIGHT_VALID;
1143 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1146 if (XFS_IS_CORRUPT(mp, i != 1)) {
1147 error = -EFSCORRUPTED;
1150 if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1151 error = -EFSCORRUPTED;
1154 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1155 cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
1156 RIGHT.rm_blockcount, RIGHT.rm_owner,
1157 RIGHT.rm_offset, RIGHT.rm_flags);
1158 if (bno + len == RIGHT.rm_startblock &&
1159 offset + len == RIGHT.rm_offset &&
1160 xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1161 state |= RMAP_RIGHT_CONTIG;
1164 /* check that left + prev + right is not too long */
1165 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1166 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1167 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1168 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1169 (unsigned long)LEFT.rm_blockcount + len +
1170 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1171 state &= ~RMAP_RIGHT_CONTIG;
1173 trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
1176 /* reset the cursor back to PREV */
1177 error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, NULL, &i);
1180 if (XFS_IS_CORRUPT(mp, i != 1)) {
1181 error = -EFSCORRUPTED;
1186 * Switch out based on the FILLING and CONTIG state bits.
1188 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1189 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1190 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1191 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1193 * Setting all of a previous oldext extent to newext.
1194 * The left and right neighbors are both contiguous with new.
1196 error = xfs_btree_increment(cur, 0, &i);
1199 if (XFS_IS_CORRUPT(mp, i != 1)) {
1200 error = -EFSCORRUPTED;
1203 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1204 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1205 RIGHT.rm_owner, RIGHT.rm_offset,
1207 error = xfs_btree_delete(cur, &i);
1210 if (XFS_IS_CORRUPT(mp, i != 1)) {
1211 error = -EFSCORRUPTED;
1214 error = xfs_btree_decrement(cur, 0, &i);
1217 if (XFS_IS_CORRUPT(mp, i != 1)) {
1218 error = -EFSCORRUPTED;
1221 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1222 PREV.rm_startblock, PREV.rm_blockcount,
1223 PREV.rm_owner, PREV.rm_offset,
1225 error = xfs_btree_delete(cur, &i);
1228 if (XFS_IS_CORRUPT(mp, i != 1)) {
1229 error = -EFSCORRUPTED;
1232 error = xfs_btree_decrement(cur, 0, &i);
1235 if (XFS_IS_CORRUPT(mp, i != 1)) {
1236 error = -EFSCORRUPTED;
1240 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1241 error = xfs_rmap_update(cur, &NEW);
1246 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1248 * Setting all of a previous oldext extent to newext.
1249 * The left neighbor is contiguous, the right is not.
1251 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1252 PREV.rm_startblock, PREV.rm_blockcount,
1253 PREV.rm_owner, PREV.rm_offset,
1255 error = xfs_btree_delete(cur, &i);
1258 if (XFS_IS_CORRUPT(mp, i != 1)) {
1259 error = -EFSCORRUPTED;
1262 error = xfs_btree_decrement(cur, 0, &i);
1265 if (XFS_IS_CORRUPT(mp, i != 1)) {
1266 error = -EFSCORRUPTED;
1270 NEW.rm_blockcount += PREV.rm_blockcount;
1271 error = xfs_rmap_update(cur, &NEW);
1276 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1278 * Setting all of a previous oldext extent to newext.
1279 * The right neighbor is contiguous, the left is not.
1281 error = xfs_btree_increment(cur, 0, &i);
1284 if (XFS_IS_CORRUPT(mp, i != 1)) {
1285 error = -EFSCORRUPTED;
1288 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1289 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1290 RIGHT.rm_owner, RIGHT.rm_offset,
1292 error = xfs_btree_delete(cur, &i);
1295 if (XFS_IS_CORRUPT(mp, i != 1)) {
1296 error = -EFSCORRUPTED;
1299 error = xfs_btree_decrement(cur, 0, &i);
1302 if (XFS_IS_CORRUPT(mp, i != 1)) {
1303 error = -EFSCORRUPTED;
1307 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1308 NEW.rm_flags = newext;
1309 error = xfs_rmap_update(cur, &NEW);
1314 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1316 * Setting all of a previous oldext extent to newext.
1317 * Neither the left nor right neighbors are contiguous with
1321 NEW.rm_flags = newext;
1322 error = xfs_rmap_update(cur, &NEW);
1327 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1329 * Setting the first part of a previous oldext extent to newext.
1330 * The left neighbor is contiguous.
1333 NEW.rm_offset += len;
1334 NEW.rm_startblock += len;
1335 NEW.rm_blockcount -= len;
1336 error = xfs_rmap_update(cur, &NEW);
1339 error = xfs_btree_decrement(cur, 0, &i);
1343 NEW.rm_blockcount += len;
1344 error = xfs_rmap_update(cur, &NEW);
1349 case RMAP_LEFT_FILLING:
1351 * Setting the first part of a previous oldext extent to newext.
1352 * The left neighbor is not contiguous.
1355 NEW.rm_startblock += len;
1356 NEW.rm_offset += len;
1357 NEW.rm_blockcount -= len;
1358 error = xfs_rmap_update(cur, &NEW);
1361 NEW.rm_startblock = bno;
1362 NEW.rm_owner = owner;
1363 NEW.rm_offset = offset;
1364 NEW.rm_blockcount = len;
1365 NEW.rm_flags = newext;
1366 cur->bc_rec.r = NEW;
1367 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
1368 len, owner, offset, newext);
1369 error = xfs_btree_insert(cur, &i);
1372 if (XFS_IS_CORRUPT(mp, i != 1)) {
1373 error = -EFSCORRUPTED;
1378 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1380 * Setting the last part of a previous oldext extent to newext.
1381 * The right neighbor is contiguous with the new allocation.
1384 NEW.rm_blockcount -= len;
1385 error = xfs_rmap_update(cur, &NEW);
1388 error = xfs_btree_increment(cur, 0, &i);
1392 NEW.rm_offset = offset;
1393 NEW.rm_startblock = bno;
1394 NEW.rm_blockcount += len;
1395 error = xfs_rmap_update(cur, &NEW);
1400 case RMAP_RIGHT_FILLING:
1402 * Setting the last part of a previous oldext extent to newext.
1403 * The right neighbor is not contiguous.
1406 NEW.rm_blockcount -= len;
1407 error = xfs_rmap_update(cur, &NEW);
1410 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1414 if (XFS_IS_CORRUPT(mp, i != 0)) {
1415 error = -EFSCORRUPTED;
1418 NEW.rm_startblock = bno;
1419 NEW.rm_owner = owner;
1420 NEW.rm_offset = offset;
1421 NEW.rm_blockcount = len;
1422 NEW.rm_flags = newext;
1423 cur->bc_rec.r = NEW;
1424 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
1425 len, owner, offset, newext);
1426 error = xfs_btree_insert(cur, &i);
1429 if (XFS_IS_CORRUPT(mp, i != 1)) {
1430 error = -EFSCORRUPTED;
1437 * Setting the middle part of a previous oldext extent to
1438 * newext. Contiguity is impossible here.
1439 * One extent becomes three extents.
1441 /* new right extent - oldext */
1442 NEW.rm_startblock = bno + len;
1443 NEW.rm_owner = owner;
1444 NEW.rm_offset = new_endoff;
1445 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1447 NEW.rm_flags = PREV.rm_flags;
1448 error = xfs_rmap_update(cur, &NEW);
1451 /* new left extent - oldext */
1453 NEW.rm_blockcount = offset - PREV.rm_offset;
1454 cur->bc_rec.r = NEW;
1455 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
1456 NEW.rm_startblock, NEW.rm_blockcount,
1457 NEW.rm_owner, NEW.rm_offset,
1459 error = xfs_btree_insert(cur, &i);
1462 if (XFS_IS_CORRUPT(mp, i != 1)) {
1463 error = -EFSCORRUPTED;
1467 * Reset the cursor to the position of the new extent
1468 * we are about to insert as we can't trust it after
1469 * the previous insert.
1471 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1475 if (XFS_IS_CORRUPT(mp, i != 0)) {
1476 error = -EFSCORRUPTED;
1479 /* new middle extent - newext */
1480 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1481 cur->bc_rec.r.rm_flags |= newext;
1482 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1483 owner, offset, newext);
1484 error = xfs_btree_insert(cur, &i);
1487 if (XFS_IS_CORRUPT(mp, i != 1)) {
1488 error = -EFSCORRUPTED;
1493 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1494 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1495 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1496 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1497 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1498 case RMAP_LEFT_CONTIG:
1499 case RMAP_RIGHT_CONTIG:
1501 * These cases are all impossible.
1506 trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1510 trace_xfs_rmap_convert_error(cur->bc_mp,
1511 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
1516 * Convert an unwritten extent to a real extent or vice versa. If there is no
1517 * possibility of overlapping extents, delegate to the simpler convert
1521 xfs_rmap_convert_shared(
1522 struct xfs_btree_cur *cur,
1526 const struct xfs_owner_info *oinfo)
1528 struct xfs_mount *mp = cur->bc_mp;
1529 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1530 /* left is 0, right is 1, */
1531 /* prev is 2, new is 3 */
1534 uint64_t new_endoff;
1535 unsigned int oldext;
1536 unsigned int newext;
1537 unsigned int flags = 0;
1542 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1543 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1544 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1545 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1546 new_endoff = offset + len;
1547 trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1551 * For the initial lookup, look for and exact match or the left-adjacent
1552 * record for our insertion point. This will also give us the record for
1553 * start block contiguity tests.
1555 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, oldext,
1559 if (XFS_IS_CORRUPT(mp, i != 1)) {
1560 error = -EFSCORRUPTED;
1564 ASSERT(PREV.rm_offset <= offset);
1565 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1566 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1567 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1570 * Set flags determining what part of the previous oldext allocation
1571 * extent is being replaced by a newext allocation.
1573 if (PREV.rm_offset == offset)
1574 state |= RMAP_LEFT_FILLING;
1575 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1576 state |= RMAP_RIGHT_FILLING;
1578 /* Is there a left record that abuts our range? */
1579 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1584 state |= RMAP_LEFT_VALID;
1585 if (XFS_IS_CORRUPT(mp,
1586 LEFT.rm_startblock + LEFT.rm_blockcount >
1588 error = -EFSCORRUPTED;
1591 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1592 state |= RMAP_LEFT_CONTIG;
1595 /* Is there a right record that abuts our range? */
1596 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1601 state |= RMAP_RIGHT_VALID;
1602 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1605 if (XFS_IS_CORRUPT(mp, i != 1)) {
1606 error = -EFSCORRUPTED;
1609 if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1610 error = -EFSCORRUPTED;
1613 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1614 cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
1615 RIGHT.rm_blockcount, RIGHT.rm_owner,
1616 RIGHT.rm_offset, RIGHT.rm_flags);
1617 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1618 state |= RMAP_RIGHT_CONTIG;
1621 /* check that left + prev + right is not too long */
1622 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1623 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1624 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1625 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1626 (unsigned long)LEFT.rm_blockcount + len +
1627 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1628 state &= ~RMAP_RIGHT_CONTIG;
1630 trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
1633 * Switch out based on the FILLING and CONTIG state bits.
1635 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1636 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1637 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1638 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1640 * Setting all of a previous oldext extent to newext.
1641 * The left and right neighbors are both contiguous with new.
1643 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1644 RIGHT.rm_blockcount, RIGHT.rm_owner,
1645 RIGHT.rm_offset, RIGHT.rm_flags);
1648 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1649 PREV.rm_blockcount, PREV.rm_owner,
1650 PREV.rm_offset, PREV.rm_flags);
1654 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1655 NEW.rm_blockcount, NEW.rm_owner,
1656 NEW.rm_offset, NEW.rm_flags, &i);
1659 if (XFS_IS_CORRUPT(mp, i != 1)) {
1660 error = -EFSCORRUPTED;
1663 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1664 error = xfs_rmap_update(cur, &NEW);
1669 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1671 * Setting all of a previous oldext extent to newext.
1672 * The left neighbor is contiguous, the right is not.
1674 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1675 PREV.rm_blockcount, PREV.rm_owner,
1676 PREV.rm_offset, PREV.rm_flags);
1680 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1681 NEW.rm_blockcount, NEW.rm_owner,
1682 NEW.rm_offset, NEW.rm_flags, &i);
1685 if (XFS_IS_CORRUPT(mp, i != 1)) {
1686 error = -EFSCORRUPTED;
1689 NEW.rm_blockcount += PREV.rm_blockcount;
1690 error = xfs_rmap_update(cur, &NEW);
1695 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1697 * Setting all of a previous oldext extent to newext.
1698 * The right neighbor is contiguous, the left is not.
1700 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1701 RIGHT.rm_blockcount, RIGHT.rm_owner,
1702 RIGHT.rm_offset, RIGHT.rm_flags);
1706 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1707 NEW.rm_blockcount, NEW.rm_owner,
1708 NEW.rm_offset, NEW.rm_flags, &i);
1711 if (XFS_IS_CORRUPT(mp, i != 1)) {
1712 error = -EFSCORRUPTED;
1715 NEW.rm_blockcount += RIGHT.rm_blockcount;
1716 NEW.rm_flags = RIGHT.rm_flags;
1717 error = xfs_rmap_update(cur, &NEW);
1722 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1724 * Setting all of a previous oldext extent to newext.
1725 * Neither the left nor right neighbors are contiguous with
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_flags = newext;
1739 error = xfs_rmap_update(cur, &NEW);
1744 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1746 * Setting the first part of a previous oldext extent to newext.
1747 * The left neighbor is contiguous.
1750 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1751 NEW.rm_blockcount, NEW.rm_owner,
1752 NEW.rm_offset, NEW.rm_flags);
1755 NEW.rm_offset += len;
1756 NEW.rm_startblock += len;
1757 NEW.rm_blockcount -= len;
1758 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1759 NEW.rm_blockcount, NEW.rm_owner,
1760 NEW.rm_offset, NEW.rm_flags);
1764 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1765 NEW.rm_blockcount, NEW.rm_owner,
1766 NEW.rm_offset, NEW.rm_flags, &i);
1769 if (XFS_IS_CORRUPT(mp, i != 1)) {
1770 error = -EFSCORRUPTED;
1773 NEW.rm_blockcount += len;
1774 error = xfs_rmap_update(cur, &NEW);
1779 case RMAP_LEFT_FILLING:
1781 * Setting the first part of a previous oldext extent to newext.
1782 * The left neighbor is not contiguous.
1785 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1786 NEW.rm_blockcount, NEW.rm_owner,
1787 NEW.rm_offset, NEW.rm_flags);
1790 NEW.rm_offset += len;
1791 NEW.rm_startblock += len;
1792 NEW.rm_blockcount -= len;
1793 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1794 NEW.rm_blockcount, NEW.rm_owner,
1795 NEW.rm_offset, NEW.rm_flags);
1798 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1803 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1805 * Setting the last part of a previous oldext extent to newext.
1806 * The right neighbor is contiguous with the new allocation.
1809 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1810 NEW.rm_blockcount, NEW.rm_owner,
1811 NEW.rm_offset, NEW.rm_flags, &i);
1814 if (XFS_IS_CORRUPT(mp, i != 1)) {
1815 error = -EFSCORRUPTED;
1818 NEW.rm_blockcount = offset - NEW.rm_offset;
1819 error = xfs_rmap_update(cur, &NEW);
1823 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1824 NEW.rm_blockcount, NEW.rm_owner,
1825 NEW.rm_offset, NEW.rm_flags);
1828 NEW.rm_offset = offset;
1829 NEW.rm_startblock = bno;
1830 NEW.rm_blockcount += len;
1831 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1832 NEW.rm_blockcount, NEW.rm_owner,
1833 NEW.rm_offset, NEW.rm_flags);
1838 case RMAP_RIGHT_FILLING:
1840 * Setting the last part of a previous oldext extent to newext.
1841 * The right neighbor is not contiguous.
1844 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1845 NEW.rm_blockcount, NEW.rm_owner,
1846 NEW.rm_offset, NEW.rm_flags, &i);
1849 if (XFS_IS_CORRUPT(mp, i != 1)) {
1850 error = -EFSCORRUPTED;
1853 NEW.rm_blockcount -= len;
1854 error = xfs_rmap_update(cur, &NEW);
1857 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1864 * Setting the middle part of a previous oldext extent to
1865 * newext. Contiguity is impossible here.
1866 * One extent becomes three extents.
1868 /* new right extent - oldext */
1869 NEW.rm_startblock = bno + len;
1870 NEW.rm_owner = owner;
1871 NEW.rm_offset = new_endoff;
1872 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1874 NEW.rm_flags = PREV.rm_flags;
1875 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1876 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1880 /* new left extent - oldext */
1882 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1883 NEW.rm_blockcount, NEW.rm_owner,
1884 NEW.rm_offset, NEW.rm_flags, &i);
1887 if (XFS_IS_CORRUPT(mp, i != 1)) {
1888 error = -EFSCORRUPTED;
1891 NEW.rm_blockcount = offset - NEW.rm_offset;
1892 error = xfs_rmap_update(cur, &NEW);
1895 /* new middle extent - newext */
1896 NEW.rm_startblock = bno;
1897 NEW.rm_blockcount = len;
1898 NEW.rm_owner = owner;
1899 NEW.rm_offset = offset;
1900 NEW.rm_flags = newext;
1901 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1902 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1908 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1909 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1910 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1911 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1912 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1913 case RMAP_LEFT_CONTIG:
1914 case RMAP_RIGHT_CONTIG:
1916 * These cases are all impossible.
1921 trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1925 trace_xfs_rmap_convert_error(cur->bc_mp,
1926 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
1936 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1937 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1938 * that the prev/next records in the btree might belong to another owner.
1939 * Therefore we must use delete+insert to alter any of the key fields.
1941 * For every other situation there can only be one owner for a given extent,
1942 * so we can call the regular _free function.
1945 xfs_rmap_unmap_shared(
1946 struct xfs_btree_cur *cur,
1950 const struct xfs_owner_info *oinfo)
1952 struct xfs_mount *mp = cur->bc_mp;
1953 struct xfs_rmap_irec ltrec;
1961 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1963 flags |= XFS_RMAP_UNWRITTEN;
1964 trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
1968 * We should always have a left record because there's a static record
1969 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1970 * will not ever be removed from the tree.
1972 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1976 if (XFS_IS_CORRUPT(mp, i != 1)) {
1977 error = -EFSCORRUPTED;
1980 ltoff = ltrec.rm_offset;
1982 /* Make sure the extent we found covers the entire freeing range. */
1983 if (XFS_IS_CORRUPT(mp,
1984 ltrec.rm_startblock > bno ||
1985 ltrec.rm_startblock + ltrec.rm_blockcount <
1987 error = -EFSCORRUPTED;
1991 /* Make sure the owner matches what we expect to find in the tree. */
1992 if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) {
1993 error = -EFSCORRUPTED;
1997 /* Make sure the unwritten flag matches. */
1998 if (XFS_IS_CORRUPT(mp,
1999 (flags & XFS_RMAP_UNWRITTEN) !=
2000 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) {
2001 error = -EFSCORRUPTED;
2005 /* Check the offset. */
2006 if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) {
2007 error = -EFSCORRUPTED;
2010 if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) {
2011 error = -EFSCORRUPTED;
2015 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
2016 /* Exact match, simply remove the record from rmap tree. */
2017 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2018 ltrec.rm_blockcount, ltrec.rm_owner,
2019 ltrec.rm_offset, ltrec.rm_flags);
2022 } else if (ltrec.rm_startblock == bno) {
2024 * Overlap left hand side of extent: move the start, trim the
2025 * length and update the current record.
2028 * Orig: |oooooooooooooooooooo|
2029 * Freeing: |fffffffff|
2030 * Result: |rrrrrrrrrr|
2034 /* Delete prev rmap. */
2035 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2036 ltrec.rm_blockcount, ltrec.rm_owner,
2037 ltrec.rm_offset, ltrec.rm_flags);
2041 /* Add an rmap at the new offset. */
2042 ltrec.rm_startblock += len;
2043 ltrec.rm_blockcount -= len;
2044 ltrec.rm_offset += len;
2045 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
2046 ltrec.rm_blockcount, ltrec.rm_owner,
2047 ltrec.rm_offset, ltrec.rm_flags);
2050 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
2052 * Overlap right hand side of extent: trim the length and
2053 * update the current record.
2056 * Orig: |oooooooooooooooooooo|
2057 * Freeing: |fffffffff|
2058 * Result: |rrrrrrrrrr|
2061 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2062 ltrec.rm_blockcount, ltrec.rm_owner,
2063 ltrec.rm_offset, ltrec.rm_flags, &i);
2066 if (XFS_IS_CORRUPT(mp, i != 1)) {
2067 error = -EFSCORRUPTED;
2070 ltrec.rm_blockcount -= len;
2071 error = xfs_rmap_update(cur, <rec);
2076 * Overlap middle of extent: trim the length of the existing
2077 * record to the length of the new left-extent size, increment
2078 * the insertion position so we can insert a new record
2079 * containing the remaining right-extent space.
2082 * Orig: |oooooooooooooooooooo|
2083 * Freeing: |fffffffff|
2084 * Result: |rrrrr| |rrrr|
2087 xfs_extlen_t orig_len = ltrec.rm_blockcount;
2089 /* Shrink the left side of the rmap */
2090 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2091 ltrec.rm_blockcount, ltrec.rm_owner,
2092 ltrec.rm_offset, ltrec.rm_flags, &i);
2095 if (XFS_IS_CORRUPT(mp, i != 1)) {
2096 error = -EFSCORRUPTED;
2099 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
2100 error = xfs_rmap_update(cur, <rec);
2104 /* Add an rmap at the new offset */
2105 error = xfs_rmap_insert(cur, bno + len,
2106 orig_len - len - ltrec.rm_blockcount,
2107 ltrec.rm_owner, offset + len,
2113 trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2117 trace_xfs_rmap_unmap_error(cur->bc_mp,
2118 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2123 * Find an extent in the rmap btree and map it. For rmap extent types that
2124 * can overlap (data fork rmaps on reflink filesystems) we must be careful
2125 * that the prev/next records in the btree might belong to another owner.
2126 * Therefore we must use delete+insert to alter any of the key fields.
2128 * For every other situation there can only be one owner for a given extent,
2129 * so we can call the regular _alloc function.
2132 xfs_rmap_map_shared(
2133 struct xfs_btree_cur *cur,
2137 const struct xfs_owner_info *oinfo)
2139 struct xfs_mount *mp = cur->bc_mp;
2140 struct xfs_rmap_irec ltrec;
2141 struct xfs_rmap_irec gtrec;
2148 unsigned int flags = 0;
2150 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2152 flags |= XFS_RMAP_UNWRITTEN;
2153 trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
2156 /* Is there a left record that abuts our range? */
2157 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
2162 !xfs_rmap_is_mergeable(<rec, owner, flags))
2165 /* Is there a right record that abuts our range? */
2166 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
2171 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
2174 if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
2175 error = -EFSCORRUPTED;
2178 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
2179 cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
2180 gtrec.rm_blockcount, gtrec.rm_owner,
2181 gtrec.rm_offset, gtrec.rm_flags);
2183 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
2188 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
2189 ltrec.rm_offset + ltrec.rm_blockcount == offset) {
2191 * Left edge contiguous, merge into left record.
2195 * adding: |aaaaaaaaa|
2196 * result: |rrrrrrrrrrrrrrrrrrr|
2199 ltrec.rm_blockcount += len;
2201 bno + len == gtrec.rm_startblock &&
2202 offset + len == gtrec.rm_offset) {
2204 * Right edge also contiguous, delete right record
2205 * and merge into left record.
2207 * ltbno ltlen gtbno gtlen
2208 * orig: |ooooooooo| |ooooooooo|
2209 * adding: |aaaaaaaaa|
2210 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
2212 ltrec.rm_blockcount += gtrec.rm_blockcount;
2213 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2214 gtrec.rm_blockcount, gtrec.rm_owner,
2215 gtrec.rm_offset, gtrec.rm_flags);
2220 /* Point the cursor back to the left record and update. */
2221 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2222 ltrec.rm_blockcount, ltrec.rm_owner,
2223 ltrec.rm_offset, ltrec.rm_flags, &i);
2226 if (XFS_IS_CORRUPT(mp, i != 1)) {
2227 error = -EFSCORRUPTED;
2231 error = xfs_rmap_update(cur, <rec);
2234 } else if (have_gt &&
2235 bno + len == gtrec.rm_startblock &&
2236 offset + len == gtrec.rm_offset) {
2238 * Right edge contiguous, merge into right record.
2242 * adding: |aaaaaaaaa|
2243 * Result: |rrrrrrrrrrrrrrrrrrr|
2246 /* Delete the old record. */
2247 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2248 gtrec.rm_blockcount, gtrec.rm_owner,
2249 gtrec.rm_offset, gtrec.rm_flags);
2253 /* Move the start and re-add it. */
2254 gtrec.rm_startblock = bno;
2255 gtrec.rm_blockcount += len;
2256 gtrec.rm_offset = offset;
2257 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2258 gtrec.rm_blockcount, gtrec.rm_owner,
2259 gtrec.rm_offset, gtrec.rm_flags);
2264 * No contiguous edge with identical owner, insert
2265 * new record at current cursor position.
2267 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2272 trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2276 trace_xfs_rmap_map_error(cur->bc_mp,
2277 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2281 /* Insert a raw rmap into the rmapbt. */
2284 struct xfs_btree_cur *cur,
2285 struct xfs_rmap_irec *rmap)
2287 struct xfs_owner_info oinfo;
2289 oinfo.oi_owner = rmap->rm_owner;
2290 oinfo.oi_offset = rmap->rm_offset;
2292 if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
2293 oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
2294 if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
2295 oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
2297 if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2298 return xfs_rmap_map(cur, rmap->rm_startblock,
2299 rmap->rm_blockcount,
2300 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2303 return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2304 rmap->rm_blockcount,
2305 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2309 struct xfs_rmap_query_range_info {
2310 xfs_rmap_query_range_fn fn;
2314 /* Format btree record and pass to our callback. */
2316 xfs_rmap_query_range_helper(
2317 struct xfs_btree_cur *cur,
2318 const union xfs_btree_rec *rec,
2321 struct xfs_rmap_query_range_info *query = priv;
2322 struct xfs_rmap_irec irec;
2325 error = xfs_rmap_btrec_to_irec(rec, &irec);
2328 return query->fn(cur, &irec, query->priv);
2331 /* Find all rmaps between two keys. */
2333 xfs_rmap_query_range(
2334 struct xfs_btree_cur *cur,
2335 const struct xfs_rmap_irec *low_rec,
2336 const struct xfs_rmap_irec *high_rec,
2337 xfs_rmap_query_range_fn fn,
2340 union xfs_btree_irec low_brec;
2341 union xfs_btree_irec high_brec;
2342 struct xfs_rmap_query_range_info query;
2344 low_brec.r = *low_rec;
2345 high_brec.r = *high_rec;
2348 return xfs_btree_query_range(cur, &low_brec, &high_brec,
2349 xfs_rmap_query_range_helper, &query);
2352 /* Find all rmaps. */
2355 struct xfs_btree_cur *cur,
2356 xfs_rmap_query_range_fn fn,
2359 struct xfs_rmap_query_range_info query;
2363 return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2366 /* Clean up after calling xfs_rmap_finish_one. */
2368 xfs_rmap_finish_one_cleanup(
2369 struct xfs_trans *tp,
2370 struct xfs_btree_cur *rcur,
2373 struct xfs_buf *agbp;
2377 agbp = rcur->bc_ag.agbp;
2378 xfs_btree_del_cursor(rcur, error);
2380 xfs_trans_brelse(tp, agbp);
2384 * Process one of the deferred rmap operations. We pass back the
2385 * btree cursor to maintain our lock on the rmapbt between calls.
2386 * This saves time and eliminates a buffer deadlock between the
2387 * superblock and the AGF because we'll always grab them in the same
2391 xfs_rmap_finish_one(
2392 struct xfs_trans *tp,
2393 enum xfs_rmap_intent_type type,
2396 xfs_fileoff_t startoff,
2397 xfs_fsblock_t startblock,
2398 xfs_filblks_t blockcount,
2400 struct xfs_btree_cur **pcur)
2402 struct xfs_mount *mp = tp->t_mountp;
2403 struct xfs_perag *pag;
2404 struct xfs_btree_cur *rcur;
2405 struct xfs_buf *agbp = NULL;
2407 struct xfs_owner_info oinfo;
2411 pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, startblock));
2412 bno = XFS_FSB_TO_AGBNO(mp, startblock);
2414 trace_xfs_rmap_deferred(mp, pag->pag_agno, type, bno, owner, whichfork,
2415 startoff, blockcount, state);
2417 if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE)) {
2424 * If we haven't gotten a cursor or the cursor AG doesn't match
2425 * the startblock, get one now.
2428 if (rcur != NULL && rcur->bc_ag.pag != pag) {
2429 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2435 * Refresh the freelist before we start changing the
2436 * rmapbt, because a shape change could cause us to
2439 error = xfs_free_extent_fix_freelist(tp, pag, &agbp);
2442 if (XFS_IS_CORRUPT(tp->t_mountp, !agbp)) {
2443 error = -EFSCORRUPTED;
2447 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
2451 xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2452 unwritten = state == XFS_EXT_UNWRITTEN;
2453 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2456 case XFS_RMAP_ALLOC:
2458 error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2460 case XFS_RMAP_MAP_SHARED:
2461 error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2465 case XFS_RMAP_UNMAP:
2466 error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2469 case XFS_RMAP_UNMAP_SHARED:
2470 error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2473 case XFS_RMAP_CONVERT:
2474 error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2477 case XFS_RMAP_CONVERT_SHARED:
2478 error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2479 !unwritten, &oinfo);
2483 error = -EFSCORRUPTED;
2491 * Don't defer an rmap if we aren't an rmap filesystem.
2494 xfs_rmap_update_is_needed(
2495 struct xfs_mount *mp,
2498 return xfs_has_rmapbt(mp) && whichfork != XFS_COW_FORK;
2502 * Record a rmap intent; the list is kept sorted first by AG and then by
2507 struct xfs_trans *tp,
2508 enum xfs_rmap_intent_type type,
2511 struct xfs_bmbt_irec *bmap)
2513 struct xfs_rmap_intent *ri;
2515 trace_xfs_rmap_defer(tp->t_mountp,
2516 XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock),
2518 XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock),
2521 bmap->br_blockcount,
2524 ri = kmem_cache_alloc(xfs_rmap_intent_cache, GFP_NOFS | __GFP_NOFAIL);
2525 INIT_LIST_HEAD(&ri->ri_list);
2527 ri->ri_owner = owner;
2528 ri->ri_whichfork = whichfork;
2529 ri->ri_bmap = *bmap;
2531 xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
2534 /* Map an extent into a file. */
2536 xfs_rmap_map_extent(
2537 struct xfs_trans *tp,
2538 struct xfs_inode *ip,
2540 struct xfs_bmbt_irec *PREV)
2542 enum xfs_rmap_intent_type type = XFS_RMAP_MAP;
2544 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2547 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2548 type = XFS_RMAP_MAP_SHARED;
2550 __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2553 /* Unmap an extent out of a file. */
2555 xfs_rmap_unmap_extent(
2556 struct xfs_trans *tp,
2557 struct xfs_inode *ip,
2559 struct xfs_bmbt_irec *PREV)
2561 enum xfs_rmap_intent_type type = XFS_RMAP_UNMAP;
2563 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2566 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2567 type = XFS_RMAP_UNMAP_SHARED;
2569 __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2573 * Convert a data fork extent from unwritten to real or vice versa.
2575 * Note that tp can be NULL here as no transaction is used for COW fork
2576 * unwritten conversion.
2579 xfs_rmap_convert_extent(
2580 struct xfs_mount *mp,
2581 struct xfs_trans *tp,
2582 struct xfs_inode *ip,
2584 struct xfs_bmbt_irec *PREV)
2586 enum xfs_rmap_intent_type type = XFS_RMAP_CONVERT;
2588 if (!xfs_rmap_update_is_needed(mp, whichfork))
2591 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2592 type = XFS_RMAP_CONVERT_SHARED;
2594 __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2597 /* Schedule the creation of an rmap for non-file data. */
2599 xfs_rmap_alloc_extent(
2600 struct xfs_trans *tp,
2601 xfs_agnumber_t agno,
2606 struct xfs_bmbt_irec bmap;
2608 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2611 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2612 bmap.br_blockcount = len;
2613 bmap.br_startoff = 0;
2614 bmap.br_state = XFS_EXT_NORM;
2616 __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
2619 /* Schedule the deletion of an rmap for non-file data. */
2621 xfs_rmap_free_extent(
2622 struct xfs_trans *tp,
2623 xfs_agnumber_t agno,
2628 struct xfs_bmbt_irec bmap;
2630 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2633 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2634 bmap.br_blockcount = len;
2635 bmap.br_startoff = 0;
2636 bmap.br_state = XFS_EXT_NORM;
2638 __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
2641 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2644 const struct xfs_rmap_irec *a,
2645 const struct xfs_rmap_irec *b)
2650 oa = xfs_rmap_irec_offset_pack(a);
2651 ob = xfs_rmap_irec_offset_pack(b);
2653 if (a->rm_startblock < b->rm_startblock)
2655 else if (a->rm_startblock > b->rm_startblock)
2657 else if (a->rm_owner < b->rm_owner)
2659 else if (a->rm_owner > b->rm_owner)
2669 /* Is there a record covering a given extent? */
2671 xfs_rmap_has_record(
2672 struct xfs_btree_cur *cur,
2677 union xfs_btree_irec low;
2678 union xfs_btree_irec high;
2680 memset(&low, 0, sizeof(low));
2681 low.r.rm_startblock = bno;
2682 memset(&high, 0xFF, sizeof(high));
2683 high.r.rm_startblock = bno + len - 1;
2685 return xfs_btree_has_record(cur, &low, &high, exists);
2689 * Is there a record for this owner completely covering a given physical
2690 * extent? If so, *has_rmap will be set to true. If there is no record
2691 * or the record only covers part of the range, we set *has_rmap to false.
2692 * This function doesn't perform range lookups or offset checks, so it is
2693 * not suitable for checking data fork blocks.
2696 xfs_rmap_record_exists(
2697 struct xfs_btree_cur *cur,
2700 const struct xfs_owner_info *oinfo,
2707 struct xfs_rmap_irec irec;
2710 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2711 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
2712 (flags & XFS_RMAP_BMBT_BLOCK));
2714 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, &irec,
2723 *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
2724 irec.rm_startblock + irec.rm_blockcount >= bno + len);
2728 struct xfs_rmap_key_state {
2734 /* For each rmap given, figure out if it doesn't match the key we want. */
2736 xfs_rmap_has_other_keys_helper(
2737 struct xfs_btree_cur *cur,
2738 const struct xfs_rmap_irec *rec,
2741 struct xfs_rmap_key_state *rks = priv;
2743 if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset &&
2744 ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags)
2750 * Given an extent and some owner info, can we find records overlapping
2751 * the extent whose owner info does not match the given owner?
2754 xfs_rmap_has_other_keys(
2755 struct xfs_btree_cur *cur,
2758 const struct xfs_owner_info *oinfo,
2761 struct xfs_rmap_irec low = {0};
2762 struct xfs_rmap_irec high;
2763 struct xfs_rmap_key_state rks;
2766 xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags);
2769 low.rm_startblock = bno;
2770 memset(&high, 0xFF, sizeof(high));
2771 high.rm_startblock = bno + len - 1;
2773 error = xfs_rmap_query_range(cur, &low, &high,
2774 xfs_rmap_has_other_keys_helper, &rks);
2775 if (error == -ECANCELED) {
2783 const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
2784 .oi_owner = XFS_RMAP_OWN_NULL,
2786 const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
2787 .oi_owner = XFS_RMAP_OWN_UNKNOWN,
2789 const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
2790 .oi_owner = XFS_RMAP_OWN_FS,
2792 const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
2793 .oi_owner = XFS_RMAP_OWN_LOG,
2795 const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
2796 .oi_owner = XFS_RMAP_OWN_AG,
2798 const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
2799 .oi_owner = XFS_RMAP_OWN_INOBT,
2801 const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
2802 .oi_owner = XFS_RMAP_OWN_INODES,
2804 const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
2805 .oi_owner = XFS_RMAP_OWN_REFC,
2807 const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
2808 .oi_owner = XFS_RMAP_OWN_COW,
2812 xfs_rmap_intent_init_cache(void)
2814 xfs_rmap_intent_cache = kmem_cache_create("xfs_rmap_intent",
2815 sizeof(struct xfs_rmap_intent),
2818 return xfs_rmap_intent_cache != NULL ? 0 : -ENOMEM;
2822 xfs_rmap_intent_destroy_cache(void)
2824 kmem_cache_destroy(xfs_rmap_intent_cache);
2825 xfs_rmap_intent_cache = NULL;