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"
26 #include "xfs_health.h"
28 struct kmem_cache *xfs_rmap_intent_cache;
31 * Lookup the first record less than or equal to [bno, len, owner, offset]
32 * in the btree given by cur.
36 struct xfs_btree_cur *cur,
41 struct xfs_rmap_irec *irec,
47 cur->bc_rec.r.rm_startblock = bno;
48 cur->bc_rec.r.rm_blockcount = 0;
49 cur->bc_rec.r.rm_owner = owner;
50 cur->bc_rec.r.rm_offset = offset;
51 cur->bc_rec.r.rm_flags = flags;
53 error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
54 if (error || !(*stat) || !irec)
57 error = xfs_rmap_get_rec(cur, irec, &get_stat);
61 xfs_btree_mark_sick(cur);
69 * Lookup the record exactly matching [bno, len, owner, offset]
70 * in the btree given by cur.
74 struct xfs_btree_cur *cur,
82 cur->bc_rec.r.rm_startblock = bno;
83 cur->bc_rec.r.rm_blockcount = len;
84 cur->bc_rec.r.rm_owner = owner;
85 cur->bc_rec.r.rm_offset = offset;
86 cur->bc_rec.r.rm_flags = flags;
87 return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
91 * Update the record referred to by cur to the value given
92 * by [bno, len, owner, offset].
93 * This either works (return 0) or gets an EFSCORRUPTED error.
97 struct xfs_btree_cur *cur,
98 struct xfs_rmap_irec *irec)
100 union xfs_btree_rec rec;
103 trace_xfs_rmap_update(cur->bc_mp, cur->bc_ag.pag->pag_agno,
104 irec->rm_startblock, irec->rm_blockcount,
105 irec->rm_owner, irec->rm_offset, irec->rm_flags);
107 rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
108 rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
109 rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
110 rec.rmap.rm_offset = cpu_to_be64(
111 xfs_rmap_irec_offset_pack(irec));
112 error = xfs_btree_update(cur, &rec);
114 trace_xfs_rmap_update_error(cur->bc_mp,
115 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
121 struct xfs_btree_cur *rcur,
131 trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno,
132 len, owner, offset, flags);
134 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
137 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 0)) {
138 xfs_btree_mark_sick(rcur);
139 error = -EFSCORRUPTED;
143 rcur->bc_rec.r.rm_startblock = agbno;
144 rcur->bc_rec.r.rm_blockcount = len;
145 rcur->bc_rec.r.rm_owner = owner;
146 rcur->bc_rec.r.rm_offset = offset;
147 rcur->bc_rec.r.rm_flags = flags;
148 error = xfs_btree_insert(rcur, &i);
151 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
152 xfs_btree_mark_sick(rcur);
153 error = -EFSCORRUPTED;
158 trace_xfs_rmap_insert_error(rcur->bc_mp,
159 rcur->bc_ag.pag->pag_agno, error, _RET_IP_);
165 struct xfs_btree_cur *rcur,
175 trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno,
176 len, owner, offset, flags);
178 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
181 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
182 xfs_btree_mark_sick(rcur);
183 error = -EFSCORRUPTED;
187 error = xfs_btree_delete(rcur, &i);
190 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
191 xfs_btree_mark_sick(rcur);
192 error = -EFSCORRUPTED;
197 trace_xfs_rmap_delete_error(rcur->bc_mp,
198 rcur->bc_ag.pag->pag_agno, error, _RET_IP_);
202 /* Convert an internal btree record to an rmap record. */
204 xfs_rmap_btrec_to_irec(
205 const union xfs_btree_rec *rec,
206 struct xfs_rmap_irec *irec)
208 irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
209 irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
210 irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
211 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
215 /* Simple checks for rmap records. */
218 struct xfs_perag *pag,
219 const struct xfs_rmap_irec *irec)
221 struct xfs_mount *mp = pag->pag_mount;
227 if (irec->rm_blockcount == 0)
228 return __this_address;
229 if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
230 if (irec->rm_owner != XFS_RMAP_OWN_FS)
231 return __this_address;
232 if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
233 return __this_address;
235 /* check for valid extent range, including overflow */
236 if (!xfs_verify_agbext(pag, irec->rm_startblock,
237 irec->rm_blockcount))
238 return __this_address;
241 if (!(xfs_verify_ino(mp, irec->rm_owner) ||
242 (irec->rm_owner <= XFS_RMAP_OWN_FS &&
243 irec->rm_owner >= XFS_RMAP_OWN_MIN)))
244 return __this_address;
247 is_inode = !XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
248 is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
249 is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
250 is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
252 if (is_bmbt && irec->rm_offset != 0)
253 return __this_address;
255 if (!is_inode && irec->rm_offset != 0)
256 return __this_address;
258 if (is_unwritten && (is_bmbt || !is_inode || is_attr))
259 return __this_address;
261 if (!is_inode && (is_bmbt || is_unwritten || is_attr))
262 return __this_address;
264 /* Check for a valid fork offset, if applicable. */
265 if (is_inode && !is_bmbt &&
266 !xfs_verify_fileext(mp, irec->rm_offset, irec->rm_blockcount))
267 return __this_address;
272 static inline xfs_failaddr_t
273 xfs_rmap_check_btrec(
274 struct xfs_btree_cur *cur,
275 const struct xfs_rmap_irec *irec)
277 if (xfs_btree_is_mem_rmap(cur->bc_ops))
278 return xfs_rmap_check_irec(cur->bc_mem.pag, irec);
279 return xfs_rmap_check_irec(cur->bc_ag.pag, irec);
283 xfs_rmap_complain_bad_rec(
284 struct xfs_btree_cur *cur,
286 const struct xfs_rmap_irec *irec)
288 struct xfs_mount *mp = cur->bc_mp;
290 if (xfs_btree_is_mem_rmap(cur->bc_ops))
292 "In-Memory Reverse Mapping BTree record corruption detected at %pS!", fa);
295 "Reverse Mapping BTree record corruption in AG %d detected at %pS!",
296 cur->bc_ag.pag->pag_agno, fa);
298 "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
299 irec->rm_owner, irec->rm_flags, irec->rm_startblock,
300 irec->rm_blockcount);
301 xfs_btree_mark_sick(cur);
302 return -EFSCORRUPTED;
306 * Get the data from the pointed-to record.
310 struct xfs_btree_cur *cur,
311 struct xfs_rmap_irec *irec,
314 union xfs_btree_rec *rec;
318 error = xfs_btree_get_rec(cur, &rec, stat);
322 fa = xfs_rmap_btrec_to_irec(rec, irec);
324 fa = xfs_rmap_check_btrec(cur, irec);
326 return xfs_rmap_complain_bad_rec(cur, fa, irec);
331 struct xfs_find_left_neighbor_info {
332 struct xfs_rmap_irec high;
333 struct xfs_rmap_irec *irec;
336 /* For each rmap given, figure out if it matches the key we want. */
338 xfs_rmap_find_left_neighbor_helper(
339 struct xfs_btree_cur *cur,
340 const struct xfs_rmap_irec *rec,
343 struct xfs_find_left_neighbor_info *info = priv;
345 trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
346 cur->bc_ag.pag->pag_agno, rec->rm_startblock,
347 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
350 if (rec->rm_owner != info->high.rm_owner)
352 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
353 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
354 rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
362 * Find the record to the left of the given extent, being careful only to
363 * return a match with the same owner and adjacent physical and logical
367 xfs_rmap_find_left_neighbor(
368 struct xfs_btree_cur *cur,
373 struct xfs_rmap_irec *irec,
376 struct xfs_find_left_neighbor_info info;
383 info.high.rm_startblock = bno - 1;
384 info.high.rm_owner = owner;
385 if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
386 !(flags & XFS_RMAP_BMBT_BLOCK)) {
389 info.high.rm_offset = offset - 1;
391 info.high.rm_offset = 0;
392 info.high.rm_flags = flags;
393 info.high.rm_blockcount = 0;
396 trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
397 cur->bc_ag.pag->pag_agno, bno, 0, owner, offset, flags);
400 * Historically, we always used the range query to walk every reverse
401 * mapping that could possibly overlap the key that the caller asked
402 * for, and filter out the ones that don't. That is very slow when
403 * there are a lot of records.
405 * However, there are two scenarios where the classic btree search can
406 * produce correct results -- if the index contains a record that is an
407 * exact match for the lookup key; and if there are no other records
408 * between the record we want and the key we supplied.
410 * As an optimization, try a non-overlapped lookup first. This makes
411 * extent conversion and remap operations run a bit faster if the
412 * physical extents aren't being shared. If we don't find what we
413 * want, we fall back to the overlapped query.
415 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
420 error = xfs_rmap_find_left_neighbor_helper(cur, irec, &info);
422 error = xfs_rmap_query_range(cur, &info.high, &info.high,
423 xfs_rmap_find_left_neighbor_helper, &info);
424 if (error != -ECANCELED)
428 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
429 cur->bc_ag.pag->pag_agno, irec->rm_startblock,
430 irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
435 /* For each rmap given, figure out if it matches the key we want. */
437 xfs_rmap_lookup_le_range_helper(
438 struct xfs_btree_cur *cur,
439 const struct xfs_rmap_irec *rec,
442 struct xfs_find_left_neighbor_info *info = priv;
444 trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
445 cur->bc_ag.pag->pag_agno, rec->rm_startblock,
446 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
449 if (rec->rm_owner != info->high.rm_owner)
451 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
452 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
453 (rec->rm_offset > info->high.rm_offset ||
454 rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
462 * Find the record to the left of the given extent, being careful only to
463 * return a match with the same owner and overlapping physical and logical
464 * block ranges. This is the overlapping-interval version of
465 * xfs_rmap_lookup_le.
468 xfs_rmap_lookup_le_range(
469 struct xfs_btree_cur *cur,
474 struct xfs_rmap_irec *irec,
477 struct xfs_find_left_neighbor_info info;
481 info.high.rm_startblock = bno;
482 info.high.rm_owner = owner;
483 if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
484 info.high.rm_offset = offset;
486 info.high.rm_offset = 0;
487 info.high.rm_flags = flags;
488 info.high.rm_blockcount = 0;
492 trace_xfs_rmap_lookup_le_range(cur->bc_mp, cur->bc_ag.pag->pag_agno,
493 bno, 0, owner, offset, flags);
496 * Historically, we always used the range query to walk every reverse
497 * mapping that could possibly overlap the key that the caller asked
498 * for, and filter out the ones that don't. That is very slow when
499 * there are a lot of records.
501 * However, there are two scenarios where the classic btree search can
502 * produce correct results -- if the index contains a record that is an
503 * exact match for the lookup key; and if there are no other records
504 * between the record we want and the key we supplied.
506 * As an optimization, try a non-overlapped lookup first. This makes
507 * scrub run much faster on most filesystems because bmbt records are
508 * usually an exact match for rmap records. If we don't find what we
509 * want, we fall back to the overlapped query.
511 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
516 error = xfs_rmap_lookup_le_range_helper(cur, irec, &info);
518 error = xfs_rmap_query_range(cur, &info.high, &info.high,
519 xfs_rmap_lookup_le_range_helper, &info);
520 if (error != -ECANCELED)
524 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
525 cur->bc_ag.pag->pag_agno, irec->rm_startblock,
526 irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
532 * Perform all the relevant owner checks for a removal op. If we're doing an
533 * unknown-owner removal then we have no owner information to check.
536 xfs_rmap_free_check_owner(
537 struct xfs_btree_cur *cur,
539 struct xfs_rmap_irec *rec,
545 struct xfs_mount *mp = cur->bc_mp;
548 if (owner == XFS_RMAP_OWN_UNKNOWN)
551 /* Make sure the unwritten flag matches. */
552 if (XFS_IS_CORRUPT(mp,
553 (flags & XFS_RMAP_UNWRITTEN) !=
554 (rec->rm_flags & XFS_RMAP_UNWRITTEN))) {
555 xfs_btree_mark_sick(cur);
556 error = -EFSCORRUPTED;
560 /* Make sure the owner matches what we expect to find in the tree. */
561 if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) {
562 xfs_btree_mark_sick(cur);
563 error = -EFSCORRUPTED;
567 /* Check the offset, if necessary. */
568 if (XFS_RMAP_NON_INODE_OWNER(owner))
571 if (flags & XFS_RMAP_BMBT_BLOCK) {
572 if (XFS_IS_CORRUPT(mp,
573 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) {
574 xfs_btree_mark_sick(cur);
575 error = -EFSCORRUPTED;
579 if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) {
580 xfs_btree_mark_sick(cur);
581 error = -EFSCORRUPTED;
584 if (XFS_IS_CORRUPT(mp,
585 offset + len > ltoff + rec->rm_blockcount)) {
586 xfs_btree_mark_sick(cur);
587 error = -EFSCORRUPTED;
597 * Find the extent in the rmap btree and remove it.
599 * The record we find should always be an exact match for the extent that we're
600 * looking for, since we insert them into the btree without modification.
602 * Special Case #1: when growing the filesystem, we "free" an extent when
603 * growing the last AG. This extent is new space and so it is not tracked as
604 * used space in the btree. The growfs code will pass in an owner of
605 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
606 * extent. We verify that - the extent lookup result in a record that does not
609 * Special Case #2: EFIs do not record the owner of the extent, so when
610 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
611 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
612 * corruption checks during log recovery.
616 struct xfs_btree_cur *cur,
620 const struct xfs_owner_info *oinfo)
622 struct xfs_mount *mp = cur->bc_mp;
623 struct xfs_rmap_irec ltrec;
632 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
633 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
634 (flags & XFS_RMAP_BMBT_BLOCK);
636 flags |= XFS_RMAP_UNWRITTEN;
637 trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
641 * We should always have a left record because there's a static record
642 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
643 * will not ever be removed from the tree.
645 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, <rec, &i);
648 if (XFS_IS_CORRUPT(mp, i != 1)) {
649 xfs_btree_mark_sick(cur);
650 error = -EFSCORRUPTED;
654 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
655 cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
656 ltrec.rm_blockcount, ltrec.rm_owner,
657 ltrec.rm_offset, ltrec.rm_flags);
658 ltoff = ltrec.rm_offset;
661 * For growfs, the incoming extent must be beyond the left record we
662 * just found as it is new space and won't be used by anyone. This is
663 * just a corruption check as we don't actually do anything with this
664 * extent. Note that we need to use >= instead of > because it might
665 * be the case that the "left" extent goes all the way to EOFS.
667 if (owner == XFS_RMAP_OWN_NULL) {
668 if (XFS_IS_CORRUPT(mp,
670 ltrec.rm_startblock + ltrec.rm_blockcount)) {
671 xfs_btree_mark_sick(cur);
672 error = -EFSCORRUPTED;
679 * If we're doing an unknown-owner removal for EFI recovery, we expect
680 * to find the full range in the rmapbt or nothing at all. If we
681 * don't find any rmaps overlapping either end of the range, we're
682 * done. Hopefully this means that the EFI creator already queued
683 * (and finished) a RUI to remove the rmap.
685 if (owner == XFS_RMAP_OWN_UNKNOWN &&
686 ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
687 struct xfs_rmap_irec rtrec;
689 error = xfs_btree_increment(cur, 0, &i);
694 error = xfs_rmap_get_rec(cur, &rtrec, &i);
697 if (XFS_IS_CORRUPT(mp, i != 1)) {
698 xfs_btree_mark_sick(cur);
699 error = -EFSCORRUPTED;
702 if (rtrec.rm_startblock >= bno + len)
706 /* Make sure the extent we found covers the entire freeing range. */
707 if (XFS_IS_CORRUPT(mp,
708 ltrec.rm_startblock > bno ||
709 ltrec.rm_startblock + ltrec.rm_blockcount <
711 xfs_btree_mark_sick(cur);
712 error = -EFSCORRUPTED;
716 /* Check owner information. */
717 error = xfs_rmap_free_check_owner(cur, ltoff, <rec, len, owner,
722 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
723 /* exact match, simply remove the record from rmap tree */
724 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
725 ltrec.rm_startblock, ltrec.rm_blockcount,
726 ltrec.rm_owner, ltrec.rm_offset,
728 error = xfs_btree_delete(cur, &i);
731 if (XFS_IS_CORRUPT(mp, i != 1)) {
732 xfs_btree_mark_sick(cur);
733 error = -EFSCORRUPTED;
736 } else if (ltrec.rm_startblock == bno) {
738 * overlap left hand side of extent: move the start, trim the
739 * length and update the current record.
742 * Orig: |oooooooooooooooooooo|
743 * Freeing: |fffffffff|
744 * Result: |rrrrrrrrrr|
747 ltrec.rm_startblock += len;
748 ltrec.rm_blockcount -= len;
750 ltrec.rm_offset += len;
751 error = xfs_rmap_update(cur, <rec);
754 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
756 * overlap right hand side of extent: trim the length and update
757 * the current record.
760 * Orig: |oooooooooooooooooooo|
761 * Freeing: |fffffffff|
762 * Result: |rrrrrrrrrr|
765 ltrec.rm_blockcount -= len;
766 error = xfs_rmap_update(cur, <rec);
772 * overlap middle of extent: trim the length of the existing
773 * record to the length of the new left-extent size, increment
774 * the insertion position so we can insert a new record
775 * containing the remaining right-extent space.
778 * Orig: |oooooooooooooooooooo|
779 * Freeing: |fffffffff|
780 * Result: |rrrrr| |rrrr|
783 xfs_extlen_t orig_len = ltrec.rm_blockcount;
785 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
786 error = xfs_rmap_update(cur, <rec);
790 error = xfs_btree_increment(cur, 0, &i);
794 cur->bc_rec.r.rm_startblock = bno + len;
795 cur->bc_rec.r.rm_blockcount = orig_len - len -
797 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
799 cur->bc_rec.r.rm_offset = 0;
801 cur->bc_rec.r.rm_offset = offset + len;
802 cur->bc_rec.r.rm_flags = flags;
803 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
804 cur->bc_rec.r.rm_startblock,
805 cur->bc_rec.r.rm_blockcount,
806 cur->bc_rec.r.rm_owner,
807 cur->bc_rec.r.rm_offset,
808 cur->bc_rec.r.rm_flags);
809 error = xfs_btree_insert(cur, &i);
815 trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
819 trace_xfs_rmap_unmap_error(mp, cur->bc_ag.pag->pag_agno,
824 #ifdef CONFIG_XFS_LIVE_HOOKS
826 * Use a static key here to reduce the overhead of rmapbt live updates. If
827 * the compiler supports jump labels, the static branch will be replaced by a
828 * nop sled when there are no hook users. Online fsck is currently the only
829 * caller, so this is a reasonable tradeoff.
831 * Note: Patching the kernel code requires taking the cpu hotplug lock. Other
832 * parts of the kernel allocate memory with that lock held, which means that
833 * XFS callers cannot hold any locks that might be used by memory reclaim or
834 * writeback when calling the static_branch_{inc,dec} functions.
836 DEFINE_STATIC_XFS_HOOK_SWITCH(xfs_rmap_hooks_switch);
839 xfs_rmap_hook_disable(void)
841 xfs_hooks_switch_off(&xfs_rmap_hooks_switch);
845 xfs_rmap_hook_enable(void)
847 xfs_hooks_switch_on(&xfs_rmap_hooks_switch);
850 /* Call downstream hooks for a reverse mapping update. */
852 xfs_rmap_update_hook(
853 struct xfs_trans *tp,
854 struct xfs_perag *pag,
855 enum xfs_rmap_intent_type op,
856 xfs_agblock_t startblock,
857 xfs_extlen_t blockcount,
859 const struct xfs_owner_info *oinfo)
861 if (xfs_hooks_switched_on(&xfs_rmap_hooks_switch)) {
862 struct xfs_rmap_update_params p = {
863 .startblock = startblock,
864 .blockcount = blockcount,
865 .unwritten = unwritten,
866 .oinfo = *oinfo, /* struct copy */
870 xfs_hooks_call(&pag->pag_rmap_update_hooks, op, &p);
874 /* Call the specified function during a reverse mapping update. */
877 struct xfs_perag *pag,
878 struct xfs_rmap_hook *hook)
880 return xfs_hooks_add(&pag->pag_rmap_update_hooks, &hook->rmap_hook);
883 /* Stop calling the specified function during a reverse mapping update. */
886 struct xfs_perag *pag,
887 struct xfs_rmap_hook *hook)
889 xfs_hooks_del(&pag->pag_rmap_update_hooks, &hook->rmap_hook);
892 /* Configure rmap update hook functions. */
895 struct xfs_rmap_hook *hook,
896 notifier_fn_t mod_fn)
898 xfs_hook_setup(&hook->rmap_hook, mod_fn);
901 # define xfs_rmap_update_hook(t, p, o, s, b, u, oi) do { } while (0)
902 #endif /* CONFIG_XFS_LIVE_HOOKS */
905 * Remove a reference to an extent in the rmap btree.
909 struct xfs_trans *tp,
910 struct xfs_buf *agbp,
911 struct xfs_perag *pag,
914 const struct xfs_owner_info *oinfo)
916 struct xfs_mount *mp = tp->t_mountp;
917 struct xfs_btree_cur *cur;
920 if (!xfs_has_rmapbt(mp))
923 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
924 xfs_rmap_update_hook(tp, pag, XFS_RMAP_UNMAP, bno, len, false, oinfo);
925 error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
927 xfs_btree_del_cursor(cur, error);
932 * A mergeable rmap must have the same owner and the same values for
933 * the unwritten, attr_fork, and bmbt flags. The startblock and
934 * offset are checked separately.
937 xfs_rmap_is_mergeable(
938 struct xfs_rmap_irec *irec,
942 if (irec->rm_owner == XFS_RMAP_OWN_NULL)
944 if (irec->rm_owner != owner)
946 if ((flags & XFS_RMAP_UNWRITTEN) ^
947 (irec->rm_flags & XFS_RMAP_UNWRITTEN))
949 if ((flags & XFS_RMAP_ATTR_FORK) ^
950 (irec->rm_flags & XFS_RMAP_ATTR_FORK))
952 if ((flags & XFS_RMAP_BMBT_BLOCK) ^
953 (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
959 * When we allocate a new block, the first thing we do is add a reference to
960 * the extent in the rmap btree. This takes the form of a [agbno, length,
961 * owner, offset] record. Flags are encoded in the high bits of the offset
966 struct xfs_btree_cur *cur,
970 const struct xfs_owner_info *oinfo)
972 struct xfs_mount *mp = cur->bc_mp;
973 struct xfs_rmap_irec ltrec;
974 struct xfs_rmap_irec gtrec;
981 unsigned int flags = 0;
984 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
986 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
987 (flags & XFS_RMAP_BMBT_BLOCK);
989 flags |= XFS_RMAP_UNWRITTEN;
990 trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
992 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
995 * For the initial lookup, look for an exact match or the left-adjacent
996 * record for our insertion point. This will also give us the record for
997 * start block contiguity tests.
999 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, <rec,
1004 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
1005 cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
1006 ltrec.rm_blockcount, ltrec.rm_owner,
1007 ltrec.rm_offset, ltrec.rm_flags);
1009 if (!xfs_rmap_is_mergeable(<rec, owner, flags))
1013 if (XFS_IS_CORRUPT(mp,
1015 ltrec.rm_startblock + ltrec.rm_blockcount > bno)) {
1016 xfs_btree_mark_sick(cur);
1017 error = -EFSCORRUPTED;
1022 * Increment the cursor to see if we have a right-adjacent record to our
1023 * insertion point. This will give us the record for end block
1026 error = xfs_btree_increment(cur, 0, &have_gt);
1030 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
1033 if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
1034 xfs_btree_mark_sick(cur);
1035 error = -EFSCORRUPTED;
1038 if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) {
1039 xfs_btree_mark_sick(cur);
1040 error = -EFSCORRUPTED;
1043 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1044 cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
1045 gtrec.rm_blockcount, gtrec.rm_owner,
1046 gtrec.rm_offset, gtrec.rm_flags);
1047 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
1052 * Note: cursor currently points one record to the right of ltrec, even
1053 * if there is no record in the tree to the right.
1056 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
1057 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
1059 * left edge contiguous, merge into left record.
1063 * adding: |aaaaaaaaa|
1064 * result: |rrrrrrrrrrrrrrrrrrr|
1067 ltrec.rm_blockcount += len;
1069 bno + len == gtrec.rm_startblock &&
1070 (ignore_off || offset + len == gtrec.rm_offset) &&
1071 (unsigned long)ltrec.rm_blockcount + len +
1072 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
1074 * right edge also contiguous, delete right record
1075 * and merge into left record.
1077 * ltbno ltlen gtbno gtlen
1078 * orig: |ooooooooo| |ooooooooo|
1079 * adding: |aaaaaaaaa|
1080 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1082 ltrec.rm_blockcount += gtrec.rm_blockcount;
1083 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1084 gtrec.rm_startblock,
1085 gtrec.rm_blockcount,
1089 error = xfs_btree_delete(cur, &i);
1092 if (XFS_IS_CORRUPT(mp, i != 1)) {
1093 xfs_btree_mark_sick(cur);
1094 error = -EFSCORRUPTED;
1099 /* point the cursor back to the left record and update */
1100 error = xfs_btree_decrement(cur, 0, &have_gt);
1103 error = xfs_rmap_update(cur, <rec);
1106 } else if (have_gt &&
1107 bno + len == gtrec.rm_startblock &&
1108 (ignore_off || offset + len == gtrec.rm_offset)) {
1110 * right edge contiguous, merge into right record.
1114 * adding: |aaaaaaaaa|
1115 * Result: |rrrrrrrrrrrrrrrrrrr|
1118 gtrec.rm_startblock = bno;
1119 gtrec.rm_blockcount += len;
1121 gtrec.rm_offset = offset;
1122 error = xfs_rmap_update(cur, >rec);
1127 * no contiguous edge with identical owner, insert
1128 * new record at current cursor position.
1130 cur->bc_rec.r.rm_startblock = bno;
1131 cur->bc_rec.r.rm_blockcount = len;
1132 cur->bc_rec.r.rm_owner = owner;
1133 cur->bc_rec.r.rm_offset = offset;
1134 cur->bc_rec.r.rm_flags = flags;
1135 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1136 owner, offset, flags);
1137 error = xfs_btree_insert(cur, &i);
1140 if (XFS_IS_CORRUPT(mp, i != 1)) {
1141 xfs_btree_mark_sick(cur);
1142 error = -EFSCORRUPTED;
1147 trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1151 trace_xfs_rmap_map_error(mp, cur->bc_ag.pag->pag_agno,
1157 * Add a reference to an extent in the rmap btree.
1161 struct xfs_trans *tp,
1162 struct xfs_buf *agbp,
1163 struct xfs_perag *pag,
1166 const struct xfs_owner_info *oinfo)
1168 struct xfs_mount *mp = tp->t_mountp;
1169 struct xfs_btree_cur *cur;
1172 if (!xfs_has_rmapbt(mp))
1175 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
1176 xfs_rmap_update_hook(tp, pag, XFS_RMAP_MAP, bno, len, false, oinfo);
1177 error = xfs_rmap_map(cur, bno, len, false, oinfo);
1179 xfs_btree_del_cursor(cur, error);
1183 #define RMAP_LEFT_CONTIG (1 << 0)
1184 #define RMAP_RIGHT_CONTIG (1 << 1)
1185 #define RMAP_LEFT_FILLING (1 << 2)
1186 #define RMAP_RIGHT_FILLING (1 << 3)
1187 #define RMAP_LEFT_VALID (1 << 6)
1188 #define RMAP_RIGHT_VALID (1 << 7)
1196 * Convert an unwritten extent to a real extent or vice versa.
1197 * Does not handle overlapping extents.
1201 struct xfs_btree_cur *cur,
1205 const struct xfs_owner_info *oinfo)
1207 struct xfs_mount *mp = cur->bc_mp;
1208 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1209 /* left is 0, right is 1, */
1210 /* prev is 2, new is 3 */
1213 uint64_t new_endoff;
1214 unsigned int oldext;
1215 unsigned int newext;
1216 unsigned int flags = 0;
1221 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1222 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1223 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1224 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1225 new_endoff = offset + len;
1226 trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1230 * For the initial lookup, look for an exact match or the left-adjacent
1231 * record for our insertion point. This will also give us the record for
1232 * start block contiguity tests.
1234 error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, &PREV, &i);
1237 if (XFS_IS_CORRUPT(mp, i != 1)) {
1238 xfs_btree_mark_sick(cur);
1239 error = -EFSCORRUPTED;
1243 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
1244 cur->bc_ag.pag->pag_agno, PREV.rm_startblock,
1245 PREV.rm_blockcount, PREV.rm_owner,
1246 PREV.rm_offset, PREV.rm_flags);
1248 ASSERT(PREV.rm_offset <= offset);
1249 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1250 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1251 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1254 * Set flags determining what part of the previous oldext allocation
1255 * extent is being replaced by a newext allocation.
1257 if (PREV.rm_offset == offset)
1258 state |= RMAP_LEFT_FILLING;
1259 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1260 state |= RMAP_RIGHT_FILLING;
1263 * Decrement the cursor to see if we have a left-adjacent record to our
1264 * insertion point. This will give us the record for end block
1267 error = xfs_btree_decrement(cur, 0, &i);
1271 state |= RMAP_LEFT_VALID;
1272 error = xfs_rmap_get_rec(cur, &LEFT, &i);
1275 if (XFS_IS_CORRUPT(mp, i != 1)) {
1276 xfs_btree_mark_sick(cur);
1277 error = -EFSCORRUPTED;
1280 if (XFS_IS_CORRUPT(mp,
1281 LEFT.rm_startblock + LEFT.rm_blockcount >
1283 xfs_btree_mark_sick(cur);
1284 error = -EFSCORRUPTED;
1287 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
1288 cur->bc_ag.pag->pag_agno, LEFT.rm_startblock,
1289 LEFT.rm_blockcount, LEFT.rm_owner,
1290 LEFT.rm_offset, LEFT.rm_flags);
1291 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1292 LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1293 xfs_rmap_is_mergeable(&LEFT, owner, newext))
1294 state |= RMAP_LEFT_CONTIG;
1298 * Increment the cursor to see if we have a right-adjacent record to our
1299 * insertion point. This will give us the record for end block
1302 error = xfs_btree_increment(cur, 0, &i);
1305 if (XFS_IS_CORRUPT(mp, i != 1)) {
1306 xfs_btree_mark_sick(cur);
1307 error = -EFSCORRUPTED;
1310 error = xfs_btree_increment(cur, 0, &i);
1314 state |= RMAP_RIGHT_VALID;
1315 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1318 if (XFS_IS_CORRUPT(mp, i != 1)) {
1319 xfs_btree_mark_sick(cur);
1320 error = -EFSCORRUPTED;
1323 if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1324 xfs_btree_mark_sick(cur);
1325 error = -EFSCORRUPTED;
1328 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1329 cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
1330 RIGHT.rm_blockcount, RIGHT.rm_owner,
1331 RIGHT.rm_offset, RIGHT.rm_flags);
1332 if (bno + len == RIGHT.rm_startblock &&
1333 offset + len == RIGHT.rm_offset &&
1334 xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1335 state |= RMAP_RIGHT_CONTIG;
1338 /* check that left + prev + right is not too long */
1339 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1340 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1341 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1342 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1343 (unsigned long)LEFT.rm_blockcount + len +
1344 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1345 state &= ~RMAP_RIGHT_CONTIG;
1347 trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
1350 /* reset the cursor back to PREV */
1351 error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, NULL, &i);
1354 if (XFS_IS_CORRUPT(mp, i != 1)) {
1355 xfs_btree_mark_sick(cur);
1356 error = -EFSCORRUPTED;
1361 * Switch out based on the FILLING and CONTIG state bits.
1363 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1364 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1365 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1366 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1368 * Setting all of a previous oldext extent to newext.
1369 * The left and right neighbors are both contiguous with new.
1371 error = xfs_btree_increment(cur, 0, &i);
1374 if (XFS_IS_CORRUPT(mp, i != 1)) {
1375 xfs_btree_mark_sick(cur);
1376 error = -EFSCORRUPTED;
1379 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1380 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1381 RIGHT.rm_owner, RIGHT.rm_offset,
1383 error = xfs_btree_delete(cur, &i);
1386 if (XFS_IS_CORRUPT(mp, i != 1)) {
1387 xfs_btree_mark_sick(cur);
1388 error = -EFSCORRUPTED;
1391 error = xfs_btree_decrement(cur, 0, &i);
1394 if (XFS_IS_CORRUPT(mp, i != 1)) {
1395 xfs_btree_mark_sick(cur);
1396 error = -EFSCORRUPTED;
1399 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1400 PREV.rm_startblock, PREV.rm_blockcount,
1401 PREV.rm_owner, PREV.rm_offset,
1403 error = xfs_btree_delete(cur, &i);
1406 if (XFS_IS_CORRUPT(mp, i != 1)) {
1407 xfs_btree_mark_sick(cur);
1408 error = -EFSCORRUPTED;
1411 error = xfs_btree_decrement(cur, 0, &i);
1414 if (XFS_IS_CORRUPT(mp, i != 1)) {
1415 xfs_btree_mark_sick(cur);
1416 error = -EFSCORRUPTED;
1420 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1421 error = xfs_rmap_update(cur, &NEW);
1426 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1428 * Setting all of a previous oldext extent to newext.
1429 * The left neighbor is contiguous, the right is not.
1431 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1432 PREV.rm_startblock, PREV.rm_blockcount,
1433 PREV.rm_owner, PREV.rm_offset,
1435 error = xfs_btree_delete(cur, &i);
1438 if (XFS_IS_CORRUPT(mp, i != 1)) {
1439 xfs_btree_mark_sick(cur);
1440 error = -EFSCORRUPTED;
1443 error = xfs_btree_decrement(cur, 0, &i);
1446 if (XFS_IS_CORRUPT(mp, i != 1)) {
1447 xfs_btree_mark_sick(cur);
1448 error = -EFSCORRUPTED;
1452 NEW.rm_blockcount += PREV.rm_blockcount;
1453 error = xfs_rmap_update(cur, &NEW);
1458 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1460 * Setting all of a previous oldext extent to newext.
1461 * The right neighbor is contiguous, the left is not.
1463 error = xfs_btree_increment(cur, 0, &i);
1466 if (XFS_IS_CORRUPT(mp, i != 1)) {
1467 xfs_btree_mark_sick(cur);
1468 error = -EFSCORRUPTED;
1471 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1472 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1473 RIGHT.rm_owner, RIGHT.rm_offset,
1475 error = xfs_btree_delete(cur, &i);
1478 if (XFS_IS_CORRUPT(mp, i != 1)) {
1479 xfs_btree_mark_sick(cur);
1480 error = -EFSCORRUPTED;
1483 error = xfs_btree_decrement(cur, 0, &i);
1486 if (XFS_IS_CORRUPT(mp, i != 1)) {
1487 xfs_btree_mark_sick(cur);
1488 error = -EFSCORRUPTED;
1492 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1493 NEW.rm_flags = newext;
1494 error = xfs_rmap_update(cur, &NEW);
1499 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1501 * Setting all of a previous oldext extent to newext.
1502 * Neither the left nor right neighbors are contiguous with
1506 NEW.rm_flags = newext;
1507 error = xfs_rmap_update(cur, &NEW);
1512 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1514 * Setting the first part of a previous oldext extent to newext.
1515 * The left neighbor is contiguous.
1518 NEW.rm_offset += len;
1519 NEW.rm_startblock += len;
1520 NEW.rm_blockcount -= len;
1521 error = xfs_rmap_update(cur, &NEW);
1524 error = xfs_btree_decrement(cur, 0, &i);
1528 NEW.rm_blockcount += len;
1529 error = xfs_rmap_update(cur, &NEW);
1534 case RMAP_LEFT_FILLING:
1536 * Setting the first part of a previous oldext extent to newext.
1537 * The left neighbor is not contiguous.
1540 NEW.rm_startblock += len;
1541 NEW.rm_offset += len;
1542 NEW.rm_blockcount -= len;
1543 error = xfs_rmap_update(cur, &NEW);
1546 NEW.rm_startblock = bno;
1547 NEW.rm_owner = owner;
1548 NEW.rm_offset = offset;
1549 NEW.rm_blockcount = len;
1550 NEW.rm_flags = newext;
1551 cur->bc_rec.r = NEW;
1552 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
1553 len, owner, offset, newext);
1554 error = xfs_btree_insert(cur, &i);
1557 if (XFS_IS_CORRUPT(mp, i != 1)) {
1558 xfs_btree_mark_sick(cur);
1559 error = -EFSCORRUPTED;
1564 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1566 * Setting the last part of a previous oldext extent to newext.
1567 * The right neighbor is contiguous with the new allocation.
1570 NEW.rm_blockcount -= len;
1571 error = xfs_rmap_update(cur, &NEW);
1574 error = xfs_btree_increment(cur, 0, &i);
1578 NEW.rm_offset = offset;
1579 NEW.rm_startblock = bno;
1580 NEW.rm_blockcount += len;
1581 error = xfs_rmap_update(cur, &NEW);
1586 case RMAP_RIGHT_FILLING:
1588 * Setting the last part of a previous oldext extent to newext.
1589 * The right neighbor is not contiguous.
1592 NEW.rm_blockcount -= len;
1593 error = xfs_rmap_update(cur, &NEW);
1596 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1600 if (XFS_IS_CORRUPT(mp, i != 0)) {
1601 xfs_btree_mark_sick(cur);
1602 error = -EFSCORRUPTED;
1605 NEW.rm_startblock = bno;
1606 NEW.rm_owner = owner;
1607 NEW.rm_offset = offset;
1608 NEW.rm_blockcount = len;
1609 NEW.rm_flags = newext;
1610 cur->bc_rec.r = NEW;
1611 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
1612 len, owner, offset, newext);
1613 error = xfs_btree_insert(cur, &i);
1616 if (XFS_IS_CORRUPT(mp, i != 1)) {
1617 xfs_btree_mark_sick(cur);
1618 error = -EFSCORRUPTED;
1625 * Setting the middle part of a previous oldext extent to
1626 * newext. Contiguity is impossible here.
1627 * One extent becomes three extents.
1629 /* new right extent - oldext */
1630 NEW.rm_startblock = bno + len;
1631 NEW.rm_owner = owner;
1632 NEW.rm_offset = new_endoff;
1633 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1635 NEW.rm_flags = PREV.rm_flags;
1636 error = xfs_rmap_update(cur, &NEW);
1639 /* new left extent - oldext */
1641 NEW.rm_blockcount = offset - PREV.rm_offset;
1642 cur->bc_rec.r = NEW;
1643 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
1644 NEW.rm_startblock, NEW.rm_blockcount,
1645 NEW.rm_owner, NEW.rm_offset,
1647 error = xfs_btree_insert(cur, &i);
1650 if (XFS_IS_CORRUPT(mp, i != 1)) {
1651 xfs_btree_mark_sick(cur);
1652 error = -EFSCORRUPTED;
1656 * Reset the cursor to the position of the new extent
1657 * we are about to insert as we can't trust it after
1658 * the previous insert.
1660 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1664 if (XFS_IS_CORRUPT(mp, i != 0)) {
1665 xfs_btree_mark_sick(cur);
1666 error = -EFSCORRUPTED;
1669 /* new middle extent - newext */
1670 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1671 cur->bc_rec.r.rm_flags |= newext;
1672 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1673 owner, offset, newext);
1674 error = xfs_btree_insert(cur, &i);
1677 if (XFS_IS_CORRUPT(mp, i != 1)) {
1678 xfs_btree_mark_sick(cur);
1679 error = -EFSCORRUPTED;
1684 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1685 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1686 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1687 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1688 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1689 case RMAP_LEFT_CONTIG:
1690 case RMAP_RIGHT_CONTIG:
1692 * These cases are all impossible.
1697 trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1701 trace_xfs_rmap_convert_error(cur->bc_mp,
1702 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
1707 * Convert an unwritten extent to a real extent or vice versa. If there is no
1708 * possibility of overlapping extents, delegate to the simpler convert
1712 xfs_rmap_convert_shared(
1713 struct xfs_btree_cur *cur,
1717 const struct xfs_owner_info *oinfo)
1719 struct xfs_mount *mp = cur->bc_mp;
1720 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1721 /* left is 0, right is 1, */
1722 /* prev is 2, new is 3 */
1725 uint64_t new_endoff;
1726 unsigned int oldext;
1727 unsigned int newext;
1728 unsigned int flags = 0;
1733 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1734 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1735 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1736 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1737 new_endoff = offset + len;
1738 trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1742 * For the initial lookup, look for and exact match or the left-adjacent
1743 * record for our insertion point. This will also give us the record for
1744 * start block contiguity tests.
1746 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, oldext,
1750 if (XFS_IS_CORRUPT(mp, i != 1)) {
1751 xfs_btree_mark_sick(cur);
1752 error = -EFSCORRUPTED;
1756 ASSERT(PREV.rm_offset <= offset);
1757 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1758 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1759 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1762 * Set flags determining what part of the previous oldext allocation
1763 * extent is being replaced by a newext allocation.
1765 if (PREV.rm_offset == offset)
1766 state |= RMAP_LEFT_FILLING;
1767 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1768 state |= RMAP_RIGHT_FILLING;
1770 /* Is there a left record that abuts our range? */
1771 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1776 state |= RMAP_LEFT_VALID;
1777 if (XFS_IS_CORRUPT(mp,
1778 LEFT.rm_startblock + LEFT.rm_blockcount >
1780 xfs_btree_mark_sick(cur);
1781 error = -EFSCORRUPTED;
1784 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1785 state |= RMAP_LEFT_CONTIG;
1788 /* Is there a right record that abuts our range? */
1789 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1794 state |= RMAP_RIGHT_VALID;
1795 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1798 if (XFS_IS_CORRUPT(mp, i != 1)) {
1799 xfs_btree_mark_sick(cur);
1800 error = -EFSCORRUPTED;
1803 if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1804 xfs_btree_mark_sick(cur);
1805 error = -EFSCORRUPTED;
1808 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1809 cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
1810 RIGHT.rm_blockcount, RIGHT.rm_owner,
1811 RIGHT.rm_offset, RIGHT.rm_flags);
1812 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1813 state |= RMAP_RIGHT_CONTIG;
1816 /* check that left + prev + right is not too long */
1817 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1818 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1819 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1820 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1821 (unsigned long)LEFT.rm_blockcount + len +
1822 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1823 state &= ~RMAP_RIGHT_CONTIG;
1825 trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
1828 * Switch out based on the FILLING and CONTIG state bits.
1830 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1831 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1832 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1833 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1835 * Setting all of a previous oldext extent to newext.
1836 * The left and right neighbors are both contiguous with new.
1838 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1839 RIGHT.rm_blockcount, RIGHT.rm_owner,
1840 RIGHT.rm_offset, RIGHT.rm_flags);
1843 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1844 PREV.rm_blockcount, PREV.rm_owner,
1845 PREV.rm_offset, PREV.rm_flags);
1849 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1850 NEW.rm_blockcount, NEW.rm_owner,
1851 NEW.rm_offset, NEW.rm_flags, &i);
1854 if (XFS_IS_CORRUPT(mp, i != 1)) {
1855 xfs_btree_mark_sick(cur);
1856 error = -EFSCORRUPTED;
1859 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1860 error = xfs_rmap_update(cur, &NEW);
1865 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1867 * Setting all of a previous oldext extent to newext.
1868 * The left neighbor is contiguous, the right is not.
1870 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1871 PREV.rm_blockcount, PREV.rm_owner,
1872 PREV.rm_offset, PREV.rm_flags);
1876 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1877 NEW.rm_blockcount, NEW.rm_owner,
1878 NEW.rm_offset, NEW.rm_flags, &i);
1881 if (XFS_IS_CORRUPT(mp, i != 1)) {
1882 xfs_btree_mark_sick(cur);
1883 error = -EFSCORRUPTED;
1886 NEW.rm_blockcount += PREV.rm_blockcount;
1887 error = xfs_rmap_update(cur, &NEW);
1892 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1894 * Setting all of a previous oldext extent to newext.
1895 * The right neighbor is contiguous, the left is not.
1897 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1898 RIGHT.rm_blockcount, RIGHT.rm_owner,
1899 RIGHT.rm_offset, RIGHT.rm_flags);
1903 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1904 NEW.rm_blockcount, NEW.rm_owner,
1905 NEW.rm_offset, NEW.rm_flags, &i);
1908 if (XFS_IS_CORRUPT(mp, i != 1)) {
1909 xfs_btree_mark_sick(cur);
1910 error = -EFSCORRUPTED;
1913 NEW.rm_blockcount += RIGHT.rm_blockcount;
1914 NEW.rm_flags = RIGHT.rm_flags;
1915 error = xfs_rmap_update(cur, &NEW);
1920 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1922 * Setting all of a previous oldext extent to newext.
1923 * Neither the left nor right neighbors are contiguous with
1927 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1928 NEW.rm_blockcount, NEW.rm_owner,
1929 NEW.rm_offset, NEW.rm_flags, &i);
1932 if (XFS_IS_CORRUPT(mp, i != 1)) {
1933 xfs_btree_mark_sick(cur);
1934 error = -EFSCORRUPTED;
1937 NEW.rm_flags = newext;
1938 error = xfs_rmap_update(cur, &NEW);
1943 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1945 * Setting the first part of a previous oldext extent to newext.
1946 * The left neighbor is contiguous.
1949 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1950 NEW.rm_blockcount, NEW.rm_owner,
1951 NEW.rm_offset, NEW.rm_flags);
1954 NEW.rm_offset += len;
1955 NEW.rm_startblock += len;
1956 NEW.rm_blockcount -= len;
1957 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1958 NEW.rm_blockcount, NEW.rm_owner,
1959 NEW.rm_offset, NEW.rm_flags);
1963 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1964 NEW.rm_blockcount, NEW.rm_owner,
1965 NEW.rm_offset, NEW.rm_flags, &i);
1968 if (XFS_IS_CORRUPT(mp, i != 1)) {
1969 xfs_btree_mark_sick(cur);
1970 error = -EFSCORRUPTED;
1973 NEW.rm_blockcount += len;
1974 error = xfs_rmap_update(cur, &NEW);
1979 case RMAP_LEFT_FILLING:
1981 * Setting the first part of a previous oldext extent to newext.
1982 * The left neighbor is not contiguous.
1985 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1986 NEW.rm_blockcount, NEW.rm_owner,
1987 NEW.rm_offset, NEW.rm_flags);
1990 NEW.rm_offset += len;
1991 NEW.rm_startblock += len;
1992 NEW.rm_blockcount -= len;
1993 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1994 NEW.rm_blockcount, NEW.rm_owner,
1995 NEW.rm_offset, NEW.rm_flags);
1998 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
2003 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
2005 * Setting the last part of a previous oldext extent to newext.
2006 * The right neighbor is contiguous with the new allocation.
2009 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
2010 NEW.rm_blockcount, NEW.rm_owner,
2011 NEW.rm_offset, NEW.rm_flags, &i);
2014 if (XFS_IS_CORRUPT(mp, i != 1)) {
2015 xfs_btree_mark_sick(cur);
2016 error = -EFSCORRUPTED;
2019 NEW.rm_blockcount = offset - NEW.rm_offset;
2020 error = xfs_rmap_update(cur, &NEW);
2024 error = xfs_rmap_delete(cur, NEW.rm_startblock,
2025 NEW.rm_blockcount, NEW.rm_owner,
2026 NEW.rm_offset, NEW.rm_flags);
2029 NEW.rm_offset = offset;
2030 NEW.rm_startblock = bno;
2031 NEW.rm_blockcount += len;
2032 error = xfs_rmap_insert(cur, NEW.rm_startblock,
2033 NEW.rm_blockcount, NEW.rm_owner,
2034 NEW.rm_offset, NEW.rm_flags);
2039 case RMAP_RIGHT_FILLING:
2041 * Setting the last part of a previous oldext extent to newext.
2042 * The right neighbor is not contiguous.
2045 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
2046 NEW.rm_blockcount, NEW.rm_owner,
2047 NEW.rm_offset, NEW.rm_flags, &i);
2050 if (XFS_IS_CORRUPT(mp, i != 1)) {
2051 xfs_btree_mark_sick(cur);
2052 error = -EFSCORRUPTED;
2055 NEW.rm_blockcount -= len;
2056 error = xfs_rmap_update(cur, &NEW);
2059 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
2066 * Setting the middle part of a previous oldext extent to
2067 * newext. Contiguity is impossible here.
2068 * One extent becomes three extents.
2070 /* new right extent - oldext */
2071 NEW.rm_startblock = bno + len;
2072 NEW.rm_owner = owner;
2073 NEW.rm_offset = new_endoff;
2074 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
2076 NEW.rm_flags = PREV.rm_flags;
2077 error = xfs_rmap_insert(cur, NEW.rm_startblock,
2078 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
2082 /* new left extent - oldext */
2084 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
2085 NEW.rm_blockcount, NEW.rm_owner,
2086 NEW.rm_offset, NEW.rm_flags, &i);
2089 if (XFS_IS_CORRUPT(mp, i != 1)) {
2090 xfs_btree_mark_sick(cur);
2091 error = -EFSCORRUPTED;
2094 NEW.rm_blockcount = offset - NEW.rm_offset;
2095 error = xfs_rmap_update(cur, &NEW);
2098 /* new middle extent - newext */
2099 NEW.rm_startblock = bno;
2100 NEW.rm_blockcount = len;
2101 NEW.rm_owner = owner;
2102 NEW.rm_offset = offset;
2103 NEW.rm_flags = newext;
2104 error = xfs_rmap_insert(cur, NEW.rm_startblock,
2105 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
2111 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
2112 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
2113 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
2114 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
2115 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
2116 case RMAP_LEFT_CONTIG:
2117 case RMAP_RIGHT_CONTIG:
2119 * These cases are all impossible.
2124 trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2128 trace_xfs_rmap_convert_error(cur->bc_mp,
2129 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2139 * Find an extent in the rmap btree and unmap it. For rmap extent types that
2140 * can overlap (data fork rmaps on reflink filesystems) we must be careful
2141 * that the prev/next records in the btree might belong to another owner.
2142 * Therefore we must use delete+insert to alter any of the key fields.
2144 * For every other situation there can only be one owner for a given extent,
2145 * so we can call the regular _free function.
2148 xfs_rmap_unmap_shared(
2149 struct xfs_btree_cur *cur,
2153 const struct xfs_owner_info *oinfo)
2155 struct xfs_mount *mp = cur->bc_mp;
2156 struct xfs_rmap_irec ltrec;
2164 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2166 flags |= XFS_RMAP_UNWRITTEN;
2167 trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
2171 * We should always have a left record because there's a static record
2172 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
2173 * will not ever be removed from the tree.
2175 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
2179 if (XFS_IS_CORRUPT(mp, i != 1)) {
2180 xfs_btree_mark_sick(cur);
2181 error = -EFSCORRUPTED;
2184 ltoff = ltrec.rm_offset;
2186 /* Make sure the extent we found covers the entire freeing range. */
2187 if (XFS_IS_CORRUPT(mp,
2188 ltrec.rm_startblock > bno ||
2189 ltrec.rm_startblock + ltrec.rm_blockcount <
2191 xfs_btree_mark_sick(cur);
2192 error = -EFSCORRUPTED;
2196 /* Make sure the owner matches what we expect to find in the tree. */
2197 if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) {
2198 xfs_btree_mark_sick(cur);
2199 error = -EFSCORRUPTED;
2203 /* Make sure the unwritten flag matches. */
2204 if (XFS_IS_CORRUPT(mp,
2205 (flags & XFS_RMAP_UNWRITTEN) !=
2206 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) {
2207 xfs_btree_mark_sick(cur);
2208 error = -EFSCORRUPTED;
2212 /* Check the offset. */
2213 if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) {
2214 xfs_btree_mark_sick(cur);
2215 error = -EFSCORRUPTED;
2218 if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) {
2219 xfs_btree_mark_sick(cur);
2220 error = -EFSCORRUPTED;
2224 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
2225 /* Exact match, simply remove the record from rmap tree. */
2226 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2227 ltrec.rm_blockcount, ltrec.rm_owner,
2228 ltrec.rm_offset, ltrec.rm_flags);
2231 } else if (ltrec.rm_startblock == bno) {
2233 * Overlap left hand side of extent: move the start, trim the
2234 * length and update the current record.
2237 * Orig: |oooooooooooooooooooo|
2238 * Freeing: |fffffffff|
2239 * Result: |rrrrrrrrrr|
2243 /* Delete prev rmap. */
2244 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2245 ltrec.rm_blockcount, ltrec.rm_owner,
2246 ltrec.rm_offset, ltrec.rm_flags);
2250 /* Add an rmap at the new offset. */
2251 ltrec.rm_startblock += len;
2252 ltrec.rm_blockcount -= len;
2253 ltrec.rm_offset += len;
2254 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
2255 ltrec.rm_blockcount, ltrec.rm_owner,
2256 ltrec.rm_offset, ltrec.rm_flags);
2259 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
2261 * Overlap right hand side of extent: trim the length and
2262 * update the current record.
2265 * Orig: |oooooooooooooooooooo|
2266 * Freeing: |fffffffff|
2267 * Result: |rrrrrrrrrr|
2270 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2271 ltrec.rm_blockcount, ltrec.rm_owner,
2272 ltrec.rm_offset, ltrec.rm_flags, &i);
2275 if (XFS_IS_CORRUPT(mp, i != 1)) {
2276 xfs_btree_mark_sick(cur);
2277 error = -EFSCORRUPTED;
2280 ltrec.rm_blockcount -= len;
2281 error = xfs_rmap_update(cur, <rec);
2286 * Overlap middle of extent: trim the length of the existing
2287 * record to the length of the new left-extent size, increment
2288 * the insertion position so we can insert a new record
2289 * containing the remaining right-extent space.
2292 * Orig: |oooooooooooooooooooo|
2293 * Freeing: |fffffffff|
2294 * Result: |rrrrr| |rrrr|
2297 xfs_extlen_t orig_len = ltrec.rm_blockcount;
2299 /* Shrink the left side of the rmap */
2300 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2301 ltrec.rm_blockcount, ltrec.rm_owner,
2302 ltrec.rm_offset, ltrec.rm_flags, &i);
2305 if (XFS_IS_CORRUPT(mp, i != 1)) {
2306 xfs_btree_mark_sick(cur);
2307 error = -EFSCORRUPTED;
2310 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
2311 error = xfs_rmap_update(cur, <rec);
2315 /* Add an rmap at the new offset */
2316 error = xfs_rmap_insert(cur, bno + len,
2317 orig_len - len - ltrec.rm_blockcount,
2318 ltrec.rm_owner, offset + len,
2324 trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2328 trace_xfs_rmap_unmap_error(cur->bc_mp,
2329 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2334 * Find an extent in the rmap btree and map it. For rmap extent types that
2335 * can overlap (data fork rmaps on reflink filesystems) we must be careful
2336 * that the prev/next records in the btree might belong to another owner.
2337 * Therefore we must use delete+insert to alter any of the key fields.
2339 * For every other situation there can only be one owner for a given extent,
2340 * so we can call the regular _alloc function.
2343 xfs_rmap_map_shared(
2344 struct xfs_btree_cur *cur,
2348 const struct xfs_owner_info *oinfo)
2350 struct xfs_mount *mp = cur->bc_mp;
2351 struct xfs_rmap_irec ltrec;
2352 struct xfs_rmap_irec gtrec;
2359 unsigned int flags = 0;
2361 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2363 flags |= XFS_RMAP_UNWRITTEN;
2364 trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
2367 /* Is there a left record that abuts our range? */
2368 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
2373 !xfs_rmap_is_mergeable(<rec, owner, flags))
2376 /* Is there a right record that abuts our range? */
2377 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
2382 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
2385 if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
2386 xfs_btree_mark_sick(cur);
2387 error = -EFSCORRUPTED;
2390 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
2391 cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
2392 gtrec.rm_blockcount, gtrec.rm_owner,
2393 gtrec.rm_offset, gtrec.rm_flags);
2395 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
2400 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
2401 ltrec.rm_offset + ltrec.rm_blockcount == offset) {
2403 * Left edge contiguous, merge into left record.
2407 * adding: |aaaaaaaaa|
2408 * result: |rrrrrrrrrrrrrrrrrrr|
2411 ltrec.rm_blockcount += len;
2413 bno + len == gtrec.rm_startblock &&
2414 offset + len == gtrec.rm_offset) {
2416 * Right edge also contiguous, delete right record
2417 * and merge into left record.
2419 * ltbno ltlen gtbno gtlen
2420 * orig: |ooooooooo| |ooooooooo|
2421 * adding: |aaaaaaaaa|
2422 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
2424 ltrec.rm_blockcount += gtrec.rm_blockcount;
2425 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2426 gtrec.rm_blockcount, gtrec.rm_owner,
2427 gtrec.rm_offset, gtrec.rm_flags);
2432 /* Point the cursor back to the left record and update. */
2433 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2434 ltrec.rm_blockcount, ltrec.rm_owner,
2435 ltrec.rm_offset, ltrec.rm_flags, &i);
2438 if (XFS_IS_CORRUPT(mp, i != 1)) {
2439 xfs_btree_mark_sick(cur);
2440 error = -EFSCORRUPTED;
2444 error = xfs_rmap_update(cur, <rec);
2447 } else if (have_gt &&
2448 bno + len == gtrec.rm_startblock &&
2449 offset + len == gtrec.rm_offset) {
2451 * Right edge contiguous, merge into right record.
2455 * adding: |aaaaaaaaa|
2456 * Result: |rrrrrrrrrrrrrrrrrrr|
2459 /* Delete the old record. */
2460 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2461 gtrec.rm_blockcount, gtrec.rm_owner,
2462 gtrec.rm_offset, gtrec.rm_flags);
2466 /* Move the start and re-add it. */
2467 gtrec.rm_startblock = bno;
2468 gtrec.rm_blockcount += len;
2469 gtrec.rm_offset = offset;
2470 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2471 gtrec.rm_blockcount, gtrec.rm_owner,
2472 gtrec.rm_offset, gtrec.rm_flags);
2477 * No contiguous edge with identical owner, insert
2478 * new record at current cursor position.
2480 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2485 trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2489 trace_xfs_rmap_map_error(cur->bc_mp,
2490 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2494 /* Insert a raw rmap into the rmapbt. */
2497 struct xfs_btree_cur *cur,
2498 struct xfs_rmap_irec *rmap)
2500 struct xfs_owner_info oinfo;
2502 xfs_owner_info_pack(&oinfo, rmap->rm_owner, rmap->rm_offset,
2505 if ((rmap->rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK |
2506 XFS_RMAP_UNWRITTEN)) ||
2507 XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2508 return xfs_rmap_map(cur, rmap->rm_startblock,
2509 rmap->rm_blockcount,
2510 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2513 return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2514 rmap->rm_blockcount,
2515 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2519 struct xfs_rmap_query_range_info {
2520 xfs_rmap_query_range_fn fn;
2524 /* Format btree record and pass to our callback. */
2526 xfs_rmap_query_range_helper(
2527 struct xfs_btree_cur *cur,
2528 const union xfs_btree_rec *rec,
2531 struct xfs_rmap_query_range_info *query = priv;
2532 struct xfs_rmap_irec irec;
2535 fa = xfs_rmap_btrec_to_irec(rec, &irec);
2537 fa = xfs_rmap_check_btrec(cur, &irec);
2539 return xfs_rmap_complain_bad_rec(cur, fa, &irec);
2541 return query->fn(cur, &irec, query->priv);
2544 /* Find all rmaps between two keys. */
2546 xfs_rmap_query_range(
2547 struct xfs_btree_cur *cur,
2548 const struct xfs_rmap_irec *low_rec,
2549 const struct xfs_rmap_irec *high_rec,
2550 xfs_rmap_query_range_fn fn,
2553 union xfs_btree_irec low_brec = { .r = *low_rec };
2554 union xfs_btree_irec high_brec = { .r = *high_rec };
2555 struct xfs_rmap_query_range_info query = { .priv = priv, .fn = fn };
2557 return xfs_btree_query_range(cur, &low_brec, &high_brec,
2558 xfs_rmap_query_range_helper, &query);
2561 /* Find all rmaps. */
2564 struct xfs_btree_cur *cur,
2565 xfs_rmap_query_range_fn fn,
2568 struct xfs_rmap_query_range_info query;
2572 return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2575 /* Clean up after calling xfs_rmap_finish_one. */
2577 xfs_rmap_finish_one_cleanup(
2578 struct xfs_trans *tp,
2579 struct xfs_btree_cur *rcur,
2582 struct xfs_buf *agbp;
2586 agbp = rcur->bc_ag.agbp;
2587 xfs_btree_del_cursor(rcur, error);
2589 xfs_trans_brelse(tp, agbp);
2592 /* Commit an rmap operation into the ondisk tree. */
2594 __xfs_rmap_finish_intent(
2595 struct xfs_btree_cur *rcur,
2596 enum xfs_rmap_intent_type op,
2599 const struct xfs_owner_info *oinfo,
2603 case XFS_RMAP_ALLOC:
2605 return xfs_rmap_map(rcur, bno, len, unwritten, oinfo);
2606 case XFS_RMAP_MAP_SHARED:
2607 return xfs_rmap_map_shared(rcur, bno, len, unwritten, oinfo);
2609 case XFS_RMAP_UNMAP:
2610 return xfs_rmap_unmap(rcur, bno, len, unwritten, oinfo);
2611 case XFS_RMAP_UNMAP_SHARED:
2612 return xfs_rmap_unmap_shared(rcur, bno, len, unwritten, oinfo);
2613 case XFS_RMAP_CONVERT:
2614 return xfs_rmap_convert(rcur, bno, len, !unwritten, oinfo);
2615 case XFS_RMAP_CONVERT_SHARED:
2616 return xfs_rmap_convert_shared(rcur, bno, len, !unwritten,
2620 return -EFSCORRUPTED;
2625 * Process one of the deferred rmap operations. We pass back the
2626 * btree cursor to maintain our lock on the rmapbt between calls.
2627 * This saves time and eliminates a buffer deadlock between the
2628 * superblock and the AGF because we'll always grab them in the same
2632 xfs_rmap_finish_one(
2633 struct xfs_trans *tp,
2634 struct xfs_rmap_intent *ri,
2635 struct xfs_btree_cur **pcur)
2637 struct xfs_mount *mp = tp->t_mountp;
2638 struct xfs_btree_cur *rcur;
2639 struct xfs_buf *agbp = NULL;
2641 struct xfs_owner_info oinfo;
2645 bno = XFS_FSB_TO_AGBNO(mp, ri->ri_bmap.br_startblock);
2647 trace_xfs_rmap_deferred(mp, ri->ri_pag->pag_agno, ri->ri_type, bno,
2648 ri->ri_owner, ri->ri_whichfork,
2649 ri->ri_bmap.br_startoff, ri->ri_bmap.br_blockcount,
2650 ri->ri_bmap.br_state);
2652 if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE))
2656 * If we haven't gotten a cursor or the cursor AG doesn't match
2657 * the startblock, get one now.
2660 if (rcur != NULL && rcur->bc_ag.pag != ri->ri_pag) {
2661 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2667 * Refresh the freelist before we start changing the
2668 * rmapbt, because a shape change could cause us to
2671 error = xfs_free_extent_fix_freelist(tp, ri->ri_pag, &agbp);
2673 xfs_ag_mark_sick(ri->ri_pag, XFS_SICK_AG_AGFL);
2676 if (XFS_IS_CORRUPT(tp->t_mountp, !agbp)) {
2677 xfs_ag_mark_sick(ri->ri_pag, XFS_SICK_AG_AGFL);
2678 return -EFSCORRUPTED;
2681 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, ri->ri_pag);
2685 xfs_rmap_ino_owner(&oinfo, ri->ri_owner, ri->ri_whichfork,
2686 ri->ri_bmap.br_startoff);
2687 unwritten = ri->ri_bmap.br_state == XFS_EXT_UNWRITTEN;
2688 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, ri->ri_bmap.br_startblock);
2690 error = __xfs_rmap_finish_intent(rcur, ri->ri_type, bno,
2691 ri->ri_bmap.br_blockcount, &oinfo, unwritten);
2695 xfs_rmap_update_hook(tp, ri->ri_pag, ri->ri_type, bno,
2696 ri->ri_bmap.br_blockcount, unwritten, &oinfo);
2701 * Don't defer an rmap if we aren't an rmap filesystem.
2704 xfs_rmap_update_is_needed(
2705 struct xfs_mount *mp,
2708 return xfs_has_rmapbt(mp) && whichfork != XFS_COW_FORK;
2712 * Record a rmap intent; the list is kept sorted first by AG and then by
2717 struct xfs_trans *tp,
2718 enum xfs_rmap_intent_type type,
2721 struct xfs_bmbt_irec *bmap)
2723 struct xfs_rmap_intent *ri;
2725 trace_xfs_rmap_defer(tp->t_mountp,
2726 XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock),
2728 XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock),
2731 bmap->br_blockcount,
2734 ri = kmem_cache_alloc(xfs_rmap_intent_cache, GFP_KERNEL | __GFP_NOFAIL);
2735 INIT_LIST_HEAD(&ri->ri_list);
2737 ri->ri_owner = owner;
2738 ri->ri_whichfork = whichfork;
2739 ri->ri_bmap = *bmap;
2741 xfs_rmap_update_get_group(tp->t_mountp, ri);
2742 xfs_defer_add(tp, &ri->ri_list, &xfs_rmap_update_defer_type);
2745 /* Map an extent into a file. */
2747 xfs_rmap_map_extent(
2748 struct xfs_trans *tp,
2749 struct xfs_inode *ip,
2751 struct xfs_bmbt_irec *PREV)
2753 enum xfs_rmap_intent_type type = XFS_RMAP_MAP;
2755 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2758 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2759 type = XFS_RMAP_MAP_SHARED;
2761 __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2764 /* Unmap an extent out of a file. */
2766 xfs_rmap_unmap_extent(
2767 struct xfs_trans *tp,
2768 struct xfs_inode *ip,
2770 struct xfs_bmbt_irec *PREV)
2772 enum xfs_rmap_intent_type type = XFS_RMAP_UNMAP;
2774 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2777 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2778 type = XFS_RMAP_UNMAP_SHARED;
2780 __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2784 * Convert a data fork extent from unwritten to real or vice versa.
2786 * Note that tp can be NULL here as no transaction is used for COW fork
2787 * unwritten conversion.
2790 xfs_rmap_convert_extent(
2791 struct xfs_mount *mp,
2792 struct xfs_trans *tp,
2793 struct xfs_inode *ip,
2795 struct xfs_bmbt_irec *PREV)
2797 enum xfs_rmap_intent_type type = XFS_RMAP_CONVERT;
2799 if (!xfs_rmap_update_is_needed(mp, whichfork))
2802 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2803 type = XFS_RMAP_CONVERT_SHARED;
2805 __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2808 /* Schedule the creation of an rmap for non-file data. */
2810 xfs_rmap_alloc_extent(
2811 struct xfs_trans *tp,
2812 xfs_agnumber_t agno,
2817 struct xfs_bmbt_irec bmap;
2819 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2822 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2823 bmap.br_blockcount = len;
2824 bmap.br_startoff = 0;
2825 bmap.br_state = XFS_EXT_NORM;
2827 __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
2830 /* Schedule the deletion of an rmap for non-file data. */
2832 xfs_rmap_free_extent(
2833 struct xfs_trans *tp,
2834 xfs_agnumber_t agno,
2839 struct xfs_bmbt_irec bmap;
2841 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2844 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2845 bmap.br_blockcount = len;
2846 bmap.br_startoff = 0;
2847 bmap.br_state = XFS_EXT_NORM;
2849 __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
2852 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2855 const struct xfs_rmap_irec *a,
2856 const struct xfs_rmap_irec *b)
2861 oa = xfs_rmap_irec_offset_pack(a);
2862 ob = xfs_rmap_irec_offset_pack(b);
2864 if (a->rm_startblock < b->rm_startblock)
2866 else if (a->rm_startblock > b->rm_startblock)
2868 else if (a->rm_owner < b->rm_owner)
2870 else if (a->rm_owner > b->rm_owner)
2881 * Scan the physical storage part of the keyspace of the reverse mapping index
2882 * and tell us if the area has no records, is fully mapped by records, or is
2886 xfs_rmap_has_records(
2887 struct xfs_btree_cur *cur,
2890 enum xbtree_recpacking *outcome)
2892 union xfs_btree_key mask = {
2893 .rmap.rm_startblock = cpu_to_be32(-1U),
2895 union xfs_btree_irec low;
2896 union xfs_btree_irec high;
2898 memset(&low, 0, sizeof(low));
2899 low.r.rm_startblock = bno;
2900 memset(&high, 0xFF, sizeof(high));
2901 high.r.rm_startblock = bno + len - 1;
2903 return xfs_btree_has_records(cur, &low, &high, &mask, outcome);
2906 struct xfs_rmap_ownercount {
2907 /* Owner that we're looking for. */
2908 struct xfs_rmap_irec good;
2910 /* rmap search keys */
2911 struct xfs_rmap_irec low;
2912 struct xfs_rmap_irec high;
2914 struct xfs_rmap_matches *results;
2916 /* Stop early if we find a nonmatch? */
2917 bool stop_on_nonmatch;
2920 /* Does this rmap represent space that can have multiple owners? */
2923 struct xfs_mount *mp,
2924 const struct xfs_rmap_irec *rmap)
2926 if (!xfs_has_reflink(mp))
2928 if (XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2930 if (rmap->rm_flags & (XFS_RMAP_ATTR_FORK |
2931 XFS_RMAP_BMBT_BLOCK))
2937 xfs_rmap_ownercount_init(
2938 struct xfs_rmap_ownercount *roc,
2941 const struct xfs_owner_info *oinfo,
2942 struct xfs_rmap_matches *results)
2944 memset(roc, 0, sizeof(*roc));
2945 roc->results = results;
2947 roc->low.rm_startblock = bno;
2948 memset(&roc->high, 0xFF, sizeof(roc->high));
2949 roc->high.rm_startblock = bno + len - 1;
2951 memset(results, 0, sizeof(*results));
2952 roc->good.rm_startblock = bno;
2953 roc->good.rm_blockcount = len;
2954 roc->good.rm_owner = oinfo->oi_owner;
2955 roc->good.rm_offset = oinfo->oi_offset;
2956 if (oinfo->oi_flags & XFS_OWNER_INFO_ATTR_FORK)
2957 roc->good.rm_flags |= XFS_RMAP_ATTR_FORK;
2958 if (oinfo->oi_flags & XFS_OWNER_INFO_BMBT_BLOCK)
2959 roc->good.rm_flags |= XFS_RMAP_BMBT_BLOCK;
2962 /* Figure out if this is a match for the owner. */
2964 xfs_rmap_count_owners_helper(
2965 struct xfs_btree_cur *cur,
2966 const struct xfs_rmap_irec *rec,
2969 struct xfs_rmap_ownercount *roc = priv;
2970 struct xfs_rmap_irec check = *rec;
2971 unsigned int keyflags;
2975 filedata = !XFS_RMAP_NON_INODE_OWNER(check.rm_owner) &&
2976 !(check.rm_flags & XFS_RMAP_BMBT_BLOCK);
2978 /* Trim the part of check that comes before the comparison range. */
2979 delta = (int64_t)roc->good.rm_startblock - check.rm_startblock;
2981 check.rm_startblock += delta;
2982 check.rm_blockcount -= delta;
2984 check.rm_offset += delta;
2987 /* Trim the part of check that comes after the comparison range. */
2988 delta = (check.rm_startblock + check.rm_blockcount) -
2989 (roc->good.rm_startblock + roc->good.rm_blockcount);
2991 check.rm_blockcount -= delta;
2993 /* Don't care about unwritten status for establishing ownership. */
2994 keyflags = check.rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK);
2996 if (check.rm_startblock == roc->good.rm_startblock &&
2997 check.rm_blockcount == roc->good.rm_blockcount &&
2998 check.rm_owner == roc->good.rm_owner &&
2999 check.rm_offset == roc->good.rm_offset &&
3000 keyflags == roc->good.rm_flags) {
3001 roc->results->matches++;
3003 roc->results->non_owner_matches++;
3004 if (xfs_rmap_shareable(cur->bc_mp, &roc->good) ^
3005 xfs_rmap_shareable(cur->bc_mp, &check))
3006 roc->results->bad_non_owner_matches++;
3009 if (roc->results->non_owner_matches && roc->stop_on_nonmatch)
3015 /* Count the number of owners and non-owners of this range of blocks. */
3017 xfs_rmap_count_owners(
3018 struct xfs_btree_cur *cur,
3021 const struct xfs_owner_info *oinfo,
3022 struct xfs_rmap_matches *results)
3024 struct xfs_rmap_ownercount roc;
3027 xfs_rmap_ownercount_init(&roc, bno, len, oinfo, results);
3028 error = xfs_rmap_query_range(cur, &roc.low, &roc.high,
3029 xfs_rmap_count_owners_helper, &roc);
3034 * There can't be any non-owner rmaps that conflict with the given
3035 * owner if we didn't find any rmaps matching the owner.
3037 if (!results->matches)
3038 results->bad_non_owner_matches = 0;
3044 * Given an extent and some owner info, can we find records overlapping
3045 * the extent whose owner info does not match the given owner?
3048 xfs_rmap_has_other_keys(
3049 struct xfs_btree_cur *cur,
3052 const struct xfs_owner_info *oinfo,
3055 struct xfs_rmap_matches res;
3056 struct xfs_rmap_ownercount roc;
3059 xfs_rmap_ownercount_init(&roc, bno, len, oinfo, &res);
3060 roc.stop_on_nonmatch = true;
3062 error = xfs_rmap_query_range(cur, &roc.low, &roc.high,
3063 xfs_rmap_count_owners_helper, &roc);
3064 if (error == -ECANCELED) {
3075 const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
3076 .oi_owner = XFS_RMAP_OWN_NULL,
3078 const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
3079 .oi_owner = XFS_RMAP_OWN_UNKNOWN,
3081 const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
3082 .oi_owner = XFS_RMAP_OWN_FS,
3084 const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
3085 .oi_owner = XFS_RMAP_OWN_LOG,
3087 const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
3088 .oi_owner = XFS_RMAP_OWN_AG,
3090 const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
3091 .oi_owner = XFS_RMAP_OWN_INOBT,
3093 const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
3094 .oi_owner = XFS_RMAP_OWN_INODES,
3096 const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
3097 .oi_owner = XFS_RMAP_OWN_REFC,
3099 const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
3100 .oi_owner = XFS_RMAP_OWN_COW,
3104 xfs_rmap_intent_init_cache(void)
3106 xfs_rmap_intent_cache = kmem_cache_create("xfs_rmap_intent",
3107 sizeof(struct xfs_rmap_intent),
3110 return xfs_rmap_intent_cache != NULL ? 0 : -ENOMEM;
3114 xfs_rmap_intent_destroy_cache(void)
3116 kmem_cache_destroy(xfs_rmap_intent_cache);
3117 xfs_rmap_intent_cache = NULL;