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
18 #include "libxfs_priv.h"
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"
38 #include "xfs_inode.h"
41 * Lookup the first record less than or equal to [bno, len, owner, offset]
42 * in the btree given by cur.
46 struct xfs_btree_cur
*cur
,
54 cur
->bc_rec
.r
.rm_startblock
= bno
;
55 cur
->bc_rec
.r
.rm_blockcount
= len
;
56 cur
->bc_rec
.r
.rm_owner
= owner
;
57 cur
->bc_rec
.r
.rm_offset
= offset
;
58 cur
->bc_rec
.r
.rm_flags
= flags
;
59 return xfs_btree_lookup(cur
, XFS_LOOKUP_LE
, stat
);
63 * Lookup the record exactly matching [bno, len, owner, offset]
64 * in the btree given by cur.
68 struct xfs_btree_cur
*cur
,
76 cur
->bc_rec
.r
.rm_startblock
= bno
;
77 cur
->bc_rec
.r
.rm_blockcount
= len
;
78 cur
->bc_rec
.r
.rm_owner
= owner
;
79 cur
->bc_rec
.r
.rm_offset
= offset
;
80 cur
->bc_rec
.r
.rm_flags
= flags
;
81 return xfs_btree_lookup(cur
, XFS_LOOKUP_EQ
, stat
);
85 * Update the record referred to by cur to the value given
86 * by [bno, len, owner, offset].
87 * This either works (return 0) or gets an EFSCORRUPTED error.
91 struct xfs_btree_cur
*cur
,
92 struct xfs_rmap_irec
*irec
)
94 union xfs_btree_rec rec
;
97 trace_xfs_rmap_update(cur
->bc_mp
, cur
->bc_private
.a
.agno
,
98 irec
->rm_startblock
, irec
->rm_blockcount
,
99 irec
->rm_owner
, irec
->rm_offset
, irec
->rm_flags
);
101 rec
.rmap
.rm_startblock
= cpu_to_be32(irec
->rm_startblock
);
102 rec
.rmap
.rm_blockcount
= cpu_to_be32(irec
->rm_blockcount
);
103 rec
.rmap
.rm_owner
= cpu_to_be64(irec
->rm_owner
);
104 rec
.rmap
.rm_offset
= cpu_to_be64(
105 xfs_rmap_irec_offset_pack(irec
));
106 error
= xfs_btree_update(cur
, &rec
);
108 trace_xfs_rmap_update_error(cur
->bc_mp
,
109 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
115 struct xfs_btree_cur
*rcur
,
125 trace_xfs_rmap_insert(rcur
->bc_mp
, rcur
->bc_private
.a
.agno
, agbno
,
126 len
, owner
, offset
, flags
);
128 error
= xfs_rmap_lookup_eq(rcur
, agbno
, len
, owner
, offset
, flags
, &i
);
131 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 0, done
);
133 rcur
->bc_rec
.r
.rm_startblock
= agbno
;
134 rcur
->bc_rec
.r
.rm_blockcount
= len
;
135 rcur
->bc_rec
.r
.rm_owner
= owner
;
136 rcur
->bc_rec
.r
.rm_offset
= offset
;
137 rcur
->bc_rec
.r
.rm_flags
= flags
;
138 error
= xfs_btree_insert(rcur
, &i
);
141 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 1, done
);
144 trace_xfs_rmap_insert_error(rcur
->bc_mp
,
145 rcur
->bc_private
.a
.agno
, error
, _RET_IP_
);
151 struct xfs_btree_cur
*rcur
,
161 trace_xfs_rmap_delete(rcur
->bc_mp
, rcur
->bc_private
.a
.agno
, agbno
,
162 len
, owner
, offset
, flags
);
164 error
= xfs_rmap_lookup_eq(rcur
, agbno
, len
, owner
, offset
, flags
, &i
);
167 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 1, done
);
169 error
= xfs_btree_delete(rcur
, &i
);
172 XFS_WANT_CORRUPTED_GOTO(rcur
->bc_mp
, i
== 1, done
);
175 trace_xfs_rmap_delete_error(rcur
->bc_mp
,
176 rcur
->bc_private
.a
.agno
, error
, _RET_IP_
);
181 xfs_rmap_btrec_to_irec(
182 union xfs_btree_rec
*rec
,
183 struct xfs_rmap_irec
*irec
)
186 irec
->rm_startblock
= be32_to_cpu(rec
->rmap
.rm_startblock
);
187 irec
->rm_blockcount
= be32_to_cpu(rec
->rmap
.rm_blockcount
);
188 irec
->rm_owner
= be64_to_cpu(rec
->rmap
.rm_owner
);
189 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec
->rmap
.rm_offset
),
194 * Get the data from the pointed-to record.
198 struct xfs_btree_cur
*cur
,
199 struct xfs_rmap_irec
*irec
,
202 union xfs_btree_rec
*rec
;
205 error
= xfs_btree_get_rec(cur
, &rec
, stat
);
209 return xfs_rmap_btrec_to_irec(rec
, irec
);
212 struct xfs_find_left_neighbor_info
{
213 struct xfs_rmap_irec high
;
214 struct xfs_rmap_irec
*irec
;
218 /* For each rmap given, figure out if it matches the key we want. */
220 xfs_rmap_find_left_neighbor_helper(
221 struct xfs_btree_cur
*cur
,
222 struct xfs_rmap_irec
*rec
,
225 struct xfs_find_left_neighbor_info
*info
= priv
;
227 trace_xfs_rmap_find_left_neighbor_candidate(cur
->bc_mp
,
228 cur
->bc_private
.a
.agno
, rec
->rm_startblock
,
229 rec
->rm_blockcount
, rec
->rm_owner
, rec
->rm_offset
,
232 if (rec
->rm_owner
!= info
->high
.rm_owner
)
233 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
234 if (!XFS_RMAP_NON_INODE_OWNER(rec
->rm_owner
) &&
235 !(rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
) &&
236 rec
->rm_offset
+ rec
->rm_blockcount
- 1 != info
->high
.rm_offset
)
237 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
241 return XFS_BTREE_QUERY_RANGE_ABORT
;
245 * Find the record to the left of the given extent, being careful only to
246 * return a match with the same owner and adjacent physical and logical
250 xfs_rmap_find_left_neighbor(
251 struct xfs_btree_cur
*cur
,
256 struct xfs_rmap_irec
*irec
,
259 struct xfs_find_left_neighbor_info info
;
265 info
.high
.rm_startblock
= bno
- 1;
266 info
.high
.rm_owner
= owner
;
267 if (!XFS_RMAP_NON_INODE_OWNER(owner
) &&
268 !(flags
& XFS_RMAP_BMBT_BLOCK
)) {
271 info
.high
.rm_offset
= offset
- 1;
273 info
.high
.rm_offset
= 0;
274 info
.high
.rm_flags
= flags
;
275 info
.high
.rm_blockcount
= 0;
279 trace_xfs_rmap_find_left_neighbor_query(cur
->bc_mp
,
280 cur
->bc_private
.a
.agno
, bno
, 0, owner
, offset
, flags
);
282 error
= xfs_rmap_query_range(cur
, &info
.high
, &info
.high
,
283 xfs_rmap_find_left_neighbor_helper
, &info
);
284 if (error
== XFS_BTREE_QUERY_RANGE_ABORT
)
287 trace_xfs_rmap_find_left_neighbor_result(cur
->bc_mp
,
288 cur
->bc_private
.a
.agno
, irec
->rm_startblock
,
289 irec
->rm_blockcount
, irec
->rm_owner
,
290 irec
->rm_offset
, irec
->rm_flags
);
294 /* For each rmap given, figure out if it matches the key we want. */
296 xfs_rmap_lookup_le_range_helper(
297 struct xfs_btree_cur
*cur
,
298 struct xfs_rmap_irec
*rec
,
301 struct xfs_find_left_neighbor_info
*info
= priv
;
303 trace_xfs_rmap_lookup_le_range_candidate(cur
->bc_mp
,
304 cur
->bc_private
.a
.agno
, rec
->rm_startblock
,
305 rec
->rm_blockcount
, rec
->rm_owner
, rec
->rm_offset
,
308 if (rec
->rm_owner
!= info
->high
.rm_owner
)
309 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
310 if (!XFS_RMAP_NON_INODE_OWNER(rec
->rm_owner
) &&
311 !(rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
) &&
312 (rec
->rm_offset
> info
->high
.rm_offset
||
313 rec
->rm_offset
+ rec
->rm_blockcount
<= info
->high
.rm_offset
))
314 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
318 return XFS_BTREE_QUERY_RANGE_ABORT
;
322 * Find the record to the left of the given extent, being careful only to
323 * return a match with the same owner and overlapping physical and logical
324 * block ranges. This is the overlapping-interval version of
325 * xfs_rmap_lookup_le.
328 xfs_rmap_lookup_le_range(
329 struct xfs_btree_cur
*cur
,
334 struct xfs_rmap_irec
*irec
,
337 struct xfs_find_left_neighbor_info info
;
340 info
.high
.rm_startblock
= bno
;
341 info
.high
.rm_owner
= owner
;
342 if (!XFS_RMAP_NON_INODE_OWNER(owner
) && !(flags
& XFS_RMAP_BMBT_BLOCK
))
343 info
.high
.rm_offset
= offset
;
345 info
.high
.rm_offset
= 0;
346 info
.high
.rm_flags
= flags
;
347 info
.high
.rm_blockcount
= 0;
352 trace_xfs_rmap_lookup_le_range(cur
->bc_mp
,
353 cur
->bc_private
.a
.agno
, bno
, 0, owner
, offset
, flags
);
354 error
= xfs_rmap_query_range(cur
, &info
.high
, &info
.high
,
355 xfs_rmap_lookup_le_range_helper
, &info
);
356 if (error
== XFS_BTREE_QUERY_RANGE_ABORT
)
359 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
360 cur
->bc_private
.a
.agno
, irec
->rm_startblock
,
361 irec
->rm_blockcount
, irec
->rm_owner
,
362 irec
->rm_offset
, irec
->rm_flags
);
367 * Find the extent in the rmap btree and remove it.
369 * The record we find should always be an exact match for the extent that we're
370 * looking for, since we insert them into the btree without modification.
372 * Special Case #1: when growing the filesystem, we "free" an extent when
373 * growing the last AG. This extent is new space and so it is not tracked as
374 * used space in the btree. The growfs code will pass in an owner of
375 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
376 * extent. We verify that - the extent lookup result in a record that does not
379 * Special Case #2: EFIs do not record the owner of the extent, so when
380 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
381 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
382 * corruption checks during log recovery.
386 struct xfs_btree_cur
*cur
,
390 struct xfs_owner_info
*oinfo
)
392 struct xfs_mount
*mp
= cur
->bc_mp
;
393 struct xfs_rmap_irec ltrec
;
402 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
403 ignore_off
= XFS_RMAP_NON_INODE_OWNER(owner
) ||
404 (flags
& XFS_RMAP_BMBT_BLOCK
);
406 flags
|= XFS_RMAP_UNWRITTEN
;
407 trace_xfs_rmap_unmap(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
411 * We should always have a left record because there's a static record
412 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
413 * will not ever be removed from the tree.
415 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
, &i
);
418 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
420 error
= xfs_rmap_get_rec(cur
, <rec
, &i
);
423 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
424 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
425 cur
->bc_private
.a
.agno
, ltrec
.rm_startblock
,
426 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
427 ltrec
.rm_offset
, ltrec
.rm_flags
);
428 ltoff
= ltrec
.rm_offset
;
431 * For growfs, the incoming extent must be beyond the left record we
432 * just found as it is new space and won't be used by anyone. This is
433 * just a corruption check as we don't actually do anything with this
434 * extent. Note that we need to use >= instead of > because it might
435 * be the case that the "left" extent goes all the way to EOFS.
437 if (owner
== XFS_RMAP_OWN_NULL
) {
438 XFS_WANT_CORRUPTED_GOTO(mp
, bno
>= ltrec
.rm_startblock
+
439 ltrec
.rm_blockcount
, out_error
);
443 /* Make sure the unwritten flag matches. */
444 XFS_WANT_CORRUPTED_GOTO(mp
, (flags
& XFS_RMAP_UNWRITTEN
) ==
445 (ltrec
.rm_flags
& XFS_RMAP_UNWRITTEN
), out_error
);
447 /* Make sure the extent we found covers the entire freeing range. */
448 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_startblock
<= bno
&&
449 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
>=
450 bno
+ len
, out_error
);
452 /* Make sure the owner matches what we expect to find in the tree. */
453 XFS_WANT_CORRUPTED_GOTO(mp
, owner
== ltrec
.rm_owner
||
454 XFS_RMAP_NON_INODE_OWNER(owner
), out_error
);
456 /* Check the offset, if necessary. */
457 if (!XFS_RMAP_NON_INODE_OWNER(owner
)) {
458 if (flags
& XFS_RMAP_BMBT_BLOCK
) {
459 XFS_WANT_CORRUPTED_GOTO(mp
,
460 ltrec
.rm_flags
& XFS_RMAP_BMBT_BLOCK
,
463 XFS_WANT_CORRUPTED_GOTO(mp
,
464 ltrec
.rm_offset
<= offset
, out_error
);
465 XFS_WANT_CORRUPTED_GOTO(mp
,
466 ltoff
+ ltrec
.rm_blockcount
>= offset
+ len
,
471 if (ltrec
.rm_startblock
== bno
&& ltrec
.rm_blockcount
== len
) {
472 /* exact match, simply remove the record from rmap tree */
473 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
474 ltrec
.rm_startblock
, ltrec
.rm_blockcount
,
475 ltrec
.rm_owner
, ltrec
.rm_offset
,
477 error
= xfs_btree_delete(cur
, &i
);
480 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
481 } else if (ltrec
.rm_startblock
== bno
) {
483 * overlap left hand side of extent: move the start, trim the
484 * length and update the current record.
487 * Orig: |oooooooooooooooooooo|
488 * Freeing: |fffffffff|
489 * Result: |rrrrrrrrrr|
492 ltrec
.rm_startblock
+= len
;
493 ltrec
.rm_blockcount
-= len
;
495 ltrec
.rm_offset
+= len
;
496 error
= xfs_rmap_update(cur
, <rec
);
499 } else if (ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
+ len
) {
501 * overlap right hand side of extent: trim the length and update
502 * the current record.
505 * Orig: |oooooooooooooooooooo|
506 * Freeing: |fffffffff|
507 * Result: |rrrrrrrrrr|
510 ltrec
.rm_blockcount
-= len
;
511 error
= xfs_rmap_update(cur
, <rec
);
517 * overlap middle of extent: trim the length of the existing
518 * record to the length of the new left-extent size, increment
519 * the insertion position so we can insert a new record
520 * containing the remaining right-extent space.
523 * Orig: |oooooooooooooooooooo|
524 * Freeing: |fffffffff|
525 * Result: |rrrrr| |rrrr|
528 xfs_extlen_t orig_len
= ltrec
.rm_blockcount
;
530 ltrec
.rm_blockcount
= bno
- ltrec
.rm_startblock
;
531 error
= xfs_rmap_update(cur
, <rec
);
535 error
= xfs_btree_increment(cur
, 0, &i
);
539 cur
->bc_rec
.r
.rm_startblock
= bno
+ len
;
540 cur
->bc_rec
.r
.rm_blockcount
= orig_len
- len
-
542 cur
->bc_rec
.r
.rm_owner
= ltrec
.rm_owner
;
544 cur
->bc_rec
.r
.rm_offset
= 0;
546 cur
->bc_rec
.r
.rm_offset
= offset
+ len
;
547 cur
->bc_rec
.r
.rm_flags
= flags
;
548 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
,
549 cur
->bc_rec
.r
.rm_startblock
,
550 cur
->bc_rec
.r
.rm_blockcount
,
551 cur
->bc_rec
.r
.rm_owner
,
552 cur
->bc_rec
.r
.rm_offset
,
553 cur
->bc_rec
.r
.rm_flags
);
554 error
= xfs_btree_insert(cur
, &i
);
560 trace_xfs_rmap_unmap_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
564 trace_xfs_rmap_unmap_error(mp
, cur
->bc_private
.a
.agno
,
570 * Remove a reference to an extent in the rmap btree.
574 struct xfs_trans
*tp
,
575 struct xfs_buf
*agbp
,
579 struct xfs_owner_info
*oinfo
)
581 struct xfs_mount
*mp
= tp
->t_mountp
;
582 struct xfs_btree_cur
*cur
;
585 if (!xfs_sb_version_hasrmapbt(&mp
->m_sb
))
588 cur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
590 error
= xfs_rmap_unmap(cur
, bno
, len
, false, oinfo
);
594 xfs_btree_del_cursor(cur
, XFS_BTREE_NOERROR
);
598 xfs_btree_del_cursor(cur
, XFS_BTREE_ERROR
);
603 * A mergeable rmap must have the same owner and the same values for
604 * the unwritten, attr_fork, and bmbt flags. The startblock and
605 * offset are checked separately.
608 xfs_rmap_is_mergeable(
609 struct xfs_rmap_irec
*irec
,
613 if (irec
->rm_owner
== XFS_RMAP_OWN_NULL
)
615 if (irec
->rm_owner
!= owner
)
617 if ((flags
& XFS_RMAP_UNWRITTEN
) ^
618 (irec
->rm_flags
& XFS_RMAP_UNWRITTEN
))
620 if ((flags
& XFS_RMAP_ATTR_FORK
) ^
621 (irec
->rm_flags
& XFS_RMAP_ATTR_FORK
))
623 if ((flags
& XFS_RMAP_BMBT_BLOCK
) ^
624 (irec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
))
630 * When we allocate a new block, the first thing we do is add a reference to
631 * the extent in the rmap btree. This takes the form of a [agbno, length,
632 * owner, offset] record. Flags are encoded in the high bits of the offset
637 struct xfs_btree_cur
*cur
,
641 struct xfs_owner_info
*oinfo
)
643 struct xfs_mount
*mp
= cur
->bc_mp
;
644 struct xfs_rmap_irec ltrec
;
645 struct xfs_rmap_irec gtrec
;
652 unsigned int flags
= 0;
655 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
657 ignore_off
= XFS_RMAP_NON_INODE_OWNER(owner
) ||
658 (flags
& XFS_RMAP_BMBT_BLOCK
);
660 flags
|= XFS_RMAP_UNWRITTEN
;
661 trace_xfs_rmap_map(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
665 * For the initial lookup, look for an exact match or the left-adjacent
666 * record for our insertion point. This will also give us the record for
667 * start block contiguity tests.
669 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, flags
,
673 XFS_WANT_CORRUPTED_GOTO(mp
, have_lt
== 1, out_error
);
675 error
= xfs_rmap_get_rec(cur
, <rec
, &have_lt
);
678 XFS_WANT_CORRUPTED_GOTO(mp
, have_lt
== 1, out_error
);
679 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
680 cur
->bc_private
.a
.agno
, ltrec
.rm_startblock
,
681 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
682 ltrec
.rm_offset
, ltrec
.rm_flags
);
684 if (!xfs_rmap_is_mergeable(<rec
, owner
, flags
))
687 XFS_WANT_CORRUPTED_GOTO(mp
,
689 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
<= bno
, out_error
);
692 * Increment the cursor to see if we have a right-adjacent record to our
693 * insertion point. This will give us the record for end block
696 error
= xfs_btree_increment(cur
, 0, &have_gt
);
700 error
= xfs_rmap_get_rec(cur
, >rec
, &have_gt
);
703 XFS_WANT_CORRUPTED_GOTO(mp
, have_gt
== 1, out_error
);
704 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= gtrec
.rm_startblock
,
706 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
707 cur
->bc_private
.a
.agno
, gtrec
.rm_startblock
,
708 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
709 gtrec
.rm_offset
, gtrec
.rm_flags
);
710 if (!xfs_rmap_is_mergeable(>rec
, owner
, flags
))
715 * Note: cursor currently points one record to the right of ltrec, even
716 * if there is no record in the tree to the right.
719 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
&&
720 (ignore_off
|| ltrec
.rm_offset
+ ltrec
.rm_blockcount
== offset
)) {
722 * left edge contiguous, merge into left record.
726 * adding: |aaaaaaaaa|
727 * result: |rrrrrrrrrrrrrrrrrrr|
730 ltrec
.rm_blockcount
+= len
;
732 bno
+ len
== gtrec
.rm_startblock
&&
733 (ignore_off
|| offset
+ len
== gtrec
.rm_offset
) &&
734 (unsigned long)ltrec
.rm_blockcount
+ len
+
735 gtrec
.rm_blockcount
<= XFS_RMAP_LEN_MAX
) {
737 * right edge also contiguous, delete right record
738 * and merge into left record.
740 * ltbno ltlen gtbno gtlen
741 * orig: |ooooooooo| |ooooooooo|
742 * adding: |aaaaaaaaa|
743 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
745 ltrec
.rm_blockcount
+= gtrec
.rm_blockcount
;
746 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
752 error
= xfs_btree_delete(cur
, &i
);
755 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
758 /* point the cursor back to the left record and update */
759 error
= xfs_btree_decrement(cur
, 0, &have_gt
);
762 error
= xfs_rmap_update(cur
, <rec
);
765 } else if (have_gt
&&
766 bno
+ len
== gtrec
.rm_startblock
&&
767 (ignore_off
|| offset
+ len
== gtrec
.rm_offset
)) {
769 * right edge contiguous, merge into right record.
773 * adding: |aaaaaaaaa|
774 * Result: |rrrrrrrrrrrrrrrrrrr|
777 gtrec
.rm_startblock
= bno
;
778 gtrec
.rm_blockcount
+= len
;
780 gtrec
.rm_offset
= offset
;
781 error
= xfs_rmap_update(cur
, >rec
);
786 * no contiguous edge with identical owner, insert
787 * new record at current cursor position.
789 cur
->bc_rec
.r
.rm_startblock
= bno
;
790 cur
->bc_rec
.r
.rm_blockcount
= len
;
791 cur
->bc_rec
.r
.rm_owner
= owner
;
792 cur
->bc_rec
.r
.rm_offset
= offset
;
793 cur
->bc_rec
.r
.rm_flags
= flags
;
794 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
795 owner
, offset
, flags
);
796 error
= xfs_btree_insert(cur
, &i
);
799 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
802 trace_xfs_rmap_map_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
806 trace_xfs_rmap_map_error(mp
, cur
->bc_private
.a
.agno
,
812 * Add a reference to an extent in the rmap btree.
816 struct xfs_trans
*tp
,
817 struct xfs_buf
*agbp
,
821 struct xfs_owner_info
*oinfo
)
823 struct xfs_mount
*mp
= tp
->t_mountp
;
824 struct xfs_btree_cur
*cur
;
827 if (!xfs_sb_version_hasrmapbt(&mp
->m_sb
))
830 cur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
831 error
= xfs_rmap_map(cur
, bno
, len
, false, oinfo
);
835 xfs_btree_del_cursor(cur
, XFS_BTREE_NOERROR
);
839 xfs_btree_del_cursor(cur
, XFS_BTREE_ERROR
);
843 #define RMAP_LEFT_CONTIG (1 << 0)
844 #define RMAP_RIGHT_CONTIG (1 << 1)
845 #define RMAP_LEFT_FILLING (1 << 2)
846 #define RMAP_RIGHT_FILLING (1 << 3)
847 #define RMAP_LEFT_VALID (1 << 6)
848 #define RMAP_RIGHT_VALID (1 << 7)
856 * Convert an unwritten extent to a real extent or vice versa.
857 * Does not handle overlapping extents.
861 struct xfs_btree_cur
*cur
,
865 struct xfs_owner_info
*oinfo
)
867 struct xfs_mount
*mp
= cur
->bc_mp
;
868 struct xfs_rmap_irec r
[4]; /* neighbor extent entries */
869 /* left is 0, right is 1, prev is 2 */
876 unsigned int flags
= 0;
881 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
882 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner
) ||
883 (flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
))));
884 oldext
= unwritten
? XFS_RMAP_UNWRITTEN
: 0;
885 new_endoff
= offset
+ len
;
886 trace_xfs_rmap_convert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
890 * For the initial lookup, look for an exact match or the left-adjacent
891 * record for our insertion point. This will also give us the record for
892 * start block contiguity tests.
894 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, oldext
, &i
);
897 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
899 error
= xfs_rmap_get_rec(cur
, &PREV
, &i
);
902 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
903 trace_xfs_rmap_lookup_le_range_result(cur
->bc_mp
,
904 cur
->bc_private
.a
.agno
, PREV
.rm_startblock
,
905 PREV
.rm_blockcount
, PREV
.rm_owner
,
906 PREV
.rm_offset
, PREV
.rm_flags
);
908 ASSERT(PREV
.rm_offset
<= offset
);
909 ASSERT(PREV
.rm_offset
+ PREV
.rm_blockcount
>= new_endoff
);
910 ASSERT((PREV
.rm_flags
& XFS_RMAP_UNWRITTEN
) == oldext
);
911 newext
= ~oldext
& XFS_RMAP_UNWRITTEN
;
914 * Set flags determining what part of the previous oldext allocation
915 * extent is being replaced by a newext allocation.
917 if (PREV
.rm_offset
== offset
)
918 state
|= RMAP_LEFT_FILLING
;
919 if (PREV
.rm_offset
+ PREV
.rm_blockcount
== new_endoff
)
920 state
|= RMAP_RIGHT_FILLING
;
923 * Decrement the cursor to see if we have a left-adjacent record to our
924 * insertion point. This will give us the record for end block
927 error
= xfs_btree_decrement(cur
, 0, &i
);
931 state
|= RMAP_LEFT_VALID
;
932 error
= xfs_rmap_get_rec(cur
, &LEFT
, &i
);
935 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
936 XFS_WANT_CORRUPTED_GOTO(mp
,
937 LEFT
.rm_startblock
+ LEFT
.rm_blockcount
<= bno
,
939 trace_xfs_rmap_find_left_neighbor_result(cur
->bc_mp
,
940 cur
->bc_private
.a
.agno
, LEFT
.rm_startblock
,
941 LEFT
.rm_blockcount
, LEFT
.rm_owner
,
942 LEFT
.rm_offset
, LEFT
.rm_flags
);
943 if (LEFT
.rm_startblock
+ LEFT
.rm_blockcount
== bno
&&
944 LEFT
.rm_offset
+ LEFT
.rm_blockcount
== offset
&&
945 xfs_rmap_is_mergeable(&LEFT
, owner
, newext
))
946 state
|= RMAP_LEFT_CONTIG
;
950 * Increment the cursor to see if we have a right-adjacent record to our
951 * insertion point. This will give us the record for end block
954 error
= xfs_btree_increment(cur
, 0, &i
);
957 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
958 error
= xfs_btree_increment(cur
, 0, &i
);
962 state
|= RMAP_RIGHT_VALID
;
963 error
= xfs_rmap_get_rec(cur
, &RIGHT
, &i
);
966 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
967 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= RIGHT
.rm_startblock
,
969 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
970 cur
->bc_private
.a
.agno
, RIGHT
.rm_startblock
,
971 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
972 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
973 if (bno
+ len
== RIGHT
.rm_startblock
&&
974 offset
+ len
== RIGHT
.rm_offset
&&
975 xfs_rmap_is_mergeable(&RIGHT
, owner
, newext
))
976 state
|= RMAP_RIGHT_CONTIG
;
979 /* check that left + prev + right is not too long */
980 if ((state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
981 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) ==
982 (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
983 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
) &&
984 (unsigned long)LEFT
.rm_blockcount
+ len
+
985 RIGHT
.rm_blockcount
> XFS_RMAP_LEN_MAX
)
986 state
&= ~RMAP_RIGHT_CONTIG
;
988 trace_xfs_rmap_convert_state(mp
, cur
->bc_private
.a
.agno
, state
,
991 /* reset the cursor back to PREV */
992 error
= xfs_rmap_lookup_le(cur
, bno
, len
, owner
, offset
, oldext
, &i
);
995 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
998 * Switch out based on the FILLING and CONTIG state bits.
1000 switch (state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1001 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) {
1002 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1003 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1005 * Setting all of a previous oldext extent to newext.
1006 * The left and right neighbors are both contiguous with new.
1008 error
= xfs_btree_increment(cur
, 0, &i
);
1011 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1012 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1013 RIGHT
.rm_startblock
, RIGHT
.rm_blockcount
,
1014 RIGHT
.rm_owner
, RIGHT
.rm_offset
,
1016 error
= xfs_btree_delete(cur
, &i
);
1019 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1020 error
= xfs_btree_decrement(cur
, 0, &i
);
1023 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1024 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1025 PREV
.rm_startblock
, PREV
.rm_blockcount
,
1026 PREV
.rm_owner
, PREV
.rm_offset
,
1028 error
= xfs_btree_delete(cur
, &i
);
1031 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1032 error
= xfs_btree_decrement(cur
, 0, &i
);
1035 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1037 NEW
.rm_blockcount
+= PREV
.rm_blockcount
+ RIGHT
.rm_blockcount
;
1038 error
= xfs_rmap_update(cur
, &NEW
);
1043 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1045 * Setting all of a previous oldext extent to newext.
1046 * The left neighbor is contiguous, the right is not.
1048 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1049 PREV
.rm_startblock
, PREV
.rm_blockcount
,
1050 PREV
.rm_owner
, PREV
.rm_offset
,
1052 error
= xfs_btree_delete(cur
, &i
);
1055 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1056 error
= xfs_btree_decrement(cur
, 0, &i
);
1059 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1061 NEW
.rm_blockcount
+= PREV
.rm_blockcount
;
1062 error
= xfs_rmap_update(cur
, &NEW
);
1067 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1069 * Setting all of a previous oldext extent to newext.
1070 * The right neighbor is contiguous, the left is not.
1072 error
= xfs_btree_increment(cur
, 0, &i
);
1075 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1076 trace_xfs_rmap_delete(mp
, cur
->bc_private
.a
.agno
,
1077 RIGHT
.rm_startblock
, RIGHT
.rm_blockcount
,
1078 RIGHT
.rm_owner
, RIGHT
.rm_offset
,
1080 error
= xfs_btree_delete(cur
, &i
);
1083 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1084 error
= xfs_btree_decrement(cur
, 0, &i
);
1087 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1089 NEW
.rm_blockcount
= len
+ RIGHT
.rm_blockcount
;
1090 NEW
.rm_flags
= newext
;
1091 error
= xfs_rmap_update(cur
, &NEW
);
1096 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
:
1098 * Setting all of a previous oldext extent to newext.
1099 * Neither the left nor right neighbors are contiguous with
1103 NEW
.rm_flags
= newext
;
1104 error
= xfs_rmap_update(cur
, &NEW
);
1109 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
:
1111 * Setting the first part of a previous oldext extent to newext.
1112 * The left neighbor is contiguous.
1115 NEW
.rm_offset
+= len
;
1116 NEW
.rm_startblock
+= len
;
1117 NEW
.rm_blockcount
-= len
;
1118 error
= xfs_rmap_update(cur
, &NEW
);
1121 error
= xfs_btree_decrement(cur
, 0, &i
);
1125 NEW
.rm_blockcount
+= len
;
1126 error
= xfs_rmap_update(cur
, &NEW
);
1131 case RMAP_LEFT_FILLING
:
1133 * Setting the first part of a previous oldext extent to newext.
1134 * The left neighbor is not contiguous.
1137 NEW
.rm_startblock
+= len
;
1138 NEW
.rm_offset
+= len
;
1139 NEW
.rm_blockcount
-= len
;
1140 error
= xfs_rmap_update(cur
, &NEW
);
1143 NEW
.rm_startblock
= bno
;
1144 NEW
.rm_owner
= owner
;
1145 NEW
.rm_offset
= offset
;
1146 NEW
.rm_blockcount
= len
;
1147 NEW
.rm_flags
= newext
;
1148 cur
->bc_rec
.r
= NEW
;
1149 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
,
1150 len
, owner
, offset
, newext
);
1151 error
= xfs_btree_insert(cur
, &i
);
1154 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1157 case RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1159 * Setting the last part of a previous oldext extent to newext.
1160 * The right neighbor is contiguous with the new allocation.
1163 NEW
.rm_blockcount
-= len
;
1164 error
= xfs_rmap_update(cur
, &NEW
);
1167 error
= xfs_btree_increment(cur
, 0, &i
);
1171 NEW
.rm_offset
= offset
;
1172 NEW
.rm_startblock
= bno
;
1173 NEW
.rm_blockcount
+= len
;
1174 error
= xfs_rmap_update(cur
, &NEW
);
1179 case RMAP_RIGHT_FILLING
:
1181 * Setting the last part of a previous oldext extent to newext.
1182 * The right neighbor is not contiguous.
1185 NEW
.rm_blockcount
-= len
;
1186 error
= xfs_rmap_update(cur
, &NEW
);
1189 error
= xfs_rmap_lookup_eq(cur
, bno
, len
, owner
, offset
,
1193 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 0, done
);
1194 NEW
.rm_startblock
= bno
;
1195 NEW
.rm_owner
= owner
;
1196 NEW
.rm_offset
= offset
;
1197 NEW
.rm_blockcount
= len
;
1198 NEW
.rm_flags
= newext
;
1199 cur
->bc_rec
.r
= NEW
;
1200 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
,
1201 len
, owner
, offset
, newext
);
1202 error
= xfs_btree_insert(cur
, &i
);
1205 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1210 * Setting the middle part of a previous oldext extent to
1211 * newext. Contiguity is impossible here.
1212 * One extent becomes three extents.
1214 /* new right extent - oldext */
1215 NEW
.rm_startblock
= bno
+ len
;
1216 NEW
.rm_owner
= owner
;
1217 NEW
.rm_offset
= new_endoff
;
1218 NEW
.rm_blockcount
= PREV
.rm_offset
+ PREV
.rm_blockcount
-
1220 NEW
.rm_flags
= PREV
.rm_flags
;
1221 error
= xfs_rmap_update(cur
, &NEW
);
1224 /* new left extent - oldext */
1226 NEW
.rm_blockcount
= offset
- PREV
.rm_offset
;
1227 cur
->bc_rec
.r
= NEW
;
1228 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
,
1229 NEW
.rm_startblock
, NEW
.rm_blockcount
,
1230 NEW
.rm_owner
, NEW
.rm_offset
,
1232 error
= xfs_btree_insert(cur
, &i
);
1235 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1237 * Reset the cursor to the position of the new extent
1238 * we are about to insert as we can't trust it after
1239 * the previous insert.
1241 error
= xfs_rmap_lookup_eq(cur
, bno
, len
, owner
, offset
,
1245 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 0, done
);
1246 /* new middle extent - newext */
1247 cur
->bc_rec
.r
.rm_flags
&= ~XFS_RMAP_UNWRITTEN
;
1248 cur
->bc_rec
.r
.rm_flags
|= newext
;
1249 trace_xfs_rmap_insert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1250 owner
, offset
, newext
);
1251 error
= xfs_btree_insert(cur
, &i
);
1254 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1257 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1258 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1259 case RMAP_LEFT_FILLING
| RMAP_RIGHT_CONTIG
:
1260 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1261 case RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1262 case RMAP_LEFT_CONTIG
:
1263 case RMAP_RIGHT_CONTIG
:
1265 * These cases are all impossible.
1270 trace_xfs_rmap_convert_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1274 trace_xfs_rmap_convert_error(cur
->bc_mp
,
1275 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1280 * Convert an unwritten extent to a real extent or vice versa. If there is no
1281 * possibility of overlapping extents, delegate to the simpler convert
1285 xfs_rmap_convert_shared(
1286 struct xfs_btree_cur
*cur
,
1290 struct xfs_owner_info
*oinfo
)
1292 struct xfs_mount
*mp
= cur
->bc_mp
;
1293 struct xfs_rmap_irec r
[4]; /* neighbor extent entries */
1294 /* left is 0, right is 1, prev is 2 */
1298 uint64_t new_endoff
;
1299 unsigned int oldext
;
1300 unsigned int newext
;
1301 unsigned int flags
= 0;
1306 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1307 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner
) ||
1308 (flags
& (XFS_RMAP_ATTR_FORK
| XFS_RMAP_BMBT_BLOCK
))));
1309 oldext
= unwritten
? XFS_RMAP_UNWRITTEN
: 0;
1310 new_endoff
= offset
+ len
;
1311 trace_xfs_rmap_convert(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1315 * For the initial lookup, look for and exact match or the left-adjacent
1316 * record for our insertion point. This will also give us the record for
1317 * start block contiguity tests.
1319 error
= xfs_rmap_lookup_le_range(cur
, bno
, owner
, offset
, flags
,
1321 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1323 ASSERT(PREV
.rm_offset
<= offset
);
1324 ASSERT(PREV
.rm_offset
+ PREV
.rm_blockcount
>= new_endoff
);
1325 ASSERT((PREV
.rm_flags
& XFS_RMAP_UNWRITTEN
) == oldext
);
1326 newext
= ~oldext
& XFS_RMAP_UNWRITTEN
;
1329 * Set flags determining what part of the previous oldext allocation
1330 * extent is being replaced by a newext allocation.
1332 if (PREV
.rm_offset
== offset
)
1333 state
|= RMAP_LEFT_FILLING
;
1334 if (PREV
.rm_offset
+ PREV
.rm_blockcount
== new_endoff
)
1335 state
|= RMAP_RIGHT_FILLING
;
1337 /* Is there a left record that abuts our range? */
1338 error
= xfs_rmap_find_left_neighbor(cur
, bno
, owner
, offset
, newext
,
1343 state
|= RMAP_LEFT_VALID
;
1344 XFS_WANT_CORRUPTED_GOTO(mp
,
1345 LEFT
.rm_startblock
+ LEFT
.rm_blockcount
<= bno
,
1347 if (xfs_rmap_is_mergeable(&LEFT
, owner
, newext
))
1348 state
|= RMAP_LEFT_CONTIG
;
1351 /* Is there a right record that abuts our range? */
1352 error
= xfs_rmap_lookup_eq(cur
, bno
+ len
, len
, owner
, offset
+ len
,
1357 state
|= RMAP_RIGHT_VALID
;
1358 error
= xfs_rmap_get_rec(cur
, &RIGHT
, &i
);
1361 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1362 XFS_WANT_CORRUPTED_GOTO(mp
, bno
+ len
<= RIGHT
.rm_startblock
,
1364 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1365 cur
->bc_private
.a
.agno
, RIGHT
.rm_startblock
,
1366 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1367 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1368 if (xfs_rmap_is_mergeable(&RIGHT
, owner
, newext
))
1369 state
|= RMAP_RIGHT_CONTIG
;
1372 /* check that left + prev + right is not too long */
1373 if ((state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1374 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) ==
1375 (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1376 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
) &&
1377 (unsigned long)LEFT
.rm_blockcount
+ len
+
1378 RIGHT
.rm_blockcount
> XFS_RMAP_LEN_MAX
)
1379 state
&= ~RMAP_RIGHT_CONTIG
;
1381 trace_xfs_rmap_convert_state(mp
, cur
->bc_private
.a
.agno
, state
,
1384 * Switch out based on the FILLING and CONTIG state bits.
1386 switch (state
& (RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1387 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
)) {
1388 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
|
1389 RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1391 * Setting all of a previous oldext extent to newext.
1392 * The left and right neighbors are both contiguous with new.
1394 error
= xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1395 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1396 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1399 error
= xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1400 PREV
.rm_blockcount
, PREV
.rm_owner
,
1401 PREV
.rm_offset
, PREV
.rm_flags
);
1405 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1406 NEW
.rm_blockcount
, NEW
.rm_owner
,
1407 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1410 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1411 NEW
.rm_blockcount
+= PREV
.rm_blockcount
+ RIGHT
.rm_blockcount
;
1412 error
= xfs_rmap_update(cur
, &NEW
);
1417 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1419 * Setting all of a previous oldext extent to newext.
1420 * The left neighbor is contiguous, the right is not.
1422 error
= xfs_rmap_delete(cur
, PREV
.rm_startblock
,
1423 PREV
.rm_blockcount
, PREV
.rm_owner
,
1424 PREV
.rm_offset
, PREV
.rm_flags
);
1428 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1429 NEW
.rm_blockcount
, NEW
.rm_owner
,
1430 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1433 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1434 NEW
.rm_blockcount
+= PREV
.rm_blockcount
;
1435 error
= xfs_rmap_update(cur
, &NEW
);
1440 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1442 * Setting all of a previous oldext extent to newext.
1443 * The right neighbor is contiguous, the left is not.
1445 error
= xfs_rmap_delete(cur
, RIGHT
.rm_startblock
,
1446 RIGHT
.rm_blockcount
, RIGHT
.rm_owner
,
1447 RIGHT
.rm_offset
, RIGHT
.rm_flags
);
1451 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1452 NEW
.rm_blockcount
, NEW
.rm_owner
,
1453 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1456 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1457 NEW
.rm_blockcount
+= RIGHT
.rm_blockcount
;
1458 NEW
.rm_flags
= RIGHT
.rm_flags
;
1459 error
= xfs_rmap_update(cur
, &NEW
);
1464 case RMAP_LEFT_FILLING
| RMAP_RIGHT_FILLING
:
1466 * Setting all of a previous oldext extent to newext.
1467 * Neither the left nor right neighbors are contiguous with
1471 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1472 NEW
.rm_blockcount
, NEW
.rm_owner
,
1473 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1476 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1477 NEW
.rm_flags
= newext
;
1478 error
= xfs_rmap_update(cur
, &NEW
);
1483 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
:
1485 * Setting the first part of a previous oldext extent to newext.
1486 * The left neighbor is contiguous.
1489 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1490 NEW
.rm_blockcount
, NEW
.rm_owner
,
1491 NEW
.rm_offset
, NEW
.rm_flags
);
1494 NEW
.rm_offset
+= len
;
1495 NEW
.rm_startblock
+= len
;
1496 NEW
.rm_blockcount
-= len
;
1497 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1498 NEW
.rm_blockcount
, NEW
.rm_owner
,
1499 NEW
.rm_offset
, NEW
.rm_flags
);
1503 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1504 NEW
.rm_blockcount
, NEW
.rm_owner
,
1505 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1508 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1509 NEW
.rm_blockcount
+= len
;
1510 error
= xfs_rmap_update(cur
, &NEW
);
1515 case RMAP_LEFT_FILLING
:
1517 * Setting the first part of a previous oldext extent to newext.
1518 * The left neighbor is not contiguous.
1521 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1522 NEW
.rm_blockcount
, NEW
.rm_owner
,
1523 NEW
.rm_offset
, NEW
.rm_flags
);
1526 NEW
.rm_offset
+= len
;
1527 NEW
.rm_startblock
+= len
;
1528 NEW
.rm_blockcount
-= len
;
1529 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1530 NEW
.rm_blockcount
, NEW
.rm_owner
,
1531 NEW
.rm_offset
, NEW
.rm_flags
);
1534 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1539 case RMAP_RIGHT_FILLING
| RMAP_RIGHT_CONTIG
:
1541 * Setting the last part of a previous oldext extent to newext.
1542 * The right neighbor is contiguous with the new allocation.
1545 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1546 NEW
.rm_blockcount
, NEW
.rm_owner
,
1547 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1550 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1551 NEW
.rm_blockcount
= offset
- NEW
.rm_offset
;
1552 error
= xfs_rmap_update(cur
, &NEW
);
1556 error
= xfs_rmap_delete(cur
, NEW
.rm_startblock
,
1557 NEW
.rm_blockcount
, NEW
.rm_owner
,
1558 NEW
.rm_offset
, NEW
.rm_flags
);
1561 NEW
.rm_offset
= offset
;
1562 NEW
.rm_startblock
= bno
;
1563 NEW
.rm_blockcount
+= len
;
1564 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1565 NEW
.rm_blockcount
, NEW
.rm_owner
,
1566 NEW
.rm_offset
, NEW
.rm_flags
);
1571 case RMAP_RIGHT_FILLING
:
1573 * Setting the last part of a previous oldext extent to newext.
1574 * The right neighbor is not contiguous.
1577 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1578 NEW
.rm_blockcount
, NEW
.rm_owner
,
1579 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1582 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1583 NEW
.rm_blockcount
-= len
;
1584 error
= xfs_rmap_update(cur
, &NEW
);
1587 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, newext
);
1594 * Setting the middle part of a previous oldext extent to
1595 * newext. Contiguity is impossible here.
1596 * One extent becomes three extents.
1598 /* new right extent - oldext */
1599 NEW
.rm_startblock
= bno
+ len
;
1600 NEW
.rm_owner
= owner
;
1601 NEW
.rm_offset
= new_endoff
;
1602 NEW
.rm_blockcount
= PREV
.rm_offset
+ PREV
.rm_blockcount
-
1604 NEW
.rm_flags
= PREV
.rm_flags
;
1605 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1606 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
1610 /* new left extent - oldext */
1612 error
= xfs_rmap_lookup_eq(cur
, NEW
.rm_startblock
,
1613 NEW
.rm_blockcount
, NEW
.rm_owner
,
1614 NEW
.rm_offset
, NEW
.rm_flags
, &i
);
1617 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, done
);
1618 NEW
.rm_blockcount
= offset
- NEW
.rm_offset
;
1619 error
= xfs_rmap_update(cur
, &NEW
);
1622 /* new middle extent - newext */
1623 NEW
.rm_startblock
= bno
;
1624 NEW
.rm_blockcount
= len
;
1625 NEW
.rm_owner
= owner
;
1626 NEW
.rm_offset
= offset
;
1627 NEW
.rm_flags
= newext
;
1628 error
= xfs_rmap_insert(cur
, NEW
.rm_startblock
,
1629 NEW
.rm_blockcount
, NEW
.rm_owner
, NEW
.rm_offset
,
1635 case RMAP_LEFT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1636 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1637 case RMAP_LEFT_FILLING
| RMAP_RIGHT_CONTIG
:
1638 case RMAP_RIGHT_FILLING
| RMAP_LEFT_CONTIG
:
1639 case RMAP_LEFT_CONTIG
| RMAP_RIGHT_CONTIG
:
1640 case RMAP_LEFT_CONTIG
:
1641 case RMAP_RIGHT_CONTIG
:
1643 * These cases are all impossible.
1648 trace_xfs_rmap_convert_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1652 trace_xfs_rmap_convert_error(cur
->bc_mp
,
1653 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1663 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1664 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1665 * that the prev/next records in the btree might belong to another owner.
1666 * Therefore we must use delete+insert to alter any of the key fields.
1668 * For every other situation there can only be one owner for a given extent,
1669 * so we can call the regular _free function.
1672 xfs_rmap_unmap_shared(
1673 struct xfs_btree_cur
*cur
,
1677 struct xfs_owner_info
*oinfo
)
1679 struct xfs_mount
*mp
= cur
->bc_mp
;
1680 struct xfs_rmap_irec ltrec
;
1688 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1690 flags
|= XFS_RMAP_UNWRITTEN
;
1691 trace_xfs_rmap_unmap(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1695 * We should always have a left record because there's a static record
1696 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1697 * will not ever be removed from the tree.
1699 error
= xfs_rmap_lookup_le_range(cur
, bno
, owner
, offset
, flags
,
1703 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1704 ltoff
= ltrec
.rm_offset
;
1706 /* Make sure the extent we found covers the entire freeing range. */
1707 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_startblock
<= bno
&&
1708 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
>=
1709 bno
+ len
, out_error
);
1711 /* Make sure the owner matches what we expect to find in the tree. */
1712 XFS_WANT_CORRUPTED_GOTO(mp
, owner
== ltrec
.rm_owner
, out_error
);
1714 /* Make sure the unwritten flag matches. */
1715 XFS_WANT_CORRUPTED_GOTO(mp
, (flags
& XFS_RMAP_UNWRITTEN
) ==
1716 (ltrec
.rm_flags
& XFS_RMAP_UNWRITTEN
), out_error
);
1718 /* Check the offset. */
1719 XFS_WANT_CORRUPTED_GOTO(mp
, ltrec
.rm_offset
<= offset
, out_error
);
1720 XFS_WANT_CORRUPTED_GOTO(mp
, offset
<= ltoff
+ ltrec
.rm_blockcount
,
1723 if (ltrec
.rm_startblock
== bno
&& ltrec
.rm_blockcount
== len
) {
1724 /* Exact match, simply remove the record from rmap tree. */
1725 error
= xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
1726 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1727 ltrec
.rm_offset
, ltrec
.rm_flags
);
1730 } else if (ltrec
.rm_startblock
== bno
) {
1732 * Overlap left hand side of extent: move the start, trim the
1733 * length and update the current record.
1736 * Orig: |oooooooooooooooooooo|
1737 * Freeing: |fffffffff|
1738 * Result: |rrrrrrrrrr|
1742 /* Delete prev rmap. */
1743 error
= xfs_rmap_delete(cur
, ltrec
.rm_startblock
,
1744 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1745 ltrec
.rm_offset
, ltrec
.rm_flags
);
1749 /* Add an rmap at the new offset. */
1750 ltrec
.rm_startblock
+= len
;
1751 ltrec
.rm_blockcount
-= len
;
1752 ltrec
.rm_offset
+= len
;
1753 error
= xfs_rmap_insert(cur
, ltrec
.rm_startblock
,
1754 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1755 ltrec
.rm_offset
, ltrec
.rm_flags
);
1758 } else if (ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
+ len
) {
1760 * Overlap right hand side of extent: trim the length and
1761 * update the current record.
1764 * Orig: |oooooooooooooooooooo|
1765 * Freeing: |fffffffff|
1766 * Result: |rrrrrrrrrr|
1769 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1770 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1771 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1774 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1775 ltrec
.rm_blockcount
-= len
;
1776 error
= xfs_rmap_update(cur
, <rec
);
1781 * Overlap middle of extent: trim the length of the existing
1782 * record to the length of the new left-extent size, increment
1783 * the insertion position so we can insert a new record
1784 * containing the remaining right-extent space.
1787 * Orig: |oooooooooooooooooooo|
1788 * Freeing: |fffffffff|
1789 * Result: |rrrrr| |rrrr|
1792 xfs_extlen_t orig_len
= ltrec
.rm_blockcount
;
1794 /* Shrink the left side of the rmap */
1795 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1796 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1797 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1800 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1801 ltrec
.rm_blockcount
= bno
- ltrec
.rm_startblock
;
1802 error
= xfs_rmap_update(cur
, <rec
);
1806 /* Add an rmap at the new offset */
1807 error
= xfs_rmap_insert(cur
, bno
+ len
,
1808 orig_len
- len
- ltrec
.rm_blockcount
,
1809 ltrec
.rm_owner
, offset
+ len
,
1815 trace_xfs_rmap_unmap_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1819 trace_xfs_rmap_unmap_error(cur
->bc_mp
,
1820 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1825 * Find an extent in the rmap btree and map it. For rmap extent types that
1826 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1827 * that the prev/next records in the btree might belong to another owner.
1828 * Therefore we must use delete+insert to alter any of the key fields.
1830 * For every other situation there can only be one owner for a given extent,
1831 * so we can call the regular _alloc function.
1834 xfs_rmap_map_shared(
1835 struct xfs_btree_cur
*cur
,
1839 struct xfs_owner_info
*oinfo
)
1841 struct xfs_mount
*mp
= cur
->bc_mp
;
1842 struct xfs_rmap_irec ltrec
;
1843 struct xfs_rmap_irec gtrec
;
1850 unsigned int flags
= 0;
1852 xfs_owner_info_unpack(oinfo
, &owner
, &offset
, &flags
);
1854 flags
|= XFS_RMAP_UNWRITTEN
;
1855 trace_xfs_rmap_map(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1858 /* Is there a left record that abuts our range? */
1859 error
= xfs_rmap_find_left_neighbor(cur
, bno
, owner
, offset
, flags
,
1864 !xfs_rmap_is_mergeable(<rec
, owner
, flags
))
1867 /* Is there a right record that abuts our range? */
1868 error
= xfs_rmap_lookup_eq(cur
, bno
+ len
, len
, owner
, offset
+ len
,
1873 error
= xfs_rmap_get_rec(cur
, >rec
, &have_gt
);
1876 XFS_WANT_CORRUPTED_GOTO(mp
, have_gt
== 1, out_error
);
1877 trace_xfs_rmap_find_right_neighbor_result(cur
->bc_mp
,
1878 cur
->bc_private
.a
.agno
, gtrec
.rm_startblock
,
1879 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
1880 gtrec
.rm_offset
, gtrec
.rm_flags
);
1882 if (!xfs_rmap_is_mergeable(>rec
, owner
, flags
))
1887 ltrec
.rm_startblock
+ ltrec
.rm_blockcount
== bno
&&
1888 ltrec
.rm_offset
+ ltrec
.rm_blockcount
== offset
) {
1890 * Left edge contiguous, merge into left record.
1894 * adding: |aaaaaaaaa|
1895 * result: |rrrrrrrrrrrrrrrrrrr|
1898 ltrec
.rm_blockcount
+= len
;
1900 bno
+ len
== gtrec
.rm_startblock
&&
1901 offset
+ len
== gtrec
.rm_offset
) {
1903 * Right edge also contiguous, delete right record
1904 * and merge into left record.
1906 * ltbno ltlen gtbno gtlen
1907 * orig: |ooooooooo| |ooooooooo|
1908 * adding: |aaaaaaaaa|
1909 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1911 ltrec
.rm_blockcount
+= gtrec
.rm_blockcount
;
1912 error
= xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
1913 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
1914 gtrec
.rm_offset
, gtrec
.rm_flags
);
1919 /* Point the cursor back to the left record and update. */
1920 error
= xfs_rmap_lookup_eq(cur
, ltrec
.rm_startblock
,
1921 ltrec
.rm_blockcount
, ltrec
.rm_owner
,
1922 ltrec
.rm_offset
, ltrec
.rm_flags
, &i
);
1925 XFS_WANT_CORRUPTED_GOTO(mp
, i
== 1, out_error
);
1927 error
= xfs_rmap_update(cur
, <rec
);
1930 } else if (have_gt
&&
1931 bno
+ len
== gtrec
.rm_startblock
&&
1932 offset
+ len
== gtrec
.rm_offset
) {
1934 * Right edge contiguous, merge into right record.
1938 * adding: |aaaaaaaaa|
1939 * Result: |rrrrrrrrrrrrrrrrrrr|
1942 /* Delete the old record. */
1943 error
= xfs_rmap_delete(cur
, gtrec
.rm_startblock
,
1944 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
1945 gtrec
.rm_offset
, gtrec
.rm_flags
);
1949 /* Move the start and re-add it. */
1950 gtrec
.rm_startblock
= bno
;
1951 gtrec
.rm_blockcount
+= len
;
1952 gtrec
.rm_offset
= offset
;
1953 error
= xfs_rmap_insert(cur
, gtrec
.rm_startblock
,
1954 gtrec
.rm_blockcount
, gtrec
.rm_owner
,
1955 gtrec
.rm_offset
, gtrec
.rm_flags
);
1960 * No contiguous edge with identical owner, insert
1961 * new record at current cursor position.
1963 error
= xfs_rmap_insert(cur
, bno
, len
, owner
, offset
, flags
);
1968 trace_xfs_rmap_map_done(mp
, cur
->bc_private
.a
.agno
, bno
, len
,
1972 trace_xfs_rmap_map_error(cur
->bc_mp
,
1973 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
1977 struct xfs_rmap_query_range_info
{
1978 xfs_rmap_query_range_fn fn
;
1982 /* Format btree record and pass to our callback. */
1984 xfs_rmap_query_range_helper(
1985 struct xfs_btree_cur
*cur
,
1986 union xfs_btree_rec
*rec
,
1989 struct xfs_rmap_query_range_info
*query
= priv
;
1990 struct xfs_rmap_irec irec
;
1993 error
= xfs_rmap_btrec_to_irec(rec
, &irec
);
1996 return query
->fn(cur
, &irec
, query
->priv
);
1999 /* Find all rmaps between two keys. */
2001 xfs_rmap_query_range(
2002 struct xfs_btree_cur
*cur
,
2003 struct xfs_rmap_irec
*low_rec
,
2004 struct xfs_rmap_irec
*high_rec
,
2005 xfs_rmap_query_range_fn fn
,
2008 union xfs_btree_irec low_brec
;
2009 union xfs_btree_irec high_brec
;
2010 struct xfs_rmap_query_range_info query
;
2012 low_brec
.r
= *low_rec
;
2013 high_brec
.r
= *high_rec
;
2016 return xfs_btree_query_range(cur
, &low_brec
, &high_brec
,
2017 xfs_rmap_query_range_helper
, &query
);
2020 /* Clean up after calling xfs_rmap_finish_one. */
2022 xfs_rmap_finish_one_cleanup(
2023 struct xfs_trans
*tp
,
2024 struct xfs_btree_cur
*rcur
,
2027 struct xfs_buf
*agbp
;
2031 agbp
= rcur
->bc_private
.a
.agbp
;
2032 xfs_btree_del_cursor(rcur
, error
? XFS_BTREE_ERROR
: XFS_BTREE_NOERROR
);
2034 xfs_trans_brelse(tp
, agbp
);
2038 * Process one of the deferred rmap operations. We pass back the
2039 * btree cursor to maintain our lock on the rmapbt between calls.
2040 * This saves time and eliminates a buffer deadlock between the
2041 * superblock and the AGF because we'll always grab them in the same
2045 xfs_rmap_finish_one(
2046 struct xfs_trans
*tp
,
2047 enum xfs_rmap_intent_type type
,
2050 xfs_fileoff_t startoff
,
2051 xfs_fsblock_t startblock
,
2052 xfs_filblks_t blockcount
,
2054 struct xfs_btree_cur
**pcur
)
2056 struct xfs_mount
*mp
= tp
->t_mountp
;
2057 struct xfs_btree_cur
*rcur
;
2058 struct xfs_buf
*agbp
= NULL
;
2060 xfs_agnumber_t agno
;
2061 struct xfs_owner_info oinfo
;
2065 agno
= XFS_FSB_TO_AGNO(mp
, startblock
);
2066 ASSERT(agno
!= NULLAGNUMBER
);
2067 bno
= XFS_FSB_TO_AGBNO(mp
, startblock
);
2069 trace_xfs_rmap_deferred(mp
, agno
, type
, bno
, owner
, whichfork
,
2070 startoff
, blockcount
, state
);
2072 if (XFS_TEST_ERROR(false, mp
,
2073 XFS_ERRTAG_RMAP_FINISH_ONE
,
2074 XFS_RANDOM_RMAP_FINISH_ONE
))
2078 * If we haven't gotten a cursor or the cursor AG doesn't match
2079 * the startblock, get one now.
2082 if (rcur
!= NULL
&& rcur
->bc_private
.a
.agno
!= agno
) {
2083 xfs_rmap_finish_one_cleanup(tp
, rcur
, 0);
2089 * Refresh the freelist before we start changing the
2090 * rmapbt, because a shape change could cause us to
2093 error
= xfs_free_extent_fix_freelist(tp
, agno
, &agbp
);
2097 return -EFSCORRUPTED
;
2099 rcur
= xfs_rmapbt_init_cursor(mp
, tp
, agbp
, agno
);
2107 xfs_rmap_ino_owner(&oinfo
, owner
, whichfork
, startoff
);
2108 unwritten
= state
== XFS_EXT_UNWRITTEN
;
2109 bno
= XFS_FSB_TO_AGBNO(rcur
->bc_mp
, startblock
);
2112 case XFS_RMAP_ALLOC
:
2114 error
= xfs_rmap_map(rcur
, bno
, blockcount
, unwritten
, &oinfo
);
2116 case XFS_RMAP_MAP_SHARED
:
2117 error
= xfs_rmap_map_shared(rcur
, bno
, blockcount
, unwritten
,
2121 case XFS_RMAP_UNMAP
:
2122 error
= xfs_rmap_unmap(rcur
, bno
, blockcount
, unwritten
,
2125 case XFS_RMAP_UNMAP_SHARED
:
2126 error
= xfs_rmap_unmap_shared(rcur
, bno
, blockcount
, unwritten
,
2129 case XFS_RMAP_CONVERT
:
2130 error
= xfs_rmap_convert(rcur
, bno
, blockcount
, !unwritten
,
2133 case XFS_RMAP_CONVERT_SHARED
:
2134 error
= xfs_rmap_convert_shared(rcur
, bno
, blockcount
,
2135 !unwritten
, &oinfo
);
2139 error
= -EFSCORRUPTED
;
2144 xfs_trans_brelse(tp
, agbp
);
2150 * Don't defer an rmap if we aren't an rmap filesystem.
2153 xfs_rmap_update_is_needed(
2154 struct xfs_mount
*mp
,
2157 return xfs_sb_version_hasrmapbt(&mp
->m_sb
) && whichfork
!= XFS_COW_FORK
;
2161 * Record a rmap intent; the list is kept sorted first by AG and then by
2166 struct xfs_mount
*mp
,
2167 struct xfs_defer_ops
*dfops
,
2168 enum xfs_rmap_intent_type type
,
2171 struct xfs_bmbt_irec
*bmap
)
2173 struct xfs_rmap_intent
*ri
;
2175 trace_xfs_rmap_defer(mp
, XFS_FSB_TO_AGNO(mp
, bmap
->br_startblock
),
2177 XFS_FSB_TO_AGBNO(mp
, bmap
->br_startblock
),
2180 bmap
->br_blockcount
,
2183 ri
= kmem_alloc(sizeof(struct xfs_rmap_intent
), KM_SLEEP
| KM_NOFS
);
2184 INIT_LIST_HEAD(&ri
->ri_list
);
2186 ri
->ri_owner
= owner
;
2187 ri
->ri_whichfork
= whichfork
;
2188 ri
->ri_bmap
= *bmap
;
2190 xfs_defer_add(dfops
, XFS_DEFER_OPS_TYPE_RMAP
, &ri
->ri_list
);
2194 /* Map an extent into a file. */
2196 xfs_rmap_map_extent(
2197 struct xfs_mount
*mp
,
2198 struct xfs_defer_ops
*dfops
,
2199 struct xfs_inode
*ip
,
2201 struct xfs_bmbt_irec
*PREV
)
2203 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2206 return __xfs_rmap_add(mp
, dfops
, xfs_is_reflink_inode(ip
) ?
2207 XFS_RMAP_MAP_SHARED
: XFS_RMAP_MAP
, ip
->i_ino
,
2211 /* Unmap an extent out of a file. */
2213 xfs_rmap_unmap_extent(
2214 struct xfs_mount
*mp
,
2215 struct xfs_defer_ops
*dfops
,
2216 struct xfs_inode
*ip
,
2218 struct xfs_bmbt_irec
*PREV
)
2220 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2223 return __xfs_rmap_add(mp
, dfops
, xfs_is_reflink_inode(ip
) ?
2224 XFS_RMAP_UNMAP_SHARED
: XFS_RMAP_UNMAP
, ip
->i_ino
,
2228 /* Convert a data fork extent from unwritten to real or vice versa. */
2230 xfs_rmap_convert_extent(
2231 struct xfs_mount
*mp
,
2232 struct xfs_defer_ops
*dfops
,
2233 struct xfs_inode
*ip
,
2235 struct xfs_bmbt_irec
*PREV
)
2237 if (!xfs_rmap_update_is_needed(mp
, whichfork
))
2240 return __xfs_rmap_add(mp
, dfops
, xfs_is_reflink_inode(ip
) ?
2241 XFS_RMAP_CONVERT_SHARED
: XFS_RMAP_CONVERT
, ip
->i_ino
,
2245 /* Schedule the creation of an rmap for non-file data. */
2247 xfs_rmap_alloc_extent(
2248 struct xfs_mount
*mp
,
2249 struct xfs_defer_ops
*dfops
,
2250 xfs_agnumber_t agno
,
2255 struct xfs_bmbt_irec bmap
;
2257 if (!xfs_rmap_update_is_needed(mp
, XFS_DATA_FORK
))
2260 bmap
.br_startblock
= XFS_AGB_TO_FSB(mp
, agno
, bno
);
2261 bmap
.br_blockcount
= len
;
2262 bmap
.br_startoff
= 0;
2263 bmap
.br_state
= XFS_EXT_NORM
;
2265 return __xfs_rmap_add(mp
, dfops
, XFS_RMAP_ALLOC
, owner
,
2266 XFS_DATA_FORK
, &bmap
);
2269 /* Schedule the deletion of an rmap for non-file data. */
2271 xfs_rmap_free_extent(
2272 struct xfs_mount
*mp
,
2273 struct xfs_defer_ops
*dfops
,
2274 xfs_agnumber_t agno
,
2279 struct xfs_bmbt_irec bmap
;
2281 if (!xfs_rmap_update_is_needed(mp
, XFS_DATA_FORK
))
2284 bmap
.br_startblock
= XFS_AGB_TO_FSB(mp
, agno
, bno
);
2285 bmap
.br_blockcount
= len
;
2286 bmap
.br_startoff
= 0;
2287 bmap
.br_state
= XFS_EXT_NORM
;
2289 return __xfs_rmap_add(mp
, dfops
, XFS_RMAP_FREE
, owner
,
2290 XFS_DATA_FORK
, &bmap
);