2 * Copyright (C) 2016 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it would be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include "xfs_shared.h"
23 #include "xfs_format.h"
24 #include "xfs_log_format.h"
25 #include "xfs_trans_resv.h"
27 #include "xfs_mount.h"
28 #include "xfs_defer.h"
29 #include "xfs_btree.h"
31 #include "xfs_refcount_btree.h"
32 #include "xfs_alloc.h"
33 #include "xfs_error.h"
34 #include "xfs_trace.h"
35 #include "xfs_cksum.h"
36 #include "xfs_trans.h"
38 #include "xfs_refcount.h"
40 /* Allowable refcount adjustment amounts. */
41 enum xfs_refc_adjust_op
{
42 XFS_REFCOUNT_ADJUST_INCREASE
= 1,
43 XFS_REFCOUNT_ADJUST_DECREASE
= -1,
47 * Look up the first record less than or equal to [bno, len] in the btree
51 xfs_refcount_lookup_le(
52 struct xfs_btree_cur
*cur
,
56 trace_xfs_refcount_lookup(cur
->bc_mp
, cur
->bc_private
.a
.agno
, bno
,
58 cur
->bc_rec
.rc
.rc_startblock
= bno
;
59 cur
->bc_rec
.rc
.rc_blockcount
= 0;
60 return xfs_btree_lookup(cur
, XFS_LOOKUP_LE
, stat
);
64 * Look up the first record greater than or equal to [bno, len] in the btree
68 xfs_refcount_lookup_ge(
69 struct xfs_btree_cur
*cur
,
73 trace_xfs_refcount_lookup(cur
->bc_mp
, cur
->bc_private
.a
.agno
, bno
,
75 cur
->bc_rec
.rc
.rc_startblock
= bno
;
76 cur
->bc_rec
.rc
.rc_blockcount
= 0;
77 return xfs_btree_lookup(cur
, XFS_LOOKUP_GE
, stat
);
81 * Get the data from the pointed-to record.
85 struct xfs_btree_cur
*cur
,
86 struct xfs_refcount_irec
*irec
,
89 union xfs_btree_rec
*rec
;
92 error
= xfs_btree_get_rec(cur
, &rec
, stat
);
93 if (!error
&& *stat
== 1) {
94 irec
->rc_startblock
= be32_to_cpu(rec
->refc
.rc_startblock
);
95 irec
->rc_blockcount
= be32_to_cpu(rec
->refc
.rc_blockcount
);
96 irec
->rc_refcount
= be32_to_cpu(rec
->refc
.rc_refcount
);
97 trace_xfs_refcount_get(cur
->bc_mp
, cur
->bc_private
.a
.agno
,
104 * Update the record referred to by cur to the value given
105 * by [bno, len, refcount].
106 * This either works (return 0) or gets an EFSCORRUPTED error.
110 struct xfs_btree_cur
*cur
,
111 struct xfs_refcount_irec
*irec
)
113 union xfs_btree_rec rec
;
116 trace_xfs_refcount_update(cur
->bc_mp
, cur
->bc_private
.a
.agno
, irec
);
117 rec
.refc
.rc_startblock
= cpu_to_be32(irec
->rc_startblock
);
118 rec
.refc
.rc_blockcount
= cpu_to_be32(irec
->rc_blockcount
);
119 rec
.refc
.rc_refcount
= cpu_to_be32(irec
->rc_refcount
);
120 error
= xfs_btree_update(cur
, &rec
);
122 trace_xfs_refcount_update_error(cur
->bc_mp
,
123 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
128 * Insert the record referred to by cur to the value given
129 * by [bno, len, refcount].
130 * This either works (return 0) or gets an EFSCORRUPTED error.
134 struct xfs_btree_cur
*cur
,
135 struct xfs_refcount_irec
*irec
,
140 trace_xfs_refcount_insert(cur
->bc_mp
, cur
->bc_private
.a
.agno
, irec
);
141 cur
->bc_rec
.rc
.rc_startblock
= irec
->rc_startblock
;
142 cur
->bc_rec
.rc
.rc_blockcount
= irec
->rc_blockcount
;
143 cur
->bc_rec
.rc
.rc_refcount
= irec
->rc_refcount
;
144 error
= xfs_btree_insert(cur
, i
);
145 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, *i
== 1, out_error
);
148 trace_xfs_refcount_insert_error(cur
->bc_mp
,
149 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
154 * Remove the record referred to by cur, then set the pointer to the spot
155 * where the record could be re-inserted, in case we want to increment or
156 * decrement the cursor.
157 * This either works (return 0) or gets an EFSCORRUPTED error.
161 struct xfs_btree_cur
*cur
,
164 struct xfs_refcount_irec irec
;
168 error
= xfs_refcount_get_rec(cur
, &irec
, &found_rec
);
171 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, found_rec
== 1, out_error
);
172 trace_xfs_refcount_delete(cur
->bc_mp
, cur
->bc_private
.a
.agno
, &irec
);
173 error
= xfs_btree_delete(cur
, i
);
174 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, *i
== 1, out_error
);
177 error
= xfs_refcount_lookup_ge(cur
, irec
.rc_startblock
, &found_rec
);
180 trace_xfs_refcount_delete_error(cur
->bc_mp
,
181 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
186 * Adjusting the Reference Count
188 * As stated elsewhere, the reference count btree (refcbt) stores
189 * >1 reference counts for extents of physical blocks. In this
190 * operation, we're either raising or lowering the reference count of
191 * some subrange stored in the tree:
193 * <------ adjustment range ------>
194 * ----+ +---+-----+ +--+--------+---------
195 * 2 | | 3 | 4 | |17| 55 | 10
196 * ----+ +---+-----+ +--+--------+---------
197 * X axis is physical blocks number;
198 * reference counts are the numbers inside the rectangles
200 * The first thing we need to do is to ensure that there are no
201 * refcount extents crossing either boundary of the range to be
202 * adjusted. For any extent that does cross a boundary, split it into
203 * two extents so that we can increment the refcount of one of the
206 * <------ adjustment range ------>
207 * ----+ +---+-----+ +--+--------+----+----
208 * 2 | | 3 | 2 | |17| 55 | 10 | 10
209 * ----+ +---+-----+ +--+--------+----+----
211 * For this next step, let's assume that all the physical blocks in
212 * the adjustment range are mapped to a file and are therefore in use
213 * at least once. Therefore, we can infer that any gap in the
214 * refcount tree within the adjustment range represents a physical
215 * extent with refcount == 1:
217 * <------ adjustment range ------>
218 * ----+---+---+-----+-+--+--------+----+----
219 * 2 |"1"| 3 | 2 |1|17| 55 | 10 | 10
220 * ----+---+---+-----+-+--+--------+----+----
223 * For each extent that falls within the interval range, figure out
224 * which extent is to the left or the right of that extent. Now we
225 * have a left, current, and right extent. If the new reference count
226 * of the center extent enables us to merge left, center, and right
227 * into one record covering all three, do so. If the center extent is
228 * at the left end of the range, abuts the left extent, and its new
229 * reference count matches the left extent's record, then merge them.
230 * If the center extent is at the right end of the range, abuts the
231 * right extent, and the reference counts match, merge those. In the
232 * example, we can left merge (assuming an increment operation):
234 * <------ adjustment range ------>
235 * --------+---+-----+-+--+--------+----+----
236 * 2 | 3 | 2 |1|17| 55 | 10 | 10
237 * --------+---+-----+-+--+--------+----+----
240 * For all other extents within the range, adjust the reference count
241 * or delete it if the refcount falls below 2. If we were
242 * incrementing, the end result looks like this:
244 * <------ adjustment range ------>
245 * --------+---+-----+-+--+--------+----+----
246 * 2 | 4 | 3 |2|18| 56 | 11 | 10
247 * --------+---+-----+-+--+--------+----+----
249 * The result of a decrement operation looks as such:
251 * <------ adjustment range ------>
252 * ----+ +---+ +--+--------+----+----
253 * 2 | | 2 | |16| 54 | 9 | 10
254 * ----+ +---+ +--+--------+----+----
257 * The blocks marked "D" are freed; the blocks marked "1" are only
258 * referenced once and therefore the record is removed from the
262 /* Next block after this extent. */
263 static inline xfs_agblock_t
265 struct xfs_refcount_irec
*rc
)
267 return rc
->rc_startblock
+ rc
->rc_blockcount
;
271 * Split a refcount extent that crosses agbno.
274 xfs_refcount_split_extent(
275 struct xfs_btree_cur
*cur
,
279 struct xfs_refcount_irec rcext
, tmp
;
283 *shape_changed
= false;
284 error
= xfs_refcount_lookup_le(cur
, agbno
, &found_rec
);
290 error
= xfs_refcount_get_rec(cur
, &rcext
, &found_rec
);
293 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, found_rec
== 1, out_error
);
294 if (rcext
.rc_startblock
== agbno
|| xfs_refc_next(&rcext
) <= agbno
)
297 *shape_changed
= true;
298 trace_xfs_refcount_split_extent(cur
->bc_mp
, cur
->bc_private
.a
.agno
,
301 /* Establish the right extent. */
303 tmp
.rc_startblock
= agbno
;
304 tmp
.rc_blockcount
-= (agbno
- rcext
.rc_startblock
);
305 error
= xfs_refcount_update(cur
, &tmp
);
309 /* Insert the left extent. */
311 tmp
.rc_blockcount
= agbno
- rcext
.rc_startblock
;
312 error
= xfs_refcount_insert(cur
, &tmp
, &found_rec
);
315 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, found_rec
== 1, out_error
);
319 trace_xfs_refcount_split_extent_error(cur
->bc_mp
,
320 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
325 * Merge the left, center, and right extents.
328 xfs_refcount_merge_center_extents(
329 struct xfs_btree_cur
*cur
,
330 struct xfs_refcount_irec
*left
,
331 struct xfs_refcount_irec
*center
,
332 struct xfs_refcount_irec
*right
,
333 unsigned long long extlen
,
334 xfs_agblock_t
*agbno
,
340 trace_xfs_refcount_merge_center_extents(cur
->bc_mp
,
341 cur
->bc_private
.a
.agno
, left
, center
, right
);
344 * Make sure the center and right extents are not in the btree.
345 * If the center extent was synthesized, the first delete call
346 * removes the right extent and we skip the second deletion.
347 * If center and right were in the btree, then the first delete
348 * call removes the center and the second one removes the right
351 error
= xfs_refcount_lookup_ge(cur
, center
->rc_startblock
,
355 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, found_rec
== 1, out_error
);
357 error
= xfs_refcount_delete(cur
, &found_rec
);
360 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, found_rec
== 1, out_error
);
362 if (center
->rc_refcount
> 1) {
363 error
= xfs_refcount_delete(cur
, &found_rec
);
366 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, found_rec
== 1,
370 /* Enlarge the left extent. */
371 error
= xfs_refcount_lookup_le(cur
, left
->rc_startblock
,
375 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, found_rec
== 1, out_error
);
377 left
->rc_blockcount
= extlen
;
378 error
= xfs_refcount_update(cur
, left
);
386 trace_xfs_refcount_merge_center_extents_error(cur
->bc_mp
,
387 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
392 * Merge with the left extent.
395 xfs_refcount_merge_left_extent(
396 struct xfs_btree_cur
*cur
,
397 struct xfs_refcount_irec
*left
,
398 struct xfs_refcount_irec
*cleft
,
399 xfs_agblock_t
*agbno
,
405 trace_xfs_refcount_merge_left_extent(cur
->bc_mp
,
406 cur
->bc_private
.a
.agno
, left
, cleft
);
408 /* If the extent at agbno (cleft) wasn't synthesized, remove it. */
409 if (cleft
->rc_refcount
> 1) {
410 error
= xfs_refcount_lookup_le(cur
, cleft
->rc_startblock
,
414 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, found_rec
== 1,
417 error
= xfs_refcount_delete(cur
, &found_rec
);
420 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, found_rec
== 1,
424 /* Enlarge the left extent. */
425 error
= xfs_refcount_lookup_le(cur
, left
->rc_startblock
,
429 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, found_rec
== 1, out_error
);
431 left
->rc_blockcount
+= cleft
->rc_blockcount
;
432 error
= xfs_refcount_update(cur
, left
);
436 *agbno
+= cleft
->rc_blockcount
;
437 *aglen
-= cleft
->rc_blockcount
;
441 trace_xfs_refcount_merge_left_extent_error(cur
->bc_mp
,
442 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
447 * Merge with the right extent.
450 xfs_refcount_merge_right_extent(
451 struct xfs_btree_cur
*cur
,
452 struct xfs_refcount_irec
*right
,
453 struct xfs_refcount_irec
*cright
,
454 xfs_agblock_t
*agbno
,
460 trace_xfs_refcount_merge_right_extent(cur
->bc_mp
,
461 cur
->bc_private
.a
.agno
, cright
, right
);
464 * If the extent ending at agbno+aglen (cright) wasn't synthesized,
467 if (cright
->rc_refcount
> 1) {
468 error
= xfs_refcount_lookup_le(cur
, cright
->rc_startblock
,
472 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, found_rec
== 1,
475 error
= xfs_refcount_delete(cur
, &found_rec
);
478 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, found_rec
== 1,
482 /* Enlarge the right extent. */
483 error
= xfs_refcount_lookup_le(cur
, right
->rc_startblock
,
487 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, found_rec
== 1, out_error
);
489 right
->rc_startblock
-= cright
->rc_blockcount
;
490 right
->rc_blockcount
+= cright
->rc_blockcount
;
491 error
= xfs_refcount_update(cur
, right
);
495 *aglen
-= cright
->rc_blockcount
;
499 trace_xfs_refcount_merge_right_extent_error(cur
->bc_mp
,
500 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
505 * Find the left extent and the one after it (cleft). This function assumes
506 * that we've already split any extent crossing agbno.
509 xfs_refcount_find_left_extents(
510 struct xfs_btree_cur
*cur
,
511 struct xfs_refcount_irec
*left
,
512 struct xfs_refcount_irec
*cleft
,
516 struct xfs_refcount_irec tmp
;
520 left
->rc_startblock
= cleft
->rc_startblock
= NULLAGBLOCK
;
521 error
= xfs_refcount_lookup_le(cur
, agbno
- 1, &found_rec
);
527 error
= xfs_refcount_get_rec(cur
, &tmp
, &found_rec
);
530 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, found_rec
== 1, out_error
);
532 if (xfs_refc_next(&tmp
) != agbno
)
534 /* We have a left extent; retrieve (or invent) the next right one */
537 error
= xfs_btree_increment(cur
, 0, &found_rec
);
541 error
= xfs_refcount_get_rec(cur
, &tmp
, &found_rec
);
544 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, found_rec
== 1,
547 /* if tmp starts at the end of our range, just use that */
548 if (tmp
.rc_startblock
== agbno
)
552 * There's a gap in the refcntbt at the start of the
553 * range we're interested in (refcount == 1) so
554 * synthesize the implied extent and pass it back.
555 * We assume here that the agbno/aglen range was
556 * passed in from a data fork extent mapping and
557 * therefore is allocated to exactly one owner.
559 cleft
->rc_startblock
= agbno
;
560 cleft
->rc_blockcount
= min(aglen
,
561 tmp
.rc_startblock
- agbno
);
562 cleft
->rc_refcount
= 1;
566 * No extents, so pretend that there's one covering the whole
569 cleft
->rc_startblock
= agbno
;
570 cleft
->rc_blockcount
= aglen
;
571 cleft
->rc_refcount
= 1;
573 trace_xfs_refcount_find_left_extent(cur
->bc_mp
, cur
->bc_private
.a
.agno
,
578 trace_xfs_refcount_find_left_extent_error(cur
->bc_mp
,
579 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
584 * Find the right extent and the one before it (cright). This function
585 * assumes that we've already split any extents crossing agbno + aglen.
588 xfs_refcount_find_right_extents(
589 struct xfs_btree_cur
*cur
,
590 struct xfs_refcount_irec
*right
,
591 struct xfs_refcount_irec
*cright
,
595 struct xfs_refcount_irec tmp
;
599 right
->rc_startblock
= cright
->rc_startblock
= NULLAGBLOCK
;
600 error
= xfs_refcount_lookup_ge(cur
, agbno
+ aglen
, &found_rec
);
606 error
= xfs_refcount_get_rec(cur
, &tmp
, &found_rec
);
609 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, found_rec
== 1, out_error
);
611 if (tmp
.rc_startblock
!= agbno
+ aglen
)
613 /* We have a right extent; retrieve (or invent) the next left one */
616 error
= xfs_btree_decrement(cur
, 0, &found_rec
);
620 error
= xfs_refcount_get_rec(cur
, &tmp
, &found_rec
);
623 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
, found_rec
== 1,
626 /* if tmp ends at the end of our range, just use that */
627 if (xfs_refc_next(&tmp
) == agbno
+ aglen
)
631 * There's a gap in the refcntbt at the end of the
632 * range we're interested in (refcount == 1) so
633 * create the implied extent and pass it back.
634 * We assume here that the agbno/aglen range was
635 * passed in from a data fork extent mapping and
636 * therefore is allocated to exactly one owner.
638 cright
->rc_startblock
= max(agbno
, xfs_refc_next(&tmp
));
639 cright
->rc_blockcount
= right
->rc_startblock
-
640 cright
->rc_startblock
;
641 cright
->rc_refcount
= 1;
645 * No extents, so pretend that there's one covering the whole
648 cright
->rc_startblock
= agbno
;
649 cright
->rc_blockcount
= aglen
;
650 cright
->rc_refcount
= 1;
652 trace_xfs_refcount_find_right_extent(cur
->bc_mp
, cur
->bc_private
.a
.agno
,
653 cright
, right
, agbno
+ aglen
);
657 trace_xfs_refcount_find_right_extent_error(cur
->bc_mp
,
658 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
662 /* Is this extent valid? */
665 struct xfs_refcount_irec
*rc
)
667 return rc
->rc_startblock
!= NULLAGBLOCK
;
671 * Try to merge with any extents on the boundaries of the adjustment range.
674 xfs_refcount_merge_extents(
675 struct xfs_btree_cur
*cur
,
676 xfs_agblock_t
*agbno
,
678 enum xfs_refc_adjust_op adjust
,
681 struct xfs_refcount_irec left
= {0}, cleft
= {0};
682 struct xfs_refcount_irec cright
= {0}, right
= {0};
684 unsigned long long ulen
;
687 *shape_changed
= false;
689 * Find the extent just below agbno [left], just above agbno [cleft],
690 * just below (agbno + aglen) [cright], and just above (agbno + aglen)
693 error
= xfs_refcount_find_left_extents(cur
, &left
, &cleft
, *agbno
,
697 error
= xfs_refcount_find_right_extents(cur
, &right
, &cright
, *agbno
,
702 /* No left or right extent to merge; exit. */
703 if (!xfs_refc_valid(&left
) && !xfs_refc_valid(&right
))
706 cequal
= (cleft
.rc_startblock
== cright
.rc_startblock
) &&
707 (cleft
.rc_blockcount
== cright
.rc_blockcount
);
709 /* Try to merge left, cleft, and right. cleft must == cright. */
710 ulen
= (unsigned long long)left
.rc_blockcount
+ cleft
.rc_blockcount
+
712 if (xfs_refc_valid(&left
) && xfs_refc_valid(&right
) &&
713 xfs_refc_valid(&cleft
) && xfs_refc_valid(&cright
) && cequal
&&
714 left
.rc_refcount
== cleft
.rc_refcount
+ adjust
&&
715 right
.rc_refcount
== cleft
.rc_refcount
+ adjust
&&
716 ulen
< MAXREFCEXTLEN
) {
717 *shape_changed
= true;
718 return xfs_refcount_merge_center_extents(cur
, &left
, &cleft
,
719 &right
, ulen
, agbno
, aglen
);
722 /* Try to merge left and cleft. */
723 ulen
= (unsigned long long)left
.rc_blockcount
+ cleft
.rc_blockcount
;
724 if (xfs_refc_valid(&left
) && xfs_refc_valid(&cleft
) &&
725 left
.rc_refcount
== cleft
.rc_refcount
+ adjust
&&
726 ulen
< MAXREFCEXTLEN
) {
727 *shape_changed
= true;
728 error
= xfs_refcount_merge_left_extent(cur
, &left
, &cleft
,
734 * If we just merged left + cleft and cleft == cright,
735 * we no longer have a cright to merge with right. We're done.
741 /* Try to merge cright and right. */
742 ulen
= (unsigned long long)right
.rc_blockcount
+ cright
.rc_blockcount
;
743 if (xfs_refc_valid(&right
) && xfs_refc_valid(&cright
) &&
744 right
.rc_refcount
== cright
.rc_refcount
+ adjust
&&
745 ulen
< MAXREFCEXTLEN
) {
746 *shape_changed
= true;
747 return xfs_refcount_merge_right_extent(cur
, &right
, &cright
,
755 * While we're adjusting the refcounts records of an extent, we have
756 * to keep an eye on the number of extents we're dirtying -- run too
757 * many in a single transaction and we'll exceed the transaction's
758 * reservation and crash the fs. Each record adds 12 bytes to the
759 * log (plus any key updates) so we'll conservatively assume 24 bytes
760 * per record. We must also leave space for btree splits on both ends
761 * of the range and space for the CUD and a new CUI.
763 * XXX: This is a pretty hand-wavy estimate. The penalty for guessing
764 * true incorrectly is a shutdown FS; the penalty for guessing false
765 * incorrectly is more transaction rolls than might be necessary.
766 * Be conservative here.
769 xfs_refcount_still_have_space(
770 struct xfs_btree_cur
*cur
)
772 unsigned long overhead
;
774 overhead
= cur
->bc_private
.a
.priv
.refc
.shape_changes
*
775 xfs_allocfree_log_count(cur
->bc_mp
, 1);
776 overhead
*= cur
->bc_mp
->m_sb
.sb_blocksize
;
779 * Only allow 2 refcount extent updates per transaction if the
780 * refcount continue update "error" has been injected.
782 if (cur
->bc_private
.a
.priv
.refc
.nr_ops
> 2 &&
783 XFS_TEST_ERROR(false, cur
->bc_mp
,
784 XFS_ERRTAG_REFCOUNT_CONTINUE_UPDATE
,
785 XFS_RANDOM_REFCOUNT_CONTINUE_UPDATE
))
788 if (cur
->bc_private
.a
.priv
.refc
.nr_ops
== 0)
790 else if (overhead
> cur
->bc_tp
->t_log_res
)
792 return cur
->bc_tp
->t_log_res
- overhead
>
793 cur
->bc_private
.a
.priv
.refc
.nr_ops
* 32;
797 * Adjust the refcounts of middle extents. At this point we should have
798 * split extents that crossed the adjustment range; merged with adjacent
799 * extents; and updated agbno/aglen to reflect the merges. Therefore,
800 * all we have to do is update the extents inside [agbno, agbno + aglen].
803 xfs_refcount_adjust_extents(
804 struct xfs_btree_cur
*cur
,
805 xfs_agblock_t
*agbno
,
807 enum xfs_refc_adjust_op adj
,
808 struct xfs_defer_ops
*dfops
,
809 struct xfs_owner_info
*oinfo
)
811 struct xfs_refcount_irec ext
, tmp
;
813 int found_rec
, found_tmp
;
816 /* Merging did all the work already. */
820 error
= xfs_refcount_lookup_ge(cur
, *agbno
, &found_rec
);
824 while (*aglen
> 0 && xfs_refcount_still_have_space(cur
)) {
825 error
= xfs_refcount_get_rec(cur
, &ext
, &found_rec
);
829 ext
.rc_startblock
= cur
->bc_mp
->m_sb
.sb_agblocks
;
830 ext
.rc_blockcount
= 0;
835 * Deal with a hole in the refcount tree; if a file maps to
836 * these blocks and there's no refcountbt record, pretend that
837 * there is one with refcount == 1.
839 if (ext
.rc_startblock
!= *agbno
) {
840 tmp
.rc_startblock
= *agbno
;
841 tmp
.rc_blockcount
= min(*aglen
,
842 ext
.rc_startblock
- *agbno
);
843 tmp
.rc_refcount
= 1 + adj
;
844 trace_xfs_refcount_modify_extent(cur
->bc_mp
,
845 cur
->bc_private
.a
.agno
, &tmp
);
848 * Either cover the hole (increment) or
849 * delete the range (decrement).
851 if (tmp
.rc_refcount
) {
852 error
= xfs_refcount_insert(cur
, &tmp
,
856 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
,
857 found_tmp
== 1, out_error
);
858 cur
->bc_private
.a
.priv
.refc
.nr_ops
++;
860 fsbno
= XFS_AGB_TO_FSB(cur
->bc_mp
,
861 cur
->bc_private
.a
.agno
,
863 xfs_bmap_add_free(cur
->bc_mp
, dfops
, fsbno
,
864 tmp
.rc_blockcount
, oinfo
);
867 (*agbno
) += tmp
.rc_blockcount
;
868 (*aglen
) -= tmp
.rc_blockcount
;
870 error
= xfs_refcount_lookup_ge(cur
, *agbno
,
876 /* Stop if there's nothing left to modify */
877 if (*aglen
== 0 || !xfs_refcount_still_have_space(cur
))
881 * Adjust the reference count and either update the tree
882 * (incr) or free the blocks (decr).
884 if (ext
.rc_refcount
== MAXREFCOUNT
)
886 ext
.rc_refcount
+= adj
;
887 trace_xfs_refcount_modify_extent(cur
->bc_mp
,
888 cur
->bc_private
.a
.agno
, &ext
);
889 if (ext
.rc_refcount
> 1) {
890 error
= xfs_refcount_update(cur
, &ext
);
893 cur
->bc_private
.a
.priv
.refc
.nr_ops
++;
894 } else if (ext
.rc_refcount
== 1) {
895 error
= xfs_refcount_delete(cur
, &found_rec
);
898 XFS_WANT_CORRUPTED_GOTO(cur
->bc_mp
,
899 found_rec
== 1, out_error
);
900 cur
->bc_private
.a
.priv
.refc
.nr_ops
++;
903 fsbno
= XFS_AGB_TO_FSB(cur
->bc_mp
,
904 cur
->bc_private
.a
.agno
,
906 xfs_bmap_add_free(cur
->bc_mp
, dfops
, fsbno
,
907 ext
.rc_blockcount
, oinfo
);
911 error
= xfs_btree_increment(cur
, 0, &found_rec
);
916 (*agbno
) += ext
.rc_blockcount
;
917 (*aglen
) -= ext
.rc_blockcount
;
922 trace_xfs_refcount_modify_extent_error(cur
->bc_mp
,
923 cur
->bc_private
.a
.agno
, error
, _RET_IP_
);
927 /* Adjust the reference count of a range of AG blocks. */
930 struct xfs_btree_cur
*cur
,
933 xfs_agblock_t
*new_agbno
,
934 xfs_extlen_t
*new_aglen
,
935 enum xfs_refc_adjust_op adj
,
936 struct xfs_defer_ops
*dfops
,
937 struct xfs_owner_info
*oinfo
)
940 int shape_changes
= 0;
945 if (adj
== XFS_REFCOUNT_ADJUST_INCREASE
)
946 trace_xfs_refcount_increase(cur
->bc_mp
, cur
->bc_private
.a
.agno
,
949 trace_xfs_refcount_decrease(cur
->bc_mp
, cur
->bc_private
.a
.agno
,
953 * Ensure that no rcextents cross the boundary of the adjustment range.
955 error
= xfs_refcount_split_extent(cur
, agbno
, &shape_changed
);
961 error
= xfs_refcount_split_extent(cur
, agbno
+ aglen
, &shape_changed
);
968 * Try to merge with the left or right extents of the range.
970 error
= xfs_refcount_merge_extents(cur
, new_agbno
, new_aglen
, adj
,
977 cur
->bc_private
.a
.priv
.refc
.shape_changes
++;
979 /* Now that we've taken care of the ends, adjust the middle extents */
980 error
= xfs_refcount_adjust_extents(cur
, new_agbno
, new_aglen
,
988 trace_xfs_refcount_adjust_error(cur
->bc_mp
, cur
->bc_private
.a
.agno
,