2 * Copyright (c) 2014 Red Hat, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "xfs_shared.h"
21 #include "xfs_format.h"
22 #include "xfs_log_format.h"
23 #include "xfs_trans_resv.h"
26 #include "xfs_mount.h"
27 #include "xfs_defer.h"
28 #include "xfs_da_format.h"
29 #include "xfs_da_btree.h"
30 #include "xfs_btree.h"
31 #include "xfs_trans.h"
32 #include "xfs_alloc.h"
34 #include "xfs_rmap_btree.h"
35 #include "xfs_trans_space.h"
36 #include "xfs_trace.h"
37 #include "xfs_errortag.h"
38 #include "xfs_error.h"
39 #include "xfs_extent_busy.h"
41 #include "xfs_inode.h"
44 * Lookup the first record less than or equal to [bno, len, owner, offset]
45 * in the btree given by cur.
49 struct xfs_btree_cur *cur,
57 cur->bc_rec.r.rm_startblock = bno;
58 cur->bc_rec.r.rm_blockcount = len;
59 cur->bc_rec.r.rm_owner = owner;
60 cur->bc_rec.r.rm_offset = offset;
61 cur->bc_rec.r.rm_flags = flags;
62 return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
66 * Lookup the record exactly matching [bno, len, owner, offset]
67 * in the btree given by cur.
71 struct xfs_btree_cur *cur,
79 cur->bc_rec.r.rm_startblock = bno;
80 cur->bc_rec.r.rm_blockcount = len;
81 cur->bc_rec.r.rm_owner = owner;
82 cur->bc_rec.r.rm_offset = offset;
83 cur->bc_rec.r.rm_flags = flags;
84 return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
88 * Update the record referred to by cur to the value given
89 * by [bno, len, owner, offset].
90 * This either works (return 0) or gets an EFSCORRUPTED error.
94 struct xfs_btree_cur *cur,
95 struct xfs_rmap_irec *irec)
97 union xfs_btree_rec rec;
100 trace_xfs_rmap_update(cur->bc_mp, cur->bc_private.a.agno,
101 irec->rm_startblock, irec->rm_blockcount,
102 irec->rm_owner, irec->rm_offset, irec->rm_flags);
104 rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
105 rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
106 rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
107 rec.rmap.rm_offset = cpu_to_be64(
108 xfs_rmap_irec_offset_pack(irec));
109 error = xfs_btree_update(cur, &rec);
111 trace_xfs_rmap_update_error(cur->bc_mp,
112 cur->bc_private.a.agno, error, _RET_IP_);
118 struct xfs_btree_cur *rcur,
128 trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
129 len, owner, offset, flags);
131 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
134 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 0, done);
136 rcur->bc_rec.r.rm_startblock = agbno;
137 rcur->bc_rec.r.rm_blockcount = len;
138 rcur->bc_rec.r.rm_owner = owner;
139 rcur->bc_rec.r.rm_offset = offset;
140 rcur->bc_rec.r.rm_flags = flags;
141 error = xfs_btree_insert(rcur, &i);
144 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
147 trace_xfs_rmap_insert_error(rcur->bc_mp,
148 rcur->bc_private.a.agno, error, _RET_IP_);
154 struct xfs_btree_cur *rcur,
164 trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
165 len, owner, offset, flags);
167 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
170 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
172 error = xfs_btree_delete(rcur, &i);
175 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
178 trace_xfs_rmap_delete_error(rcur->bc_mp,
179 rcur->bc_private.a.agno, error, _RET_IP_);
183 /* Convert an internal btree record to an rmap record. */
185 xfs_rmap_btrec_to_irec(
186 union xfs_btree_rec *rec,
187 struct xfs_rmap_irec *irec)
190 irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
191 irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
192 irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
193 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
198 * Get the data from the pointed-to record.
202 struct xfs_btree_cur *cur,
203 struct xfs_rmap_irec *irec,
206 union xfs_btree_rec *rec;
209 error = xfs_btree_get_rec(cur, &rec, stat);
213 return xfs_rmap_btrec_to_irec(rec, irec);
216 struct xfs_find_left_neighbor_info {
217 struct xfs_rmap_irec high;
218 struct xfs_rmap_irec *irec;
222 /* For each rmap given, figure out if it matches the key we want. */
224 xfs_rmap_find_left_neighbor_helper(
225 struct xfs_btree_cur *cur,
226 struct xfs_rmap_irec *rec,
229 struct xfs_find_left_neighbor_info *info = priv;
231 trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
232 cur->bc_private.a.agno, rec->rm_startblock,
233 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
236 if (rec->rm_owner != info->high.rm_owner)
237 return XFS_BTREE_QUERY_RANGE_CONTINUE;
238 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
239 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
240 rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
241 return XFS_BTREE_QUERY_RANGE_CONTINUE;
245 return XFS_BTREE_QUERY_RANGE_ABORT;
249 * Find the record to the left of the given extent, being careful only to
250 * return a match with the same owner and adjacent physical and logical
254 xfs_rmap_find_left_neighbor(
255 struct xfs_btree_cur *cur,
260 struct xfs_rmap_irec *irec,
263 struct xfs_find_left_neighbor_info info;
269 info.high.rm_startblock = bno - 1;
270 info.high.rm_owner = owner;
271 if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
272 !(flags & XFS_RMAP_BMBT_BLOCK)) {
275 info.high.rm_offset = offset - 1;
277 info.high.rm_offset = 0;
278 info.high.rm_flags = flags;
279 info.high.rm_blockcount = 0;
283 trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
284 cur->bc_private.a.agno, bno, 0, owner, offset, flags);
286 error = xfs_rmap_query_range(cur, &info.high, &info.high,
287 xfs_rmap_find_left_neighbor_helper, &info);
288 if (error == XFS_BTREE_QUERY_RANGE_ABORT)
291 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
292 cur->bc_private.a.agno, irec->rm_startblock,
293 irec->rm_blockcount, irec->rm_owner,
294 irec->rm_offset, irec->rm_flags);
298 /* For each rmap given, figure out if it matches the key we want. */
300 xfs_rmap_lookup_le_range_helper(
301 struct xfs_btree_cur *cur,
302 struct xfs_rmap_irec *rec,
305 struct xfs_find_left_neighbor_info *info = priv;
307 trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
308 cur->bc_private.a.agno, rec->rm_startblock,
309 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
312 if (rec->rm_owner != info->high.rm_owner)
313 return XFS_BTREE_QUERY_RANGE_CONTINUE;
314 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
315 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
316 (rec->rm_offset > info->high.rm_offset ||
317 rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
318 return XFS_BTREE_QUERY_RANGE_CONTINUE;
322 return XFS_BTREE_QUERY_RANGE_ABORT;
326 * Find the record to the left of the given extent, being careful only to
327 * return a match with the same owner and overlapping physical and logical
328 * block ranges. This is the overlapping-interval version of
329 * xfs_rmap_lookup_le.
332 xfs_rmap_lookup_le_range(
333 struct xfs_btree_cur *cur,
338 struct xfs_rmap_irec *irec,
341 struct xfs_find_left_neighbor_info info;
344 info.high.rm_startblock = bno;
345 info.high.rm_owner = owner;
346 if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
347 info.high.rm_offset = offset;
349 info.high.rm_offset = 0;
350 info.high.rm_flags = flags;
351 info.high.rm_blockcount = 0;
356 trace_xfs_rmap_lookup_le_range(cur->bc_mp,
357 cur->bc_private.a.agno, bno, 0, owner, offset, flags);
358 error = xfs_rmap_query_range(cur, &info.high, &info.high,
359 xfs_rmap_lookup_le_range_helper, &info);
360 if (error == XFS_BTREE_QUERY_RANGE_ABORT)
363 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
364 cur->bc_private.a.agno, irec->rm_startblock,
365 irec->rm_blockcount, irec->rm_owner,
366 irec->rm_offset, irec->rm_flags);
371 * Perform all the relevant owner checks for a removal op. If we're doing an
372 * unknown-owner removal then we have no owner information to check.
375 xfs_rmap_free_check_owner(
376 struct xfs_mount *mp,
378 struct xfs_rmap_irec *rec,
386 if (owner == XFS_RMAP_OWN_UNKNOWN)
389 /* Make sure the unwritten flag matches. */
390 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
391 (rec->rm_flags & XFS_RMAP_UNWRITTEN), out);
393 /* Make sure the owner matches what we expect to find in the tree. */
394 XFS_WANT_CORRUPTED_GOTO(mp, owner == rec->rm_owner, out);
396 /* Check the offset, if necessary. */
397 if (XFS_RMAP_NON_INODE_OWNER(owner))
400 if (flags & XFS_RMAP_BMBT_BLOCK) {
401 XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_flags & XFS_RMAP_BMBT_BLOCK,
404 XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_offset <= offset, out);
405 XFS_WANT_CORRUPTED_GOTO(mp,
406 ltoff + rec->rm_blockcount >= offset + len,
415 * Find the extent in the rmap btree and remove it.
417 * The record we find should always be an exact match for the extent that we're
418 * looking for, since we insert them into the btree without modification.
420 * Special Case #1: when growing the filesystem, we "free" an extent when
421 * growing the last AG. This extent is new space and so it is not tracked as
422 * used space in the btree. The growfs code will pass in an owner of
423 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
424 * extent. We verify that - the extent lookup result in a record that does not
427 * Special Case #2: EFIs do not record the owner of the extent, so when
428 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
429 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
430 * corruption checks during log recovery.
434 struct xfs_btree_cur *cur,
438 struct xfs_owner_info *oinfo)
440 struct xfs_mount *mp = cur->bc_mp;
441 struct xfs_rmap_irec ltrec;
450 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
451 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
452 (flags & XFS_RMAP_BMBT_BLOCK);
454 flags |= XFS_RMAP_UNWRITTEN;
455 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
459 * We should always have a left record because there's a static record
460 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
461 * will not ever be removed from the tree.
463 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i);
466 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
468 error = xfs_rmap_get_rec(cur, <rec, &i);
471 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
472 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
473 cur->bc_private.a.agno, ltrec.rm_startblock,
474 ltrec.rm_blockcount, ltrec.rm_owner,
475 ltrec.rm_offset, ltrec.rm_flags);
476 ltoff = ltrec.rm_offset;
479 * For growfs, the incoming extent must be beyond the left record we
480 * just found as it is new space and won't be used by anyone. This is
481 * just a corruption check as we don't actually do anything with this
482 * extent. Note that we need to use >= instead of > because it might
483 * be the case that the "left" extent goes all the way to EOFS.
485 if (owner == XFS_RMAP_OWN_NULL) {
486 XFS_WANT_CORRUPTED_GOTO(mp, bno >= ltrec.rm_startblock +
487 ltrec.rm_blockcount, out_error);
492 * If we're doing an unknown-owner removal for EFI recovery, we expect
493 * to find the full range in the rmapbt or nothing at all. If we
494 * don't find any rmaps overlapping either end of the range, we're
495 * done. Hopefully this means that the EFI creator already queued
496 * (and finished) a RUI to remove the rmap.
498 if (owner == XFS_RMAP_OWN_UNKNOWN &&
499 ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
500 struct xfs_rmap_irec rtrec;
502 error = xfs_btree_increment(cur, 0, &i);
507 error = xfs_rmap_get_rec(cur, &rtrec, &i);
510 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
511 if (rtrec.rm_startblock >= bno + len)
515 /* Make sure the extent we found covers the entire freeing range. */
516 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
517 ltrec.rm_startblock + ltrec.rm_blockcount >=
518 bno + len, out_error);
520 /* Check owner information. */
521 error = xfs_rmap_free_check_owner(mp, ltoff, <rec, len, owner,
526 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
527 /* exact match, simply remove the record from rmap tree */
528 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
529 ltrec.rm_startblock, ltrec.rm_blockcount,
530 ltrec.rm_owner, ltrec.rm_offset,
532 error = xfs_btree_delete(cur, &i);
535 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
536 } else if (ltrec.rm_startblock == bno) {
538 * overlap left hand side of extent: move the start, trim the
539 * length and update the current record.
542 * Orig: |oooooooooooooooooooo|
543 * Freeing: |fffffffff|
544 * Result: |rrrrrrrrrr|
547 ltrec.rm_startblock += len;
548 ltrec.rm_blockcount -= len;
550 ltrec.rm_offset += len;
551 error = xfs_rmap_update(cur, <rec);
554 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
556 * overlap right hand side of extent: trim the length and update
557 * the current record.
560 * Orig: |oooooooooooooooooooo|
561 * Freeing: |fffffffff|
562 * Result: |rrrrrrrrrr|
565 ltrec.rm_blockcount -= len;
566 error = xfs_rmap_update(cur, <rec);
572 * overlap middle of extent: trim the length of the existing
573 * record to the length of the new left-extent size, increment
574 * the insertion position so we can insert a new record
575 * containing the remaining right-extent space.
578 * Orig: |oooooooooooooooooooo|
579 * Freeing: |fffffffff|
580 * Result: |rrrrr| |rrrr|
583 xfs_extlen_t orig_len = ltrec.rm_blockcount;
585 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
586 error = xfs_rmap_update(cur, <rec);
590 error = xfs_btree_increment(cur, 0, &i);
594 cur->bc_rec.r.rm_startblock = bno + len;
595 cur->bc_rec.r.rm_blockcount = orig_len - len -
597 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
599 cur->bc_rec.r.rm_offset = 0;
601 cur->bc_rec.r.rm_offset = offset + len;
602 cur->bc_rec.r.rm_flags = flags;
603 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
604 cur->bc_rec.r.rm_startblock,
605 cur->bc_rec.r.rm_blockcount,
606 cur->bc_rec.r.rm_owner,
607 cur->bc_rec.r.rm_offset,
608 cur->bc_rec.r.rm_flags);
609 error = xfs_btree_insert(cur, &i);
615 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
619 trace_xfs_rmap_unmap_error(mp, cur->bc_private.a.agno,
625 * Remove a reference to an extent in the rmap btree.
629 struct xfs_trans *tp,
630 struct xfs_buf *agbp,
634 struct xfs_owner_info *oinfo)
636 struct xfs_mount *mp = tp->t_mountp;
637 struct xfs_btree_cur *cur;
640 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
643 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
645 error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
649 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
653 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
658 * A mergeable rmap must have the same owner and the same values for
659 * the unwritten, attr_fork, and bmbt flags. The startblock and
660 * offset are checked separately.
663 xfs_rmap_is_mergeable(
664 struct xfs_rmap_irec *irec,
668 if (irec->rm_owner == XFS_RMAP_OWN_NULL)
670 if (irec->rm_owner != owner)
672 if ((flags & XFS_RMAP_UNWRITTEN) ^
673 (irec->rm_flags & XFS_RMAP_UNWRITTEN))
675 if ((flags & XFS_RMAP_ATTR_FORK) ^
676 (irec->rm_flags & XFS_RMAP_ATTR_FORK))
678 if ((flags & XFS_RMAP_BMBT_BLOCK) ^
679 (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
685 * When we allocate a new block, the first thing we do is add a reference to
686 * the extent in the rmap btree. This takes the form of a [agbno, length,
687 * owner, offset] record. Flags are encoded in the high bits of the offset
692 struct xfs_btree_cur *cur,
696 struct xfs_owner_info *oinfo)
698 struct xfs_mount *mp = cur->bc_mp;
699 struct xfs_rmap_irec ltrec;
700 struct xfs_rmap_irec gtrec;
707 unsigned int flags = 0;
710 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
712 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
713 (flags & XFS_RMAP_BMBT_BLOCK);
715 flags |= XFS_RMAP_UNWRITTEN;
716 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
718 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
721 * For the initial lookup, look for an exact match or the left-adjacent
722 * record for our insertion point. This will also give us the record for
723 * start block contiguity tests.
725 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
729 XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
731 error = xfs_rmap_get_rec(cur, <rec, &have_lt);
734 XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
735 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
736 cur->bc_private.a.agno, ltrec.rm_startblock,
737 ltrec.rm_blockcount, ltrec.rm_owner,
738 ltrec.rm_offset, ltrec.rm_flags);
740 if (!xfs_rmap_is_mergeable(<rec, owner, flags))
743 XFS_WANT_CORRUPTED_GOTO(mp,
745 ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error);
748 * Increment the cursor to see if we have a right-adjacent record to our
749 * insertion point. This will give us the record for end block
752 error = xfs_btree_increment(cur, 0, &have_gt);
756 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
759 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
760 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock,
762 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
763 cur->bc_private.a.agno, gtrec.rm_startblock,
764 gtrec.rm_blockcount, gtrec.rm_owner,
765 gtrec.rm_offset, gtrec.rm_flags);
766 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
771 * Note: cursor currently points one record to the right of ltrec, even
772 * if there is no record in the tree to the right.
775 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
776 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
778 * left edge contiguous, merge into left record.
782 * adding: |aaaaaaaaa|
783 * result: |rrrrrrrrrrrrrrrrrrr|
786 ltrec.rm_blockcount += len;
788 bno + len == gtrec.rm_startblock &&
789 (ignore_off || offset + len == gtrec.rm_offset) &&
790 (unsigned long)ltrec.rm_blockcount + len +
791 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
793 * right edge also contiguous, delete right record
794 * and merge into left record.
796 * ltbno ltlen gtbno gtlen
797 * orig: |ooooooooo| |ooooooooo|
798 * adding: |aaaaaaaaa|
799 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
801 ltrec.rm_blockcount += gtrec.rm_blockcount;
802 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
808 error = xfs_btree_delete(cur, &i);
811 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
814 /* point the cursor back to the left record and update */
815 error = xfs_btree_decrement(cur, 0, &have_gt);
818 error = xfs_rmap_update(cur, <rec);
821 } else if (have_gt &&
822 bno + len == gtrec.rm_startblock &&
823 (ignore_off || offset + len == gtrec.rm_offset)) {
825 * right edge contiguous, merge into right record.
829 * adding: |aaaaaaaaa|
830 * Result: |rrrrrrrrrrrrrrrrrrr|
833 gtrec.rm_startblock = bno;
834 gtrec.rm_blockcount += len;
836 gtrec.rm_offset = offset;
837 error = xfs_rmap_update(cur, >rec);
842 * no contiguous edge with identical owner, insert
843 * new record at current cursor position.
845 cur->bc_rec.r.rm_startblock = bno;
846 cur->bc_rec.r.rm_blockcount = len;
847 cur->bc_rec.r.rm_owner = owner;
848 cur->bc_rec.r.rm_offset = offset;
849 cur->bc_rec.r.rm_flags = flags;
850 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
851 owner, offset, flags);
852 error = xfs_btree_insert(cur, &i);
855 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
858 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
862 trace_xfs_rmap_map_error(mp, cur->bc_private.a.agno,
868 * Add a reference to an extent in the rmap btree.
872 struct xfs_trans *tp,
873 struct xfs_buf *agbp,
877 struct xfs_owner_info *oinfo)
879 struct xfs_mount *mp = tp->t_mountp;
880 struct xfs_btree_cur *cur;
883 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
886 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
887 error = xfs_rmap_map(cur, bno, len, false, oinfo);
891 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
895 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
899 #define RMAP_LEFT_CONTIG (1 << 0)
900 #define RMAP_RIGHT_CONTIG (1 << 1)
901 #define RMAP_LEFT_FILLING (1 << 2)
902 #define RMAP_RIGHT_FILLING (1 << 3)
903 #define RMAP_LEFT_VALID (1 << 6)
904 #define RMAP_RIGHT_VALID (1 << 7)
912 * Convert an unwritten extent to a real extent or vice versa.
913 * Does not handle overlapping extents.
917 struct xfs_btree_cur *cur,
921 struct xfs_owner_info *oinfo)
923 struct xfs_mount *mp = cur->bc_mp;
924 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
925 /* left is 0, right is 1, prev is 2 */
932 unsigned int flags = 0;
937 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
938 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
939 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
940 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
941 new_endoff = offset + len;
942 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
946 * For the initial lookup, look for an exact match or the left-adjacent
947 * record for our insertion point. This will also give us the record for
948 * start block contiguity tests.
950 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
953 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
955 error = xfs_rmap_get_rec(cur, &PREV, &i);
958 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
959 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
960 cur->bc_private.a.agno, PREV.rm_startblock,
961 PREV.rm_blockcount, PREV.rm_owner,
962 PREV.rm_offset, PREV.rm_flags);
964 ASSERT(PREV.rm_offset <= offset);
965 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
966 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
967 newext = ~oldext & XFS_RMAP_UNWRITTEN;
970 * Set flags determining what part of the previous oldext allocation
971 * extent is being replaced by a newext allocation.
973 if (PREV.rm_offset == offset)
974 state |= RMAP_LEFT_FILLING;
975 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
976 state |= RMAP_RIGHT_FILLING;
979 * Decrement the cursor to see if we have a left-adjacent record to our
980 * insertion point. This will give us the record for end block
983 error = xfs_btree_decrement(cur, 0, &i);
987 state |= RMAP_LEFT_VALID;
988 error = xfs_rmap_get_rec(cur, &LEFT, &i);
991 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
992 XFS_WANT_CORRUPTED_GOTO(mp,
993 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
995 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
996 cur->bc_private.a.agno, LEFT.rm_startblock,
997 LEFT.rm_blockcount, LEFT.rm_owner,
998 LEFT.rm_offset, LEFT.rm_flags);
999 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1000 LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1001 xfs_rmap_is_mergeable(&LEFT, owner, newext))
1002 state |= RMAP_LEFT_CONTIG;
1006 * Increment the cursor to see if we have a right-adjacent record to our
1007 * insertion point. This will give us the record for end block
1010 error = xfs_btree_increment(cur, 0, &i);
1013 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1014 error = xfs_btree_increment(cur, 0, &i);
1018 state |= RMAP_RIGHT_VALID;
1019 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1022 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1023 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1025 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1026 cur->bc_private.a.agno, RIGHT.rm_startblock,
1027 RIGHT.rm_blockcount, RIGHT.rm_owner,
1028 RIGHT.rm_offset, RIGHT.rm_flags);
1029 if (bno + len == RIGHT.rm_startblock &&
1030 offset + len == RIGHT.rm_offset &&
1031 xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1032 state |= RMAP_RIGHT_CONTIG;
1035 /* check that left + prev + right is not too long */
1036 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1037 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1038 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1039 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1040 (unsigned long)LEFT.rm_blockcount + len +
1041 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1042 state &= ~RMAP_RIGHT_CONTIG;
1044 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1047 /* reset the cursor back to PREV */
1048 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1051 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1054 * Switch out based on the FILLING and CONTIG state bits.
1056 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1057 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1058 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1059 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1061 * Setting all of a previous oldext extent to newext.
1062 * The left and right neighbors are both contiguous with new.
1064 error = xfs_btree_increment(cur, 0, &i);
1067 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1068 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1069 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1070 RIGHT.rm_owner, RIGHT.rm_offset,
1072 error = xfs_btree_delete(cur, &i);
1075 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1076 error = xfs_btree_decrement(cur, 0, &i);
1079 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1080 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1081 PREV.rm_startblock, PREV.rm_blockcount,
1082 PREV.rm_owner, PREV.rm_offset,
1084 error = xfs_btree_delete(cur, &i);
1087 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1088 error = xfs_btree_decrement(cur, 0, &i);
1091 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1093 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1094 error = xfs_rmap_update(cur, &NEW);
1099 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1101 * Setting all of a previous oldext extent to newext.
1102 * The left neighbor is contiguous, the right is not.
1104 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1105 PREV.rm_startblock, PREV.rm_blockcount,
1106 PREV.rm_owner, PREV.rm_offset,
1108 error = xfs_btree_delete(cur, &i);
1111 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1112 error = xfs_btree_decrement(cur, 0, &i);
1115 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1117 NEW.rm_blockcount += PREV.rm_blockcount;
1118 error = xfs_rmap_update(cur, &NEW);
1123 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1125 * Setting all of a previous oldext extent to newext.
1126 * The right neighbor is contiguous, the left is not.
1128 error = xfs_btree_increment(cur, 0, &i);
1131 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1132 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1133 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1134 RIGHT.rm_owner, RIGHT.rm_offset,
1136 error = xfs_btree_delete(cur, &i);
1139 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1140 error = xfs_btree_decrement(cur, 0, &i);
1143 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1145 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1146 NEW.rm_flags = newext;
1147 error = xfs_rmap_update(cur, &NEW);
1152 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1154 * Setting all of a previous oldext extent to newext.
1155 * Neither the left nor right neighbors are contiguous with
1159 NEW.rm_flags = newext;
1160 error = xfs_rmap_update(cur, &NEW);
1165 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1167 * Setting the first part of a previous oldext extent to newext.
1168 * The left neighbor is contiguous.
1171 NEW.rm_offset += len;
1172 NEW.rm_startblock += len;
1173 NEW.rm_blockcount -= len;
1174 error = xfs_rmap_update(cur, &NEW);
1177 error = xfs_btree_decrement(cur, 0, &i);
1181 NEW.rm_blockcount += len;
1182 error = xfs_rmap_update(cur, &NEW);
1187 case RMAP_LEFT_FILLING:
1189 * Setting the first part of a previous oldext extent to newext.
1190 * The left neighbor is not contiguous.
1193 NEW.rm_startblock += len;
1194 NEW.rm_offset += len;
1195 NEW.rm_blockcount -= len;
1196 error = xfs_rmap_update(cur, &NEW);
1199 NEW.rm_startblock = bno;
1200 NEW.rm_owner = owner;
1201 NEW.rm_offset = offset;
1202 NEW.rm_blockcount = len;
1203 NEW.rm_flags = newext;
1204 cur->bc_rec.r = NEW;
1205 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1206 len, owner, offset, newext);
1207 error = xfs_btree_insert(cur, &i);
1210 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1213 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1215 * Setting the last part of a previous oldext extent to newext.
1216 * The right neighbor is contiguous with the new allocation.
1219 NEW.rm_blockcount -= len;
1220 error = xfs_rmap_update(cur, &NEW);
1223 error = xfs_btree_increment(cur, 0, &i);
1227 NEW.rm_offset = offset;
1228 NEW.rm_startblock = bno;
1229 NEW.rm_blockcount += len;
1230 error = xfs_rmap_update(cur, &NEW);
1235 case RMAP_RIGHT_FILLING:
1237 * Setting the last part of a previous oldext extent to newext.
1238 * The right neighbor is not contiguous.
1241 NEW.rm_blockcount -= len;
1242 error = xfs_rmap_update(cur, &NEW);
1245 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1249 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1250 NEW.rm_startblock = bno;
1251 NEW.rm_owner = owner;
1252 NEW.rm_offset = offset;
1253 NEW.rm_blockcount = len;
1254 NEW.rm_flags = newext;
1255 cur->bc_rec.r = NEW;
1256 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1257 len, owner, offset, newext);
1258 error = xfs_btree_insert(cur, &i);
1261 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1266 * Setting the middle part of a previous oldext extent to
1267 * newext. Contiguity is impossible here.
1268 * One extent becomes three extents.
1270 /* new right extent - oldext */
1271 NEW.rm_startblock = bno + len;
1272 NEW.rm_owner = owner;
1273 NEW.rm_offset = new_endoff;
1274 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1276 NEW.rm_flags = PREV.rm_flags;
1277 error = xfs_rmap_update(cur, &NEW);
1280 /* new left extent - oldext */
1282 NEW.rm_blockcount = offset - PREV.rm_offset;
1283 cur->bc_rec.r = NEW;
1284 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
1285 NEW.rm_startblock, NEW.rm_blockcount,
1286 NEW.rm_owner, NEW.rm_offset,
1288 error = xfs_btree_insert(cur, &i);
1291 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1293 * Reset the cursor to the position of the new extent
1294 * we are about to insert as we can't trust it after
1295 * the previous insert.
1297 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1301 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1302 /* new middle extent - newext */
1303 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1304 cur->bc_rec.r.rm_flags |= newext;
1305 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
1306 owner, offset, newext);
1307 error = xfs_btree_insert(cur, &i);
1310 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1313 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1314 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1315 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1316 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1317 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1318 case RMAP_LEFT_CONTIG:
1319 case RMAP_RIGHT_CONTIG:
1321 * These cases are all impossible.
1326 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1330 trace_xfs_rmap_convert_error(cur->bc_mp,
1331 cur->bc_private.a.agno, error, _RET_IP_);
1336 * Convert an unwritten extent to a real extent or vice versa. If there is no
1337 * possibility of overlapping extents, delegate to the simpler convert
1341 xfs_rmap_convert_shared(
1342 struct xfs_btree_cur *cur,
1346 struct xfs_owner_info *oinfo)
1348 struct xfs_mount *mp = cur->bc_mp;
1349 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1350 /* left is 0, right is 1, prev is 2 */
1354 uint64_t new_endoff;
1355 unsigned int oldext;
1356 unsigned int newext;
1357 unsigned int flags = 0;
1362 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1363 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1364 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1365 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1366 new_endoff = offset + len;
1367 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
1371 * For the initial lookup, look for and exact match or the left-adjacent
1372 * record for our insertion point. This will also give us the record for
1373 * start block contiguity tests.
1375 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1379 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1381 ASSERT(PREV.rm_offset <= offset);
1382 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1383 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1384 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1387 * Set flags determining what part of the previous oldext allocation
1388 * extent is being replaced by a newext allocation.
1390 if (PREV.rm_offset == offset)
1391 state |= RMAP_LEFT_FILLING;
1392 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1393 state |= RMAP_RIGHT_FILLING;
1395 /* Is there a left record that abuts our range? */
1396 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1401 state |= RMAP_LEFT_VALID;
1402 XFS_WANT_CORRUPTED_GOTO(mp,
1403 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
1405 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1406 state |= RMAP_LEFT_CONTIG;
1409 /* Is there a right record that abuts our range? */
1410 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1415 state |= RMAP_RIGHT_VALID;
1416 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1419 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1420 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1422 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1423 cur->bc_private.a.agno, RIGHT.rm_startblock,
1424 RIGHT.rm_blockcount, RIGHT.rm_owner,
1425 RIGHT.rm_offset, RIGHT.rm_flags);
1426 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1427 state |= RMAP_RIGHT_CONTIG;
1430 /* check that left + prev + right is not too long */
1431 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1432 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1433 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1434 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1435 (unsigned long)LEFT.rm_blockcount + len +
1436 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1437 state &= ~RMAP_RIGHT_CONTIG;
1439 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1442 * Switch out based on the FILLING and CONTIG state bits.
1444 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1445 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1446 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1447 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1449 * Setting all of a previous oldext extent to newext.
1450 * The left and right neighbors are both contiguous with new.
1452 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1453 RIGHT.rm_blockcount, RIGHT.rm_owner,
1454 RIGHT.rm_offset, RIGHT.rm_flags);
1457 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1458 PREV.rm_blockcount, PREV.rm_owner,
1459 PREV.rm_offset, PREV.rm_flags);
1463 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1464 NEW.rm_blockcount, NEW.rm_owner,
1465 NEW.rm_offset, NEW.rm_flags, &i);
1468 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1469 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1470 error = xfs_rmap_update(cur, &NEW);
1475 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1477 * Setting all of a previous oldext extent to newext.
1478 * The left neighbor is contiguous, the right is not.
1480 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1481 PREV.rm_blockcount, PREV.rm_owner,
1482 PREV.rm_offset, PREV.rm_flags);
1486 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1487 NEW.rm_blockcount, NEW.rm_owner,
1488 NEW.rm_offset, NEW.rm_flags, &i);
1491 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1492 NEW.rm_blockcount += PREV.rm_blockcount;
1493 error = xfs_rmap_update(cur, &NEW);
1498 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1500 * Setting all of a previous oldext extent to newext.
1501 * The right neighbor is contiguous, the left is not.
1503 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1504 RIGHT.rm_blockcount, RIGHT.rm_owner,
1505 RIGHT.rm_offset, RIGHT.rm_flags);
1509 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1510 NEW.rm_blockcount, NEW.rm_owner,
1511 NEW.rm_offset, NEW.rm_flags, &i);
1514 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1515 NEW.rm_blockcount += RIGHT.rm_blockcount;
1516 NEW.rm_flags = RIGHT.rm_flags;
1517 error = xfs_rmap_update(cur, &NEW);
1522 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1524 * Setting all of a previous oldext extent to newext.
1525 * Neither the left nor right neighbors are contiguous with
1529 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1530 NEW.rm_blockcount, NEW.rm_owner,
1531 NEW.rm_offset, NEW.rm_flags, &i);
1534 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1535 NEW.rm_flags = newext;
1536 error = xfs_rmap_update(cur, &NEW);
1541 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1543 * Setting the first part of a previous oldext extent to newext.
1544 * The left neighbor is contiguous.
1547 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1548 NEW.rm_blockcount, NEW.rm_owner,
1549 NEW.rm_offset, NEW.rm_flags);
1552 NEW.rm_offset += len;
1553 NEW.rm_startblock += len;
1554 NEW.rm_blockcount -= len;
1555 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1556 NEW.rm_blockcount, NEW.rm_owner,
1557 NEW.rm_offset, NEW.rm_flags);
1561 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1562 NEW.rm_blockcount, NEW.rm_owner,
1563 NEW.rm_offset, NEW.rm_flags, &i);
1566 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1567 NEW.rm_blockcount += len;
1568 error = xfs_rmap_update(cur, &NEW);
1573 case RMAP_LEFT_FILLING:
1575 * Setting the first part of a previous oldext extent to newext.
1576 * The left neighbor is not contiguous.
1579 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1580 NEW.rm_blockcount, NEW.rm_owner,
1581 NEW.rm_offset, NEW.rm_flags);
1584 NEW.rm_offset += len;
1585 NEW.rm_startblock += len;
1586 NEW.rm_blockcount -= len;
1587 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1588 NEW.rm_blockcount, NEW.rm_owner,
1589 NEW.rm_offset, NEW.rm_flags);
1592 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1597 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1599 * Setting the last part of a previous oldext extent to newext.
1600 * The right neighbor is contiguous with the new allocation.
1603 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1604 NEW.rm_blockcount, NEW.rm_owner,
1605 NEW.rm_offset, NEW.rm_flags, &i);
1608 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1609 NEW.rm_blockcount = offset - NEW.rm_offset;
1610 error = xfs_rmap_update(cur, &NEW);
1614 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1615 NEW.rm_blockcount, NEW.rm_owner,
1616 NEW.rm_offset, NEW.rm_flags);
1619 NEW.rm_offset = offset;
1620 NEW.rm_startblock = bno;
1621 NEW.rm_blockcount += len;
1622 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1623 NEW.rm_blockcount, NEW.rm_owner,
1624 NEW.rm_offset, NEW.rm_flags);
1629 case RMAP_RIGHT_FILLING:
1631 * Setting the last part of a previous oldext extent to newext.
1632 * The right neighbor is not contiguous.
1635 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1636 NEW.rm_blockcount, NEW.rm_owner,
1637 NEW.rm_offset, NEW.rm_flags, &i);
1640 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1641 NEW.rm_blockcount -= len;
1642 error = xfs_rmap_update(cur, &NEW);
1645 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1652 * Setting the middle part of a previous oldext extent to
1653 * newext. Contiguity is impossible here.
1654 * One extent becomes three extents.
1656 /* new right extent - oldext */
1657 NEW.rm_startblock = bno + len;
1658 NEW.rm_owner = owner;
1659 NEW.rm_offset = new_endoff;
1660 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1662 NEW.rm_flags = PREV.rm_flags;
1663 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1664 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1668 /* new left extent - oldext */
1670 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1671 NEW.rm_blockcount, NEW.rm_owner,
1672 NEW.rm_offset, NEW.rm_flags, &i);
1675 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1676 NEW.rm_blockcount = offset - NEW.rm_offset;
1677 error = xfs_rmap_update(cur, &NEW);
1680 /* new middle extent - newext */
1681 NEW.rm_startblock = bno;
1682 NEW.rm_blockcount = len;
1683 NEW.rm_owner = owner;
1684 NEW.rm_offset = offset;
1685 NEW.rm_flags = newext;
1686 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1687 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1693 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1694 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1695 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1696 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1697 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1698 case RMAP_LEFT_CONTIG:
1699 case RMAP_RIGHT_CONTIG:
1701 * These cases are all impossible.
1706 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1710 trace_xfs_rmap_convert_error(cur->bc_mp,
1711 cur->bc_private.a.agno, error, _RET_IP_);
1721 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1722 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1723 * that the prev/next records in the btree might belong to another owner.
1724 * Therefore we must use delete+insert to alter any of the key fields.
1726 * For every other situation there can only be one owner for a given extent,
1727 * so we can call the regular _free function.
1730 xfs_rmap_unmap_shared(
1731 struct xfs_btree_cur *cur,
1735 struct xfs_owner_info *oinfo)
1737 struct xfs_mount *mp = cur->bc_mp;
1738 struct xfs_rmap_irec ltrec;
1746 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1748 flags |= XFS_RMAP_UNWRITTEN;
1749 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
1753 * We should always have a left record because there's a static record
1754 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1755 * will not ever be removed from the tree.
1757 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1761 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1762 ltoff = ltrec.rm_offset;
1764 /* Make sure the extent we found covers the entire freeing range. */
1765 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
1766 ltrec.rm_startblock + ltrec.rm_blockcount >=
1767 bno + len, out_error);
1769 /* Make sure the owner matches what we expect to find in the tree. */
1770 XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner, out_error);
1772 /* Make sure the unwritten flag matches. */
1773 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
1774 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error);
1776 /* Check the offset. */
1777 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error);
1778 XFS_WANT_CORRUPTED_GOTO(mp, offset <= ltoff + ltrec.rm_blockcount,
1781 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
1782 /* Exact match, simply remove the record from rmap tree. */
1783 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1784 ltrec.rm_blockcount, ltrec.rm_owner,
1785 ltrec.rm_offset, ltrec.rm_flags);
1788 } else if (ltrec.rm_startblock == bno) {
1790 * Overlap left hand side of extent: move the start, trim the
1791 * length and update the current record.
1794 * Orig: |oooooooooooooooooooo|
1795 * Freeing: |fffffffff|
1796 * Result: |rrrrrrrrrr|
1800 /* Delete prev rmap. */
1801 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1802 ltrec.rm_blockcount, ltrec.rm_owner,
1803 ltrec.rm_offset, ltrec.rm_flags);
1807 /* Add an rmap at the new offset. */
1808 ltrec.rm_startblock += len;
1809 ltrec.rm_blockcount -= len;
1810 ltrec.rm_offset += len;
1811 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
1812 ltrec.rm_blockcount, ltrec.rm_owner,
1813 ltrec.rm_offset, ltrec.rm_flags);
1816 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
1818 * Overlap right hand side of extent: trim the length and
1819 * update the current record.
1822 * Orig: |oooooooooooooooooooo|
1823 * Freeing: |fffffffff|
1824 * Result: |rrrrrrrrrr|
1827 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1828 ltrec.rm_blockcount, ltrec.rm_owner,
1829 ltrec.rm_offset, ltrec.rm_flags, &i);
1832 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1833 ltrec.rm_blockcount -= len;
1834 error = xfs_rmap_update(cur, <rec);
1839 * Overlap middle of extent: trim the length of the existing
1840 * record to the length of the new left-extent size, increment
1841 * the insertion position so we can insert a new record
1842 * containing the remaining right-extent space.
1845 * Orig: |oooooooooooooooooooo|
1846 * Freeing: |fffffffff|
1847 * Result: |rrrrr| |rrrr|
1850 xfs_extlen_t orig_len = ltrec.rm_blockcount;
1852 /* Shrink the left side of the rmap */
1853 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1854 ltrec.rm_blockcount, ltrec.rm_owner,
1855 ltrec.rm_offset, ltrec.rm_flags, &i);
1858 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1859 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
1860 error = xfs_rmap_update(cur, <rec);
1864 /* Add an rmap at the new offset */
1865 error = xfs_rmap_insert(cur, bno + len,
1866 orig_len - len - ltrec.rm_blockcount,
1867 ltrec.rm_owner, offset + len,
1873 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
1877 trace_xfs_rmap_unmap_error(cur->bc_mp,
1878 cur->bc_private.a.agno, error, _RET_IP_);
1883 * Find an extent in the rmap btree and map it. For rmap extent types that
1884 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1885 * that the prev/next records in the btree might belong to another owner.
1886 * Therefore we must use delete+insert to alter any of the key fields.
1888 * For every other situation there can only be one owner for a given extent,
1889 * so we can call the regular _alloc function.
1892 xfs_rmap_map_shared(
1893 struct xfs_btree_cur *cur,
1897 struct xfs_owner_info *oinfo)
1899 struct xfs_mount *mp = cur->bc_mp;
1900 struct xfs_rmap_irec ltrec;
1901 struct xfs_rmap_irec gtrec;
1908 unsigned int flags = 0;
1910 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1912 flags |= XFS_RMAP_UNWRITTEN;
1913 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
1916 /* Is there a left record that abuts our range? */
1917 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
1922 !xfs_rmap_is_mergeable(<rec, owner, flags))
1925 /* Is there a right record that abuts our range? */
1926 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1931 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
1934 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
1935 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1936 cur->bc_private.a.agno, gtrec.rm_startblock,
1937 gtrec.rm_blockcount, gtrec.rm_owner,
1938 gtrec.rm_offset, gtrec.rm_flags);
1940 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
1945 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
1946 ltrec.rm_offset + ltrec.rm_blockcount == offset) {
1948 * Left edge contiguous, merge into left record.
1952 * adding: |aaaaaaaaa|
1953 * result: |rrrrrrrrrrrrrrrrrrr|
1956 ltrec.rm_blockcount += len;
1958 bno + len == gtrec.rm_startblock &&
1959 offset + len == gtrec.rm_offset) {
1961 * Right edge also contiguous, delete right record
1962 * and merge into left record.
1964 * ltbno ltlen gtbno gtlen
1965 * orig: |ooooooooo| |ooooooooo|
1966 * adding: |aaaaaaaaa|
1967 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1969 ltrec.rm_blockcount += gtrec.rm_blockcount;
1970 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
1971 gtrec.rm_blockcount, gtrec.rm_owner,
1972 gtrec.rm_offset, gtrec.rm_flags);
1977 /* Point the cursor back to the left record and update. */
1978 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1979 ltrec.rm_blockcount, ltrec.rm_owner,
1980 ltrec.rm_offset, ltrec.rm_flags, &i);
1983 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1985 error = xfs_rmap_update(cur, <rec);
1988 } else if (have_gt &&
1989 bno + len == gtrec.rm_startblock &&
1990 offset + len == gtrec.rm_offset) {
1992 * Right edge contiguous, merge into right record.
1996 * adding: |aaaaaaaaa|
1997 * Result: |rrrrrrrrrrrrrrrrrrr|
2000 /* Delete the old record. */
2001 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2002 gtrec.rm_blockcount, gtrec.rm_owner,
2003 gtrec.rm_offset, gtrec.rm_flags);
2007 /* Move the start and re-add it. */
2008 gtrec.rm_startblock = bno;
2009 gtrec.rm_blockcount += len;
2010 gtrec.rm_offset = offset;
2011 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2012 gtrec.rm_blockcount, gtrec.rm_owner,
2013 gtrec.rm_offset, gtrec.rm_flags);
2018 * No contiguous edge with identical owner, insert
2019 * new record at current cursor position.
2021 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2026 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
2030 trace_xfs_rmap_map_error(cur->bc_mp,
2031 cur->bc_private.a.agno, error, _RET_IP_);
2035 /* Insert a raw rmap into the rmapbt. */
2038 struct xfs_btree_cur *cur,
2039 struct xfs_rmap_irec *rmap)
2041 struct xfs_owner_info oinfo;
2043 oinfo.oi_owner = rmap->rm_owner;
2044 oinfo.oi_offset = rmap->rm_offset;
2046 if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
2047 oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
2048 if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
2049 oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
2051 if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2052 return xfs_rmap_map(cur, rmap->rm_startblock,
2053 rmap->rm_blockcount,
2054 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2057 return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2058 rmap->rm_blockcount,
2059 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2063 struct xfs_rmap_query_range_info {
2064 xfs_rmap_query_range_fn fn;
2068 /* Format btree record and pass to our callback. */
2070 xfs_rmap_query_range_helper(
2071 struct xfs_btree_cur *cur,
2072 union xfs_btree_rec *rec,
2075 struct xfs_rmap_query_range_info *query = priv;
2076 struct xfs_rmap_irec irec;
2079 error = xfs_rmap_btrec_to_irec(rec, &irec);
2082 return query->fn(cur, &irec, query->priv);
2085 /* Find all rmaps between two keys. */
2087 xfs_rmap_query_range(
2088 struct xfs_btree_cur *cur,
2089 struct xfs_rmap_irec *low_rec,
2090 struct xfs_rmap_irec *high_rec,
2091 xfs_rmap_query_range_fn fn,
2094 union xfs_btree_irec low_brec;
2095 union xfs_btree_irec high_brec;
2096 struct xfs_rmap_query_range_info query;
2098 low_brec.r = *low_rec;
2099 high_brec.r = *high_rec;
2102 return xfs_btree_query_range(cur, &low_brec, &high_brec,
2103 xfs_rmap_query_range_helper, &query);
2106 /* Find all rmaps. */
2109 struct xfs_btree_cur *cur,
2110 xfs_rmap_query_range_fn fn,
2113 struct xfs_rmap_query_range_info query;
2117 return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2120 /* Clean up after calling xfs_rmap_finish_one. */
2122 xfs_rmap_finish_one_cleanup(
2123 struct xfs_trans *tp,
2124 struct xfs_btree_cur *rcur,
2127 struct xfs_buf *agbp;
2131 agbp = rcur->bc_private.a.agbp;
2132 xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
2134 xfs_trans_brelse(tp, agbp);
2138 * Process one of the deferred rmap operations. We pass back the
2139 * btree cursor to maintain our lock on the rmapbt between calls.
2140 * This saves time and eliminates a buffer deadlock between the
2141 * superblock and the AGF because we'll always grab them in the same
2145 xfs_rmap_finish_one(
2146 struct xfs_trans *tp,
2147 enum xfs_rmap_intent_type type,
2150 xfs_fileoff_t startoff,
2151 xfs_fsblock_t startblock,
2152 xfs_filblks_t blockcount,
2154 struct xfs_btree_cur **pcur)
2156 struct xfs_mount *mp = tp->t_mountp;
2157 struct xfs_btree_cur *rcur;
2158 struct xfs_buf *agbp = NULL;
2160 xfs_agnumber_t agno;
2161 struct xfs_owner_info oinfo;
2165 agno = XFS_FSB_TO_AGNO(mp, startblock);
2166 ASSERT(agno != NULLAGNUMBER);
2167 bno = XFS_FSB_TO_AGBNO(mp, startblock);
2169 trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork,
2170 startoff, blockcount, state);
2172 if (XFS_TEST_ERROR(false, mp,
2173 XFS_ERRTAG_RMAP_FINISH_ONE))
2177 * If we haven't gotten a cursor or the cursor AG doesn't match
2178 * the startblock, get one now.
2181 if (rcur != NULL && rcur->bc_private.a.agno != agno) {
2182 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2188 * Refresh the freelist before we start changing the
2189 * rmapbt, because a shape change could cause us to
2192 error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
2196 return -EFSCORRUPTED;
2198 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
2206 xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2207 unwritten = state == XFS_EXT_UNWRITTEN;
2208 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2211 case XFS_RMAP_ALLOC:
2213 error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2215 case XFS_RMAP_MAP_SHARED:
2216 error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2220 case XFS_RMAP_UNMAP:
2221 error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2224 case XFS_RMAP_UNMAP_SHARED:
2225 error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2228 case XFS_RMAP_CONVERT:
2229 error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2232 case XFS_RMAP_CONVERT_SHARED:
2233 error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2234 !unwritten, &oinfo);
2238 error = -EFSCORRUPTED;
2243 xfs_trans_brelse(tp, agbp);
2249 * Don't defer an rmap if we aren't an rmap filesystem.
2252 xfs_rmap_update_is_needed(
2253 struct xfs_mount *mp,
2256 return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK;
2260 * Record a rmap intent; the list is kept sorted first by AG and then by
2265 struct xfs_mount *mp,
2266 struct xfs_defer_ops *dfops,
2267 enum xfs_rmap_intent_type type,
2270 struct xfs_bmbt_irec *bmap)
2272 struct xfs_rmap_intent *ri;
2274 trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, bmap->br_startblock),
2276 XFS_FSB_TO_AGBNO(mp, bmap->br_startblock),
2279 bmap->br_blockcount,
2282 ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_SLEEP | KM_NOFS);
2283 INIT_LIST_HEAD(&ri->ri_list);
2285 ri->ri_owner = owner;
2286 ri->ri_whichfork = whichfork;
2287 ri->ri_bmap = *bmap;
2289 xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
2293 /* Map an extent into a file. */
2295 xfs_rmap_map_extent(
2296 struct xfs_mount *mp,
2297 struct xfs_defer_ops *dfops,
2298 struct xfs_inode *ip,
2300 struct xfs_bmbt_irec *PREV)
2302 if (!xfs_rmap_update_is_needed(mp, whichfork))
2305 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2306 XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino,
2310 /* Unmap an extent out of a file. */
2312 xfs_rmap_unmap_extent(
2313 struct xfs_mount *mp,
2314 struct xfs_defer_ops *dfops,
2315 struct xfs_inode *ip,
2317 struct xfs_bmbt_irec *PREV)
2319 if (!xfs_rmap_update_is_needed(mp, whichfork))
2322 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2323 XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino,
2327 /* Convert a data fork extent from unwritten to real or vice versa. */
2329 xfs_rmap_convert_extent(
2330 struct xfs_mount *mp,
2331 struct xfs_defer_ops *dfops,
2332 struct xfs_inode *ip,
2334 struct xfs_bmbt_irec *PREV)
2336 if (!xfs_rmap_update_is_needed(mp, whichfork))
2339 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2340 XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino,
2344 /* Schedule the creation of an rmap for non-file data. */
2346 xfs_rmap_alloc_extent(
2347 struct xfs_mount *mp,
2348 struct xfs_defer_ops *dfops,
2349 xfs_agnumber_t agno,
2354 struct xfs_bmbt_irec bmap;
2356 if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
2359 bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
2360 bmap.br_blockcount = len;
2361 bmap.br_startoff = 0;
2362 bmap.br_state = XFS_EXT_NORM;
2364 return __xfs_rmap_add(mp, dfops, XFS_RMAP_ALLOC, owner,
2365 XFS_DATA_FORK, &bmap);
2368 /* Schedule the deletion of an rmap for non-file data. */
2370 xfs_rmap_free_extent(
2371 struct xfs_mount *mp,
2372 struct xfs_defer_ops *dfops,
2373 xfs_agnumber_t agno,
2378 struct xfs_bmbt_irec bmap;
2380 if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
2383 bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
2384 bmap.br_blockcount = len;
2385 bmap.br_startoff = 0;
2386 bmap.br_state = XFS_EXT_NORM;
2388 return __xfs_rmap_add(mp, dfops, XFS_RMAP_FREE, owner,
2389 XFS_DATA_FORK, &bmap);
2392 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2395 const struct xfs_rmap_irec *a,
2396 const struct xfs_rmap_irec *b)
2401 oa = xfs_rmap_irec_offset_pack(a);
2402 ob = xfs_rmap_irec_offset_pack(b);
2404 if (a->rm_startblock < b->rm_startblock)
2406 else if (a->rm_startblock > b->rm_startblock)
2408 else if (a->rm_owner < b->rm_owner)
2410 else if (a->rm_owner > b->rm_owner)
2420 /* Is there a record covering a given extent? */
2422 xfs_rmap_has_record(
2423 struct xfs_btree_cur *cur,
2428 union xfs_btree_irec low;
2429 union xfs_btree_irec high;
2431 memset(&low, 0, sizeof(low));
2432 low.r.rm_startblock = bno;
2433 memset(&high, 0xFF, sizeof(high));
2434 high.r.rm_startblock = bno + len - 1;
2436 return xfs_btree_has_record(cur, &low, &high, exists);
2440 * Is there a record for this owner completely covering a given physical
2441 * extent? If so, *has_rmap will be set to true. If there is no record
2442 * or the record only covers part of the range, we set *has_rmap to false.
2443 * This function doesn't perform range lookups or offset checks, so it is
2444 * not suitable for checking data fork blocks.
2447 xfs_rmap_record_exists(
2448 struct xfs_btree_cur *cur,
2451 struct xfs_owner_info *oinfo,
2458 struct xfs_rmap_irec irec;
2461 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2462 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
2463 (flags & XFS_RMAP_BMBT_BLOCK));
2465 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
2474 error = xfs_rmap_get_rec(cur, &irec, &has_record);
2482 *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
2483 irec.rm_startblock + irec.rm_blockcount >= bno + len);
2487 struct xfs_rmap_key_state {
2494 /* For each rmap given, figure out if it doesn't match the key we want. */
2496 xfs_rmap_has_other_keys_helper(
2497 struct xfs_btree_cur *cur,
2498 struct xfs_rmap_irec *rec,
2501 struct xfs_rmap_key_state *rks = priv;
2503 if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset &&
2504 ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags)
2506 rks->has_rmap = true;
2507 return XFS_BTREE_QUERY_RANGE_ABORT;
2511 * Given an extent and some owner info, can we find records overlapping
2512 * the extent whose owner info does not match the given owner?
2515 xfs_rmap_has_other_keys(
2516 struct xfs_btree_cur *cur,
2519 struct xfs_owner_info *oinfo,
2522 struct xfs_rmap_irec low = {0};
2523 struct xfs_rmap_irec high;
2524 struct xfs_rmap_key_state rks;
2527 xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags);
2528 rks.has_rmap = false;
2530 low.rm_startblock = bno;
2531 memset(&high, 0xFF, sizeof(high));
2532 high.rm_startblock = bno + len - 1;
2534 error = xfs_rmap_query_range(cur, &low, &high,
2535 xfs_rmap_has_other_keys_helper, &rks);
2536 *has_rmap = rks.has_rmap;