]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - fs/xfs/libxfs/xfs_refcount.c
xfs: adjust refcount of an extent of blocks in refcount btree
[mirror_ubuntu-bionic-kernel.git] / fs / xfs / libxfs / xfs_refcount.c
1 /*
2 * Copyright (C) 2016 Oracle. All Rights Reserved.
3 *
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
5 *
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.
10 *
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.
15 *
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.
19 */
20 #include "xfs.h"
21 #include "xfs_fs.h"
22 #include "xfs_shared.h"
23 #include "xfs_format.h"
24 #include "xfs_log_format.h"
25 #include "xfs_trans_resv.h"
26 #include "xfs_sb.h"
27 #include "xfs_mount.h"
28 #include "xfs_defer.h"
29 #include "xfs_btree.h"
30 #include "xfs_bmap.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"
37 #include "xfs_bit.h"
38 #include "xfs_refcount.h"
39
40 /* Allowable refcount adjustment amounts. */
41 enum xfs_refc_adjust_op {
42 XFS_REFCOUNT_ADJUST_INCREASE = 1,
43 XFS_REFCOUNT_ADJUST_DECREASE = -1,
44 };
45
46 /*
47 * Look up the first record less than or equal to [bno, len] in the btree
48 * given by cur.
49 */
50 int
51 xfs_refcount_lookup_le(
52 struct xfs_btree_cur *cur,
53 xfs_agblock_t bno,
54 int *stat)
55 {
56 trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_private.a.agno, bno,
57 XFS_LOOKUP_LE);
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);
61 }
62
63 /*
64 * Look up the first record greater than or equal to [bno, len] in the btree
65 * given by cur.
66 */
67 int
68 xfs_refcount_lookup_ge(
69 struct xfs_btree_cur *cur,
70 xfs_agblock_t bno,
71 int *stat)
72 {
73 trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_private.a.agno, bno,
74 XFS_LOOKUP_GE);
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);
78 }
79
80 /*
81 * Get the data from the pointed-to record.
82 */
83 int
84 xfs_refcount_get_rec(
85 struct xfs_btree_cur *cur,
86 struct xfs_refcount_irec *irec,
87 int *stat)
88 {
89 union xfs_btree_rec *rec;
90 int error;
91
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,
98 irec);
99 }
100 return error;
101 }
102
103 /*
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.
107 */
108 STATIC int
109 xfs_refcount_update(
110 struct xfs_btree_cur *cur,
111 struct xfs_refcount_irec *irec)
112 {
113 union xfs_btree_rec rec;
114 int error;
115
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);
121 if (error)
122 trace_xfs_refcount_update_error(cur->bc_mp,
123 cur->bc_private.a.agno, error, _RET_IP_);
124 return error;
125 }
126
127 /*
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.
131 */
132 STATIC int
133 xfs_refcount_insert(
134 struct xfs_btree_cur *cur,
135 struct xfs_refcount_irec *irec,
136 int *i)
137 {
138 int error;
139
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);
146 out_error:
147 if (error)
148 trace_xfs_refcount_insert_error(cur->bc_mp,
149 cur->bc_private.a.agno, error, _RET_IP_);
150 return error;
151 }
152
153 /*
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.
158 */
159 STATIC int
160 xfs_refcount_delete(
161 struct xfs_btree_cur *cur,
162 int *i)
163 {
164 struct xfs_refcount_irec irec;
165 int found_rec;
166 int error;
167
168 error = xfs_refcount_get_rec(cur, &irec, &found_rec);
169 if (error)
170 goto out_error;
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);
175 if (error)
176 goto out_error;
177 error = xfs_refcount_lookup_ge(cur, irec.rc_startblock, &found_rec);
178 out_error:
179 if (error)
180 trace_xfs_refcount_delete_error(cur->bc_mp,
181 cur->bc_private.a.agno, error, _RET_IP_);
182 return error;
183 }
184
185 /*
186 * Adjusting the Reference Count
187 *
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:
192 *
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
199 *
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
204 * pieces later:
205 *
206 * <------ adjustment range ------>
207 * ----+ +---+-----+ +--+--------+----+----
208 * 2 | | 3 | 2 | |17| 55 | 10 | 10
209 * ----+ +---+-----+ +--+--------+----+----
210 *
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:
216 *
217 * <------ adjustment range ------>
218 * ----+---+---+-----+-+--+--------+----+----
219 * 2 |"1"| 3 | 2 |1|17| 55 | 10 | 10
220 * ----+---+---+-----+-+--+--------+----+----
221 * ^
222 *
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):
233 *
234 * <------ adjustment range ------>
235 * --------+---+-----+-+--+--------+----+----
236 * 2 | 3 | 2 |1|17| 55 | 10 | 10
237 * --------+---+-----+-+--+--------+----+----
238 * ^
239 *
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:
243 *
244 * <------ adjustment range ------>
245 * --------+---+-----+-+--+--------+----+----
246 * 2 | 4 | 3 |2|18| 56 | 11 | 10
247 * --------+---+-----+-+--+--------+----+----
248 *
249 * The result of a decrement operation looks as such:
250 *
251 * <------ adjustment range ------>
252 * ----+ +---+ +--+--------+----+----
253 * 2 | | 2 | |16| 54 | 9 | 10
254 * ----+ +---+ +--+--------+----+----
255 * DDDD 111111DD
256 *
257 * The blocks marked "D" are freed; the blocks marked "1" are only
258 * referenced once and therefore the record is removed from the
259 * refcount btree.
260 */
261
262 /* Next block after this extent. */
263 static inline xfs_agblock_t
264 xfs_refc_next(
265 struct xfs_refcount_irec *rc)
266 {
267 return rc->rc_startblock + rc->rc_blockcount;
268 }
269
270 /*
271 * Split a refcount extent that crosses agbno.
272 */
273 STATIC int
274 xfs_refcount_split_extent(
275 struct xfs_btree_cur *cur,
276 xfs_agblock_t agbno,
277 bool *shape_changed)
278 {
279 struct xfs_refcount_irec rcext, tmp;
280 int found_rec;
281 int error;
282
283 *shape_changed = false;
284 error = xfs_refcount_lookup_le(cur, agbno, &found_rec);
285 if (error)
286 goto out_error;
287 if (!found_rec)
288 return 0;
289
290 error = xfs_refcount_get_rec(cur, &rcext, &found_rec);
291 if (error)
292 goto out_error;
293 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
294 if (rcext.rc_startblock == agbno || xfs_refc_next(&rcext) <= agbno)
295 return 0;
296
297 *shape_changed = true;
298 trace_xfs_refcount_split_extent(cur->bc_mp, cur->bc_private.a.agno,
299 &rcext, agbno);
300
301 /* Establish the right extent. */
302 tmp = rcext;
303 tmp.rc_startblock = agbno;
304 tmp.rc_blockcount -= (agbno - rcext.rc_startblock);
305 error = xfs_refcount_update(cur, &tmp);
306 if (error)
307 goto out_error;
308
309 /* Insert the left extent. */
310 tmp = rcext;
311 tmp.rc_blockcount = agbno - rcext.rc_startblock;
312 error = xfs_refcount_insert(cur, &tmp, &found_rec);
313 if (error)
314 goto out_error;
315 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
316 return error;
317
318 out_error:
319 trace_xfs_refcount_split_extent_error(cur->bc_mp,
320 cur->bc_private.a.agno, error, _RET_IP_);
321 return error;
322 }
323
324 /*
325 * Merge the left, center, and right extents.
326 */
327 STATIC int
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,
335 xfs_extlen_t *aglen)
336 {
337 int error;
338 int found_rec;
339
340 trace_xfs_refcount_merge_center_extents(cur->bc_mp,
341 cur->bc_private.a.agno, left, center, right);
342
343 /*
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
349 * extent.
350 */
351 error = xfs_refcount_lookup_ge(cur, center->rc_startblock,
352 &found_rec);
353 if (error)
354 goto out_error;
355 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
356
357 error = xfs_refcount_delete(cur, &found_rec);
358 if (error)
359 goto out_error;
360 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
361
362 if (center->rc_refcount > 1) {
363 error = xfs_refcount_delete(cur, &found_rec);
364 if (error)
365 goto out_error;
366 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1,
367 out_error);
368 }
369
370 /* Enlarge the left extent. */
371 error = xfs_refcount_lookup_le(cur, left->rc_startblock,
372 &found_rec);
373 if (error)
374 goto out_error;
375 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
376
377 left->rc_blockcount = extlen;
378 error = xfs_refcount_update(cur, left);
379 if (error)
380 goto out_error;
381
382 *aglen = 0;
383 return error;
384
385 out_error:
386 trace_xfs_refcount_merge_center_extents_error(cur->bc_mp,
387 cur->bc_private.a.agno, error, _RET_IP_);
388 return error;
389 }
390
391 /*
392 * Merge with the left extent.
393 */
394 STATIC int
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,
400 xfs_extlen_t *aglen)
401 {
402 int error;
403 int found_rec;
404
405 trace_xfs_refcount_merge_left_extent(cur->bc_mp,
406 cur->bc_private.a.agno, left, cleft);
407
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,
411 &found_rec);
412 if (error)
413 goto out_error;
414 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1,
415 out_error);
416
417 error = xfs_refcount_delete(cur, &found_rec);
418 if (error)
419 goto out_error;
420 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1,
421 out_error);
422 }
423
424 /* Enlarge the left extent. */
425 error = xfs_refcount_lookup_le(cur, left->rc_startblock,
426 &found_rec);
427 if (error)
428 goto out_error;
429 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
430
431 left->rc_blockcount += cleft->rc_blockcount;
432 error = xfs_refcount_update(cur, left);
433 if (error)
434 goto out_error;
435
436 *agbno += cleft->rc_blockcount;
437 *aglen -= cleft->rc_blockcount;
438 return error;
439
440 out_error:
441 trace_xfs_refcount_merge_left_extent_error(cur->bc_mp,
442 cur->bc_private.a.agno, error, _RET_IP_);
443 return error;
444 }
445
446 /*
447 * Merge with the right extent.
448 */
449 STATIC int
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,
455 xfs_extlen_t *aglen)
456 {
457 int error;
458 int found_rec;
459
460 trace_xfs_refcount_merge_right_extent(cur->bc_mp,
461 cur->bc_private.a.agno, cright, right);
462
463 /*
464 * If the extent ending at agbno+aglen (cright) wasn't synthesized,
465 * remove it.
466 */
467 if (cright->rc_refcount > 1) {
468 error = xfs_refcount_lookup_le(cur, cright->rc_startblock,
469 &found_rec);
470 if (error)
471 goto out_error;
472 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1,
473 out_error);
474
475 error = xfs_refcount_delete(cur, &found_rec);
476 if (error)
477 goto out_error;
478 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1,
479 out_error);
480 }
481
482 /* Enlarge the right extent. */
483 error = xfs_refcount_lookup_le(cur, right->rc_startblock,
484 &found_rec);
485 if (error)
486 goto out_error;
487 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
488
489 right->rc_startblock -= cright->rc_blockcount;
490 right->rc_blockcount += cright->rc_blockcount;
491 error = xfs_refcount_update(cur, right);
492 if (error)
493 goto out_error;
494
495 *aglen -= cright->rc_blockcount;
496 return error;
497
498 out_error:
499 trace_xfs_refcount_merge_right_extent_error(cur->bc_mp,
500 cur->bc_private.a.agno, error, _RET_IP_);
501 return error;
502 }
503
504 /*
505 * Find the left extent and the one after it (cleft). This function assumes
506 * that we've already split any extent crossing agbno.
507 */
508 STATIC int
509 xfs_refcount_find_left_extents(
510 struct xfs_btree_cur *cur,
511 struct xfs_refcount_irec *left,
512 struct xfs_refcount_irec *cleft,
513 xfs_agblock_t agbno,
514 xfs_extlen_t aglen)
515 {
516 struct xfs_refcount_irec tmp;
517 int error;
518 int found_rec;
519
520 left->rc_startblock = cleft->rc_startblock = NULLAGBLOCK;
521 error = xfs_refcount_lookup_le(cur, agbno - 1, &found_rec);
522 if (error)
523 goto out_error;
524 if (!found_rec)
525 return 0;
526
527 error = xfs_refcount_get_rec(cur, &tmp, &found_rec);
528 if (error)
529 goto out_error;
530 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
531
532 if (xfs_refc_next(&tmp) != agbno)
533 return 0;
534 /* We have a left extent; retrieve (or invent) the next right one */
535 *left = tmp;
536
537 error = xfs_btree_increment(cur, 0, &found_rec);
538 if (error)
539 goto out_error;
540 if (found_rec) {
541 error = xfs_refcount_get_rec(cur, &tmp, &found_rec);
542 if (error)
543 goto out_error;
544 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1,
545 out_error);
546
547 /* if tmp starts at the end of our range, just use that */
548 if (tmp.rc_startblock == agbno)
549 *cleft = tmp;
550 else {
551 /*
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.
558 */
559 cleft->rc_startblock = agbno;
560 cleft->rc_blockcount = min(aglen,
561 tmp.rc_startblock - agbno);
562 cleft->rc_refcount = 1;
563 }
564 } else {
565 /*
566 * No extents, so pretend that there's one covering the whole
567 * range.
568 */
569 cleft->rc_startblock = agbno;
570 cleft->rc_blockcount = aglen;
571 cleft->rc_refcount = 1;
572 }
573 trace_xfs_refcount_find_left_extent(cur->bc_mp, cur->bc_private.a.agno,
574 left, cleft, agbno);
575 return error;
576
577 out_error:
578 trace_xfs_refcount_find_left_extent_error(cur->bc_mp,
579 cur->bc_private.a.agno, error, _RET_IP_);
580 return error;
581 }
582
583 /*
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.
586 */
587 STATIC int
588 xfs_refcount_find_right_extents(
589 struct xfs_btree_cur *cur,
590 struct xfs_refcount_irec *right,
591 struct xfs_refcount_irec *cright,
592 xfs_agblock_t agbno,
593 xfs_extlen_t aglen)
594 {
595 struct xfs_refcount_irec tmp;
596 int error;
597 int found_rec;
598
599 right->rc_startblock = cright->rc_startblock = NULLAGBLOCK;
600 error = xfs_refcount_lookup_ge(cur, agbno + aglen, &found_rec);
601 if (error)
602 goto out_error;
603 if (!found_rec)
604 return 0;
605
606 error = xfs_refcount_get_rec(cur, &tmp, &found_rec);
607 if (error)
608 goto out_error;
609 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
610
611 if (tmp.rc_startblock != agbno + aglen)
612 return 0;
613 /* We have a right extent; retrieve (or invent) the next left one */
614 *right = tmp;
615
616 error = xfs_btree_decrement(cur, 0, &found_rec);
617 if (error)
618 goto out_error;
619 if (found_rec) {
620 error = xfs_refcount_get_rec(cur, &tmp, &found_rec);
621 if (error)
622 goto out_error;
623 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1,
624 out_error);
625
626 /* if tmp ends at the end of our range, just use that */
627 if (xfs_refc_next(&tmp) == agbno + aglen)
628 *cright = tmp;
629 else {
630 /*
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.
637 */
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;
642 }
643 } else {
644 /*
645 * No extents, so pretend that there's one covering the whole
646 * range.
647 */
648 cright->rc_startblock = agbno;
649 cright->rc_blockcount = aglen;
650 cright->rc_refcount = 1;
651 }
652 trace_xfs_refcount_find_right_extent(cur->bc_mp, cur->bc_private.a.agno,
653 cright, right, agbno + aglen);
654 return error;
655
656 out_error:
657 trace_xfs_refcount_find_right_extent_error(cur->bc_mp,
658 cur->bc_private.a.agno, error, _RET_IP_);
659 return error;
660 }
661
662 /* Is this extent valid? */
663 static inline bool
664 xfs_refc_valid(
665 struct xfs_refcount_irec *rc)
666 {
667 return rc->rc_startblock != NULLAGBLOCK;
668 }
669
670 /*
671 * Try to merge with any extents on the boundaries of the adjustment range.
672 */
673 STATIC int
674 xfs_refcount_merge_extents(
675 struct xfs_btree_cur *cur,
676 xfs_agblock_t *agbno,
677 xfs_extlen_t *aglen,
678 enum xfs_refc_adjust_op adjust,
679 bool *shape_changed)
680 {
681 struct xfs_refcount_irec left = {0}, cleft = {0};
682 struct xfs_refcount_irec cright = {0}, right = {0};
683 int error;
684 unsigned long long ulen;
685 bool cequal;
686
687 *shape_changed = false;
688 /*
689 * Find the extent just below agbno [left], just above agbno [cleft],
690 * just below (agbno + aglen) [cright], and just above (agbno + aglen)
691 * [right].
692 */
693 error = xfs_refcount_find_left_extents(cur, &left, &cleft, *agbno,
694 *aglen);
695 if (error)
696 return error;
697 error = xfs_refcount_find_right_extents(cur, &right, &cright, *agbno,
698 *aglen);
699 if (error)
700 return error;
701
702 /* No left or right extent to merge; exit. */
703 if (!xfs_refc_valid(&left) && !xfs_refc_valid(&right))
704 return 0;
705
706 cequal = (cleft.rc_startblock == cright.rc_startblock) &&
707 (cleft.rc_blockcount == cright.rc_blockcount);
708
709 /* Try to merge left, cleft, and right. cleft must == cright. */
710 ulen = (unsigned long long)left.rc_blockcount + cleft.rc_blockcount +
711 right.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);
720 }
721
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,
729 agbno, aglen);
730 if (error)
731 return error;
732
733 /*
734 * If we just merged left + cleft and cleft == cright,
735 * we no longer have a cright to merge with right. We're done.
736 */
737 if (cequal)
738 return 0;
739 }
740
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,
748 agbno, aglen);
749 }
750
751 return error;
752 }
753
754 /*
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.
762 *
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.
767 */
768 static bool
769 xfs_refcount_still_have_space(
770 struct xfs_btree_cur *cur)
771 {
772 unsigned long overhead;
773
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;
777
778 /*
779 * Only allow 2 refcount extent updates per transaction if the
780 * refcount continue update "error" has been injected.
781 */
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))
786 return false;
787
788 if (cur->bc_private.a.priv.refc.nr_ops == 0)
789 return true;
790 else if (overhead > cur->bc_tp->t_log_res)
791 return false;
792 return cur->bc_tp->t_log_res - overhead >
793 cur->bc_private.a.priv.refc.nr_ops * 32;
794 }
795
796 /*
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].
801 */
802 STATIC int
803 xfs_refcount_adjust_extents(
804 struct xfs_btree_cur *cur,
805 xfs_agblock_t *agbno,
806 xfs_extlen_t *aglen,
807 enum xfs_refc_adjust_op adj,
808 struct xfs_defer_ops *dfops,
809 struct xfs_owner_info *oinfo)
810 {
811 struct xfs_refcount_irec ext, tmp;
812 int error;
813 int found_rec, found_tmp;
814 xfs_fsblock_t fsbno;
815
816 /* Merging did all the work already. */
817 if (*aglen == 0)
818 return 0;
819
820 error = xfs_refcount_lookup_ge(cur, *agbno, &found_rec);
821 if (error)
822 goto out_error;
823
824 while (*aglen > 0 && xfs_refcount_still_have_space(cur)) {
825 error = xfs_refcount_get_rec(cur, &ext, &found_rec);
826 if (error)
827 goto out_error;
828 if (!found_rec) {
829 ext.rc_startblock = cur->bc_mp->m_sb.sb_agblocks;
830 ext.rc_blockcount = 0;
831 ext.rc_refcount = 0;
832 }
833
834 /*
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.
838 */
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);
846
847 /*
848 * Either cover the hole (increment) or
849 * delete the range (decrement).
850 */
851 if (tmp.rc_refcount) {
852 error = xfs_refcount_insert(cur, &tmp,
853 &found_tmp);
854 if (error)
855 goto out_error;
856 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp,
857 found_tmp == 1, out_error);
858 cur->bc_private.a.priv.refc.nr_ops++;
859 } else {
860 fsbno = XFS_AGB_TO_FSB(cur->bc_mp,
861 cur->bc_private.a.agno,
862 tmp.rc_startblock);
863 xfs_bmap_add_free(cur->bc_mp, dfops, fsbno,
864 tmp.rc_blockcount, oinfo);
865 }
866
867 (*agbno) += tmp.rc_blockcount;
868 (*aglen) -= tmp.rc_blockcount;
869
870 error = xfs_refcount_lookup_ge(cur, *agbno,
871 &found_rec);
872 if (error)
873 goto out_error;
874 }
875
876 /* Stop if there's nothing left to modify */
877 if (*aglen == 0 || !xfs_refcount_still_have_space(cur))
878 break;
879
880 /*
881 * Adjust the reference count and either update the tree
882 * (incr) or free the blocks (decr).
883 */
884 if (ext.rc_refcount == MAXREFCOUNT)
885 goto skip;
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);
891 if (error)
892 goto out_error;
893 cur->bc_private.a.priv.refc.nr_ops++;
894 } else if (ext.rc_refcount == 1) {
895 error = xfs_refcount_delete(cur, &found_rec);
896 if (error)
897 goto out_error;
898 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp,
899 found_rec == 1, out_error);
900 cur->bc_private.a.priv.refc.nr_ops++;
901 goto advloop;
902 } else {
903 fsbno = XFS_AGB_TO_FSB(cur->bc_mp,
904 cur->bc_private.a.agno,
905 ext.rc_startblock);
906 xfs_bmap_add_free(cur->bc_mp, dfops, fsbno,
907 ext.rc_blockcount, oinfo);
908 }
909
910 skip:
911 error = xfs_btree_increment(cur, 0, &found_rec);
912 if (error)
913 goto out_error;
914
915 advloop:
916 (*agbno) += ext.rc_blockcount;
917 (*aglen) -= ext.rc_blockcount;
918 }
919
920 return error;
921 out_error:
922 trace_xfs_refcount_modify_extent_error(cur->bc_mp,
923 cur->bc_private.a.agno, error, _RET_IP_);
924 return error;
925 }
926
927 /* Adjust the reference count of a range of AG blocks. */
928 STATIC int
929 xfs_refcount_adjust(
930 struct xfs_btree_cur *cur,
931 xfs_agblock_t agbno,
932 xfs_extlen_t aglen,
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)
938 {
939 bool shape_changed;
940 int shape_changes = 0;
941 int error;
942
943 *new_agbno = agbno;
944 *new_aglen = aglen;
945 if (adj == XFS_REFCOUNT_ADJUST_INCREASE)
946 trace_xfs_refcount_increase(cur->bc_mp, cur->bc_private.a.agno,
947 agbno, aglen);
948 else
949 trace_xfs_refcount_decrease(cur->bc_mp, cur->bc_private.a.agno,
950 agbno, aglen);
951
952 /*
953 * Ensure that no rcextents cross the boundary of the adjustment range.
954 */
955 error = xfs_refcount_split_extent(cur, agbno, &shape_changed);
956 if (error)
957 goto out_error;
958 if (shape_changed)
959 shape_changes++;
960
961 error = xfs_refcount_split_extent(cur, agbno + aglen, &shape_changed);
962 if (error)
963 goto out_error;
964 if (shape_changed)
965 shape_changes++;
966
967 /*
968 * Try to merge with the left or right extents of the range.
969 */
970 error = xfs_refcount_merge_extents(cur, new_agbno, new_aglen, adj,
971 &shape_changed);
972 if (error)
973 goto out_error;
974 if (shape_changed)
975 shape_changes++;
976 if (shape_changes)
977 cur->bc_private.a.priv.refc.shape_changes++;
978
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,
981 adj, dfops, oinfo);
982 if (error)
983 goto out_error;
984
985 return 0;
986
987 out_error:
988 trace_xfs_refcount_adjust_error(cur->bc_mp, cur->bc_private.a.agno,
989 error, _RET_IP_);
990 return error;
991 }