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"
14 #include "xfs_mount.h"
15 #include "xfs_defer.h"
16 #include "xfs_da_format.h"
17 #include "xfs_da_btree.h"
18 #include "xfs_btree.h"
19 #include "xfs_trans.h"
20 #include "xfs_alloc.h"
22 #include "xfs_rmap_btree.h"
23 #include "xfs_trans_space.h"
24 #include "xfs_trace.h"
25 #include "xfs_errortag.h"
26 #include "xfs_error.h"
27 #include "xfs_extent_busy.h"
29 #include "xfs_inode.h"
30 #include "xfs_ialloc.h"
33 * Lookup the first record less than or equal to [bno, len, owner, offset]
34 * in the btree given by cur.
38 struct xfs_btree_cur *cur,
46 cur->bc_rec.r.rm_startblock = bno;
47 cur->bc_rec.r.rm_blockcount = len;
48 cur->bc_rec.r.rm_owner = owner;
49 cur->bc_rec.r.rm_offset = offset;
50 cur->bc_rec.r.rm_flags = flags;
51 return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
55 * Lookup the record exactly matching [bno, len, owner, offset]
56 * in the btree given by cur.
60 struct xfs_btree_cur *cur,
68 cur->bc_rec.r.rm_startblock = bno;
69 cur->bc_rec.r.rm_blockcount = len;
70 cur->bc_rec.r.rm_owner = owner;
71 cur->bc_rec.r.rm_offset = offset;
72 cur->bc_rec.r.rm_flags = flags;
73 return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
77 * Update the record referred to by cur to the value given
78 * by [bno, len, owner, offset].
79 * This either works (return 0) or gets an EFSCORRUPTED error.
83 struct xfs_btree_cur *cur,
84 struct xfs_rmap_irec *irec)
86 union xfs_btree_rec rec;
89 trace_xfs_rmap_update(cur->bc_mp, cur->bc_private.a.agno,
90 irec->rm_startblock, irec->rm_blockcount,
91 irec->rm_owner, irec->rm_offset, irec->rm_flags);
93 rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
94 rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
95 rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
96 rec.rmap.rm_offset = cpu_to_be64(
97 xfs_rmap_irec_offset_pack(irec));
98 error = xfs_btree_update(cur, &rec);
100 trace_xfs_rmap_update_error(cur->bc_mp,
101 cur->bc_private.a.agno, error, _RET_IP_);
107 struct xfs_btree_cur *rcur,
117 trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
118 len, owner, offset, flags);
120 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
123 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 0, done);
125 rcur->bc_rec.r.rm_startblock = agbno;
126 rcur->bc_rec.r.rm_blockcount = len;
127 rcur->bc_rec.r.rm_owner = owner;
128 rcur->bc_rec.r.rm_offset = offset;
129 rcur->bc_rec.r.rm_flags = flags;
130 error = xfs_btree_insert(rcur, &i);
133 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
136 trace_xfs_rmap_insert_error(rcur->bc_mp,
137 rcur->bc_private.a.agno, error, _RET_IP_);
143 struct xfs_btree_cur *rcur,
153 trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
154 len, owner, offset, flags);
156 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
159 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
161 error = xfs_btree_delete(rcur, &i);
164 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
167 trace_xfs_rmap_delete_error(rcur->bc_mp,
168 rcur->bc_private.a.agno, error, _RET_IP_);
172 /* Convert an internal btree record to an rmap record. */
174 xfs_rmap_btrec_to_irec(
175 union xfs_btree_rec *rec,
176 struct xfs_rmap_irec *irec)
179 irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
180 irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
181 irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
182 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
187 * Get the data from the pointed-to record.
191 struct xfs_btree_cur *cur,
192 struct xfs_rmap_irec *irec,
195 struct xfs_mount *mp = cur->bc_mp;
196 xfs_agnumber_t agno = cur->bc_private.a.agno;
197 union xfs_btree_rec *rec;
200 error = xfs_btree_get_rec(cur, &rec, stat);
204 if (xfs_rmap_btrec_to_irec(rec, irec))
207 if (irec->rm_blockcount == 0)
209 if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
210 if (irec->rm_owner != XFS_RMAP_OWN_FS)
212 if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
215 /* check for valid extent range, including overflow */
216 if (!xfs_verify_agbno(mp, agno, irec->rm_startblock))
218 if (irec->rm_startblock >
219 irec->rm_startblock + irec->rm_blockcount)
221 if (!xfs_verify_agbno(mp, agno,
222 irec->rm_startblock + irec->rm_blockcount - 1))
226 if (!(xfs_verify_ino(mp, irec->rm_owner) ||
227 (irec->rm_owner <= XFS_RMAP_OWN_FS &&
228 irec->rm_owner >= XFS_RMAP_OWN_MIN)))
234 "Reverse Mapping BTree record corruption in AG %d detected!",
237 "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
238 irec->rm_owner, irec->rm_flags, irec->rm_startblock,
239 irec->rm_blockcount);
240 return -EFSCORRUPTED;
243 struct xfs_find_left_neighbor_info {
244 struct xfs_rmap_irec high;
245 struct xfs_rmap_irec *irec;
249 /* For each rmap given, figure out if it matches the key we want. */
251 xfs_rmap_find_left_neighbor_helper(
252 struct xfs_btree_cur *cur,
253 struct xfs_rmap_irec *rec,
256 struct xfs_find_left_neighbor_info *info = priv;
258 trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
259 cur->bc_private.a.agno, rec->rm_startblock,
260 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
263 if (rec->rm_owner != info->high.rm_owner)
264 return XFS_BTREE_QUERY_RANGE_CONTINUE;
265 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
266 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
267 rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
268 return XFS_BTREE_QUERY_RANGE_CONTINUE;
272 return XFS_BTREE_QUERY_RANGE_ABORT;
276 * Find the record to the left of the given extent, being careful only to
277 * return a match with the same owner and adjacent physical and logical
281 xfs_rmap_find_left_neighbor(
282 struct xfs_btree_cur *cur,
287 struct xfs_rmap_irec *irec,
290 struct xfs_find_left_neighbor_info info;
296 info.high.rm_startblock = bno - 1;
297 info.high.rm_owner = owner;
298 if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
299 !(flags & XFS_RMAP_BMBT_BLOCK)) {
302 info.high.rm_offset = offset - 1;
304 info.high.rm_offset = 0;
305 info.high.rm_flags = flags;
306 info.high.rm_blockcount = 0;
310 trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
311 cur->bc_private.a.agno, bno, 0, owner, offset, flags);
313 error = xfs_rmap_query_range(cur, &info.high, &info.high,
314 xfs_rmap_find_left_neighbor_helper, &info);
315 if (error == XFS_BTREE_QUERY_RANGE_ABORT)
318 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
319 cur->bc_private.a.agno, irec->rm_startblock,
320 irec->rm_blockcount, irec->rm_owner,
321 irec->rm_offset, irec->rm_flags);
325 /* For each rmap given, figure out if it matches the key we want. */
327 xfs_rmap_lookup_le_range_helper(
328 struct xfs_btree_cur *cur,
329 struct xfs_rmap_irec *rec,
332 struct xfs_find_left_neighbor_info *info = priv;
334 trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
335 cur->bc_private.a.agno, rec->rm_startblock,
336 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
339 if (rec->rm_owner != info->high.rm_owner)
340 return XFS_BTREE_QUERY_RANGE_CONTINUE;
341 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
342 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
343 (rec->rm_offset > info->high.rm_offset ||
344 rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
345 return XFS_BTREE_QUERY_RANGE_CONTINUE;
349 return XFS_BTREE_QUERY_RANGE_ABORT;
353 * Find the record to the left of the given extent, being careful only to
354 * return a match with the same owner and overlapping physical and logical
355 * block ranges. This is the overlapping-interval version of
356 * xfs_rmap_lookup_le.
359 xfs_rmap_lookup_le_range(
360 struct xfs_btree_cur *cur,
365 struct xfs_rmap_irec *irec,
368 struct xfs_find_left_neighbor_info info;
371 info.high.rm_startblock = bno;
372 info.high.rm_owner = owner;
373 if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
374 info.high.rm_offset = offset;
376 info.high.rm_offset = 0;
377 info.high.rm_flags = flags;
378 info.high.rm_blockcount = 0;
383 trace_xfs_rmap_lookup_le_range(cur->bc_mp,
384 cur->bc_private.a.agno, bno, 0, owner, offset, flags);
385 error = xfs_rmap_query_range(cur, &info.high, &info.high,
386 xfs_rmap_lookup_le_range_helper, &info);
387 if (error == XFS_BTREE_QUERY_RANGE_ABORT)
390 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
391 cur->bc_private.a.agno, irec->rm_startblock,
392 irec->rm_blockcount, irec->rm_owner,
393 irec->rm_offset, irec->rm_flags);
398 * Perform all the relevant owner checks for a removal op. If we're doing an
399 * unknown-owner removal then we have no owner information to check.
402 xfs_rmap_free_check_owner(
403 struct xfs_mount *mp,
405 struct xfs_rmap_irec *rec,
413 if (owner == XFS_RMAP_OWN_UNKNOWN)
416 /* Make sure the unwritten flag matches. */
417 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
418 (rec->rm_flags & XFS_RMAP_UNWRITTEN), out);
420 /* Make sure the owner matches what we expect to find in the tree. */
421 XFS_WANT_CORRUPTED_GOTO(mp, owner == rec->rm_owner, out);
423 /* Check the offset, if necessary. */
424 if (XFS_RMAP_NON_INODE_OWNER(owner))
427 if (flags & XFS_RMAP_BMBT_BLOCK) {
428 XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_flags & XFS_RMAP_BMBT_BLOCK,
431 XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_offset <= offset, out);
432 XFS_WANT_CORRUPTED_GOTO(mp,
433 ltoff + rec->rm_blockcount >= offset + len,
442 * Find the extent in the rmap btree and remove it.
444 * The record we find should always be an exact match for the extent that we're
445 * looking for, since we insert them into the btree without modification.
447 * Special Case #1: when growing the filesystem, we "free" an extent when
448 * growing the last AG. This extent is new space and so it is not tracked as
449 * used space in the btree. The growfs code will pass in an owner of
450 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
451 * extent. We verify that - the extent lookup result in a record that does not
454 * Special Case #2: EFIs do not record the owner of the extent, so when
455 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
456 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
457 * corruption checks during log recovery.
461 struct xfs_btree_cur *cur,
465 struct xfs_owner_info *oinfo)
467 struct xfs_mount *mp = cur->bc_mp;
468 struct xfs_rmap_irec ltrec;
477 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
478 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
479 (flags & XFS_RMAP_BMBT_BLOCK);
481 flags |= XFS_RMAP_UNWRITTEN;
482 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
486 * We should always have a left record because there's a static record
487 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
488 * will not ever be removed from the tree.
490 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i);
493 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
495 error = xfs_rmap_get_rec(cur, <rec, &i);
498 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
499 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
500 cur->bc_private.a.agno, ltrec.rm_startblock,
501 ltrec.rm_blockcount, ltrec.rm_owner,
502 ltrec.rm_offset, ltrec.rm_flags);
503 ltoff = ltrec.rm_offset;
506 * For growfs, the incoming extent must be beyond the left record we
507 * just found as it is new space and won't be used by anyone. This is
508 * just a corruption check as we don't actually do anything with this
509 * extent. Note that we need to use >= instead of > because it might
510 * be the case that the "left" extent goes all the way to EOFS.
512 if (owner == XFS_RMAP_OWN_NULL) {
513 XFS_WANT_CORRUPTED_GOTO(mp, bno >= ltrec.rm_startblock +
514 ltrec.rm_blockcount, out_error);
519 * If we're doing an unknown-owner removal for EFI recovery, we expect
520 * to find the full range in the rmapbt or nothing at all. If we
521 * don't find any rmaps overlapping either end of the range, we're
522 * done. Hopefully this means that the EFI creator already queued
523 * (and finished) a RUI to remove the rmap.
525 if (owner == XFS_RMAP_OWN_UNKNOWN &&
526 ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
527 struct xfs_rmap_irec rtrec;
529 error = xfs_btree_increment(cur, 0, &i);
534 error = xfs_rmap_get_rec(cur, &rtrec, &i);
537 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
538 if (rtrec.rm_startblock >= bno + len)
542 /* Make sure the extent we found covers the entire freeing range. */
543 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
544 ltrec.rm_startblock + ltrec.rm_blockcount >=
545 bno + len, out_error);
547 /* Check owner information. */
548 error = xfs_rmap_free_check_owner(mp, ltoff, <rec, len, owner,
553 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
554 /* exact match, simply remove the record from rmap tree */
555 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
556 ltrec.rm_startblock, ltrec.rm_blockcount,
557 ltrec.rm_owner, ltrec.rm_offset,
559 error = xfs_btree_delete(cur, &i);
562 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
563 } else if (ltrec.rm_startblock == bno) {
565 * overlap left hand side of extent: move the start, trim the
566 * length and update the current record.
569 * Orig: |oooooooooooooooooooo|
570 * Freeing: |fffffffff|
571 * Result: |rrrrrrrrrr|
574 ltrec.rm_startblock += len;
575 ltrec.rm_blockcount -= len;
577 ltrec.rm_offset += len;
578 error = xfs_rmap_update(cur, <rec);
581 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
583 * overlap right hand side of extent: trim the length and update
584 * the current record.
587 * Orig: |oooooooooooooooooooo|
588 * Freeing: |fffffffff|
589 * Result: |rrrrrrrrrr|
592 ltrec.rm_blockcount -= len;
593 error = xfs_rmap_update(cur, <rec);
599 * overlap middle of extent: trim the length of the existing
600 * record to the length of the new left-extent size, increment
601 * the insertion position so we can insert a new record
602 * containing the remaining right-extent space.
605 * Orig: |oooooooooooooooooooo|
606 * Freeing: |fffffffff|
607 * Result: |rrrrr| |rrrr|
610 xfs_extlen_t orig_len = ltrec.rm_blockcount;
612 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
613 error = xfs_rmap_update(cur, <rec);
617 error = xfs_btree_increment(cur, 0, &i);
621 cur->bc_rec.r.rm_startblock = bno + len;
622 cur->bc_rec.r.rm_blockcount = orig_len - len -
624 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
626 cur->bc_rec.r.rm_offset = 0;
628 cur->bc_rec.r.rm_offset = offset + len;
629 cur->bc_rec.r.rm_flags = flags;
630 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
631 cur->bc_rec.r.rm_startblock,
632 cur->bc_rec.r.rm_blockcount,
633 cur->bc_rec.r.rm_owner,
634 cur->bc_rec.r.rm_offset,
635 cur->bc_rec.r.rm_flags);
636 error = xfs_btree_insert(cur, &i);
642 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
646 trace_xfs_rmap_unmap_error(mp, cur->bc_private.a.agno,
652 * Remove a reference to an extent in the rmap btree.
656 struct xfs_trans *tp,
657 struct xfs_buf *agbp,
661 struct xfs_owner_info *oinfo)
663 struct xfs_mount *mp = tp->t_mountp;
664 struct xfs_btree_cur *cur;
667 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
670 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
672 error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
676 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
680 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
685 * A mergeable rmap must have the same owner and the same values for
686 * the unwritten, attr_fork, and bmbt flags. The startblock and
687 * offset are checked separately.
690 xfs_rmap_is_mergeable(
691 struct xfs_rmap_irec *irec,
695 if (irec->rm_owner == XFS_RMAP_OWN_NULL)
697 if (irec->rm_owner != owner)
699 if ((flags & XFS_RMAP_UNWRITTEN) ^
700 (irec->rm_flags & XFS_RMAP_UNWRITTEN))
702 if ((flags & XFS_RMAP_ATTR_FORK) ^
703 (irec->rm_flags & XFS_RMAP_ATTR_FORK))
705 if ((flags & XFS_RMAP_BMBT_BLOCK) ^
706 (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
712 * When we allocate a new block, the first thing we do is add a reference to
713 * the extent in the rmap btree. This takes the form of a [agbno, length,
714 * owner, offset] record. Flags are encoded in the high bits of the offset
719 struct xfs_btree_cur *cur,
723 struct xfs_owner_info *oinfo)
725 struct xfs_mount *mp = cur->bc_mp;
726 struct xfs_rmap_irec ltrec;
727 struct xfs_rmap_irec gtrec;
734 unsigned int flags = 0;
737 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
739 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
740 (flags & XFS_RMAP_BMBT_BLOCK);
742 flags |= XFS_RMAP_UNWRITTEN;
743 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
745 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
748 * For the initial lookup, look for an exact match or the left-adjacent
749 * record for our insertion point. This will also give us the record for
750 * start block contiguity tests.
752 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
756 XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
758 error = xfs_rmap_get_rec(cur, <rec, &have_lt);
761 XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
762 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
763 cur->bc_private.a.agno, ltrec.rm_startblock,
764 ltrec.rm_blockcount, ltrec.rm_owner,
765 ltrec.rm_offset, ltrec.rm_flags);
767 if (!xfs_rmap_is_mergeable(<rec, owner, flags))
770 XFS_WANT_CORRUPTED_GOTO(mp,
772 ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error);
775 * Increment the cursor to see if we have a right-adjacent record to our
776 * insertion point. This will give us the record for end block
779 error = xfs_btree_increment(cur, 0, &have_gt);
783 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
786 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
787 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock,
789 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
790 cur->bc_private.a.agno, gtrec.rm_startblock,
791 gtrec.rm_blockcount, gtrec.rm_owner,
792 gtrec.rm_offset, gtrec.rm_flags);
793 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
798 * Note: cursor currently points one record to the right of ltrec, even
799 * if there is no record in the tree to the right.
802 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
803 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
805 * left edge contiguous, merge into left record.
809 * adding: |aaaaaaaaa|
810 * result: |rrrrrrrrrrrrrrrrrrr|
813 ltrec.rm_blockcount += len;
815 bno + len == gtrec.rm_startblock &&
816 (ignore_off || offset + len == gtrec.rm_offset) &&
817 (unsigned long)ltrec.rm_blockcount + len +
818 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
820 * right edge also contiguous, delete right record
821 * and merge into left record.
823 * ltbno ltlen gtbno gtlen
824 * orig: |ooooooooo| |ooooooooo|
825 * adding: |aaaaaaaaa|
826 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
828 ltrec.rm_blockcount += gtrec.rm_blockcount;
829 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
835 error = xfs_btree_delete(cur, &i);
838 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
841 /* point the cursor back to the left record and update */
842 error = xfs_btree_decrement(cur, 0, &have_gt);
845 error = xfs_rmap_update(cur, <rec);
848 } else if (have_gt &&
849 bno + len == gtrec.rm_startblock &&
850 (ignore_off || offset + len == gtrec.rm_offset)) {
852 * right edge contiguous, merge into right record.
856 * adding: |aaaaaaaaa|
857 * Result: |rrrrrrrrrrrrrrrrrrr|
860 gtrec.rm_startblock = bno;
861 gtrec.rm_blockcount += len;
863 gtrec.rm_offset = offset;
864 error = xfs_rmap_update(cur, >rec);
869 * no contiguous edge with identical owner, insert
870 * new record at current cursor position.
872 cur->bc_rec.r.rm_startblock = bno;
873 cur->bc_rec.r.rm_blockcount = len;
874 cur->bc_rec.r.rm_owner = owner;
875 cur->bc_rec.r.rm_offset = offset;
876 cur->bc_rec.r.rm_flags = flags;
877 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
878 owner, offset, flags);
879 error = xfs_btree_insert(cur, &i);
882 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
885 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
889 trace_xfs_rmap_map_error(mp, cur->bc_private.a.agno,
895 * Add a reference to an extent in the rmap btree.
899 struct xfs_trans *tp,
900 struct xfs_buf *agbp,
904 struct xfs_owner_info *oinfo)
906 struct xfs_mount *mp = tp->t_mountp;
907 struct xfs_btree_cur *cur;
910 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
913 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
914 error = xfs_rmap_map(cur, bno, len, false, oinfo);
918 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
922 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
926 #define RMAP_LEFT_CONTIG (1 << 0)
927 #define RMAP_RIGHT_CONTIG (1 << 1)
928 #define RMAP_LEFT_FILLING (1 << 2)
929 #define RMAP_RIGHT_FILLING (1 << 3)
930 #define RMAP_LEFT_VALID (1 << 6)
931 #define RMAP_RIGHT_VALID (1 << 7)
939 * Convert an unwritten extent to a real extent or vice versa.
940 * Does not handle overlapping extents.
944 struct xfs_btree_cur *cur,
948 struct xfs_owner_info *oinfo)
950 struct xfs_mount *mp = cur->bc_mp;
951 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
952 /* left is 0, right is 1, prev is 2 */
959 unsigned int flags = 0;
964 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
965 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
966 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
967 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
968 new_endoff = offset + len;
969 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
973 * For the initial lookup, look for an exact match or the left-adjacent
974 * record for our insertion point. This will also give us the record for
975 * start block contiguity tests.
977 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
980 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
982 error = xfs_rmap_get_rec(cur, &PREV, &i);
985 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
986 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
987 cur->bc_private.a.agno, PREV.rm_startblock,
988 PREV.rm_blockcount, PREV.rm_owner,
989 PREV.rm_offset, PREV.rm_flags);
991 ASSERT(PREV.rm_offset <= offset);
992 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
993 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
994 newext = ~oldext & XFS_RMAP_UNWRITTEN;
997 * Set flags determining what part of the previous oldext allocation
998 * extent is being replaced by a newext allocation.
1000 if (PREV.rm_offset == offset)
1001 state |= RMAP_LEFT_FILLING;
1002 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1003 state |= RMAP_RIGHT_FILLING;
1006 * Decrement the cursor to see if we have a left-adjacent record to our
1007 * insertion point. This will give us the record for end block
1010 error = xfs_btree_decrement(cur, 0, &i);
1014 state |= RMAP_LEFT_VALID;
1015 error = xfs_rmap_get_rec(cur, &LEFT, &i);
1018 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1019 XFS_WANT_CORRUPTED_GOTO(mp,
1020 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
1022 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
1023 cur->bc_private.a.agno, LEFT.rm_startblock,
1024 LEFT.rm_blockcount, LEFT.rm_owner,
1025 LEFT.rm_offset, LEFT.rm_flags);
1026 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1027 LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1028 xfs_rmap_is_mergeable(&LEFT, owner, newext))
1029 state |= RMAP_LEFT_CONTIG;
1033 * Increment the cursor to see if we have a right-adjacent record to our
1034 * insertion point. This will give us the record for end block
1037 error = xfs_btree_increment(cur, 0, &i);
1040 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1041 error = xfs_btree_increment(cur, 0, &i);
1045 state |= RMAP_RIGHT_VALID;
1046 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1049 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1050 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1052 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1053 cur->bc_private.a.agno, RIGHT.rm_startblock,
1054 RIGHT.rm_blockcount, RIGHT.rm_owner,
1055 RIGHT.rm_offset, RIGHT.rm_flags);
1056 if (bno + len == RIGHT.rm_startblock &&
1057 offset + len == RIGHT.rm_offset &&
1058 xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1059 state |= RMAP_RIGHT_CONTIG;
1062 /* check that left + prev + right is not too long */
1063 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1064 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1065 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1066 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1067 (unsigned long)LEFT.rm_blockcount + len +
1068 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1069 state &= ~RMAP_RIGHT_CONTIG;
1071 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1074 /* reset the cursor back to PREV */
1075 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1078 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1081 * Switch out based on the FILLING and CONTIG state bits.
1083 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1084 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1085 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1086 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1088 * Setting all of a previous oldext extent to newext.
1089 * The left and right neighbors are both contiguous with new.
1091 error = xfs_btree_increment(cur, 0, &i);
1094 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1095 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1096 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1097 RIGHT.rm_owner, RIGHT.rm_offset,
1099 error = xfs_btree_delete(cur, &i);
1102 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1103 error = xfs_btree_decrement(cur, 0, &i);
1106 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1107 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1108 PREV.rm_startblock, PREV.rm_blockcount,
1109 PREV.rm_owner, PREV.rm_offset,
1111 error = xfs_btree_delete(cur, &i);
1114 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1115 error = xfs_btree_decrement(cur, 0, &i);
1118 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1120 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1121 error = xfs_rmap_update(cur, &NEW);
1126 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1128 * Setting all of a previous oldext extent to newext.
1129 * The left neighbor is contiguous, the right is not.
1131 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1132 PREV.rm_startblock, PREV.rm_blockcount,
1133 PREV.rm_owner, PREV.rm_offset,
1135 error = xfs_btree_delete(cur, &i);
1138 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1139 error = xfs_btree_decrement(cur, 0, &i);
1142 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1144 NEW.rm_blockcount += PREV.rm_blockcount;
1145 error = xfs_rmap_update(cur, &NEW);
1150 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1152 * Setting all of a previous oldext extent to newext.
1153 * The right neighbor is contiguous, the left is not.
1155 error = xfs_btree_increment(cur, 0, &i);
1158 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1159 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1160 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1161 RIGHT.rm_owner, RIGHT.rm_offset,
1163 error = xfs_btree_delete(cur, &i);
1166 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1167 error = xfs_btree_decrement(cur, 0, &i);
1170 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1172 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1173 NEW.rm_flags = newext;
1174 error = xfs_rmap_update(cur, &NEW);
1179 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1181 * Setting all of a previous oldext extent to newext.
1182 * Neither the left nor right neighbors are contiguous with
1186 NEW.rm_flags = newext;
1187 error = xfs_rmap_update(cur, &NEW);
1192 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1194 * Setting the first part of a previous oldext extent to newext.
1195 * The left neighbor is contiguous.
1198 NEW.rm_offset += len;
1199 NEW.rm_startblock += len;
1200 NEW.rm_blockcount -= len;
1201 error = xfs_rmap_update(cur, &NEW);
1204 error = xfs_btree_decrement(cur, 0, &i);
1208 NEW.rm_blockcount += len;
1209 error = xfs_rmap_update(cur, &NEW);
1214 case RMAP_LEFT_FILLING:
1216 * Setting the first part of a previous oldext extent to newext.
1217 * The left neighbor is not contiguous.
1220 NEW.rm_startblock += len;
1221 NEW.rm_offset += len;
1222 NEW.rm_blockcount -= len;
1223 error = xfs_rmap_update(cur, &NEW);
1226 NEW.rm_startblock = bno;
1227 NEW.rm_owner = owner;
1228 NEW.rm_offset = offset;
1229 NEW.rm_blockcount = len;
1230 NEW.rm_flags = newext;
1231 cur->bc_rec.r = NEW;
1232 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1233 len, owner, offset, newext);
1234 error = xfs_btree_insert(cur, &i);
1237 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1240 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1242 * Setting the last part of a previous oldext extent to newext.
1243 * The right neighbor is contiguous with the new allocation.
1246 NEW.rm_blockcount -= len;
1247 error = xfs_rmap_update(cur, &NEW);
1250 error = xfs_btree_increment(cur, 0, &i);
1254 NEW.rm_offset = offset;
1255 NEW.rm_startblock = bno;
1256 NEW.rm_blockcount += len;
1257 error = xfs_rmap_update(cur, &NEW);
1262 case RMAP_RIGHT_FILLING:
1264 * Setting the last part of a previous oldext extent to newext.
1265 * The right neighbor is not contiguous.
1268 NEW.rm_blockcount -= len;
1269 error = xfs_rmap_update(cur, &NEW);
1272 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1276 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1277 NEW.rm_startblock = bno;
1278 NEW.rm_owner = owner;
1279 NEW.rm_offset = offset;
1280 NEW.rm_blockcount = len;
1281 NEW.rm_flags = newext;
1282 cur->bc_rec.r = NEW;
1283 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1284 len, owner, offset, newext);
1285 error = xfs_btree_insert(cur, &i);
1288 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1293 * Setting the middle part of a previous oldext extent to
1294 * newext. Contiguity is impossible here.
1295 * One extent becomes three extents.
1297 /* new right extent - oldext */
1298 NEW.rm_startblock = bno + len;
1299 NEW.rm_owner = owner;
1300 NEW.rm_offset = new_endoff;
1301 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1303 NEW.rm_flags = PREV.rm_flags;
1304 error = xfs_rmap_update(cur, &NEW);
1307 /* new left extent - oldext */
1309 NEW.rm_blockcount = offset - PREV.rm_offset;
1310 cur->bc_rec.r = NEW;
1311 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
1312 NEW.rm_startblock, NEW.rm_blockcount,
1313 NEW.rm_owner, NEW.rm_offset,
1315 error = xfs_btree_insert(cur, &i);
1318 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1320 * Reset the cursor to the position of the new extent
1321 * we are about to insert as we can't trust it after
1322 * the previous insert.
1324 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1328 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1329 /* new middle extent - newext */
1330 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1331 cur->bc_rec.r.rm_flags |= newext;
1332 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
1333 owner, offset, newext);
1334 error = xfs_btree_insert(cur, &i);
1337 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1340 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1341 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1342 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1343 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1344 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1345 case RMAP_LEFT_CONTIG:
1346 case RMAP_RIGHT_CONTIG:
1348 * These cases are all impossible.
1353 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1357 trace_xfs_rmap_convert_error(cur->bc_mp,
1358 cur->bc_private.a.agno, error, _RET_IP_);
1363 * Convert an unwritten extent to a real extent or vice versa. If there is no
1364 * possibility of overlapping extents, delegate to the simpler convert
1368 xfs_rmap_convert_shared(
1369 struct xfs_btree_cur *cur,
1373 struct xfs_owner_info *oinfo)
1375 struct xfs_mount *mp = cur->bc_mp;
1376 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1377 /* left is 0, right is 1, prev is 2 */
1381 uint64_t new_endoff;
1382 unsigned int oldext;
1383 unsigned int newext;
1384 unsigned int flags = 0;
1389 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1390 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1391 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1392 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1393 new_endoff = offset + len;
1394 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
1398 * For the initial lookup, look for and exact match or the left-adjacent
1399 * record for our insertion point. This will also give us the record for
1400 * start block contiguity tests.
1402 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1406 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1408 ASSERT(PREV.rm_offset <= offset);
1409 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1410 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1411 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1414 * Set flags determining what part of the previous oldext allocation
1415 * extent is being replaced by a newext allocation.
1417 if (PREV.rm_offset == offset)
1418 state |= RMAP_LEFT_FILLING;
1419 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1420 state |= RMAP_RIGHT_FILLING;
1422 /* Is there a left record that abuts our range? */
1423 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1428 state |= RMAP_LEFT_VALID;
1429 XFS_WANT_CORRUPTED_GOTO(mp,
1430 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
1432 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1433 state |= RMAP_LEFT_CONTIG;
1436 /* Is there a right record that abuts our range? */
1437 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1442 state |= RMAP_RIGHT_VALID;
1443 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1446 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1447 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1449 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1450 cur->bc_private.a.agno, RIGHT.rm_startblock,
1451 RIGHT.rm_blockcount, RIGHT.rm_owner,
1452 RIGHT.rm_offset, RIGHT.rm_flags);
1453 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1454 state |= RMAP_RIGHT_CONTIG;
1457 /* check that left + prev + right is not too long */
1458 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1459 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1460 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1461 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1462 (unsigned long)LEFT.rm_blockcount + len +
1463 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1464 state &= ~RMAP_RIGHT_CONTIG;
1466 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1469 * Switch out based on the FILLING and CONTIG state bits.
1471 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1472 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1473 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1474 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1476 * Setting all of a previous oldext extent to newext.
1477 * The left and right neighbors are both contiguous with new.
1479 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1480 RIGHT.rm_blockcount, RIGHT.rm_owner,
1481 RIGHT.rm_offset, RIGHT.rm_flags);
1484 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1485 PREV.rm_blockcount, PREV.rm_owner,
1486 PREV.rm_offset, PREV.rm_flags);
1490 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1491 NEW.rm_blockcount, NEW.rm_owner,
1492 NEW.rm_offset, NEW.rm_flags, &i);
1495 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1496 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1497 error = xfs_rmap_update(cur, &NEW);
1502 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1504 * Setting all of a previous oldext extent to newext.
1505 * The left neighbor is contiguous, the right is not.
1507 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1508 PREV.rm_blockcount, PREV.rm_owner,
1509 PREV.rm_offset, PREV.rm_flags);
1513 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1514 NEW.rm_blockcount, NEW.rm_owner,
1515 NEW.rm_offset, NEW.rm_flags, &i);
1518 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1519 NEW.rm_blockcount += PREV.rm_blockcount;
1520 error = xfs_rmap_update(cur, &NEW);
1525 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1527 * Setting all of a previous oldext extent to newext.
1528 * The right neighbor is contiguous, the left is not.
1530 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1531 RIGHT.rm_blockcount, RIGHT.rm_owner,
1532 RIGHT.rm_offset, RIGHT.rm_flags);
1536 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1537 NEW.rm_blockcount, NEW.rm_owner,
1538 NEW.rm_offset, NEW.rm_flags, &i);
1541 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1542 NEW.rm_blockcount += RIGHT.rm_blockcount;
1543 NEW.rm_flags = RIGHT.rm_flags;
1544 error = xfs_rmap_update(cur, &NEW);
1549 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1551 * Setting all of a previous oldext extent to newext.
1552 * Neither the left nor right neighbors are contiguous with
1556 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1557 NEW.rm_blockcount, NEW.rm_owner,
1558 NEW.rm_offset, NEW.rm_flags, &i);
1561 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1562 NEW.rm_flags = newext;
1563 error = xfs_rmap_update(cur, &NEW);
1568 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1570 * Setting the first part of a previous oldext extent to newext.
1571 * The left neighbor is contiguous.
1574 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1575 NEW.rm_blockcount, NEW.rm_owner,
1576 NEW.rm_offset, NEW.rm_flags);
1579 NEW.rm_offset += len;
1580 NEW.rm_startblock += len;
1581 NEW.rm_blockcount -= len;
1582 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1583 NEW.rm_blockcount, NEW.rm_owner,
1584 NEW.rm_offset, NEW.rm_flags);
1588 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1589 NEW.rm_blockcount, NEW.rm_owner,
1590 NEW.rm_offset, NEW.rm_flags, &i);
1593 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1594 NEW.rm_blockcount += len;
1595 error = xfs_rmap_update(cur, &NEW);
1600 case RMAP_LEFT_FILLING:
1602 * Setting the first part of a previous oldext extent to newext.
1603 * The left neighbor is not contiguous.
1606 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1607 NEW.rm_blockcount, NEW.rm_owner,
1608 NEW.rm_offset, NEW.rm_flags);
1611 NEW.rm_offset += len;
1612 NEW.rm_startblock += len;
1613 NEW.rm_blockcount -= len;
1614 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1615 NEW.rm_blockcount, NEW.rm_owner,
1616 NEW.rm_offset, NEW.rm_flags);
1619 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1624 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1626 * Setting the last part of a previous oldext extent to newext.
1627 * The right neighbor is contiguous with the new allocation.
1630 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1631 NEW.rm_blockcount, NEW.rm_owner,
1632 NEW.rm_offset, NEW.rm_flags, &i);
1635 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1636 NEW.rm_blockcount = offset - NEW.rm_offset;
1637 error = xfs_rmap_update(cur, &NEW);
1641 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1642 NEW.rm_blockcount, NEW.rm_owner,
1643 NEW.rm_offset, NEW.rm_flags);
1646 NEW.rm_offset = offset;
1647 NEW.rm_startblock = bno;
1648 NEW.rm_blockcount += len;
1649 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1650 NEW.rm_blockcount, NEW.rm_owner,
1651 NEW.rm_offset, NEW.rm_flags);
1656 case RMAP_RIGHT_FILLING:
1658 * Setting the last part of a previous oldext extent to newext.
1659 * The right neighbor is not contiguous.
1662 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1663 NEW.rm_blockcount, NEW.rm_owner,
1664 NEW.rm_offset, NEW.rm_flags, &i);
1667 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1668 NEW.rm_blockcount -= len;
1669 error = xfs_rmap_update(cur, &NEW);
1672 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1679 * Setting the middle part of a previous oldext extent to
1680 * newext. Contiguity is impossible here.
1681 * One extent becomes three extents.
1683 /* new right extent - oldext */
1684 NEW.rm_startblock = bno + len;
1685 NEW.rm_owner = owner;
1686 NEW.rm_offset = new_endoff;
1687 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1689 NEW.rm_flags = PREV.rm_flags;
1690 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1691 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1695 /* new left extent - oldext */
1697 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1698 NEW.rm_blockcount, NEW.rm_owner,
1699 NEW.rm_offset, NEW.rm_flags, &i);
1702 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1703 NEW.rm_blockcount = offset - NEW.rm_offset;
1704 error = xfs_rmap_update(cur, &NEW);
1707 /* new middle extent - newext */
1708 NEW.rm_startblock = bno;
1709 NEW.rm_blockcount = len;
1710 NEW.rm_owner = owner;
1711 NEW.rm_offset = offset;
1712 NEW.rm_flags = newext;
1713 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1714 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1720 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1721 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1722 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1723 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1724 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1725 case RMAP_LEFT_CONTIG:
1726 case RMAP_RIGHT_CONTIG:
1728 * These cases are all impossible.
1733 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1737 trace_xfs_rmap_convert_error(cur->bc_mp,
1738 cur->bc_private.a.agno, error, _RET_IP_);
1748 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1749 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1750 * that the prev/next records in the btree might belong to another owner.
1751 * Therefore we must use delete+insert to alter any of the key fields.
1753 * For every other situation there can only be one owner for a given extent,
1754 * so we can call the regular _free function.
1757 xfs_rmap_unmap_shared(
1758 struct xfs_btree_cur *cur,
1762 struct xfs_owner_info *oinfo)
1764 struct xfs_mount *mp = cur->bc_mp;
1765 struct xfs_rmap_irec ltrec;
1773 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1775 flags |= XFS_RMAP_UNWRITTEN;
1776 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
1780 * We should always have a left record because there's a static record
1781 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1782 * will not ever be removed from the tree.
1784 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1788 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1789 ltoff = ltrec.rm_offset;
1791 /* Make sure the extent we found covers the entire freeing range. */
1792 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
1793 ltrec.rm_startblock + ltrec.rm_blockcount >=
1794 bno + len, out_error);
1796 /* Make sure the owner matches what we expect to find in the tree. */
1797 XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner, out_error);
1799 /* Make sure the unwritten flag matches. */
1800 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
1801 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error);
1803 /* Check the offset. */
1804 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error);
1805 XFS_WANT_CORRUPTED_GOTO(mp, offset <= ltoff + ltrec.rm_blockcount,
1808 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
1809 /* Exact match, simply remove the record from rmap tree. */
1810 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1811 ltrec.rm_blockcount, ltrec.rm_owner,
1812 ltrec.rm_offset, ltrec.rm_flags);
1815 } else if (ltrec.rm_startblock == bno) {
1817 * Overlap left hand side of extent: move the start, trim the
1818 * length and update the current record.
1821 * Orig: |oooooooooooooooooooo|
1822 * Freeing: |fffffffff|
1823 * Result: |rrrrrrrrrr|
1827 /* Delete prev rmap. */
1828 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1829 ltrec.rm_blockcount, ltrec.rm_owner,
1830 ltrec.rm_offset, ltrec.rm_flags);
1834 /* Add an rmap at the new offset. */
1835 ltrec.rm_startblock += len;
1836 ltrec.rm_blockcount -= len;
1837 ltrec.rm_offset += len;
1838 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
1839 ltrec.rm_blockcount, ltrec.rm_owner,
1840 ltrec.rm_offset, ltrec.rm_flags);
1843 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
1845 * Overlap right hand side of extent: trim the length and
1846 * update the current record.
1849 * Orig: |oooooooooooooooooooo|
1850 * Freeing: |fffffffff|
1851 * Result: |rrrrrrrrrr|
1854 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1855 ltrec.rm_blockcount, ltrec.rm_owner,
1856 ltrec.rm_offset, ltrec.rm_flags, &i);
1859 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1860 ltrec.rm_blockcount -= len;
1861 error = xfs_rmap_update(cur, <rec);
1866 * Overlap middle of extent: trim the length of the existing
1867 * record to the length of the new left-extent size, increment
1868 * the insertion position so we can insert a new record
1869 * containing the remaining right-extent space.
1872 * Orig: |oooooooooooooooooooo|
1873 * Freeing: |fffffffff|
1874 * Result: |rrrrr| |rrrr|
1877 xfs_extlen_t orig_len = ltrec.rm_blockcount;
1879 /* Shrink the left side of the rmap */
1880 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1881 ltrec.rm_blockcount, ltrec.rm_owner,
1882 ltrec.rm_offset, ltrec.rm_flags, &i);
1885 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1886 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
1887 error = xfs_rmap_update(cur, <rec);
1891 /* Add an rmap at the new offset */
1892 error = xfs_rmap_insert(cur, bno + len,
1893 orig_len - len - ltrec.rm_blockcount,
1894 ltrec.rm_owner, offset + len,
1900 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
1904 trace_xfs_rmap_unmap_error(cur->bc_mp,
1905 cur->bc_private.a.agno, error, _RET_IP_);
1910 * Find an extent in the rmap btree and map it. For rmap extent types that
1911 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1912 * that the prev/next records in the btree might belong to another owner.
1913 * Therefore we must use delete+insert to alter any of the key fields.
1915 * For every other situation there can only be one owner for a given extent,
1916 * so we can call the regular _alloc function.
1919 xfs_rmap_map_shared(
1920 struct xfs_btree_cur *cur,
1924 struct xfs_owner_info *oinfo)
1926 struct xfs_mount *mp = cur->bc_mp;
1927 struct xfs_rmap_irec ltrec;
1928 struct xfs_rmap_irec gtrec;
1935 unsigned int flags = 0;
1937 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1939 flags |= XFS_RMAP_UNWRITTEN;
1940 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
1943 /* Is there a left record that abuts our range? */
1944 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
1949 !xfs_rmap_is_mergeable(<rec, owner, flags))
1952 /* Is there a right record that abuts our range? */
1953 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1958 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
1961 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
1962 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1963 cur->bc_private.a.agno, gtrec.rm_startblock,
1964 gtrec.rm_blockcount, gtrec.rm_owner,
1965 gtrec.rm_offset, gtrec.rm_flags);
1967 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
1972 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
1973 ltrec.rm_offset + ltrec.rm_blockcount == offset) {
1975 * Left edge contiguous, merge into left record.
1979 * adding: |aaaaaaaaa|
1980 * result: |rrrrrrrrrrrrrrrrrrr|
1983 ltrec.rm_blockcount += len;
1985 bno + len == gtrec.rm_startblock &&
1986 offset + len == gtrec.rm_offset) {
1988 * Right edge also contiguous, delete right record
1989 * and merge into left record.
1991 * ltbno ltlen gtbno gtlen
1992 * orig: |ooooooooo| |ooooooooo|
1993 * adding: |aaaaaaaaa|
1994 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1996 ltrec.rm_blockcount += gtrec.rm_blockcount;
1997 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
1998 gtrec.rm_blockcount, gtrec.rm_owner,
1999 gtrec.rm_offset, gtrec.rm_flags);
2004 /* Point the cursor back to the left record and update. */
2005 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2006 ltrec.rm_blockcount, ltrec.rm_owner,
2007 ltrec.rm_offset, ltrec.rm_flags, &i);
2010 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
2012 error = xfs_rmap_update(cur, <rec);
2015 } else if (have_gt &&
2016 bno + len == gtrec.rm_startblock &&
2017 offset + len == gtrec.rm_offset) {
2019 * Right edge contiguous, merge into right record.
2023 * adding: |aaaaaaaaa|
2024 * Result: |rrrrrrrrrrrrrrrrrrr|
2027 /* Delete the old record. */
2028 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2029 gtrec.rm_blockcount, gtrec.rm_owner,
2030 gtrec.rm_offset, gtrec.rm_flags);
2034 /* Move the start and re-add it. */
2035 gtrec.rm_startblock = bno;
2036 gtrec.rm_blockcount += len;
2037 gtrec.rm_offset = offset;
2038 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2039 gtrec.rm_blockcount, gtrec.rm_owner,
2040 gtrec.rm_offset, gtrec.rm_flags);
2045 * No contiguous edge with identical owner, insert
2046 * new record at current cursor position.
2048 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2053 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
2057 trace_xfs_rmap_map_error(cur->bc_mp,
2058 cur->bc_private.a.agno, error, _RET_IP_);
2062 /* Insert a raw rmap into the rmapbt. */
2065 struct xfs_btree_cur *cur,
2066 struct xfs_rmap_irec *rmap)
2068 struct xfs_owner_info oinfo;
2070 oinfo.oi_owner = rmap->rm_owner;
2071 oinfo.oi_offset = rmap->rm_offset;
2073 if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
2074 oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
2075 if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
2076 oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
2078 if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2079 return xfs_rmap_map(cur, rmap->rm_startblock,
2080 rmap->rm_blockcount,
2081 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2084 return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2085 rmap->rm_blockcount,
2086 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2090 struct xfs_rmap_query_range_info {
2091 xfs_rmap_query_range_fn fn;
2095 /* Format btree record and pass to our callback. */
2097 xfs_rmap_query_range_helper(
2098 struct xfs_btree_cur *cur,
2099 union xfs_btree_rec *rec,
2102 struct xfs_rmap_query_range_info *query = priv;
2103 struct xfs_rmap_irec irec;
2106 error = xfs_rmap_btrec_to_irec(rec, &irec);
2109 return query->fn(cur, &irec, query->priv);
2112 /* Find all rmaps between two keys. */
2114 xfs_rmap_query_range(
2115 struct xfs_btree_cur *cur,
2116 struct xfs_rmap_irec *low_rec,
2117 struct xfs_rmap_irec *high_rec,
2118 xfs_rmap_query_range_fn fn,
2121 union xfs_btree_irec low_brec;
2122 union xfs_btree_irec high_brec;
2123 struct xfs_rmap_query_range_info query;
2125 low_brec.r = *low_rec;
2126 high_brec.r = *high_rec;
2129 return xfs_btree_query_range(cur, &low_brec, &high_brec,
2130 xfs_rmap_query_range_helper, &query);
2133 /* Find all rmaps. */
2136 struct xfs_btree_cur *cur,
2137 xfs_rmap_query_range_fn fn,
2140 struct xfs_rmap_query_range_info query;
2144 return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2147 /* Clean up after calling xfs_rmap_finish_one. */
2149 xfs_rmap_finish_one_cleanup(
2150 struct xfs_trans *tp,
2151 struct xfs_btree_cur *rcur,
2154 struct xfs_buf *agbp;
2158 agbp = rcur->bc_private.a.agbp;
2159 xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
2161 xfs_trans_brelse(tp, agbp);
2165 * Process one of the deferred rmap operations. We pass back the
2166 * btree cursor to maintain our lock on the rmapbt between calls.
2167 * This saves time and eliminates a buffer deadlock between the
2168 * superblock and the AGF because we'll always grab them in the same
2172 xfs_rmap_finish_one(
2173 struct xfs_trans *tp,
2174 enum xfs_rmap_intent_type type,
2177 xfs_fileoff_t startoff,
2178 xfs_fsblock_t startblock,
2179 xfs_filblks_t blockcount,
2181 struct xfs_btree_cur **pcur)
2183 struct xfs_mount *mp = tp->t_mountp;
2184 struct xfs_btree_cur *rcur;
2185 struct xfs_buf *agbp = NULL;
2187 xfs_agnumber_t agno;
2188 struct xfs_owner_info oinfo;
2192 agno = XFS_FSB_TO_AGNO(mp, startblock);
2193 ASSERT(agno != NULLAGNUMBER);
2194 bno = XFS_FSB_TO_AGBNO(mp, startblock);
2196 trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork,
2197 startoff, blockcount, state);
2199 if (XFS_TEST_ERROR(false, mp,
2200 XFS_ERRTAG_RMAP_FINISH_ONE))
2204 * If we haven't gotten a cursor or the cursor AG doesn't match
2205 * the startblock, get one now.
2208 if (rcur != NULL && rcur->bc_private.a.agno != agno) {
2209 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2215 * Refresh the freelist before we start changing the
2216 * rmapbt, because a shape change could cause us to
2219 error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
2223 return -EFSCORRUPTED;
2225 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
2233 xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2234 unwritten = state == XFS_EXT_UNWRITTEN;
2235 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2238 case XFS_RMAP_ALLOC:
2240 error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2242 case XFS_RMAP_MAP_SHARED:
2243 error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2247 case XFS_RMAP_UNMAP:
2248 error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2251 case XFS_RMAP_UNMAP_SHARED:
2252 error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2255 case XFS_RMAP_CONVERT:
2256 error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2259 case XFS_RMAP_CONVERT_SHARED:
2260 error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2261 !unwritten, &oinfo);
2265 error = -EFSCORRUPTED;
2270 xfs_trans_brelse(tp, agbp);
2276 * Don't defer an rmap if we aren't an rmap filesystem.
2279 xfs_rmap_update_is_needed(
2280 struct xfs_mount *mp,
2283 return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK;
2287 * Record a rmap intent; the list is kept sorted first by AG and then by
2292 struct xfs_mount *mp,
2293 struct xfs_defer_ops *dfops,
2294 enum xfs_rmap_intent_type type,
2297 struct xfs_bmbt_irec *bmap)
2299 struct xfs_rmap_intent *ri;
2301 trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, bmap->br_startblock),
2303 XFS_FSB_TO_AGBNO(mp, bmap->br_startblock),
2306 bmap->br_blockcount,
2309 ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_SLEEP | KM_NOFS);
2310 INIT_LIST_HEAD(&ri->ri_list);
2312 ri->ri_owner = owner;
2313 ri->ri_whichfork = whichfork;
2314 ri->ri_bmap = *bmap;
2316 xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
2320 /* Map an extent into a file. */
2322 xfs_rmap_map_extent(
2323 struct xfs_mount *mp,
2324 struct xfs_defer_ops *dfops,
2325 struct xfs_inode *ip,
2327 struct xfs_bmbt_irec *PREV)
2329 if (!xfs_rmap_update_is_needed(mp, whichfork))
2332 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2333 XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino,
2337 /* Unmap an extent out of a file. */
2339 xfs_rmap_unmap_extent(
2340 struct xfs_mount *mp,
2341 struct xfs_defer_ops *dfops,
2342 struct xfs_inode *ip,
2344 struct xfs_bmbt_irec *PREV)
2346 if (!xfs_rmap_update_is_needed(mp, whichfork))
2349 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2350 XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino,
2354 /* Convert a data fork extent from unwritten to real or vice versa. */
2356 xfs_rmap_convert_extent(
2357 struct xfs_mount *mp,
2358 struct xfs_defer_ops *dfops,
2359 struct xfs_inode *ip,
2361 struct xfs_bmbt_irec *PREV)
2363 if (!xfs_rmap_update_is_needed(mp, whichfork))
2366 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2367 XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino,
2371 /* Schedule the creation of an rmap for non-file data. */
2373 xfs_rmap_alloc_extent(
2374 struct xfs_mount *mp,
2375 struct xfs_defer_ops *dfops,
2376 xfs_agnumber_t agno,
2381 struct xfs_bmbt_irec bmap;
2383 if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
2386 bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
2387 bmap.br_blockcount = len;
2388 bmap.br_startoff = 0;
2389 bmap.br_state = XFS_EXT_NORM;
2391 return __xfs_rmap_add(mp, dfops, XFS_RMAP_ALLOC, owner,
2392 XFS_DATA_FORK, &bmap);
2395 /* Schedule the deletion of an rmap for non-file data. */
2397 xfs_rmap_free_extent(
2398 struct xfs_mount *mp,
2399 struct xfs_defer_ops *dfops,
2400 xfs_agnumber_t agno,
2405 struct xfs_bmbt_irec bmap;
2407 if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
2410 bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
2411 bmap.br_blockcount = len;
2412 bmap.br_startoff = 0;
2413 bmap.br_state = XFS_EXT_NORM;
2415 return __xfs_rmap_add(mp, dfops, XFS_RMAP_FREE, owner,
2416 XFS_DATA_FORK, &bmap);
2419 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2422 const struct xfs_rmap_irec *a,
2423 const struct xfs_rmap_irec *b)
2428 oa = xfs_rmap_irec_offset_pack(a);
2429 ob = xfs_rmap_irec_offset_pack(b);
2431 if (a->rm_startblock < b->rm_startblock)
2433 else if (a->rm_startblock > b->rm_startblock)
2435 else if (a->rm_owner < b->rm_owner)
2437 else if (a->rm_owner > b->rm_owner)
2447 /* Is there a record covering a given extent? */
2449 xfs_rmap_has_record(
2450 struct xfs_btree_cur *cur,
2455 union xfs_btree_irec low;
2456 union xfs_btree_irec high;
2458 memset(&low, 0, sizeof(low));
2459 low.r.rm_startblock = bno;
2460 memset(&high, 0xFF, sizeof(high));
2461 high.r.rm_startblock = bno + len - 1;
2463 return xfs_btree_has_record(cur, &low, &high, exists);
2467 * Is there a record for this owner completely covering a given physical
2468 * extent? If so, *has_rmap will be set to true. If there is no record
2469 * or the record only covers part of the range, we set *has_rmap to false.
2470 * This function doesn't perform range lookups or offset checks, so it is
2471 * not suitable for checking data fork blocks.
2474 xfs_rmap_record_exists(
2475 struct xfs_btree_cur *cur,
2478 struct xfs_owner_info *oinfo,
2485 struct xfs_rmap_irec irec;
2488 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2489 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
2490 (flags & XFS_RMAP_BMBT_BLOCK));
2492 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
2501 error = xfs_rmap_get_rec(cur, &irec, &has_record);
2509 *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
2510 irec.rm_startblock + irec.rm_blockcount >= bno + len);
2514 struct xfs_rmap_key_state {
2521 /* For each rmap given, figure out if it doesn't match the key we want. */
2523 xfs_rmap_has_other_keys_helper(
2524 struct xfs_btree_cur *cur,
2525 struct xfs_rmap_irec *rec,
2528 struct xfs_rmap_key_state *rks = priv;
2530 if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset &&
2531 ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags)
2533 rks->has_rmap = true;
2534 return XFS_BTREE_QUERY_RANGE_ABORT;
2538 * Given an extent and some owner info, can we find records overlapping
2539 * the extent whose owner info does not match the given owner?
2542 xfs_rmap_has_other_keys(
2543 struct xfs_btree_cur *cur,
2546 struct xfs_owner_info *oinfo,
2549 struct xfs_rmap_irec low = {0};
2550 struct xfs_rmap_irec high;
2551 struct xfs_rmap_key_state rks;
2554 xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags);
2555 rks.has_rmap = false;
2557 low.rm_startblock = bno;
2558 memset(&high, 0xFF, sizeof(high));
2559 high.rm_startblock = bno + len - 1;
2561 error = xfs_rmap_query_range(cur, &low, &high,
2562 xfs_rmap_has_other_keys_helper, &rks);
2563 *has_rmap = rks.has_rmap;