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,
387 if (owner == XFS_RMAP_OWN_UNKNOWN)
390 /* Make sure the unwritten flag matches. */
391 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
392 (rec->rm_flags & XFS_RMAP_UNWRITTEN), out);
394 /* Make sure the owner matches what we expect to find in the tree. */
395 XFS_WANT_CORRUPTED_GOTO(mp, owner == rec->rm_owner, out);
397 /* Check the offset, if necessary. */
398 if (XFS_RMAP_NON_INODE_OWNER(owner))
401 if (flags & XFS_RMAP_BMBT_BLOCK) {
402 XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_flags & XFS_RMAP_BMBT_BLOCK,
405 XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_offset <= offset, out);
406 XFS_WANT_CORRUPTED_GOTO(mp,
407 ltoff + rec->rm_blockcount >= offset + len,
416 * Find the extent in the rmap btree and remove it.
418 * The record we find should always be an exact match for the extent that we're
419 * looking for, since we insert them into the btree without modification.
421 * Special Case #1: when growing the filesystem, we "free" an extent when
422 * growing the last AG. This extent is new space and so it is not tracked as
423 * used space in the btree. The growfs code will pass in an owner of
424 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
425 * extent. We verify that - the extent lookup result in a record that does not
428 * Special Case #2: EFIs do not record the owner of the extent, so when
429 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
430 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
431 * corruption checks during log recovery.
435 struct xfs_btree_cur *cur,
439 struct xfs_owner_info *oinfo)
441 struct xfs_mount *mp = cur->bc_mp;
442 struct xfs_rmap_irec ltrec;
451 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
452 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
453 (flags & XFS_RMAP_BMBT_BLOCK);
455 flags |= XFS_RMAP_UNWRITTEN;
456 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
460 * We should always have a left record because there's a static record
461 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
462 * will not ever be removed from the tree.
464 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i);
467 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
469 error = xfs_rmap_get_rec(cur, <rec, &i);
472 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
473 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
474 cur->bc_private.a.agno, ltrec.rm_startblock,
475 ltrec.rm_blockcount, ltrec.rm_owner,
476 ltrec.rm_offset, ltrec.rm_flags);
477 ltoff = ltrec.rm_offset;
480 * For growfs, the incoming extent must be beyond the left record we
481 * just found as it is new space and won't be used by anyone. This is
482 * just a corruption check as we don't actually do anything with this
483 * extent. Note that we need to use >= instead of > because it might
484 * be the case that the "left" extent goes all the way to EOFS.
486 if (owner == XFS_RMAP_OWN_NULL) {
487 XFS_WANT_CORRUPTED_GOTO(mp, bno >= ltrec.rm_startblock +
488 ltrec.rm_blockcount, out_error);
493 * If we're doing an unknown-owner removal for EFI recovery, we expect
494 * to find the full range in the rmapbt or nothing at all. If we
495 * don't find any rmaps overlapping either end of the range, we're
496 * done. Hopefully this means that the EFI creator already queued
497 * (and finished) a RUI to remove the rmap.
499 if (owner == XFS_RMAP_OWN_UNKNOWN &&
500 ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
501 struct xfs_rmap_irec rtrec;
503 error = xfs_btree_increment(cur, 0, &i);
508 error = xfs_rmap_get_rec(cur, &rtrec, &i);
511 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
512 if (rtrec.rm_startblock >= bno + len)
516 /* Make sure the extent we found covers the entire freeing range. */
517 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
518 ltrec.rm_startblock + ltrec.rm_blockcount >=
519 bno + len, out_error);
521 /* Check owner information. */
522 error = xfs_rmap_free_check_owner(mp, ltoff, <rec, bno, len, owner,
527 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
528 /* exact match, simply remove the record from rmap tree */
529 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
530 ltrec.rm_startblock, ltrec.rm_blockcount,
531 ltrec.rm_owner, ltrec.rm_offset,
533 error = xfs_btree_delete(cur, &i);
536 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
537 } else if (ltrec.rm_startblock == bno) {
539 * overlap left hand side of extent: move the start, trim the
540 * length and update the current record.
543 * Orig: |oooooooooooooooooooo|
544 * Freeing: |fffffffff|
545 * Result: |rrrrrrrrrr|
548 ltrec.rm_startblock += len;
549 ltrec.rm_blockcount -= len;
551 ltrec.rm_offset += len;
552 error = xfs_rmap_update(cur, <rec);
555 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
557 * overlap right hand side of extent: trim the length and update
558 * the current record.
561 * Orig: |oooooooooooooooooooo|
562 * Freeing: |fffffffff|
563 * Result: |rrrrrrrrrr|
566 ltrec.rm_blockcount -= len;
567 error = xfs_rmap_update(cur, <rec);
573 * overlap middle of extent: trim the length of the existing
574 * record to the length of the new left-extent size, increment
575 * the insertion position so we can insert a new record
576 * containing the remaining right-extent space.
579 * Orig: |oooooooooooooooooooo|
580 * Freeing: |fffffffff|
581 * Result: |rrrrr| |rrrr|
584 xfs_extlen_t orig_len = ltrec.rm_blockcount;
586 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
587 error = xfs_rmap_update(cur, <rec);
591 error = xfs_btree_increment(cur, 0, &i);
595 cur->bc_rec.r.rm_startblock = bno + len;
596 cur->bc_rec.r.rm_blockcount = orig_len - len -
598 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
600 cur->bc_rec.r.rm_offset = 0;
602 cur->bc_rec.r.rm_offset = offset + len;
603 cur->bc_rec.r.rm_flags = flags;
604 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
605 cur->bc_rec.r.rm_startblock,
606 cur->bc_rec.r.rm_blockcount,
607 cur->bc_rec.r.rm_owner,
608 cur->bc_rec.r.rm_offset,
609 cur->bc_rec.r.rm_flags);
610 error = xfs_btree_insert(cur, &i);
616 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
620 trace_xfs_rmap_unmap_error(mp, cur->bc_private.a.agno,
626 * Remove a reference to an extent in the rmap btree.
630 struct xfs_trans *tp,
631 struct xfs_buf *agbp,
635 struct xfs_owner_info *oinfo)
637 struct xfs_mount *mp = tp->t_mountp;
638 struct xfs_btree_cur *cur;
641 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
644 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
646 error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
650 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
654 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
659 * A mergeable rmap must have the same owner and the same values for
660 * the unwritten, attr_fork, and bmbt flags. The startblock and
661 * offset are checked separately.
664 xfs_rmap_is_mergeable(
665 struct xfs_rmap_irec *irec,
669 if (irec->rm_owner == XFS_RMAP_OWN_NULL)
671 if (irec->rm_owner != owner)
673 if ((flags & XFS_RMAP_UNWRITTEN) ^
674 (irec->rm_flags & XFS_RMAP_UNWRITTEN))
676 if ((flags & XFS_RMAP_ATTR_FORK) ^
677 (irec->rm_flags & XFS_RMAP_ATTR_FORK))
679 if ((flags & XFS_RMAP_BMBT_BLOCK) ^
680 (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
686 * When we allocate a new block, the first thing we do is add a reference to
687 * the extent in the rmap btree. This takes the form of a [agbno, length,
688 * owner, offset] record. Flags are encoded in the high bits of the offset
693 struct xfs_btree_cur *cur,
697 struct xfs_owner_info *oinfo)
699 struct xfs_mount *mp = cur->bc_mp;
700 struct xfs_rmap_irec ltrec;
701 struct xfs_rmap_irec gtrec;
708 unsigned int flags = 0;
711 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
713 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
714 (flags & XFS_RMAP_BMBT_BLOCK);
716 flags |= XFS_RMAP_UNWRITTEN;
717 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
719 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
722 * For the initial lookup, look for an exact match or the left-adjacent
723 * record for our insertion point. This will also give us the record for
724 * start block contiguity tests.
726 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
730 XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
732 error = xfs_rmap_get_rec(cur, <rec, &have_lt);
735 XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
736 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
737 cur->bc_private.a.agno, ltrec.rm_startblock,
738 ltrec.rm_blockcount, ltrec.rm_owner,
739 ltrec.rm_offset, ltrec.rm_flags);
741 if (!xfs_rmap_is_mergeable(<rec, owner, flags))
744 XFS_WANT_CORRUPTED_GOTO(mp,
746 ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error);
749 * Increment the cursor to see if we have a right-adjacent record to our
750 * insertion point. This will give us the record for end block
753 error = xfs_btree_increment(cur, 0, &have_gt);
757 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
760 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
761 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock,
763 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
764 cur->bc_private.a.agno, gtrec.rm_startblock,
765 gtrec.rm_blockcount, gtrec.rm_owner,
766 gtrec.rm_offset, gtrec.rm_flags);
767 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
772 * Note: cursor currently points one record to the right of ltrec, even
773 * if there is no record in the tree to the right.
776 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
777 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
779 * left edge contiguous, merge into left record.
783 * adding: |aaaaaaaaa|
784 * result: |rrrrrrrrrrrrrrrrrrr|
787 ltrec.rm_blockcount += len;
789 bno + len == gtrec.rm_startblock &&
790 (ignore_off || offset + len == gtrec.rm_offset) &&
791 (unsigned long)ltrec.rm_blockcount + len +
792 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
794 * right edge also contiguous, delete right record
795 * and merge into left record.
797 * ltbno ltlen gtbno gtlen
798 * orig: |ooooooooo| |ooooooooo|
799 * adding: |aaaaaaaaa|
800 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
802 ltrec.rm_blockcount += gtrec.rm_blockcount;
803 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
809 error = xfs_btree_delete(cur, &i);
812 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
815 /* point the cursor back to the left record and update */
816 error = xfs_btree_decrement(cur, 0, &have_gt);
819 error = xfs_rmap_update(cur, <rec);
822 } else if (have_gt &&
823 bno + len == gtrec.rm_startblock &&
824 (ignore_off || offset + len == gtrec.rm_offset)) {
826 * right edge contiguous, merge into right record.
830 * adding: |aaaaaaaaa|
831 * Result: |rrrrrrrrrrrrrrrrrrr|
834 gtrec.rm_startblock = bno;
835 gtrec.rm_blockcount += len;
837 gtrec.rm_offset = offset;
838 error = xfs_rmap_update(cur, >rec);
843 * no contiguous edge with identical owner, insert
844 * new record at current cursor position.
846 cur->bc_rec.r.rm_startblock = bno;
847 cur->bc_rec.r.rm_blockcount = len;
848 cur->bc_rec.r.rm_owner = owner;
849 cur->bc_rec.r.rm_offset = offset;
850 cur->bc_rec.r.rm_flags = flags;
851 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
852 owner, offset, flags);
853 error = xfs_btree_insert(cur, &i);
856 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
859 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
863 trace_xfs_rmap_map_error(mp, cur->bc_private.a.agno,
869 * Add a reference to an extent in the rmap btree.
873 struct xfs_trans *tp,
874 struct xfs_buf *agbp,
878 struct xfs_owner_info *oinfo)
880 struct xfs_mount *mp = tp->t_mountp;
881 struct xfs_btree_cur *cur;
884 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
887 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
888 error = xfs_rmap_map(cur, bno, len, false, oinfo);
892 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
896 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
900 #define RMAP_LEFT_CONTIG (1 << 0)
901 #define RMAP_RIGHT_CONTIG (1 << 1)
902 #define RMAP_LEFT_FILLING (1 << 2)
903 #define RMAP_RIGHT_FILLING (1 << 3)
904 #define RMAP_LEFT_VALID (1 << 6)
905 #define RMAP_RIGHT_VALID (1 << 7)
913 * Convert an unwritten extent to a real extent or vice versa.
914 * Does not handle overlapping extents.
918 struct xfs_btree_cur *cur,
922 struct xfs_owner_info *oinfo)
924 struct xfs_mount *mp = cur->bc_mp;
925 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
926 /* left is 0, right is 1, prev is 2 */
933 unsigned int flags = 0;
938 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
939 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
940 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
941 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
942 new_endoff = offset + len;
943 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
947 * For the initial lookup, look for an exact match or the left-adjacent
948 * record for our insertion point. This will also give us the record for
949 * start block contiguity tests.
951 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
954 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
956 error = xfs_rmap_get_rec(cur, &PREV, &i);
959 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
960 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
961 cur->bc_private.a.agno, PREV.rm_startblock,
962 PREV.rm_blockcount, PREV.rm_owner,
963 PREV.rm_offset, PREV.rm_flags);
965 ASSERT(PREV.rm_offset <= offset);
966 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
967 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
968 newext = ~oldext & XFS_RMAP_UNWRITTEN;
971 * Set flags determining what part of the previous oldext allocation
972 * extent is being replaced by a newext allocation.
974 if (PREV.rm_offset == offset)
975 state |= RMAP_LEFT_FILLING;
976 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
977 state |= RMAP_RIGHT_FILLING;
980 * Decrement the cursor to see if we have a left-adjacent record to our
981 * insertion point. This will give us the record for end block
984 error = xfs_btree_decrement(cur, 0, &i);
988 state |= RMAP_LEFT_VALID;
989 error = xfs_rmap_get_rec(cur, &LEFT, &i);
992 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
993 XFS_WANT_CORRUPTED_GOTO(mp,
994 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
996 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
997 cur->bc_private.a.agno, LEFT.rm_startblock,
998 LEFT.rm_blockcount, LEFT.rm_owner,
999 LEFT.rm_offset, LEFT.rm_flags);
1000 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1001 LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1002 xfs_rmap_is_mergeable(&LEFT, owner, newext))
1003 state |= RMAP_LEFT_CONTIG;
1007 * Increment the cursor to see if we have a right-adjacent record to our
1008 * insertion point. This will give us the record for end block
1011 error = xfs_btree_increment(cur, 0, &i);
1014 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1015 error = xfs_btree_increment(cur, 0, &i);
1019 state |= RMAP_RIGHT_VALID;
1020 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1023 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1024 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1026 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1027 cur->bc_private.a.agno, RIGHT.rm_startblock,
1028 RIGHT.rm_blockcount, RIGHT.rm_owner,
1029 RIGHT.rm_offset, RIGHT.rm_flags);
1030 if (bno + len == RIGHT.rm_startblock &&
1031 offset + len == RIGHT.rm_offset &&
1032 xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1033 state |= RMAP_RIGHT_CONTIG;
1036 /* check that left + prev + right is not too long */
1037 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1038 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1039 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1040 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1041 (unsigned long)LEFT.rm_blockcount + len +
1042 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1043 state &= ~RMAP_RIGHT_CONTIG;
1045 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1048 /* reset the cursor back to PREV */
1049 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1052 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1055 * Switch out based on the FILLING and CONTIG state bits.
1057 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1058 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1059 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1060 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1062 * Setting all of a previous oldext extent to newext.
1063 * The left and right neighbors are both contiguous with new.
1065 error = xfs_btree_increment(cur, 0, &i);
1068 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1069 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1070 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1071 RIGHT.rm_owner, RIGHT.rm_offset,
1073 error = xfs_btree_delete(cur, &i);
1076 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1077 error = xfs_btree_decrement(cur, 0, &i);
1080 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1081 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1082 PREV.rm_startblock, PREV.rm_blockcount,
1083 PREV.rm_owner, PREV.rm_offset,
1085 error = xfs_btree_delete(cur, &i);
1088 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1089 error = xfs_btree_decrement(cur, 0, &i);
1092 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1094 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1095 error = xfs_rmap_update(cur, &NEW);
1100 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1102 * Setting all of a previous oldext extent to newext.
1103 * The left neighbor is contiguous, the right is not.
1105 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1106 PREV.rm_startblock, PREV.rm_blockcount,
1107 PREV.rm_owner, PREV.rm_offset,
1109 error = xfs_btree_delete(cur, &i);
1112 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1113 error = xfs_btree_decrement(cur, 0, &i);
1116 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1118 NEW.rm_blockcount += PREV.rm_blockcount;
1119 error = xfs_rmap_update(cur, &NEW);
1124 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1126 * Setting all of a previous oldext extent to newext.
1127 * The right neighbor is contiguous, the left is not.
1129 error = xfs_btree_increment(cur, 0, &i);
1132 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1133 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1134 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1135 RIGHT.rm_owner, RIGHT.rm_offset,
1137 error = xfs_btree_delete(cur, &i);
1140 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1141 error = xfs_btree_decrement(cur, 0, &i);
1144 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1146 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1147 NEW.rm_flags = newext;
1148 error = xfs_rmap_update(cur, &NEW);
1153 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1155 * Setting all of a previous oldext extent to newext.
1156 * Neither the left nor right neighbors are contiguous with
1160 NEW.rm_flags = newext;
1161 error = xfs_rmap_update(cur, &NEW);
1166 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1168 * Setting the first part of a previous oldext extent to newext.
1169 * The left neighbor is contiguous.
1172 NEW.rm_offset += len;
1173 NEW.rm_startblock += len;
1174 NEW.rm_blockcount -= len;
1175 error = xfs_rmap_update(cur, &NEW);
1178 error = xfs_btree_decrement(cur, 0, &i);
1182 NEW.rm_blockcount += len;
1183 error = xfs_rmap_update(cur, &NEW);
1188 case RMAP_LEFT_FILLING:
1190 * Setting the first part of a previous oldext extent to newext.
1191 * The left neighbor is not contiguous.
1194 NEW.rm_startblock += len;
1195 NEW.rm_offset += len;
1196 NEW.rm_blockcount -= len;
1197 error = xfs_rmap_update(cur, &NEW);
1200 NEW.rm_startblock = bno;
1201 NEW.rm_owner = owner;
1202 NEW.rm_offset = offset;
1203 NEW.rm_blockcount = len;
1204 NEW.rm_flags = newext;
1205 cur->bc_rec.r = NEW;
1206 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1207 len, owner, offset, newext);
1208 error = xfs_btree_insert(cur, &i);
1211 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1214 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1216 * Setting the last part of a previous oldext extent to newext.
1217 * The right neighbor is contiguous with the new allocation.
1220 NEW.rm_blockcount -= len;
1221 error = xfs_rmap_update(cur, &NEW);
1224 error = xfs_btree_increment(cur, 0, &i);
1228 NEW.rm_offset = offset;
1229 NEW.rm_startblock = bno;
1230 NEW.rm_blockcount += len;
1231 error = xfs_rmap_update(cur, &NEW);
1236 case RMAP_RIGHT_FILLING:
1238 * Setting the last part of a previous oldext extent to newext.
1239 * The right neighbor is not contiguous.
1242 NEW.rm_blockcount -= len;
1243 error = xfs_rmap_update(cur, &NEW);
1246 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1250 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1251 NEW.rm_startblock = bno;
1252 NEW.rm_owner = owner;
1253 NEW.rm_offset = offset;
1254 NEW.rm_blockcount = len;
1255 NEW.rm_flags = newext;
1256 cur->bc_rec.r = NEW;
1257 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1258 len, owner, offset, newext);
1259 error = xfs_btree_insert(cur, &i);
1262 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1267 * Setting the middle part of a previous oldext extent to
1268 * newext. Contiguity is impossible here.
1269 * One extent becomes three extents.
1271 /* new right extent - oldext */
1272 NEW.rm_startblock = bno + len;
1273 NEW.rm_owner = owner;
1274 NEW.rm_offset = new_endoff;
1275 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1277 NEW.rm_flags = PREV.rm_flags;
1278 error = xfs_rmap_update(cur, &NEW);
1281 /* new left extent - oldext */
1283 NEW.rm_blockcount = offset - PREV.rm_offset;
1284 cur->bc_rec.r = NEW;
1285 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
1286 NEW.rm_startblock, NEW.rm_blockcount,
1287 NEW.rm_owner, NEW.rm_offset,
1289 error = xfs_btree_insert(cur, &i);
1292 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1294 * Reset the cursor to the position of the new extent
1295 * we are about to insert as we can't trust it after
1296 * the previous insert.
1298 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1302 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1303 /* new middle extent - newext */
1304 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1305 cur->bc_rec.r.rm_flags |= newext;
1306 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
1307 owner, offset, newext);
1308 error = xfs_btree_insert(cur, &i);
1311 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1314 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1315 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1316 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1317 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1318 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1319 case RMAP_LEFT_CONTIG:
1320 case RMAP_RIGHT_CONTIG:
1322 * These cases are all impossible.
1327 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1331 trace_xfs_rmap_convert_error(cur->bc_mp,
1332 cur->bc_private.a.agno, error, _RET_IP_);
1337 * Convert an unwritten extent to a real extent or vice versa. If there is no
1338 * possibility of overlapping extents, delegate to the simpler convert
1342 xfs_rmap_convert_shared(
1343 struct xfs_btree_cur *cur,
1347 struct xfs_owner_info *oinfo)
1349 struct xfs_mount *mp = cur->bc_mp;
1350 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1351 /* left is 0, right is 1, prev is 2 */
1355 uint64_t new_endoff;
1356 unsigned int oldext;
1357 unsigned int newext;
1358 unsigned int flags = 0;
1363 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1364 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1365 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1366 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1367 new_endoff = offset + len;
1368 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
1372 * For the initial lookup, look for and exact match or the left-adjacent
1373 * record for our insertion point. This will also give us the record for
1374 * start block contiguity tests.
1376 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1378 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1380 ASSERT(PREV.rm_offset <= offset);
1381 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1382 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1383 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1386 * Set flags determining what part of the previous oldext allocation
1387 * extent is being replaced by a newext allocation.
1389 if (PREV.rm_offset == offset)
1390 state |= RMAP_LEFT_FILLING;
1391 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1392 state |= RMAP_RIGHT_FILLING;
1394 /* Is there a left record that abuts our range? */
1395 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1400 state |= RMAP_LEFT_VALID;
1401 XFS_WANT_CORRUPTED_GOTO(mp,
1402 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
1404 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1405 state |= RMAP_LEFT_CONTIG;
1408 /* Is there a right record that abuts our range? */
1409 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1414 state |= RMAP_RIGHT_VALID;
1415 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1418 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1419 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1421 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1422 cur->bc_private.a.agno, RIGHT.rm_startblock,
1423 RIGHT.rm_blockcount, RIGHT.rm_owner,
1424 RIGHT.rm_offset, RIGHT.rm_flags);
1425 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1426 state |= RMAP_RIGHT_CONTIG;
1429 /* check that left + prev + right is not too long */
1430 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1431 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1432 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1433 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1434 (unsigned long)LEFT.rm_blockcount + len +
1435 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1436 state &= ~RMAP_RIGHT_CONTIG;
1438 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1441 * Switch out based on the FILLING and CONTIG state bits.
1443 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1444 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1445 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1446 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1448 * Setting all of a previous oldext extent to newext.
1449 * The left and right neighbors are both contiguous with new.
1451 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1452 RIGHT.rm_blockcount, RIGHT.rm_owner,
1453 RIGHT.rm_offset, RIGHT.rm_flags);
1456 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1457 PREV.rm_blockcount, PREV.rm_owner,
1458 PREV.rm_offset, PREV.rm_flags);
1462 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1463 NEW.rm_blockcount, NEW.rm_owner,
1464 NEW.rm_offset, NEW.rm_flags, &i);
1467 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1468 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1469 error = xfs_rmap_update(cur, &NEW);
1474 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1476 * Setting all of a previous oldext extent to newext.
1477 * The left neighbor is contiguous, the right is not.
1479 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1480 PREV.rm_blockcount, PREV.rm_owner,
1481 PREV.rm_offset, PREV.rm_flags);
1485 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1486 NEW.rm_blockcount, NEW.rm_owner,
1487 NEW.rm_offset, NEW.rm_flags, &i);
1490 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1491 NEW.rm_blockcount += PREV.rm_blockcount;
1492 error = xfs_rmap_update(cur, &NEW);
1497 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1499 * Setting all of a previous oldext extent to newext.
1500 * The right neighbor is contiguous, the left is not.
1502 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1503 RIGHT.rm_blockcount, RIGHT.rm_owner,
1504 RIGHT.rm_offset, RIGHT.rm_flags);
1508 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1509 NEW.rm_blockcount, NEW.rm_owner,
1510 NEW.rm_offset, NEW.rm_flags, &i);
1513 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1514 NEW.rm_blockcount += RIGHT.rm_blockcount;
1515 NEW.rm_flags = RIGHT.rm_flags;
1516 error = xfs_rmap_update(cur, &NEW);
1521 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1523 * Setting all of a previous oldext extent to newext.
1524 * Neither the left nor right neighbors are contiguous with
1528 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1529 NEW.rm_blockcount, NEW.rm_owner,
1530 NEW.rm_offset, NEW.rm_flags, &i);
1533 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1534 NEW.rm_flags = newext;
1535 error = xfs_rmap_update(cur, &NEW);
1540 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1542 * Setting the first part of a previous oldext extent to newext.
1543 * The left neighbor is contiguous.
1546 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1547 NEW.rm_blockcount, NEW.rm_owner,
1548 NEW.rm_offset, NEW.rm_flags);
1551 NEW.rm_offset += len;
1552 NEW.rm_startblock += len;
1553 NEW.rm_blockcount -= len;
1554 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1555 NEW.rm_blockcount, NEW.rm_owner,
1556 NEW.rm_offset, NEW.rm_flags);
1560 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1561 NEW.rm_blockcount, NEW.rm_owner,
1562 NEW.rm_offset, NEW.rm_flags, &i);
1565 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1566 NEW.rm_blockcount += len;
1567 error = xfs_rmap_update(cur, &NEW);
1572 case RMAP_LEFT_FILLING:
1574 * Setting the first part of a previous oldext extent to newext.
1575 * The left neighbor is not contiguous.
1578 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1579 NEW.rm_blockcount, NEW.rm_owner,
1580 NEW.rm_offset, NEW.rm_flags);
1583 NEW.rm_offset += len;
1584 NEW.rm_startblock += len;
1585 NEW.rm_blockcount -= len;
1586 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1587 NEW.rm_blockcount, NEW.rm_owner,
1588 NEW.rm_offset, NEW.rm_flags);
1591 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1596 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1598 * Setting the last part of a previous oldext extent to newext.
1599 * The right neighbor is contiguous with the new allocation.
1602 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1603 NEW.rm_blockcount, NEW.rm_owner,
1604 NEW.rm_offset, NEW.rm_flags, &i);
1607 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1608 NEW.rm_blockcount = offset - NEW.rm_offset;
1609 error = xfs_rmap_update(cur, &NEW);
1613 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1614 NEW.rm_blockcount, NEW.rm_owner,
1615 NEW.rm_offset, NEW.rm_flags);
1618 NEW.rm_offset = offset;
1619 NEW.rm_startblock = bno;
1620 NEW.rm_blockcount += len;
1621 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1622 NEW.rm_blockcount, NEW.rm_owner,
1623 NEW.rm_offset, NEW.rm_flags);
1628 case RMAP_RIGHT_FILLING:
1630 * Setting the last part of a previous oldext extent to newext.
1631 * The right neighbor is not contiguous.
1634 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1635 NEW.rm_blockcount, NEW.rm_owner,
1636 NEW.rm_offset, NEW.rm_flags, &i);
1639 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1640 NEW.rm_blockcount -= len;
1641 error = xfs_rmap_update(cur, &NEW);
1644 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1651 * Setting the middle part of a previous oldext extent to
1652 * newext. Contiguity is impossible here.
1653 * One extent becomes three extents.
1655 /* new right extent - oldext */
1656 NEW.rm_startblock = bno + len;
1657 NEW.rm_owner = owner;
1658 NEW.rm_offset = new_endoff;
1659 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1661 NEW.rm_flags = PREV.rm_flags;
1662 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1663 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1667 /* new left extent - oldext */
1669 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1670 NEW.rm_blockcount, NEW.rm_owner,
1671 NEW.rm_offset, NEW.rm_flags, &i);
1674 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1675 NEW.rm_blockcount = offset - NEW.rm_offset;
1676 error = xfs_rmap_update(cur, &NEW);
1679 /* new middle extent - newext */
1680 NEW.rm_startblock = bno;
1681 NEW.rm_blockcount = len;
1682 NEW.rm_owner = owner;
1683 NEW.rm_offset = offset;
1684 NEW.rm_flags = newext;
1685 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1686 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1692 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1693 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1694 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1695 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1696 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1697 case RMAP_LEFT_CONTIG:
1698 case RMAP_RIGHT_CONTIG:
1700 * These cases are all impossible.
1705 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1709 trace_xfs_rmap_convert_error(cur->bc_mp,
1710 cur->bc_private.a.agno, error, _RET_IP_);
1720 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1721 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1722 * that the prev/next records in the btree might belong to another owner.
1723 * Therefore we must use delete+insert to alter any of the key fields.
1725 * For every other situation there can only be one owner for a given extent,
1726 * so we can call the regular _free function.
1729 xfs_rmap_unmap_shared(
1730 struct xfs_btree_cur *cur,
1734 struct xfs_owner_info *oinfo)
1736 struct xfs_mount *mp = cur->bc_mp;
1737 struct xfs_rmap_irec ltrec;
1745 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1747 flags |= XFS_RMAP_UNWRITTEN;
1748 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
1752 * We should always have a left record because there's a static record
1753 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1754 * will not ever be removed from the tree.
1756 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1760 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1761 ltoff = ltrec.rm_offset;
1763 /* Make sure the extent we found covers the entire freeing range. */
1764 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
1765 ltrec.rm_startblock + ltrec.rm_blockcount >=
1766 bno + len, out_error);
1768 /* Make sure the owner matches what we expect to find in the tree. */
1769 XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner, out_error);
1771 /* Make sure the unwritten flag matches. */
1772 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
1773 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error);
1775 /* Check the offset. */
1776 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error);
1777 XFS_WANT_CORRUPTED_GOTO(mp, offset <= ltoff + ltrec.rm_blockcount,
1780 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
1781 /* Exact match, simply remove the record from rmap tree. */
1782 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1783 ltrec.rm_blockcount, ltrec.rm_owner,
1784 ltrec.rm_offset, ltrec.rm_flags);
1787 } else if (ltrec.rm_startblock == bno) {
1789 * Overlap left hand side of extent: move the start, trim the
1790 * length and update the current record.
1793 * Orig: |oooooooooooooooooooo|
1794 * Freeing: |fffffffff|
1795 * Result: |rrrrrrrrrr|
1799 /* Delete prev rmap. */
1800 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1801 ltrec.rm_blockcount, ltrec.rm_owner,
1802 ltrec.rm_offset, ltrec.rm_flags);
1806 /* Add an rmap at the new offset. */
1807 ltrec.rm_startblock += len;
1808 ltrec.rm_blockcount -= len;
1809 ltrec.rm_offset += len;
1810 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
1811 ltrec.rm_blockcount, ltrec.rm_owner,
1812 ltrec.rm_offset, ltrec.rm_flags);
1815 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
1817 * Overlap right hand side of extent: trim the length and
1818 * update the current record.
1821 * Orig: |oooooooooooooooooooo|
1822 * Freeing: |fffffffff|
1823 * Result: |rrrrrrrrrr|
1826 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1827 ltrec.rm_blockcount, ltrec.rm_owner,
1828 ltrec.rm_offset, ltrec.rm_flags, &i);
1831 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1832 ltrec.rm_blockcount -= len;
1833 error = xfs_rmap_update(cur, <rec);
1838 * Overlap middle of extent: trim the length of the existing
1839 * record to the length of the new left-extent size, increment
1840 * the insertion position so we can insert a new record
1841 * containing the remaining right-extent space.
1844 * Orig: |oooooooooooooooooooo|
1845 * Freeing: |fffffffff|
1846 * Result: |rrrrr| |rrrr|
1849 xfs_extlen_t orig_len = ltrec.rm_blockcount;
1851 /* Shrink the left side of the rmap */
1852 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1853 ltrec.rm_blockcount, ltrec.rm_owner,
1854 ltrec.rm_offset, ltrec.rm_flags, &i);
1857 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1858 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
1859 error = xfs_rmap_update(cur, <rec);
1863 /* Add an rmap at the new offset */
1864 error = xfs_rmap_insert(cur, bno + len,
1865 orig_len - len - ltrec.rm_blockcount,
1866 ltrec.rm_owner, offset + len,
1872 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
1876 trace_xfs_rmap_unmap_error(cur->bc_mp,
1877 cur->bc_private.a.agno, error, _RET_IP_);
1882 * Find an extent in the rmap btree and map it. For rmap extent types that
1883 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1884 * that the prev/next records in the btree might belong to another owner.
1885 * Therefore we must use delete+insert to alter any of the key fields.
1887 * For every other situation there can only be one owner for a given extent,
1888 * so we can call the regular _alloc function.
1891 xfs_rmap_map_shared(
1892 struct xfs_btree_cur *cur,
1896 struct xfs_owner_info *oinfo)
1898 struct xfs_mount *mp = cur->bc_mp;
1899 struct xfs_rmap_irec ltrec;
1900 struct xfs_rmap_irec gtrec;
1907 unsigned int flags = 0;
1909 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1911 flags |= XFS_RMAP_UNWRITTEN;
1912 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
1915 /* Is there a left record that abuts our range? */
1916 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
1921 !xfs_rmap_is_mergeable(<rec, owner, flags))
1924 /* Is there a right record that abuts our range? */
1925 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1930 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
1933 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
1934 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1935 cur->bc_private.a.agno, gtrec.rm_startblock,
1936 gtrec.rm_blockcount, gtrec.rm_owner,
1937 gtrec.rm_offset, gtrec.rm_flags);
1939 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
1944 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
1945 ltrec.rm_offset + ltrec.rm_blockcount == offset) {
1947 * Left edge contiguous, merge into left record.
1951 * adding: |aaaaaaaaa|
1952 * result: |rrrrrrrrrrrrrrrrrrr|
1955 ltrec.rm_blockcount += len;
1957 bno + len == gtrec.rm_startblock &&
1958 offset + len == gtrec.rm_offset) {
1960 * Right edge also contiguous, delete right record
1961 * and merge into left record.
1963 * ltbno ltlen gtbno gtlen
1964 * orig: |ooooooooo| |ooooooooo|
1965 * adding: |aaaaaaaaa|
1966 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1968 ltrec.rm_blockcount += gtrec.rm_blockcount;
1969 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
1970 gtrec.rm_blockcount, gtrec.rm_owner,
1971 gtrec.rm_offset, gtrec.rm_flags);
1976 /* Point the cursor back to the left record and update. */
1977 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1978 ltrec.rm_blockcount, ltrec.rm_owner,
1979 ltrec.rm_offset, ltrec.rm_flags, &i);
1982 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1984 error = xfs_rmap_update(cur, <rec);
1987 } else if (have_gt &&
1988 bno + len == gtrec.rm_startblock &&
1989 offset + len == gtrec.rm_offset) {
1991 * Right edge contiguous, merge into right record.
1995 * adding: |aaaaaaaaa|
1996 * Result: |rrrrrrrrrrrrrrrrrrr|
1999 /* Delete the old record. */
2000 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2001 gtrec.rm_blockcount, gtrec.rm_owner,
2002 gtrec.rm_offset, gtrec.rm_flags);
2006 /* Move the start and re-add it. */
2007 gtrec.rm_startblock = bno;
2008 gtrec.rm_blockcount += len;
2009 gtrec.rm_offset = offset;
2010 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2011 gtrec.rm_blockcount, gtrec.rm_owner,
2012 gtrec.rm_offset, gtrec.rm_flags);
2017 * No contiguous edge with identical owner, insert
2018 * new record at current cursor position.
2020 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2025 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
2029 trace_xfs_rmap_map_error(cur->bc_mp,
2030 cur->bc_private.a.agno, error, _RET_IP_);
2034 struct xfs_rmap_query_range_info {
2035 xfs_rmap_query_range_fn fn;
2039 /* Format btree record and pass to our callback. */
2041 xfs_rmap_query_range_helper(
2042 struct xfs_btree_cur *cur,
2043 union xfs_btree_rec *rec,
2046 struct xfs_rmap_query_range_info *query = priv;
2047 struct xfs_rmap_irec irec;
2050 error = xfs_rmap_btrec_to_irec(rec, &irec);
2053 return query->fn(cur, &irec, query->priv);
2056 /* Find all rmaps between two keys. */
2058 xfs_rmap_query_range(
2059 struct xfs_btree_cur *cur,
2060 struct xfs_rmap_irec *low_rec,
2061 struct xfs_rmap_irec *high_rec,
2062 xfs_rmap_query_range_fn fn,
2065 union xfs_btree_irec low_brec;
2066 union xfs_btree_irec high_brec;
2067 struct xfs_rmap_query_range_info query;
2069 low_brec.r = *low_rec;
2070 high_brec.r = *high_rec;
2073 return xfs_btree_query_range(cur, &low_brec, &high_brec,
2074 xfs_rmap_query_range_helper, &query);
2077 /* Find all rmaps. */
2080 struct xfs_btree_cur *cur,
2081 xfs_rmap_query_range_fn fn,
2084 struct xfs_rmap_query_range_info query;
2088 return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2091 /* Clean up after calling xfs_rmap_finish_one. */
2093 xfs_rmap_finish_one_cleanup(
2094 struct xfs_trans *tp,
2095 struct xfs_btree_cur *rcur,
2098 struct xfs_buf *agbp;
2102 agbp = rcur->bc_private.a.agbp;
2103 xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
2105 xfs_trans_brelse(tp, agbp);
2109 * Process one of the deferred rmap operations. We pass back the
2110 * btree cursor to maintain our lock on the rmapbt between calls.
2111 * This saves time and eliminates a buffer deadlock between the
2112 * superblock and the AGF because we'll always grab them in the same
2116 xfs_rmap_finish_one(
2117 struct xfs_trans *tp,
2118 enum xfs_rmap_intent_type type,
2121 xfs_fileoff_t startoff,
2122 xfs_fsblock_t startblock,
2123 xfs_filblks_t blockcount,
2125 struct xfs_btree_cur **pcur)
2127 struct xfs_mount *mp = tp->t_mountp;
2128 struct xfs_btree_cur *rcur;
2129 struct xfs_buf *agbp = NULL;
2131 xfs_agnumber_t agno;
2132 struct xfs_owner_info oinfo;
2136 agno = XFS_FSB_TO_AGNO(mp, startblock);
2137 ASSERT(agno != NULLAGNUMBER);
2138 bno = XFS_FSB_TO_AGBNO(mp, startblock);
2140 trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork,
2141 startoff, blockcount, state);
2143 if (XFS_TEST_ERROR(false, mp,
2144 XFS_ERRTAG_RMAP_FINISH_ONE))
2148 * If we haven't gotten a cursor or the cursor AG doesn't match
2149 * the startblock, get one now.
2152 if (rcur != NULL && rcur->bc_private.a.agno != agno) {
2153 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2159 * Refresh the freelist before we start changing the
2160 * rmapbt, because a shape change could cause us to
2163 error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
2167 return -EFSCORRUPTED;
2169 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
2177 xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2178 unwritten = state == XFS_EXT_UNWRITTEN;
2179 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2182 case XFS_RMAP_ALLOC:
2184 error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2186 case XFS_RMAP_MAP_SHARED:
2187 error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2191 case XFS_RMAP_UNMAP:
2192 error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2195 case XFS_RMAP_UNMAP_SHARED:
2196 error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2199 case XFS_RMAP_CONVERT:
2200 error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2203 case XFS_RMAP_CONVERT_SHARED:
2204 error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2205 !unwritten, &oinfo);
2209 error = -EFSCORRUPTED;
2214 xfs_trans_brelse(tp, agbp);
2220 * Don't defer an rmap if we aren't an rmap filesystem.
2223 xfs_rmap_update_is_needed(
2224 struct xfs_mount *mp,
2227 return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK;
2231 * Record a rmap intent; the list is kept sorted first by AG and then by
2236 struct xfs_mount *mp,
2237 struct xfs_defer_ops *dfops,
2238 enum xfs_rmap_intent_type type,
2241 struct xfs_bmbt_irec *bmap)
2243 struct xfs_rmap_intent *ri;
2245 trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, bmap->br_startblock),
2247 XFS_FSB_TO_AGBNO(mp, bmap->br_startblock),
2250 bmap->br_blockcount,
2253 ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_SLEEP | KM_NOFS);
2254 INIT_LIST_HEAD(&ri->ri_list);
2256 ri->ri_owner = owner;
2257 ri->ri_whichfork = whichfork;
2258 ri->ri_bmap = *bmap;
2260 xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
2264 /* Map an extent into a file. */
2266 xfs_rmap_map_extent(
2267 struct xfs_mount *mp,
2268 struct xfs_defer_ops *dfops,
2269 struct xfs_inode *ip,
2271 struct xfs_bmbt_irec *PREV)
2273 if (!xfs_rmap_update_is_needed(mp, whichfork))
2276 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2277 XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino,
2281 /* Unmap an extent out of a file. */
2283 xfs_rmap_unmap_extent(
2284 struct xfs_mount *mp,
2285 struct xfs_defer_ops *dfops,
2286 struct xfs_inode *ip,
2288 struct xfs_bmbt_irec *PREV)
2290 if (!xfs_rmap_update_is_needed(mp, whichfork))
2293 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2294 XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino,
2298 /* Convert a data fork extent from unwritten to real or vice versa. */
2300 xfs_rmap_convert_extent(
2301 struct xfs_mount *mp,
2302 struct xfs_defer_ops *dfops,
2303 struct xfs_inode *ip,
2305 struct xfs_bmbt_irec *PREV)
2307 if (!xfs_rmap_update_is_needed(mp, whichfork))
2310 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2311 XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino,
2315 /* Schedule the creation of an rmap for non-file data. */
2317 xfs_rmap_alloc_extent(
2318 struct xfs_mount *mp,
2319 struct xfs_defer_ops *dfops,
2320 xfs_agnumber_t agno,
2325 struct xfs_bmbt_irec bmap;
2327 if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
2330 bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
2331 bmap.br_blockcount = len;
2332 bmap.br_startoff = 0;
2333 bmap.br_state = XFS_EXT_NORM;
2335 return __xfs_rmap_add(mp, dfops, XFS_RMAP_ALLOC, owner,
2336 XFS_DATA_FORK, &bmap);
2339 /* Schedule the deletion of an rmap for non-file data. */
2341 xfs_rmap_free_extent(
2342 struct xfs_mount *mp,
2343 struct xfs_defer_ops *dfops,
2344 xfs_agnumber_t agno,
2349 struct xfs_bmbt_irec bmap;
2351 if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
2354 bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
2355 bmap.br_blockcount = len;
2356 bmap.br_startoff = 0;
2357 bmap.br_state = XFS_EXT_NORM;
2359 return __xfs_rmap_add(mp, dfops, XFS_RMAP_FREE, owner,
2360 XFS_DATA_FORK, &bmap);
2363 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2366 const struct xfs_rmap_irec *a,
2367 const struct xfs_rmap_irec *b)
2372 oa = xfs_rmap_irec_offset_pack(a);
2373 ob = xfs_rmap_irec_offset_pack(b);
2375 if (a->rm_startblock < b->rm_startblock)
2377 else if (a->rm_startblock > b->rm_startblock)
2379 else if (a->rm_owner < b->rm_owner)
2381 else if (a->rm_owner > b->rm_owner)