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"
28 * Lookup the first record less than or equal to [bno, len, owner, offset]
29 * in the btree given by cur.
33 struct xfs_btree_cur *cur,
41 cur->bc_rec.r.rm_startblock = bno;
42 cur->bc_rec.r.rm_blockcount = len;
43 cur->bc_rec.r.rm_owner = owner;
44 cur->bc_rec.r.rm_offset = offset;
45 cur->bc_rec.r.rm_flags = flags;
46 return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
50 * Lookup the record exactly matching [bno, len, owner, offset]
51 * in the btree given by cur.
55 struct xfs_btree_cur *cur,
63 cur->bc_rec.r.rm_startblock = bno;
64 cur->bc_rec.r.rm_blockcount = len;
65 cur->bc_rec.r.rm_owner = owner;
66 cur->bc_rec.r.rm_offset = offset;
67 cur->bc_rec.r.rm_flags = flags;
68 return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
72 * Update the record referred to by cur to the value given
73 * by [bno, len, owner, offset].
74 * This either works (return 0) or gets an EFSCORRUPTED error.
78 struct xfs_btree_cur *cur,
79 struct xfs_rmap_irec *irec)
81 union xfs_btree_rec rec;
84 trace_xfs_rmap_update(cur->bc_mp, cur->bc_ag.pag->pag_agno,
85 irec->rm_startblock, irec->rm_blockcount,
86 irec->rm_owner, irec->rm_offset, irec->rm_flags);
88 rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
89 rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
90 rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
91 rec.rmap.rm_offset = cpu_to_be64(
92 xfs_rmap_irec_offset_pack(irec));
93 error = xfs_btree_update(cur, &rec);
95 trace_xfs_rmap_update_error(cur->bc_mp,
96 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
102 struct xfs_btree_cur *rcur,
112 trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno,
113 len, owner, offset, flags);
115 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
118 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 0)) {
119 error = -EFSCORRUPTED;
123 rcur->bc_rec.r.rm_startblock = agbno;
124 rcur->bc_rec.r.rm_blockcount = len;
125 rcur->bc_rec.r.rm_owner = owner;
126 rcur->bc_rec.r.rm_offset = offset;
127 rcur->bc_rec.r.rm_flags = flags;
128 error = xfs_btree_insert(rcur, &i);
131 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
132 error = -EFSCORRUPTED;
137 trace_xfs_rmap_insert_error(rcur->bc_mp,
138 rcur->bc_ag.pag->pag_agno, error, _RET_IP_);
144 struct xfs_btree_cur *rcur,
154 trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno,
155 len, owner, offset, flags);
157 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
160 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
161 error = -EFSCORRUPTED;
165 error = xfs_btree_delete(rcur, &i);
168 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
169 error = -EFSCORRUPTED;
174 trace_xfs_rmap_delete_error(rcur->bc_mp,
175 rcur->bc_ag.pag->pag_agno, error, _RET_IP_);
179 /* Convert an internal btree record to an rmap record. */
181 xfs_rmap_btrec_to_irec(
182 union xfs_btree_rec *rec,
183 struct xfs_rmap_irec *irec)
185 irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
186 irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
187 irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
188 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
193 * Get the data from the pointed-to record.
197 struct xfs_btree_cur *cur,
198 struct xfs_rmap_irec *irec,
201 struct xfs_mount *mp = cur->bc_mp;
202 xfs_agnumber_t agno = cur->bc_ag.pag->pag_agno;
203 union xfs_btree_rec *rec;
206 error = xfs_btree_get_rec(cur, &rec, stat);
210 if (xfs_rmap_btrec_to_irec(rec, irec))
213 if (irec->rm_blockcount == 0)
215 if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
216 if (irec->rm_owner != XFS_RMAP_OWN_FS)
218 if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
221 /* check for valid extent range, including overflow */
222 if (!xfs_verify_agbno(mp, agno, irec->rm_startblock))
224 if (irec->rm_startblock >
225 irec->rm_startblock + irec->rm_blockcount)
227 if (!xfs_verify_agbno(mp, agno,
228 irec->rm_startblock + irec->rm_blockcount - 1))
232 if (!(xfs_verify_ino(mp, irec->rm_owner) ||
233 (irec->rm_owner <= XFS_RMAP_OWN_FS &&
234 irec->rm_owner >= XFS_RMAP_OWN_MIN)))
240 "Reverse Mapping BTree record corruption in AG %d detected!",
243 "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
244 irec->rm_owner, irec->rm_flags, irec->rm_startblock,
245 irec->rm_blockcount);
246 return -EFSCORRUPTED;
249 struct xfs_find_left_neighbor_info {
250 struct xfs_rmap_irec high;
251 struct xfs_rmap_irec *irec;
255 /* For each rmap given, figure out if it matches the key we want. */
257 xfs_rmap_find_left_neighbor_helper(
258 struct xfs_btree_cur *cur,
259 struct xfs_rmap_irec *rec,
262 struct xfs_find_left_neighbor_info *info = priv;
264 trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
265 cur->bc_ag.pag->pag_agno, rec->rm_startblock,
266 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
269 if (rec->rm_owner != info->high.rm_owner)
271 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
272 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
273 rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
282 * Find the record to the left of the given extent, being careful only to
283 * return a match with the same owner and adjacent physical and logical
287 xfs_rmap_find_left_neighbor(
288 struct xfs_btree_cur *cur,
293 struct xfs_rmap_irec *irec,
296 struct xfs_find_left_neighbor_info info;
302 info.high.rm_startblock = bno - 1;
303 info.high.rm_owner = owner;
304 if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
305 !(flags & XFS_RMAP_BMBT_BLOCK)) {
308 info.high.rm_offset = offset - 1;
310 info.high.rm_offset = 0;
311 info.high.rm_flags = flags;
312 info.high.rm_blockcount = 0;
316 trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
317 cur->bc_ag.pag->pag_agno, bno, 0, owner, offset, flags);
319 error = xfs_rmap_query_range(cur, &info.high, &info.high,
320 xfs_rmap_find_left_neighbor_helper, &info);
321 if (error == -ECANCELED)
324 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
325 cur->bc_ag.pag->pag_agno, irec->rm_startblock,
326 irec->rm_blockcount, irec->rm_owner,
327 irec->rm_offset, irec->rm_flags);
331 /* For each rmap given, figure out if it matches the key we want. */
333 xfs_rmap_lookup_le_range_helper(
334 struct xfs_btree_cur *cur,
335 struct xfs_rmap_irec *rec,
338 struct xfs_find_left_neighbor_info *info = priv;
340 trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
341 cur->bc_ag.pag->pag_agno, rec->rm_startblock,
342 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
345 if (rec->rm_owner != info->high.rm_owner)
347 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
348 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
349 (rec->rm_offset > info->high.rm_offset ||
350 rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
359 * Find the record to the left of the given extent, being careful only to
360 * return a match with the same owner and overlapping physical and logical
361 * block ranges. This is the overlapping-interval version of
362 * xfs_rmap_lookup_le.
365 xfs_rmap_lookup_le_range(
366 struct xfs_btree_cur *cur,
371 struct xfs_rmap_irec *irec,
374 struct xfs_find_left_neighbor_info info;
377 info.high.rm_startblock = bno;
378 info.high.rm_owner = owner;
379 if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
380 info.high.rm_offset = offset;
382 info.high.rm_offset = 0;
383 info.high.rm_flags = flags;
384 info.high.rm_blockcount = 0;
389 trace_xfs_rmap_lookup_le_range(cur->bc_mp,
390 cur->bc_ag.pag->pag_agno, bno, 0, owner, offset, flags);
391 error = xfs_rmap_query_range(cur, &info.high, &info.high,
392 xfs_rmap_lookup_le_range_helper, &info);
393 if (error == -ECANCELED)
396 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
397 cur->bc_ag.pag->pag_agno, irec->rm_startblock,
398 irec->rm_blockcount, irec->rm_owner,
399 irec->rm_offset, irec->rm_flags);
404 * Perform all the relevant owner checks for a removal op. If we're doing an
405 * unknown-owner removal then we have no owner information to check.
408 xfs_rmap_free_check_owner(
409 struct xfs_mount *mp,
411 struct xfs_rmap_irec *rec,
419 if (owner == XFS_RMAP_OWN_UNKNOWN)
422 /* Make sure the unwritten flag matches. */
423 if (XFS_IS_CORRUPT(mp,
424 (flags & XFS_RMAP_UNWRITTEN) !=
425 (rec->rm_flags & XFS_RMAP_UNWRITTEN))) {
426 error = -EFSCORRUPTED;
430 /* Make sure the owner matches what we expect to find in the tree. */
431 if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) {
432 error = -EFSCORRUPTED;
436 /* Check the offset, if necessary. */
437 if (XFS_RMAP_NON_INODE_OWNER(owner))
440 if (flags & XFS_RMAP_BMBT_BLOCK) {
441 if (XFS_IS_CORRUPT(mp,
442 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) {
443 error = -EFSCORRUPTED;
447 if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) {
448 error = -EFSCORRUPTED;
451 if (XFS_IS_CORRUPT(mp,
452 offset + len > ltoff + rec->rm_blockcount)) {
453 error = -EFSCORRUPTED;
463 * Find the extent in the rmap btree and remove it.
465 * The record we find should always be an exact match for the extent that we're
466 * looking for, since we insert them into the btree without modification.
468 * Special Case #1: when growing the filesystem, we "free" an extent when
469 * growing the last AG. This extent is new space and so it is not tracked as
470 * used space in the btree. The growfs code will pass in an owner of
471 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
472 * extent. We verify that - the extent lookup result in a record that does not
475 * Special Case #2: EFIs do not record the owner of the extent, so when
476 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
477 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
478 * corruption checks during log recovery.
482 struct xfs_btree_cur *cur,
486 const struct xfs_owner_info *oinfo)
488 struct xfs_mount *mp = cur->bc_mp;
489 struct xfs_rmap_irec ltrec;
498 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
499 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
500 (flags & XFS_RMAP_BMBT_BLOCK);
502 flags |= XFS_RMAP_UNWRITTEN;
503 trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
507 * We should always have a left record because there's a static record
508 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
509 * will not ever be removed from the tree.
511 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i);
514 if (XFS_IS_CORRUPT(mp, i != 1)) {
515 error = -EFSCORRUPTED;
519 error = xfs_rmap_get_rec(cur, <rec, &i);
522 if (XFS_IS_CORRUPT(mp, i != 1)) {
523 error = -EFSCORRUPTED;
526 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
527 cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
528 ltrec.rm_blockcount, ltrec.rm_owner,
529 ltrec.rm_offset, ltrec.rm_flags);
530 ltoff = ltrec.rm_offset;
533 * For growfs, the incoming extent must be beyond the left record we
534 * just found as it is new space and won't be used by anyone. This is
535 * just a corruption check as we don't actually do anything with this
536 * extent. Note that we need to use >= instead of > because it might
537 * be the case that the "left" extent goes all the way to EOFS.
539 if (owner == XFS_RMAP_OWN_NULL) {
540 if (XFS_IS_CORRUPT(mp,
542 ltrec.rm_startblock + ltrec.rm_blockcount)) {
543 error = -EFSCORRUPTED;
550 * If we're doing an unknown-owner removal for EFI recovery, we expect
551 * to find the full range in the rmapbt or nothing at all. If we
552 * don't find any rmaps overlapping either end of the range, we're
553 * done. Hopefully this means that the EFI creator already queued
554 * (and finished) a RUI to remove the rmap.
556 if (owner == XFS_RMAP_OWN_UNKNOWN &&
557 ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
558 struct xfs_rmap_irec rtrec;
560 error = xfs_btree_increment(cur, 0, &i);
565 error = xfs_rmap_get_rec(cur, &rtrec, &i);
568 if (XFS_IS_CORRUPT(mp, i != 1)) {
569 error = -EFSCORRUPTED;
572 if (rtrec.rm_startblock >= bno + len)
576 /* Make sure the extent we found covers the entire freeing range. */
577 if (XFS_IS_CORRUPT(mp,
578 ltrec.rm_startblock > bno ||
579 ltrec.rm_startblock + ltrec.rm_blockcount <
581 error = -EFSCORRUPTED;
585 /* Check owner information. */
586 error = xfs_rmap_free_check_owner(mp, ltoff, <rec, len, owner,
591 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
592 /* exact match, simply remove the record from rmap tree */
593 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
594 ltrec.rm_startblock, ltrec.rm_blockcount,
595 ltrec.rm_owner, ltrec.rm_offset,
597 error = xfs_btree_delete(cur, &i);
600 if (XFS_IS_CORRUPT(mp, i != 1)) {
601 error = -EFSCORRUPTED;
604 } else if (ltrec.rm_startblock == bno) {
606 * overlap left hand side of extent: move the start, trim the
607 * length and update the current record.
610 * Orig: |oooooooooooooooooooo|
611 * Freeing: |fffffffff|
612 * Result: |rrrrrrrrrr|
615 ltrec.rm_startblock += len;
616 ltrec.rm_blockcount -= len;
618 ltrec.rm_offset += len;
619 error = xfs_rmap_update(cur, <rec);
622 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
624 * overlap right hand side of extent: trim the length and update
625 * the current record.
628 * Orig: |oooooooooooooooooooo|
629 * Freeing: |fffffffff|
630 * Result: |rrrrrrrrrr|
633 ltrec.rm_blockcount -= len;
634 error = xfs_rmap_update(cur, <rec);
640 * overlap middle of extent: trim the length of the existing
641 * record to the length of the new left-extent size, increment
642 * the insertion position so we can insert a new record
643 * containing the remaining right-extent space.
646 * Orig: |oooooooooooooooooooo|
647 * Freeing: |fffffffff|
648 * Result: |rrrrr| |rrrr|
651 xfs_extlen_t orig_len = ltrec.rm_blockcount;
653 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
654 error = xfs_rmap_update(cur, <rec);
658 error = xfs_btree_increment(cur, 0, &i);
662 cur->bc_rec.r.rm_startblock = bno + len;
663 cur->bc_rec.r.rm_blockcount = orig_len - len -
665 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
667 cur->bc_rec.r.rm_offset = 0;
669 cur->bc_rec.r.rm_offset = offset + len;
670 cur->bc_rec.r.rm_flags = flags;
671 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
672 cur->bc_rec.r.rm_startblock,
673 cur->bc_rec.r.rm_blockcount,
674 cur->bc_rec.r.rm_owner,
675 cur->bc_rec.r.rm_offset,
676 cur->bc_rec.r.rm_flags);
677 error = xfs_btree_insert(cur, &i);
683 trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
687 trace_xfs_rmap_unmap_error(mp, cur->bc_ag.pag->pag_agno,
693 * Remove a reference to an extent in the rmap btree.
697 struct xfs_trans *tp,
698 struct xfs_buf *agbp,
699 struct xfs_perag *pag,
702 const struct xfs_owner_info *oinfo)
704 struct xfs_mount *mp = tp->t_mountp;
705 struct xfs_btree_cur *cur;
708 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
711 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
713 error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
715 xfs_btree_del_cursor(cur, error);
720 * A mergeable rmap must have the same owner and the same values for
721 * the unwritten, attr_fork, and bmbt flags. The startblock and
722 * offset are checked separately.
725 xfs_rmap_is_mergeable(
726 struct xfs_rmap_irec *irec,
730 if (irec->rm_owner == XFS_RMAP_OWN_NULL)
732 if (irec->rm_owner != owner)
734 if ((flags & XFS_RMAP_UNWRITTEN) ^
735 (irec->rm_flags & XFS_RMAP_UNWRITTEN))
737 if ((flags & XFS_RMAP_ATTR_FORK) ^
738 (irec->rm_flags & XFS_RMAP_ATTR_FORK))
740 if ((flags & XFS_RMAP_BMBT_BLOCK) ^
741 (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
747 * When we allocate a new block, the first thing we do is add a reference to
748 * the extent in the rmap btree. This takes the form of a [agbno, length,
749 * owner, offset] record. Flags are encoded in the high bits of the offset
754 struct xfs_btree_cur *cur,
758 const struct xfs_owner_info *oinfo)
760 struct xfs_mount *mp = cur->bc_mp;
761 struct xfs_rmap_irec ltrec;
762 struct xfs_rmap_irec gtrec;
769 unsigned int flags = 0;
772 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
774 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
775 (flags & XFS_RMAP_BMBT_BLOCK);
777 flags |= XFS_RMAP_UNWRITTEN;
778 trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
780 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
783 * For the initial lookup, look for an exact match or the left-adjacent
784 * record for our insertion point. This will also give us the record for
785 * start block contiguity tests.
787 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
792 error = xfs_rmap_get_rec(cur, <rec, &have_lt);
795 if (XFS_IS_CORRUPT(mp, have_lt != 1)) {
796 error = -EFSCORRUPTED;
799 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
800 cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
801 ltrec.rm_blockcount, ltrec.rm_owner,
802 ltrec.rm_offset, ltrec.rm_flags);
804 if (!xfs_rmap_is_mergeable(<rec, owner, flags))
808 if (XFS_IS_CORRUPT(mp,
810 ltrec.rm_startblock + ltrec.rm_blockcount > bno)) {
811 error = -EFSCORRUPTED;
816 * Increment the cursor to see if we have a right-adjacent record to our
817 * insertion point. This will give us the record for end block
820 error = xfs_btree_increment(cur, 0, &have_gt);
824 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
827 if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
828 error = -EFSCORRUPTED;
831 if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) {
832 error = -EFSCORRUPTED;
835 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
836 cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
837 gtrec.rm_blockcount, gtrec.rm_owner,
838 gtrec.rm_offset, gtrec.rm_flags);
839 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
844 * Note: cursor currently points one record to the right of ltrec, even
845 * if there is no record in the tree to the right.
848 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
849 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
851 * left edge contiguous, merge into left record.
855 * adding: |aaaaaaaaa|
856 * result: |rrrrrrrrrrrrrrrrrrr|
859 ltrec.rm_blockcount += len;
861 bno + len == gtrec.rm_startblock &&
862 (ignore_off || offset + len == gtrec.rm_offset) &&
863 (unsigned long)ltrec.rm_blockcount + len +
864 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
866 * right edge also contiguous, delete right record
867 * and merge into left record.
869 * ltbno ltlen gtbno gtlen
870 * orig: |ooooooooo| |ooooooooo|
871 * adding: |aaaaaaaaa|
872 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
874 ltrec.rm_blockcount += gtrec.rm_blockcount;
875 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
881 error = xfs_btree_delete(cur, &i);
884 if (XFS_IS_CORRUPT(mp, i != 1)) {
885 error = -EFSCORRUPTED;
890 /* point the cursor back to the left record and update */
891 error = xfs_btree_decrement(cur, 0, &have_gt);
894 error = xfs_rmap_update(cur, <rec);
897 } else if (have_gt &&
898 bno + len == gtrec.rm_startblock &&
899 (ignore_off || offset + len == gtrec.rm_offset)) {
901 * right edge contiguous, merge into right record.
905 * adding: |aaaaaaaaa|
906 * Result: |rrrrrrrrrrrrrrrrrrr|
909 gtrec.rm_startblock = bno;
910 gtrec.rm_blockcount += len;
912 gtrec.rm_offset = offset;
913 error = xfs_rmap_update(cur, >rec);
918 * no contiguous edge with identical owner, insert
919 * new record at current cursor position.
921 cur->bc_rec.r.rm_startblock = bno;
922 cur->bc_rec.r.rm_blockcount = len;
923 cur->bc_rec.r.rm_owner = owner;
924 cur->bc_rec.r.rm_offset = offset;
925 cur->bc_rec.r.rm_flags = flags;
926 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
927 owner, offset, flags);
928 error = xfs_btree_insert(cur, &i);
931 if (XFS_IS_CORRUPT(mp, i != 1)) {
932 error = -EFSCORRUPTED;
937 trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
941 trace_xfs_rmap_map_error(mp, cur->bc_ag.pag->pag_agno,
947 * Add a reference to an extent in the rmap btree.
951 struct xfs_trans *tp,
952 struct xfs_buf *agbp,
953 struct xfs_perag *pag,
956 const struct xfs_owner_info *oinfo)
958 struct xfs_mount *mp = tp->t_mountp;
959 struct xfs_btree_cur *cur;
962 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
965 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
966 error = xfs_rmap_map(cur, bno, len, false, oinfo);
968 xfs_btree_del_cursor(cur, error);
972 #define RMAP_LEFT_CONTIG (1 << 0)
973 #define RMAP_RIGHT_CONTIG (1 << 1)
974 #define RMAP_LEFT_FILLING (1 << 2)
975 #define RMAP_RIGHT_FILLING (1 << 3)
976 #define RMAP_LEFT_VALID (1 << 6)
977 #define RMAP_RIGHT_VALID (1 << 7)
985 * Convert an unwritten extent to a real extent or vice versa.
986 * Does not handle overlapping extents.
990 struct xfs_btree_cur *cur,
994 const struct xfs_owner_info *oinfo)
996 struct xfs_mount *mp = cur->bc_mp;
997 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
998 /* left is 0, right is 1, */
999 /* prev is 2, new is 3 */
1002 uint64_t new_endoff;
1003 unsigned int oldext;
1004 unsigned int newext;
1005 unsigned int flags = 0;
1010 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1011 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1012 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1013 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1014 new_endoff = offset + len;
1015 trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1019 * For the initial lookup, look for an exact match or the left-adjacent
1020 * record for our insertion point. This will also give us the record for
1021 * start block contiguity tests.
1023 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1026 if (XFS_IS_CORRUPT(mp, i != 1)) {
1027 error = -EFSCORRUPTED;
1031 error = xfs_rmap_get_rec(cur, &PREV, &i);
1034 if (XFS_IS_CORRUPT(mp, i != 1)) {
1035 error = -EFSCORRUPTED;
1038 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
1039 cur->bc_ag.pag->pag_agno, PREV.rm_startblock,
1040 PREV.rm_blockcount, PREV.rm_owner,
1041 PREV.rm_offset, PREV.rm_flags);
1043 ASSERT(PREV.rm_offset <= offset);
1044 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1045 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1046 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1049 * Set flags determining what part of the previous oldext allocation
1050 * extent is being replaced by a newext allocation.
1052 if (PREV.rm_offset == offset)
1053 state |= RMAP_LEFT_FILLING;
1054 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1055 state |= RMAP_RIGHT_FILLING;
1058 * Decrement the cursor to see if we have a left-adjacent record to our
1059 * insertion point. This will give us the record for end block
1062 error = xfs_btree_decrement(cur, 0, &i);
1066 state |= RMAP_LEFT_VALID;
1067 error = xfs_rmap_get_rec(cur, &LEFT, &i);
1070 if (XFS_IS_CORRUPT(mp, i != 1)) {
1071 error = -EFSCORRUPTED;
1074 if (XFS_IS_CORRUPT(mp,
1075 LEFT.rm_startblock + LEFT.rm_blockcount >
1077 error = -EFSCORRUPTED;
1080 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
1081 cur->bc_ag.pag->pag_agno, LEFT.rm_startblock,
1082 LEFT.rm_blockcount, LEFT.rm_owner,
1083 LEFT.rm_offset, LEFT.rm_flags);
1084 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1085 LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1086 xfs_rmap_is_mergeable(&LEFT, owner, newext))
1087 state |= RMAP_LEFT_CONTIG;
1091 * Increment the cursor to see if we have a right-adjacent record to our
1092 * insertion point. This will give us the record for end block
1095 error = xfs_btree_increment(cur, 0, &i);
1098 if (XFS_IS_CORRUPT(mp, i != 1)) {
1099 error = -EFSCORRUPTED;
1102 error = xfs_btree_increment(cur, 0, &i);
1106 state |= RMAP_RIGHT_VALID;
1107 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1110 if (XFS_IS_CORRUPT(mp, i != 1)) {
1111 error = -EFSCORRUPTED;
1114 if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1115 error = -EFSCORRUPTED;
1118 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1119 cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
1120 RIGHT.rm_blockcount, RIGHT.rm_owner,
1121 RIGHT.rm_offset, RIGHT.rm_flags);
1122 if (bno + len == RIGHT.rm_startblock &&
1123 offset + len == RIGHT.rm_offset &&
1124 xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1125 state |= RMAP_RIGHT_CONTIG;
1128 /* check that left + prev + right is not too long */
1129 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1130 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1131 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1132 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1133 (unsigned long)LEFT.rm_blockcount + len +
1134 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1135 state &= ~RMAP_RIGHT_CONTIG;
1137 trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
1140 /* reset the cursor back to PREV */
1141 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1144 if (XFS_IS_CORRUPT(mp, i != 1)) {
1145 error = -EFSCORRUPTED;
1150 * Switch out based on the FILLING and CONTIG state bits.
1152 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1153 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1154 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1155 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1157 * Setting all of a previous oldext extent to newext.
1158 * The left and right neighbors are both contiguous with new.
1160 error = xfs_btree_increment(cur, 0, &i);
1163 if (XFS_IS_CORRUPT(mp, i != 1)) {
1164 error = -EFSCORRUPTED;
1167 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1168 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1169 RIGHT.rm_owner, RIGHT.rm_offset,
1171 error = xfs_btree_delete(cur, &i);
1174 if (XFS_IS_CORRUPT(mp, i != 1)) {
1175 error = -EFSCORRUPTED;
1178 error = xfs_btree_decrement(cur, 0, &i);
1181 if (XFS_IS_CORRUPT(mp, i != 1)) {
1182 error = -EFSCORRUPTED;
1185 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1186 PREV.rm_startblock, PREV.rm_blockcount,
1187 PREV.rm_owner, PREV.rm_offset,
1189 error = xfs_btree_delete(cur, &i);
1192 if (XFS_IS_CORRUPT(mp, i != 1)) {
1193 error = -EFSCORRUPTED;
1196 error = xfs_btree_decrement(cur, 0, &i);
1199 if (XFS_IS_CORRUPT(mp, i != 1)) {
1200 error = -EFSCORRUPTED;
1204 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1205 error = xfs_rmap_update(cur, &NEW);
1210 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1212 * Setting all of a previous oldext extent to newext.
1213 * The left neighbor is contiguous, the right is not.
1215 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1216 PREV.rm_startblock, PREV.rm_blockcount,
1217 PREV.rm_owner, PREV.rm_offset,
1219 error = xfs_btree_delete(cur, &i);
1222 if (XFS_IS_CORRUPT(mp, i != 1)) {
1223 error = -EFSCORRUPTED;
1226 error = xfs_btree_decrement(cur, 0, &i);
1229 if (XFS_IS_CORRUPT(mp, i != 1)) {
1230 error = -EFSCORRUPTED;
1234 NEW.rm_blockcount += PREV.rm_blockcount;
1235 error = xfs_rmap_update(cur, &NEW);
1240 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1242 * Setting all of a previous oldext extent to newext.
1243 * The right neighbor is contiguous, the left is not.
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;
1271 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1272 NEW.rm_flags = newext;
1273 error = xfs_rmap_update(cur, &NEW);
1278 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1280 * Setting all of a previous oldext extent to newext.
1281 * Neither the left nor right neighbors are contiguous with
1285 NEW.rm_flags = newext;
1286 error = xfs_rmap_update(cur, &NEW);
1291 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1293 * Setting the first part of a previous oldext extent to newext.
1294 * The left neighbor is contiguous.
1297 NEW.rm_offset += len;
1298 NEW.rm_startblock += len;
1299 NEW.rm_blockcount -= len;
1300 error = xfs_rmap_update(cur, &NEW);
1303 error = xfs_btree_decrement(cur, 0, &i);
1307 NEW.rm_blockcount += len;
1308 error = xfs_rmap_update(cur, &NEW);
1313 case RMAP_LEFT_FILLING:
1315 * Setting the first part of a previous oldext extent to newext.
1316 * The left neighbor is not contiguous.
1319 NEW.rm_startblock += len;
1320 NEW.rm_offset += len;
1321 NEW.rm_blockcount -= len;
1322 error = xfs_rmap_update(cur, &NEW);
1325 NEW.rm_startblock = bno;
1326 NEW.rm_owner = owner;
1327 NEW.rm_offset = offset;
1328 NEW.rm_blockcount = len;
1329 NEW.rm_flags = newext;
1330 cur->bc_rec.r = NEW;
1331 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
1332 len, owner, offset, newext);
1333 error = xfs_btree_insert(cur, &i);
1336 if (XFS_IS_CORRUPT(mp, i != 1)) {
1337 error = -EFSCORRUPTED;
1342 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1344 * Setting the last part of a previous oldext extent to newext.
1345 * The right neighbor is contiguous with the new allocation.
1348 NEW.rm_blockcount -= len;
1349 error = xfs_rmap_update(cur, &NEW);
1352 error = xfs_btree_increment(cur, 0, &i);
1356 NEW.rm_offset = offset;
1357 NEW.rm_startblock = bno;
1358 NEW.rm_blockcount += len;
1359 error = xfs_rmap_update(cur, &NEW);
1364 case RMAP_RIGHT_FILLING:
1366 * Setting the last part of a previous oldext extent to newext.
1367 * The right neighbor is not contiguous.
1370 NEW.rm_blockcount -= len;
1371 error = xfs_rmap_update(cur, &NEW);
1374 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1378 if (XFS_IS_CORRUPT(mp, i != 0)) {
1379 error = -EFSCORRUPTED;
1382 NEW.rm_startblock = bno;
1383 NEW.rm_owner = owner;
1384 NEW.rm_offset = offset;
1385 NEW.rm_blockcount = len;
1386 NEW.rm_flags = newext;
1387 cur->bc_rec.r = NEW;
1388 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
1389 len, owner, offset, newext);
1390 error = xfs_btree_insert(cur, &i);
1393 if (XFS_IS_CORRUPT(mp, i != 1)) {
1394 error = -EFSCORRUPTED;
1401 * Setting the middle part of a previous oldext extent to
1402 * newext. Contiguity is impossible here.
1403 * One extent becomes three extents.
1405 /* new right extent - oldext */
1406 NEW.rm_startblock = bno + len;
1407 NEW.rm_owner = owner;
1408 NEW.rm_offset = new_endoff;
1409 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1411 NEW.rm_flags = PREV.rm_flags;
1412 error = xfs_rmap_update(cur, &NEW);
1415 /* new left extent - oldext */
1417 NEW.rm_blockcount = offset - PREV.rm_offset;
1418 cur->bc_rec.r = NEW;
1419 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
1420 NEW.rm_startblock, NEW.rm_blockcount,
1421 NEW.rm_owner, NEW.rm_offset,
1423 error = xfs_btree_insert(cur, &i);
1426 if (XFS_IS_CORRUPT(mp, i != 1)) {
1427 error = -EFSCORRUPTED;
1431 * Reset the cursor to the position of the new extent
1432 * we are about to insert as we can't trust it after
1433 * the previous insert.
1435 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1439 if (XFS_IS_CORRUPT(mp, i != 0)) {
1440 error = -EFSCORRUPTED;
1443 /* new middle extent - newext */
1444 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1445 cur->bc_rec.r.rm_flags |= newext;
1446 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1447 owner, offset, newext);
1448 error = xfs_btree_insert(cur, &i);
1451 if (XFS_IS_CORRUPT(mp, i != 1)) {
1452 error = -EFSCORRUPTED;
1457 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1458 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1459 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1460 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1461 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1462 case RMAP_LEFT_CONTIG:
1463 case RMAP_RIGHT_CONTIG:
1465 * These cases are all impossible.
1470 trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1474 trace_xfs_rmap_convert_error(cur->bc_mp,
1475 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
1480 * Convert an unwritten extent to a real extent or vice versa. If there is no
1481 * possibility of overlapping extents, delegate to the simpler convert
1485 xfs_rmap_convert_shared(
1486 struct xfs_btree_cur *cur,
1490 const struct xfs_owner_info *oinfo)
1492 struct xfs_mount *mp = cur->bc_mp;
1493 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1494 /* left is 0, right is 1, */
1495 /* prev is 2, new is 3 */
1498 uint64_t new_endoff;
1499 unsigned int oldext;
1500 unsigned int newext;
1501 unsigned int flags = 0;
1506 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1507 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1508 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1509 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1510 new_endoff = offset + len;
1511 trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1515 * For the initial lookup, look for and exact match or the left-adjacent
1516 * record for our insertion point. This will also give us the record for
1517 * start block contiguity tests.
1519 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, oldext,
1523 if (XFS_IS_CORRUPT(mp, i != 1)) {
1524 error = -EFSCORRUPTED;
1528 ASSERT(PREV.rm_offset <= offset);
1529 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1530 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1531 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1534 * Set flags determining what part of the previous oldext allocation
1535 * extent is being replaced by a newext allocation.
1537 if (PREV.rm_offset == offset)
1538 state |= RMAP_LEFT_FILLING;
1539 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1540 state |= RMAP_RIGHT_FILLING;
1542 /* Is there a left record that abuts our range? */
1543 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1548 state |= RMAP_LEFT_VALID;
1549 if (XFS_IS_CORRUPT(mp,
1550 LEFT.rm_startblock + LEFT.rm_blockcount >
1552 error = -EFSCORRUPTED;
1555 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1556 state |= RMAP_LEFT_CONTIG;
1559 /* Is there a right record that abuts our range? */
1560 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1565 state |= RMAP_RIGHT_VALID;
1566 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1569 if (XFS_IS_CORRUPT(mp, i != 1)) {
1570 error = -EFSCORRUPTED;
1573 if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1574 error = -EFSCORRUPTED;
1577 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1578 cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
1579 RIGHT.rm_blockcount, RIGHT.rm_owner,
1580 RIGHT.rm_offset, RIGHT.rm_flags);
1581 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1582 state |= RMAP_RIGHT_CONTIG;
1585 /* check that left + prev + right is not too long */
1586 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1587 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1588 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1589 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1590 (unsigned long)LEFT.rm_blockcount + len +
1591 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1592 state &= ~RMAP_RIGHT_CONTIG;
1594 trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
1597 * Switch out based on the FILLING and CONTIG state bits.
1599 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1600 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1601 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1602 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1604 * Setting all of a previous oldext extent to newext.
1605 * The left and right neighbors are both contiguous with new.
1607 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1608 RIGHT.rm_blockcount, RIGHT.rm_owner,
1609 RIGHT.rm_offset, RIGHT.rm_flags);
1612 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1613 PREV.rm_blockcount, PREV.rm_owner,
1614 PREV.rm_offset, PREV.rm_flags);
1618 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1619 NEW.rm_blockcount, NEW.rm_owner,
1620 NEW.rm_offset, NEW.rm_flags, &i);
1623 if (XFS_IS_CORRUPT(mp, i != 1)) {
1624 error = -EFSCORRUPTED;
1627 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1628 error = xfs_rmap_update(cur, &NEW);
1633 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1635 * Setting all of a previous oldext extent to newext.
1636 * The left neighbor is contiguous, the right is not.
1638 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1639 PREV.rm_blockcount, PREV.rm_owner,
1640 PREV.rm_offset, PREV.rm_flags);
1644 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1645 NEW.rm_blockcount, NEW.rm_owner,
1646 NEW.rm_offset, NEW.rm_flags, &i);
1649 if (XFS_IS_CORRUPT(mp, i != 1)) {
1650 error = -EFSCORRUPTED;
1653 NEW.rm_blockcount += PREV.rm_blockcount;
1654 error = xfs_rmap_update(cur, &NEW);
1659 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1661 * Setting all of a previous oldext extent to newext.
1662 * The right neighbor is contiguous, the left is not.
1664 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1665 RIGHT.rm_blockcount, RIGHT.rm_owner,
1666 RIGHT.rm_offset, RIGHT.rm_flags);
1670 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1671 NEW.rm_blockcount, NEW.rm_owner,
1672 NEW.rm_offset, NEW.rm_flags, &i);
1675 if (XFS_IS_CORRUPT(mp, i != 1)) {
1676 error = -EFSCORRUPTED;
1679 NEW.rm_blockcount += RIGHT.rm_blockcount;
1680 NEW.rm_flags = RIGHT.rm_flags;
1681 error = xfs_rmap_update(cur, &NEW);
1686 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1688 * Setting all of a previous oldext extent to newext.
1689 * Neither the left nor right neighbors are contiguous with
1693 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1694 NEW.rm_blockcount, NEW.rm_owner,
1695 NEW.rm_offset, NEW.rm_flags, &i);
1698 if (XFS_IS_CORRUPT(mp, i != 1)) {
1699 error = -EFSCORRUPTED;
1702 NEW.rm_flags = newext;
1703 error = xfs_rmap_update(cur, &NEW);
1708 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1710 * Setting the first part of a previous oldext extent to newext.
1711 * The left neighbor is contiguous.
1714 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1715 NEW.rm_blockcount, NEW.rm_owner,
1716 NEW.rm_offset, NEW.rm_flags);
1719 NEW.rm_offset += len;
1720 NEW.rm_startblock += len;
1721 NEW.rm_blockcount -= len;
1722 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1723 NEW.rm_blockcount, NEW.rm_owner,
1724 NEW.rm_offset, NEW.rm_flags);
1728 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1729 NEW.rm_blockcount, NEW.rm_owner,
1730 NEW.rm_offset, NEW.rm_flags, &i);
1733 if (XFS_IS_CORRUPT(mp, i != 1)) {
1734 error = -EFSCORRUPTED;
1737 NEW.rm_blockcount += len;
1738 error = xfs_rmap_update(cur, &NEW);
1743 case RMAP_LEFT_FILLING:
1745 * Setting the first part of a previous oldext extent to newext.
1746 * The left neighbor is not contiguous.
1749 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1750 NEW.rm_blockcount, NEW.rm_owner,
1751 NEW.rm_offset, NEW.rm_flags);
1754 NEW.rm_offset += len;
1755 NEW.rm_startblock += len;
1756 NEW.rm_blockcount -= len;
1757 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1758 NEW.rm_blockcount, NEW.rm_owner,
1759 NEW.rm_offset, NEW.rm_flags);
1762 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1767 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1769 * Setting the last part of a previous oldext extent to newext.
1770 * The right neighbor is contiguous with the new allocation.
1773 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1774 NEW.rm_blockcount, NEW.rm_owner,
1775 NEW.rm_offset, NEW.rm_flags, &i);
1778 if (XFS_IS_CORRUPT(mp, i != 1)) {
1779 error = -EFSCORRUPTED;
1782 NEW.rm_blockcount = offset - NEW.rm_offset;
1783 error = xfs_rmap_update(cur, &NEW);
1787 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1788 NEW.rm_blockcount, NEW.rm_owner,
1789 NEW.rm_offset, NEW.rm_flags);
1792 NEW.rm_offset = offset;
1793 NEW.rm_startblock = bno;
1794 NEW.rm_blockcount += len;
1795 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1796 NEW.rm_blockcount, NEW.rm_owner,
1797 NEW.rm_offset, NEW.rm_flags);
1802 case RMAP_RIGHT_FILLING:
1804 * Setting the last part of a previous oldext extent to newext.
1805 * The right neighbor is not contiguous.
1808 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1809 NEW.rm_blockcount, NEW.rm_owner,
1810 NEW.rm_offset, NEW.rm_flags, &i);
1813 if (XFS_IS_CORRUPT(mp, i != 1)) {
1814 error = -EFSCORRUPTED;
1817 NEW.rm_blockcount -= len;
1818 error = xfs_rmap_update(cur, &NEW);
1821 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1828 * Setting the middle part of a previous oldext extent to
1829 * newext. Contiguity is impossible here.
1830 * One extent becomes three extents.
1832 /* new right extent - oldext */
1833 NEW.rm_startblock = bno + len;
1834 NEW.rm_owner = owner;
1835 NEW.rm_offset = new_endoff;
1836 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1838 NEW.rm_flags = PREV.rm_flags;
1839 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1840 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1844 /* new left extent - oldext */
1846 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1847 NEW.rm_blockcount, NEW.rm_owner,
1848 NEW.rm_offset, NEW.rm_flags, &i);
1851 if (XFS_IS_CORRUPT(mp, i != 1)) {
1852 error = -EFSCORRUPTED;
1855 NEW.rm_blockcount = offset - NEW.rm_offset;
1856 error = xfs_rmap_update(cur, &NEW);
1859 /* new middle extent - newext */
1860 NEW.rm_startblock = bno;
1861 NEW.rm_blockcount = len;
1862 NEW.rm_owner = owner;
1863 NEW.rm_offset = offset;
1864 NEW.rm_flags = newext;
1865 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1866 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1872 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1873 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1874 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1875 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1876 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1877 case RMAP_LEFT_CONTIG:
1878 case RMAP_RIGHT_CONTIG:
1880 * These cases are all impossible.
1885 trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1889 trace_xfs_rmap_convert_error(cur->bc_mp,
1890 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
1900 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1901 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1902 * that the prev/next records in the btree might belong to another owner.
1903 * Therefore we must use delete+insert to alter any of the key fields.
1905 * For every other situation there can only be one owner for a given extent,
1906 * so we can call the regular _free function.
1909 xfs_rmap_unmap_shared(
1910 struct xfs_btree_cur *cur,
1914 const struct xfs_owner_info *oinfo)
1916 struct xfs_mount *mp = cur->bc_mp;
1917 struct xfs_rmap_irec ltrec;
1925 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1927 flags |= XFS_RMAP_UNWRITTEN;
1928 trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
1932 * We should always have a left record because there's a static record
1933 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1934 * will not ever be removed from the tree.
1936 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1940 if (XFS_IS_CORRUPT(mp, i != 1)) {
1941 error = -EFSCORRUPTED;
1944 ltoff = ltrec.rm_offset;
1946 /* Make sure the extent we found covers the entire freeing range. */
1947 if (XFS_IS_CORRUPT(mp,
1948 ltrec.rm_startblock > bno ||
1949 ltrec.rm_startblock + ltrec.rm_blockcount <
1951 error = -EFSCORRUPTED;
1955 /* Make sure the owner matches what we expect to find in the tree. */
1956 if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) {
1957 error = -EFSCORRUPTED;
1961 /* Make sure the unwritten flag matches. */
1962 if (XFS_IS_CORRUPT(mp,
1963 (flags & XFS_RMAP_UNWRITTEN) !=
1964 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) {
1965 error = -EFSCORRUPTED;
1969 /* Check the offset. */
1970 if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) {
1971 error = -EFSCORRUPTED;
1974 if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) {
1975 error = -EFSCORRUPTED;
1979 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
1980 /* Exact match, simply remove the record from rmap tree. */
1981 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1982 ltrec.rm_blockcount, ltrec.rm_owner,
1983 ltrec.rm_offset, ltrec.rm_flags);
1986 } else if (ltrec.rm_startblock == bno) {
1988 * Overlap left hand side of extent: move the start, trim the
1989 * length and update the current record.
1992 * Orig: |oooooooooooooooooooo|
1993 * Freeing: |fffffffff|
1994 * Result: |rrrrrrrrrr|
1998 /* Delete prev rmap. */
1999 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2000 ltrec.rm_blockcount, ltrec.rm_owner,
2001 ltrec.rm_offset, ltrec.rm_flags);
2005 /* Add an rmap at the new offset. */
2006 ltrec.rm_startblock += len;
2007 ltrec.rm_blockcount -= len;
2008 ltrec.rm_offset += len;
2009 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
2010 ltrec.rm_blockcount, ltrec.rm_owner,
2011 ltrec.rm_offset, ltrec.rm_flags);
2014 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
2016 * Overlap right hand side of extent: trim the length and
2017 * update the current record.
2020 * Orig: |oooooooooooooooooooo|
2021 * Freeing: |fffffffff|
2022 * Result: |rrrrrrrrrr|
2025 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2026 ltrec.rm_blockcount, ltrec.rm_owner,
2027 ltrec.rm_offset, ltrec.rm_flags, &i);
2030 if (XFS_IS_CORRUPT(mp, i != 1)) {
2031 error = -EFSCORRUPTED;
2034 ltrec.rm_blockcount -= len;
2035 error = xfs_rmap_update(cur, <rec);
2040 * Overlap middle of extent: trim the length of the existing
2041 * record to the length of the new left-extent size, increment
2042 * the insertion position so we can insert a new record
2043 * containing the remaining right-extent space.
2046 * Orig: |oooooooooooooooooooo|
2047 * Freeing: |fffffffff|
2048 * Result: |rrrrr| |rrrr|
2051 xfs_extlen_t orig_len = ltrec.rm_blockcount;
2053 /* Shrink the left side of the rmap */
2054 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2055 ltrec.rm_blockcount, ltrec.rm_owner,
2056 ltrec.rm_offset, ltrec.rm_flags, &i);
2059 if (XFS_IS_CORRUPT(mp, i != 1)) {
2060 error = -EFSCORRUPTED;
2063 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
2064 error = xfs_rmap_update(cur, <rec);
2068 /* Add an rmap at the new offset */
2069 error = xfs_rmap_insert(cur, bno + len,
2070 orig_len - len - ltrec.rm_blockcount,
2071 ltrec.rm_owner, offset + len,
2077 trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2081 trace_xfs_rmap_unmap_error(cur->bc_mp,
2082 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2087 * Find an extent in the rmap btree and map it. For rmap extent types that
2088 * can overlap (data fork rmaps on reflink filesystems) we must be careful
2089 * that the prev/next records in the btree might belong to another owner.
2090 * Therefore we must use delete+insert to alter any of the key fields.
2092 * For every other situation there can only be one owner for a given extent,
2093 * so we can call the regular _alloc function.
2096 xfs_rmap_map_shared(
2097 struct xfs_btree_cur *cur,
2101 const struct xfs_owner_info *oinfo)
2103 struct xfs_mount *mp = cur->bc_mp;
2104 struct xfs_rmap_irec ltrec;
2105 struct xfs_rmap_irec gtrec;
2112 unsigned int flags = 0;
2114 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2116 flags |= XFS_RMAP_UNWRITTEN;
2117 trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
2120 /* Is there a left record that abuts our range? */
2121 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
2126 !xfs_rmap_is_mergeable(<rec, owner, flags))
2129 /* Is there a right record that abuts our range? */
2130 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
2135 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
2138 if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
2139 error = -EFSCORRUPTED;
2142 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
2143 cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
2144 gtrec.rm_blockcount, gtrec.rm_owner,
2145 gtrec.rm_offset, gtrec.rm_flags);
2147 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
2152 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
2153 ltrec.rm_offset + ltrec.rm_blockcount == offset) {
2155 * Left edge contiguous, merge into left record.
2159 * adding: |aaaaaaaaa|
2160 * result: |rrrrrrrrrrrrrrrrrrr|
2163 ltrec.rm_blockcount += len;
2165 bno + len == gtrec.rm_startblock &&
2166 offset + len == gtrec.rm_offset) {
2168 * Right edge also contiguous, delete right record
2169 * and merge into left record.
2171 * ltbno ltlen gtbno gtlen
2172 * orig: |ooooooooo| |ooooooooo|
2173 * adding: |aaaaaaaaa|
2174 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
2176 ltrec.rm_blockcount += gtrec.rm_blockcount;
2177 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2178 gtrec.rm_blockcount, gtrec.rm_owner,
2179 gtrec.rm_offset, gtrec.rm_flags);
2184 /* Point the cursor back to the left record and update. */
2185 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2186 ltrec.rm_blockcount, ltrec.rm_owner,
2187 ltrec.rm_offset, ltrec.rm_flags, &i);
2190 if (XFS_IS_CORRUPT(mp, i != 1)) {
2191 error = -EFSCORRUPTED;
2195 error = xfs_rmap_update(cur, <rec);
2198 } else if (have_gt &&
2199 bno + len == gtrec.rm_startblock &&
2200 offset + len == gtrec.rm_offset) {
2202 * Right edge contiguous, merge into right record.
2206 * adding: |aaaaaaaaa|
2207 * Result: |rrrrrrrrrrrrrrrrrrr|
2210 /* Delete the old record. */
2211 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2212 gtrec.rm_blockcount, gtrec.rm_owner,
2213 gtrec.rm_offset, gtrec.rm_flags);
2217 /* Move the start and re-add it. */
2218 gtrec.rm_startblock = bno;
2219 gtrec.rm_blockcount += len;
2220 gtrec.rm_offset = offset;
2221 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2222 gtrec.rm_blockcount, gtrec.rm_owner,
2223 gtrec.rm_offset, gtrec.rm_flags);
2228 * No contiguous edge with identical owner, insert
2229 * new record at current cursor position.
2231 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2236 trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2240 trace_xfs_rmap_map_error(cur->bc_mp,
2241 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2245 /* Insert a raw rmap into the rmapbt. */
2248 struct xfs_btree_cur *cur,
2249 struct xfs_rmap_irec *rmap)
2251 struct xfs_owner_info oinfo;
2253 oinfo.oi_owner = rmap->rm_owner;
2254 oinfo.oi_offset = rmap->rm_offset;
2256 if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
2257 oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
2258 if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
2259 oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
2261 if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2262 return xfs_rmap_map(cur, rmap->rm_startblock,
2263 rmap->rm_blockcount,
2264 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2267 return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2268 rmap->rm_blockcount,
2269 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2273 struct xfs_rmap_query_range_info {
2274 xfs_rmap_query_range_fn fn;
2278 /* Format btree record and pass to our callback. */
2280 xfs_rmap_query_range_helper(
2281 struct xfs_btree_cur *cur,
2282 union xfs_btree_rec *rec,
2285 struct xfs_rmap_query_range_info *query = priv;
2286 struct xfs_rmap_irec irec;
2289 error = xfs_rmap_btrec_to_irec(rec, &irec);
2292 return query->fn(cur, &irec, query->priv);
2295 /* Find all rmaps between two keys. */
2297 xfs_rmap_query_range(
2298 struct xfs_btree_cur *cur,
2299 struct xfs_rmap_irec *low_rec,
2300 struct xfs_rmap_irec *high_rec,
2301 xfs_rmap_query_range_fn fn,
2304 union xfs_btree_irec low_brec;
2305 union xfs_btree_irec high_brec;
2306 struct xfs_rmap_query_range_info query;
2308 low_brec.r = *low_rec;
2309 high_brec.r = *high_rec;
2312 return xfs_btree_query_range(cur, &low_brec, &high_brec,
2313 xfs_rmap_query_range_helper, &query);
2316 /* Find all rmaps. */
2319 struct xfs_btree_cur *cur,
2320 xfs_rmap_query_range_fn fn,
2323 struct xfs_rmap_query_range_info query;
2327 return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2330 /* Clean up after calling xfs_rmap_finish_one. */
2332 xfs_rmap_finish_one_cleanup(
2333 struct xfs_trans *tp,
2334 struct xfs_btree_cur *rcur,
2337 struct xfs_buf *agbp;
2341 agbp = rcur->bc_ag.agbp;
2342 xfs_btree_del_cursor(rcur, error);
2344 xfs_trans_brelse(tp, agbp);
2348 * Process one of the deferred rmap operations. We pass back the
2349 * btree cursor to maintain our lock on the rmapbt between calls.
2350 * This saves time and eliminates a buffer deadlock between the
2351 * superblock and the AGF because we'll always grab them in the same
2355 xfs_rmap_finish_one(
2356 struct xfs_trans *tp,
2357 enum xfs_rmap_intent_type type,
2360 xfs_fileoff_t startoff,
2361 xfs_fsblock_t startblock,
2362 xfs_filblks_t blockcount,
2364 struct xfs_btree_cur **pcur)
2366 struct xfs_mount *mp = tp->t_mountp;
2367 struct xfs_perag *pag;
2368 struct xfs_btree_cur *rcur;
2369 struct xfs_buf *agbp = NULL;
2371 struct xfs_owner_info oinfo;
2375 pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, startblock));
2376 bno = XFS_FSB_TO_AGBNO(mp, startblock);
2378 trace_xfs_rmap_deferred(mp, pag->pag_agno, type, bno, owner, whichfork,
2379 startoff, blockcount, state);
2381 if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE)) {
2388 * If we haven't gotten a cursor or the cursor AG doesn't match
2389 * the startblock, get one now.
2392 if (rcur != NULL && rcur->bc_ag.pag != pag) {
2393 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2399 * Refresh the freelist before we start changing the
2400 * rmapbt, because a shape change could cause us to
2403 error = xfs_free_extent_fix_freelist(tp, pag, &agbp);
2406 if (XFS_IS_CORRUPT(tp->t_mountp, !agbp)) {
2407 error = -EFSCORRUPTED;
2411 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
2415 xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2416 unwritten = state == XFS_EXT_UNWRITTEN;
2417 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2420 case XFS_RMAP_ALLOC:
2422 error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2424 case XFS_RMAP_MAP_SHARED:
2425 error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2429 case XFS_RMAP_UNMAP:
2430 error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2433 case XFS_RMAP_UNMAP_SHARED:
2434 error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2437 case XFS_RMAP_CONVERT:
2438 error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2441 case XFS_RMAP_CONVERT_SHARED:
2442 error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2443 !unwritten, &oinfo);
2447 error = -EFSCORRUPTED;
2455 * Don't defer an rmap if we aren't an rmap filesystem.
2458 xfs_rmap_update_is_needed(
2459 struct xfs_mount *mp,
2462 return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK;
2466 * Record a rmap intent; the list is kept sorted first by AG and then by
2471 struct xfs_trans *tp,
2472 enum xfs_rmap_intent_type type,
2475 struct xfs_bmbt_irec *bmap)
2477 struct xfs_rmap_intent *ri;
2479 trace_xfs_rmap_defer(tp->t_mountp,
2480 XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock),
2482 XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock),
2485 bmap->br_blockcount,
2488 ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_NOFS);
2489 INIT_LIST_HEAD(&ri->ri_list);
2491 ri->ri_owner = owner;
2492 ri->ri_whichfork = whichfork;
2493 ri->ri_bmap = *bmap;
2495 xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
2498 /* Map an extent into a file. */
2500 xfs_rmap_map_extent(
2501 struct xfs_trans *tp,
2502 struct xfs_inode *ip,
2504 struct xfs_bmbt_irec *PREV)
2506 enum xfs_rmap_intent_type type = XFS_RMAP_MAP;
2508 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2511 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2512 type = XFS_RMAP_MAP_SHARED;
2514 __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2517 /* Unmap an extent out of a file. */
2519 xfs_rmap_unmap_extent(
2520 struct xfs_trans *tp,
2521 struct xfs_inode *ip,
2523 struct xfs_bmbt_irec *PREV)
2525 enum xfs_rmap_intent_type type = XFS_RMAP_UNMAP;
2527 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2530 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2531 type = XFS_RMAP_UNMAP_SHARED;
2533 __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2537 * Convert a data fork extent from unwritten to real or vice versa.
2539 * Note that tp can be NULL here as no transaction is used for COW fork
2540 * unwritten conversion.
2543 xfs_rmap_convert_extent(
2544 struct xfs_mount *mp,
2545 struct xfs_trans *tp,
2546 struct xfs_inode *ip,
2548 struct xfs_bmbt_irec *PREV)
2550 enum xfs_rmap_intent_type type = XFS_RMAP_CONVERT;
2552 if (!xfs_rmap_update_is_needed(mp, whichfork))
2555 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2556 type = XFS_RMAP_CONVERT_SHARED;
2558 __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2561 /* Schedule the creation of an rmap for non-file data. */
2563 xfs_rmap_alloc_extent(
2564 struct xfs_trans *tp,
2565 xfs_agnumber_t agno,
2570 struct xfs_bmbt_irec bmap;
2572 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2575 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2576 bmap.br_blockcount = len;
2577 bmap.br_startoff = 0;
2578 bmap.br_state = XFS_EXT_NORM;
2580 __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
2583 /* Schedule the deletion of an rmap for non-file data. */
2585 xfs_rmap_free_extent(
2586 struct xfs_trans *tp,
2587 xfs_agnumber_t agno,
2592 struct xfs_bmbt_irec bmap;
2594 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2597 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2598 bmap.br_blockcount = len;
2599 bmap.br_startoff = 0;
2600 bmap.br_state = XFS_EXT_NORM;
2602 __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
2605 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2608 const struct xfs_rmap_irec *a,
2609 const struct xfs_rmap_irec *b)
2614 oa = xfs_rmap_irec_offset_pack(a);
2615 ob = xfs_rmap_irec_offset_pack(b);
2617 if (a->rm_startblock < b->rm_startblock)
2619 else if (a->rm_startblock > b->rm_startblock)
2621 else if (a->rm_owner < b->rm_owner)
2623 else if (a->rm_owner > b->rm_owner)
2633 /* Is there a record covering a given extent? */
2635 xfs_rmap_has_record(
2636 struct xfs_btree_cur *cur,
2641 union xfs_btree_irec low;
2642 union xfs_btree_irec high;
2644 memset(&low, 0, sizeof(low));
2645 low.r.rm_startblock = bno;
2646 memset(&high, 0xFF, sizeof(high));
2647 high.r.rm_startblock = bno + len - 1;
2649 return xfs_btree_has_record(cur, &low, &high, exists);
2653 * Is there a record for this owner completely covering a given physical
2654 * extent? If so, *has_rmap will be set to true. If there is no record
2655 * or the record only covers part of the range, we set *has_rmap to false.
2656 * This function doesn't perform range lookups or offset checks, so it is
2657 * not suitable for checking data fork blocks.
2660 xfs_rmap_record_exists(
2661 struct xfs_btree_cur *cur,
2664 const struct xfs_owner_info *oinfo,
2671 struct xfs_rmap_irec irec;
2674 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2675 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
2676 (flags & XFS_RMAP_BMBT_BLOCK));
2678 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
2687 error = xfs_rmap_get_rec(cur, &irec, &has_record);
2695 *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
2696 irec.rm_startblock + irec.rm_blockcount >= bno + len);
2700 struct xfs_rmap_key_state {
2706 /* For each rmap given, figure out if it doesn't match the key we want. */
2708 xfs_rmap_has_other_keys_helper(
2709 struct xfs_btree_cur *cur,
2710 struct xfs_rmap_irec *rec,
2713 struct xfs_rmap_key_state *rks = priv;
2715 if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset &&
2716 ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags)
2722 * Given an extent and some owner info, can we find records overlapping
2723 * the extent whose owner info does not match the given owner?
2726 xfs_rmap_has_other_keys(
2727 struct xfs_btree_cur *cur,
2730 const struct xfs_owner_info *oinfo,
2733 struct xfs_rmap_irec low = {0};
2734 struct xfs_rmap_irec high;
2735 struct xfs_rmap_key_state rks;
2738 xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags);
2741 low.rm_startblock = bno;
2742 memset(&high, 0xFF, sizeof(high));
2743 high.rm_startblock = bno + len - 1;
2745 error = xfs_rmap_query_range(cur, &low, &high,
2746 xfs_rmap_has_other_keys_helper, &rks);
2747 if (error == -ECANCELED) {
2755 const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
2756 .oi_owner = XFS_RMAP_OWN_NULL,
2758 const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
2759 .oi_owner = XFS_RMAP_OWN_UNKNOWN,
2761 const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
2762 .oi_owner = XFS_RMAP_OWN_FS,
2764 const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
2765 .oi_owner = XFS_RMAP_OWN_LOG,
2767 const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
2768 .oi_owner = XFS_RMAP_OWN_AG,
2770 const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
2771 .oi_owner = XFS_RMAP_OWN_INOBT,
2773 const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
2774 .oi_owner = XFS_RMAP_OWN_INODES,
2776 const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
2777 .oi_owner = XFS_RMAP_OWN_REFC,
2779 const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
2780 .oi_owner = XFS_RMAP_OWN_COW,