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,
1377 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1379 ASSERT(PREV.rm_offset <= offset);
1380 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1381 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1382 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1385 * Set flags determining what part of the previous oldext allocation
1386 * extent is being replaced by a newext allocation.
1388 if (PREV.rm_offset == offset)
1389 state |= RMAP_LEFT_FILLING;
1390 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1391 state |= RMAP_RIGHT_FILLING;
1393 /* Is there a left record that abuts our range? */
1394 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1399 state |= RMAP_LEFT_VALID;
1400 XFS_WANT_CORRUPTED_GOTO(mp,
1401 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
1403 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1404 state |= RMAP_LEFT_CONTIG;
1407 /* Is there a right record that abuts our range? */
1408 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1413 state |= RMAP_RIGHT_VALID;
1414 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1417 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1418 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1420 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1421 cur->bc_private.a.agno, RIGHT.rm_startblock,
1422 RIGHT.rm_blockcount, RIGHT.rm_owner,
1423 RIGHT.rm_offset, RIGHT.rm_flags);
1424 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1425 state |= RMAP_RIGHT_CONTIG;
1428 /* check that left + prev + right is not too long */
1429 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1430 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1431 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1432 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1433 (unsigned long)LEFT.rm_blockcount + len +
1434 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1435 state &= ~RMAP_RIGHT_CONTIG;
1437 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1440 * Switch out based on the FILLING and CONTIG state bits.
1442 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1443 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1444 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1445 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1447 * Setting all of a previous oldext extent to newext.
1448 * The left and right neighbors are both contiguous with new.
1450 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1451 RIGHT.rm_blockcount, RIGHT.rm_owner,
1452 RIGHT.rm_offset, RIGHT.rm_flags);
1455 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1456 PREV.rm_blockcount, PREV.rm_owner,
1457 PREV.rm_offset, PREV.rm_flags);
1461 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1462 NEW.rm_blockcount, NEW.rm_owner,
1463 NEW.rm_offset, NEW.rm_flags, &i);
1466 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1467 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1468 error = xfs_rmap_update(cur, &NEW);
1473 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1475 * Setting all of a previous oldext extent to newext.
1476 * The left neighbor is contiguous, the right is not.
1478 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1479 PREV.rm_blockcount, PREV.rm_owner,
1480 PREV.rm_offset, PREV.rm_flags);
1484 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1485 NEW.rm_blockcount, NEW.rm_owner,
1486 NEW.rm_offset, NEW.rm_flags, &i);
1489 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1490 NEW.rm_blockcount += PREV.rm_blockcount;
1491 error = xfs_rmap_update(cur, &NEW);
1496 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1498 * Setting all of a previous oldext extent to newext.
1499 * The right neighbor is contiguous, the left is not.
1501 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1502 RIGHT.rm_blockcount, RIGHT.rm_owner,
1503 RIGHT.rm_offset, RIGHT.rm_flags);
1507 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1508 NEW.rm_blockcount, NEW.rm_owner,
1509 NEW.rm_offset, NEW.rm_flags, &i);
1512 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1513 NEW.rm_blockcount += RIGHT.rm_blockcount;
1514 NEW.rm_flags = RIGHT.rm_flags;
1515 error = xfs_rmap_update(cur, &NEW);
1520 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1522 * Setting all of a previous oldext extent to newext.
1523 * Neither the left nor right neighbors are contiguous with
1527 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1528 NEW.rm_blockcount, NEW.rm_owner,
1529 NEW.rm_offset, NEW.rm_flags, &i);
1532 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1533 NEW.rm_flags = newext;
1534 error = xfs_rmap_update(cur, &NEW);
1539 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1541 * Setting the first part of a previous oldext extent to newext.
1542 * The left neighbor is contiguous.
1545 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1546 NEW.rm_blockcount, NEW.rm_owner,
1547 NEW.rm_offset, NEW.rm_flags);
1550 NEW.rm_offset += len;
1551 NEW.rm_startblock += len;
1552 NEW.rm_blockcount -= len;
1553 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1554 NEW.rm_blockcount, NEW.rm_owner,
1555 NEW.rm_offset, NEW.rm_flags);
1559 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1560 NEW.rm_blockcount, NEW.rm_owner,
1561 NEW.rm_offset, NEW.rm_flags, &i);
1564 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1565 NEW.rm_blockcount += len;
1566 error = xfs_rmap_update(cur, &NEW);
1571 case RMAP_LEFT_FILLING:
1573 * Setting the first part of a previous oldext extent to newext.
1574 * The left neighbor is not contiguous.
1577 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1578 NEW.rm_blockcount, NEW.rm_owner,
1579 NEW.rm_offset, NEW.rm_flags);
1582 NEW.rm_offset += len;
1583 NEW.rm_startblock += len;
1584 NEW.rm_blockcount -= len;
1585 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1586 NEW.rm_blockcount, NEW.rm_owner,
1587 NEW.rm_offset, NEW.rm_flags);
1590 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1595 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1597 * Setting the last part of a previous oldext extent to newext.
1598 * The right neighbor is contiguous with the new allocation.
1601 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1602 NEW.rm_blockcount, NEW.rm_owner,
1603 NEW.rm_offset, NEW.rm_flags, &i);
1606 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1607 NEW.rm_blockcount = offset - NEW.rm_offset;
1608 error = xfs_rmap_update(cur, &NEW);
1612 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1613 NEW.rm_blockcount, NEW.rm_owner,
1614 NEW.rm_offset, NEW.rm_flags);
1617 NEW.rm_offset = offset;
1618 NEW.rm_startblock = bno;
1619 NEW.rm_blockcount += len;
1620 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1621 NEW.rm_blockcount, NEW.rm_owner,
1622 NEW.rm_offset, NEW.rm_flags);
1627 case RMAP_RIGHT_FILLING:
1629 * Setting the last part of a previous oldext extent to newext.
1630 * The right neighbor is not contiguous.
1633 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1634 NEW.rm_blockcount, NEW.rm_owner,
1635 NEW.rm_offset, NEW.rm_flags, &i);
1638 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1639 NEW.rm_blockcount -= len;
1640 error = xfs_rmap_update(cur, &NEW);
1643 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1650 * Setting the middle part of a previous oldext extent to
1651 * newext. Contiguity is impossible here.
1652 * One extent becomes three extents.
1654 /* new right extent - oldext */
1655 NEW.rm_startblock = bno + len;
1656 NEW.rm_owner = owner;
1657 NEW.rm_offset = new_endoff;
1658 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1660 NEW.rm_flags = PREV.rm_flags;
1661 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1662 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1666 /* new left extent - oldext */
1668 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1669 NEW.rm_blockcount, NEW.rm_owner,
1670 NEW.rm_offset, NEW.rm_flags, &i);
1673 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1674 NEW.rm_blockcount = offset - NEW.rm_offset;
1675 error = xfs_rmap_update(cur, &NEW);
1678 /* new middle extent - newext */
1679 NEW.rm_startblock = bno;
1680 NEW.rm_blockcount = len;
1681 NEW.rm_owner = owner;
1682 NEW.rm_offset = offset;
1683 NEW.rm_flags = newext;
1684 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1685 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1691 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1692 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1693 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1694 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1695 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1696 case RMAP_LEFT_CONTIG:
1697 case RMAP_RIGHT_CONTIG:
1699 * These cases are all impossible.
1704 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1708 trace_xfs_rmap_convert_error(cur->bc_mp,
1709 cur->bc_private.a.agno, error, _RET_IP_);
1719 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1720 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1721 * that the prev/next records in the btree might belong to another owner.
1722 * Therefore we must use delete+insert to alter any of the key fields.
1724 * For every other situation there can only be one owner for a given extent,
1725 * so we can call the regular _free function.
1728 xfs_rmap_unmap_shared(
1729 struct xfs_btree_cur *cur,
1733 struct xfs_owner_info *oinfo)
1735 struct xfs_mount *mp = cur->bc_mp;
1736 struct xfs_rmap_irec ltrec;
1744 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1746 flags |= XFS_RMAP_UNWRITTEN;
1747 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
1751 * We should always have a left record because there's a static record
1752 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1753 * will not ever be removed from the tree.
1755 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1759 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1760 ltoff = ltrec.rm_offset;
1762 /* Make sure the extent we found covers the entire freeing range. */
1763 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
1764 ltrec.rm_startblock + ltrec.rm_blockcount >=
1765 bno + len, out_error);
1767 /* Make sure the owner matches what we expect to find in the tree. */
1768 XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner, out_error);
1770 /* Make sure the unwritten flag matches. */
1771 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
1772 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error);
1774 /* Check the offset. */
1775 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error);
1776 XFS_WANT_CORRUPTED_GOTO(mp, offset <= ltoff + ltrec.rm_blockcount,
1779 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
1780 /* Exact match, simply remove the record from rmap tree. */
1781 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1782 ltrec.rm_blockcount, ltrec.rm_owner,
1783 ltrec.rm_offset, ltrec.rm_flags);
1786 } else if (ltrec.rm_startblock == bno) {
1788 * Overlap left hand side of extent: move the start, trim the
1789 * length and update the current record.
1792 * Orig: |oooooooooooooooooooo|
1793 * Freeing: |fffffffff|
1794 * Result: |rrrrrrrrrr|
1798 /* Delete prev rmap. */
1799 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1800 ltrec.rm_blockcount, ltrec.rm_owner,
1801 ltrec.rm_offset, ltrec.rm_flags);
1805 /* Add an rmap at the new offset. */
1806 ltrec.rm_startblock += len;
1807 ltrec.rm_blockcount -= len;
1808 ltrec.rm_offset += len;
1809 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
1810 ltrec.rm_blockcount, ltrec.rm_owner,
1811 ltrec.rm_offset, ltrec.rm_flags);
1814 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
1816 * Overlap right hand side of extent: trim the length and
1817 * update the current record.
1820 * Orig: |oooooooooooooooooooo|
1821 * Freeing: |fffffffff|
1822 * Result: |rrrrrrrrrr|
1825 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1826 ltrec.rm_blockcount, ltrec.rm_owner,
1827 ltrec.rm_offset, ltrec.rm_flags, &i);
1830 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1831 ltrec.rm_blockcount -= len;
1832 error = xfs_rmap_update(cur, <rec);
1837 * Overlap middle of extent: trim the length of the existing
1838 * record to the length of the new left-extent size, increment
1839 * the insertion position so we can insert a new record
1840 * containing the remaining right-extent space.
1843 * Orig: |oooooooooooooooooooo|
1844 * Freeing: |fffffffff|
1845 * Result: |rrrrr| |rrrr|
1848 xfs_extlen_t orig_len = ltrec.rm_blockcount;
1850 /* Shrink the left side of the rmap */
1851 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1852 ltrec.rm_blockcount, ltrec.rm_owner,
1853 ltrec.rm_offset, ltrec.rm_flags, &i);
1856 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1857 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
1858 error = xfs_rmap_update(cur, <rec);
1862 /* Add an rmap at the new offset */
1863 error = xfs_rmap_insert(cur, bno + len,
1864 orig_len - len - ltrec.rm_blockcount,
1865 ltrec.rm_owner, offset + len,
1871 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
1875 trace_xfs_rmap_unmap_error(cur->bc_mp,
1876 cur->bc_private.a.agno, error, _RET_IP_);
1881 * Find an extent in the rmap btree and map it. For rmap extent types that
1882 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1883 * that the prev/next records in the btree might belong to another owner.
1884 * Therefore we must use delete+insert to alter any of the key fields.
1886 * For every other situation there can only be one owner for a given extent,
1887 * so we can call the regular _alloc function.
1890 xfs_rmap_map_shared(
1891 struct xfs_btree_cur *cur,
1895 struct xfs_owner_info *oinfo)
1897 struct xfs_mount *mp = cur->bc_mp;
1898 struct xfs_rmap_irec ltrec;
1899 struct xfs_rmap_irec gtrec;
1906 unsigned int flags = 0;
1908 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1910 flags |= XFS_RMAP_UNWRITTEN;
1911 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
1914 /* Is there a left record that abuts our range? */
1915 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
1920 !xfs_rmap_is_mergeable(<rec, owner, flags))
1923 /* Is there a right record that abuts our range? */
1924 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1929 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
1932 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
1933 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1934 cur->bc_private.a.agno, gtrec.rm_startblock,
1935 gtrec.rm_blockcount, gtrec.rm_owner,
1936 gtrec.rm_offset, gtrec.rm_flags);
1938 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
1943 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
1944 ltrec.rm_offset + ltrec.rm_blockcount == offset) {
1946 * Left edge contiguous, merge into left record.
1950 * adding: |aaaaaaaaa|
1951 * result: |rrrrrrrrrrrrrrrrrrr|
1954 ltrec.rm_blockcount += len;
1956 bno + len == gtrec.rm_startblock &&
1957 offset + len == gtrec.rm_offset) {
1959 * Right edge also contiguous, delete right record
1960 * and merge into left record.
1962 * ltbno ltlen gtbno gtlen
1963 * orig: |ooooooooo| |ooooooooo|
1964 * adding: |aaaaaaaaa|
1965 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1967 ltrec.rm_blockcount += gtrec.rm_blockcount;
1968 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
1969 gtrec.rm_blockcount, gtrec.rm_owner,
1970 gtrec.rm_offset, gtrec.rm_flags);
1975 /* Point the cursor back to the left record and update. */
1976 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1977 ltrec.rm_blockcount, ltrec.rm_owner,
1978 ltrec.rm_offset, ltrec.rm_flags, &i);
1981 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1983 error = xfs_rmap_update(cur, <rec);
1986 } else if (have_gt &&
1987 bno + len == gtrec.rm_startblock &&
1988 offset + len == gtrec.rm_offset) {
1990 * Right edge contiguous, merge into right record.
1994 * adding: |aaaaaaaaa|
1995 * Result: |rrrrrrrrrrrrrrrrrrr|
1998 /* Delete the old record. */
1999 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2000 gtrec.rm_blockcount, gtrec.rm_owner,
2001 gtrec.rm_offset, gtrec.rm_flags);
2005 /* Move the start and re-add it. */
2006 gtrec.rm_startblock = bno;
2007 gtrec.rm_blockcount += len;
2008 gtrec.rm_offset = offset;
2009 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2010 gtrec.rm_blockcount, gtrec.rm_owner,
2011 gtrec.rm_offset, gtrec.rm_flags);
2016 * No contiguous edge with identical owner, insert
2017 * new record at current cursor position.
2019 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2024 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
2028 trace_xfs_rmap_map_error(cur->bc_mp,
2029 cur->bc_private.a.agno, error, _RET_IP_);
2033 struct xfs_rmap_query_range_info {
2034 xfs_rmap_query_range_fn fn;
2038 /* Format btree record and pass to our callback. */
2040 xfs_rmap_query_range_helper(
2041 struct xfs_btree_cur *cur,
2042 union xfs_btree_rec *rec,
2045 struct xfs_rmap_query_range_info *query = priv;
2046 struct xfs_rmap_irec irec;
2049 error = xfs_rmap_btrec_to_irec(rec, &irec);
2052 return query->fn(cur, &irec, query->priv);
2055 /* Find all rmaps between two keys. */
2057 xfs_rmap_query_range(
2058 struct xfs_btree_cur *cur,
2059 struct xfs_rmap_irec *low_rec,
2060 struct xfs_rmap_irec *high_rec,
2061 xfs_rmap_query_range_fn fn,
2064 union xfs_btree_irec low_brec;
2065 union xfs_btree_irec high_brec;
2066 struct xfs_rmap_query_range_info query;
2068 low_brec.r = *low_rec;
2069 high_brec.r = *high_rec;
2072 return xfs_btree_query_range(cur, &low_brec, &high_brec,
2073 xfs_rmap_query_range_helper, &query);
2076 /* Find all rmaps. */
2079 struct xfs_btree_cur *cur,
2080 xfs_rmap_query_range_fn fn,
2083 struct xfs_rmap_query_range_info query;
2087 return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2090 /* Clean up after calling xfs_rmap_finish_one. */
2092 xfs_rmap_finish_one_cleanup(
2093 struct xfs_trans *tp,
2094 struct xfs_btree_cur *rcur,
2097 struct xfs_buf *agbp;
2101 agbp = rcur->bc_private.a.agbp;
2102 xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
2104 xfs_trans_brelse(tp, agbp);
2108 * Process one of the deferred rmap operations. We pass back the
2109 * btree cursor to maintain our lock on the rmapbt between calls.
2110 * This saves time and eliminates a buffer deadlock between the
2111 * superblock and the AGF because we'll always grab them in the same
2115 xfs_rmap_finish_one(
2116 struct xfs_trans *tp,
2117 enum xfs_rmap_intent_type type,
2120 xfs_fileoff_t startoff,
2121 xfs_fsblock_t startblock,
2122 xfs_filblks_t blockcount,
2124 struct xfs_btree_cur **pcur)
2126 struct xfs_mount *mp = tp->t_mountp;
2127 struct xfs_btree_cur *rcur;
2128 struct xfs_buf *agbp = NULL;
2130 xfs_agnumber_t agno;
2131 struct xfs_owner_info oinfo;
2135 agno = XFS_FSB_TO_AGNO(mp, startblock);
2136 ASSERT(agno != NULLAGNUMBER);
2137 bno = XFS_FSB_TO_AGBNO(mp, startblock);
2139 trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork,
2140 startoff, blockcount, state);
2142 if (XFS_TEST_ERROR(false, mp,
2143 XFS_ERRTAG_RMAP_FINISH_ONE))
2147 * If we haven't gotten a cursor or the cursor AG doesn't match
2148 * the startblock, get one now.
2151 if (rcur != NULL && rcur->bc_private.a.agno != agno) {
2152 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2158 * Refresh the freelist before we start changing the
2159 * rmapbt, because a shape change could cause us to
2162 error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
2166 return -EFSCORRUPTED;
2168 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
2176 xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2177 unwritten = state == XFS_EXT_UNWRITTEN;
2178 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2181 case XFS_RMAP_ALLOC:
2183 error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2185 case XFS_RMAP_MAP_SHARED:
2186 error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2190 case XFS_RMAP_UNMAP:
2191 error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2194 case XFS_RMAP_UNMAP_SHARED:
2195 error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2198 case XFS_RMAP_CONVERT:
2199 error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2202 case XFS_RMAP_CONVERT_SHARED:
2203 error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2204 !unwritten, &oinfo);
2208 error = -EFSCORRUPTED;
2213 xfs_trans_brelse(tp, agbp);
2219 * Don't defer an rmap if we aren't an rmap filesystem.
2222 xfs_rmap_update_is_needed(
2223 struct xfs_mount *mp,
2226 return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK;
2230 * Record a rmap intent; the list is kept sorted first by AG and then by
2235 struct xfs_mount *mp,
2236 struct xfs_defer_ops *dfops,
2237 enum xfs_rmap_intent_type type,
2240 struct xfs_bmbt_irec *bmap)
2242 struct xfs_rmap_intent *ri;
2244 trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, bmap->br_startblock),
2246 XFS_FSB_TO_AGBNO(mp, bmap->br_startblock),
2249 bmap->br_blockcount,
2252 ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_SLEEP | KM_NOFS);
2253 INIT_LIST_HEAD(&ri->ri_list);
2255 ri->ri_owner = owner;
2256 ri->ri_whichfork = whichfork;
2257 ri->ri_bmap = *bmap;
2259 xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
2263 /* Map an extent into a file. */
2265 xfs_rmap_map_extent(
2266 struct xfs_mount *mp,
2267 struct xfs_defer_ops *dfops,
2268 struct xfs_inode *ip,
2270 struct xfs_bmbt_irec *PREV)
2272 if (!xfs_rmap_update_is_needed(mp, whichfork))
2275 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2276 XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino,
2280 /* Unmap an extent out of a file. */
2282 xfs_rmap_unmap_extent(
2283 struct xfs_mount *mp,
2284 struct xfs_defer_ops *dfops,
2285 struct xfs_inode *ip,
2287 struct xfs_bmbt_irec *PREV)
2289 if (!xfs_rmap_update_is_needed(mp, whichfork))
2292 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2293 XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino,
2297 /* Convert a data fork extent from unwritten to real or vice versa. */
2299 xfs_rmap_convert_extent(
2300 struct xfs_mount *mp,
2301 struct xfs_defer_ops *dfops,
2302 struct xfs_inode *ip,
2304 struct xfs_bmbt_irec *PREV)
2306 if (!xfs_rmap_update_is_needed(mp, whichfork))
2309 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2310 XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino,
2314 /* Schedule the creation of an rmap for non-file data. */
2316 xfs_rmap_alloc_extent(
2317 struct xfs_mount *mp,
2318 struct xfs_defer_ops *dfops,
2319 xfs_agnumber_t agno,
2324 struct xfs_bmbt_irec bmap;
2326 if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
2329 bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
2330 bmap.br_blockcount = len;
2331 bmap.br_startoff = 0;
2332 bmap.br_state = XFS_EXT_NORM;
2334 return __xfs_rmap_add(mp, dfops, XFS_RMAP_ALLOC, owner,
2335 XFS_DATA_FORK, &bmap);
2338 /* Schedule the deletion of an rmap for non-file data. */
2340 xfs_rmap_free_extent(
2341 struct xfs_mount *mp,
2342 struct xfs_defer_ops *dfops,
2343 xfs_agnumber_t agno,
2348 struct xfs_bmbt_irec bmap;
2350 if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
2353 bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
2354 bmap.br_blockcount = len;
2355 bmap.br_startoff = 0;
2356 bmap.br_state = XFS_EXT_NORM;
2358 return __xfs_rmap_add(mp, dfops, XFS_RMAP_FREE, owner,
2359 XFS_DATA_FORK, &bmap);
2362 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2365 const struct xfs_rmap_irec *a,
2366 const struct xfs_rmap_irec *b)
2371 oa = xfs_rmap_irec_offset_pack(a);
2372 ob = xfs_rmap_irec_offset_pack(b);
2374 if (a->rm_startblock < b->rm_startblock)
2376 else if (a->rm_startblock > b->rm_startblock)
2378 else if (a->rm_owner < b->rm_owner)
2380 else if (a->rm_owner > b->rm_owner)
2390 /* Is there a record covering a given extent? */
2392 xfs_rmap_has_record(
2393 struct xfs_btree_cur *cur,
2398 union xfs_btree_irec low;
2399 union xfs_btree_irec high;
2401 memset(&low, 0, sizeof(low));
2402 low.r.rm_startblock = bno;
2403 memset(&high, 0xFF, sizeof(high));
2404 high.r.rm_startblock = bno + len - 1;
2406 return xfs_btree_has_record(cur, &low, &high, exists);
2410 * Is there a record for this owner completely covering a given physical
2411 * extent? If so, *has_rmap will be set to true. If there is no record
2412 * or the record only covers part of the range, we set *has_rmap to false.
2413 * This function doesn't perform range lookups or offset checks, so it is
2414 * not suitable for checking data fork blocks.
2417 xfs_rmap_record_exists(
2418 struct xfs_btree_cur *cur,
2421 struct xfs_owner_info *oinfo,
2428 struct xfs_rmap_irec irec;
2431 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2432 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
2433 (flags & XFS_RMAP_BMBT_BLOCK));
2435 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
2444 error = xfs_rmap_get_rec(cur, &irec, &has_record);
2452 *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
2453 irec.rm_startblock + irec.rm_blockcount >= bno + len);