]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/xfs_refcount.c
xfs: introduce reflink utility functions
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_refcount.c
CommitLineData
bc859611
DW
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 "libxfs_priv.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_trace.h"
34#include "xfs_cksum.h"
35#include "xfs_trans.h"
36#include "xfs_bit.h"
37#include "xfs_refcount.h"
38
56ef8c33
DW
39/* Allowable refcount adjustment amounts. */
40enum xfs_refc_adjust_op {
41 XFS_REFCOUNT_ADJUST_INCREASE = 1,
42 XFS_REFCOUNT_ADJUST_DECREASE = -1,
43};
44
bc859611
DW
45/*
46 * Look up the first record less than or equal to [bno, len] in the btree
47 * given by cur.
48 */
49int
50xfs_refcount_lookup_le(
51 struct xfs_btree_cur *cur,
52 xfs_agblock_t bno,
53 int *stat)
54{
55 trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_private.a.agno, bno,
56 XFS_LOOKUP_LE);
57 cur->bc_rec.rc.rc_startblock = bno;
58 cur->bc_rec.rc.rc_blockcount = 0;
59 return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
60}
61
62/*
63 * Look up the first record greater than or equal to [bno, len] in the btree
64 * given by cur.
65 */
66int
67xfs_refcount_lookup_ge(
68 struct xfs_btree_cur *cur,
69 xfs_agblock_t bno,
70 int *stat)
71{
72 trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_private.a.agno, bno,
73 XFS_LOOKUP_GE);
74 cur->bc_rec.rc.rc_startblock = bno;
75 cur->bc_rec.rc.rc_blockcount = 0;
76 return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat);
77}
78
79/*
80 * Get the data from the pointed-to record.
81 */
82int
83xfs_refcount_get_rec(
84 struct xfs_btree_cur *cur,
85 struct xfs_refcount_irec *irec,
86 int *stat)
87{
88 union xfs_btree_rec *rec;
89 int error;
90
91 error = xfs_btree_get_rec(cur, &rec, stat);
92 if (!error && *stat == 1) {
93 irec->rc_startblock = be32_to_cpu(rec->refc.rc_startblock);
94 irec->rc_blockcount = be32_to_cpu(rec->refc.rc_blockcount);
95 irec->rc_refcount = be32_to_cpu(rec->refc.rc_refcount);
96 trace_xfs_refcount_get(cur->bc_mp, cur->bc_private.a.agno,
97 irec);
98 }
99 return error;
100}
101
102/*
103 * Update the record referred to by cur to the value given
104 * by [bno, len, refcount].
105 * This either works (return 0) or gets an EFSCORRUPTED error.
106 */
107STATIC int
108xfs_refcount_update(
109 struct xfs_btree_cur *cur,
110 struct xfs_refcount_irec *irec)
111{
112 union xfs_btree_rec rec;
113 int error;
114
115 trace_xfs_refcount_update(cur->bc_mp, cur->bc_private.a.agno, irec);
116 rec.refc.rc_startblock = cpu_to_be32(irec->rc_startblock);
117 rec.refc.rc_blockcount = cpu_to_be32(irec->rc_blockcount);
118 rec.refc.rc_refcount = cpu_to_be32(irec->rc_refcount);
119 error = xfs_btree_update(cur, &rec);
120 if (error)
121 trace_xfs_refcount_update_error(cur->bc_mp,
122 cur->bc_private.a.agno, error, _RET_IP_);
123 return error;
124}
125
126/*
127 * Insert the record referred to by cur to the value given
128 * by [bno, len, refcount].
129 * This either works (return 0) or gets an EFSCORRUPTED error.
130 */
131STATIC int
132xfs_refcount_insert(
133 struct xfs_btree_cur *cur,
134 struct xfs_refcount_irec *irec,
135 int *i)
136{
137 int error;
138
139 trace_xfs_refcount_insert(cur->bc_mp, cur->bc_private.a.agno, irec);
140 cur->bc_rec.rc.rc_startblock = irec->rc_startblock;
141 cur->bc_rec.rc.rc_blockcount = irec->rc_blockcount;
142 cur->bc_rec.rc.rc_refcount = irec->rc_refcount;
143 error = xfs_btree_insert(cur, i);
144 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, *i == 1, out_error);
145out_error:
146 if (error)
147 trace_xfs_refcount_insert_error(cur->bc_mp,
148 cur->bc_private.a.agno, error, _RET_IP_);
149 return error;
150}
151
152/*
153 * Remove the record referred to by cur, then set the pointer to the spot
154 * where the record could be re-inserted, in case we want to increment or
155 * decrement the cursor.
156 * This either works (return 0) or gets an EFSCORRUPTED error.
157 */
158STATIC int
159xfs_refcount_delete(
160 struct xfs_btree_cur *cur,
161 int *i)
162{
163 struct xfs_refcount_irec irec;
164 int found_rec;
165 int error;
166
167 error = xfs_refcount_get_rec(cur, &irec, &found_rec);
168 if (error)
169 goto out_error;
170 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
171 trace_xfs_refcount_delete(cur->bc_mp, cur->bc_private.a.agno, &irec);
172 error = xfs_btree_delete(cur, i);
173 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, *i == 1, out_error);
174 if (error)
175 goto out_error;
176 error = xfs_refcount_lookup_ge(cur, irec.rc_startblock, &found_rec);
177out_error:
178 if (error)
179 trace_xfs_refcount_delete_error(cur->bc_mp,
180 cur->bc_private.a.agno, error, _RET_IP_);
181 return error;
182}
56ef8c33
DW
183
184/*
185 * Adjusting the Reference Count
186 *
187 * As stated elsewhere, the reference count btree (refcbt) stores
188 * >1 reference counts for extents of physical blocks. In this
189 * operation, we're either raising or lowering the reference count of
190 * some subrange stored in the tree:
191 *
192 * <------ adjustment range ------>
193 * ----+ +---+-----+ +--+--------+---------
194 * 2 | | 3 | 4 | |17| 55 | 10
195 * ----+ +---+-----+ +--+--------+---------
196 * X axis is physical blocks number;
197 * reference counts are the numbers inside the rectangles
198 *
199 * The first thing we need to do is to ensure that there are no
200 * refcount extents crossing either boundary of the range to be
201 * adjusted. For any extent that does cross a boundary, split it into
202 * two extents so that we can increment the refcount of one of the
203 * pieces later:
204 *
205 * <------ adjustment range ------>
206 * ----+ +---+-----+ +--+--------+----+----
207 * 2 | | 3 | 2 | |17| 55 | 10 | 10
208 * ----+ +---+-----+ +--+--------+----+----
209 *
210 * For this next step, let's assume that all the physical blocks in
211 * the adjustment range are mapped to a file and are therefore in use
212 * at least once. Therefore, we can infer that any gap in the
213 * refcount tree within the adjustment range represents a physical
214 * extent with refcount == 1:
215 *
216 * <------ adjustment range ------>
217 * ----+---+---+-----+-+--+--------+----+----
218 * 2 |"1"| 3 | 2 |1|17| 55 | 10 | 10
219 * ----+---+---+-----+-+--+--------+----+----
220 * ^
221 *
222 * For each extent that falls within the interval range, figure out
223 * which extent is to the left or the right of that extent. Now we
224 * have a left, current, and right extent. If the new reference count
225 * of the center extent enables us to merge left, center, and right
226 * into one record covering all three, do so. If the center extent is
227 * at the left end of the range, abuts the left extent, and its new
228 * reference count matches the left extent's record, then merge them.
229 * If the center extent is at the right end of the range, abuts the
230 * right extent, and the reference counts match, merge those. In the
231 * example, we can left merge (assuming an increment operation):
232 *
233 * <------ adjustment range ------>
234 * --------+---+-----+-+--+--------+----+----
235 * 2 | 3 | 2 |1|17| 55 | 10 | 10
236 * --------+---+-----+-+--+--------+----+----
237 * ^
238 *
239 * For all other extents within the range, adjust the reference count
240 * or delete it if the refcount falls below 2. If we were
241 * incrementing, the end result looks like this:
242 *
243 * <------ adjustment range ------>
244 * --------+---+-----+-+--+--------+----+----
245 * 2 | 4 | 3 |2|18| 56 | 11 | 10
246 * --------+---+-----+-+--+--------+----+----
247 *
248 * The result of a decrement operation looks as such:
249 *
250 * <------ adjustment range ------>
251 * ----+ +---+ +--+--------+----+----
252 * 2 | | 2 | |16| 54 | 9 | 10
253 * ----+ +---+ +--+--------+----+----
254 * DDDD 111111DD
255 *
256 * The blocks marked "D" are freed; the blocks marked "1" are only
257 * referenced once and therefore the record is removed from the
258 * refcount btree.
259 */
260
261/* Next block after this extent. */
262static inline xfs_agblock_t
263xfs_refc_next(
264 struct xfs_refcount_irec *rc)
265{
266 return rc->rc_startblock + rc->rc_blockcount;
267}
268
269/*
270 * Split a refcount extent that crosses agbno.
271 */
272STATIC int
273xfs_refcount_split_extent(
274 struct xfs_btree_cur *cur,
275 xfs_agblock_t agbno,
276 bool *shape_changed)
277{
278 struct xfs_refcount_irec rcext, tmp;
279 int found_rec;
280 int error;
281
282 *shape_changed = false;
283 error = xfs_refcount_lookup_le(cur, agbno, &found_rec);
284 if (error)
285 goto out_error;
286 if (!found_rec)
287 return 0;
288
289 error = xfs_refcount_get_rec(cur, &rcext, &found_rec);
290 if (error)
291 goto out_error;
292 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
293 if (rcext.rc_startblock == agbno || xfs_refc_next(&rcext) <= agbno)
294 return 0;
295
296 *shape_changed = true;
297 trace_xfs_refcount_split_extent(cur->bc_mp, cur->bc_private.a.agno,
298 &rcext, agbno);
299
300 /* Establish the right extent. */
301 tmp = rcext;
302 tmp.rc_startblock = agbno;
303 tmp.rc_blockcount -= (agbno - rcext.rc_startblock);
304 error = xfs_refcount_update(cur, &tmp);
305 if (error)
306 goto out_error;
307
308 /* Insert the left extent. */
309 tmp = rcext;
310 tmp.rc_blockcount = agbno - rcext.rc_startblock;
311 error = xfs_refcount_insert(cur, &tmp, &found_rec);
312 if (error)
313 goto out_error;
314 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
315 return error;
316
317out_error:
318 trace_xfs_refcount_split_extent_error(cur->bc_mp,
319 cur->bc_private.a.agno, error, _RET_IP_);
320 return error;
321}
322
323/*
324 * Merge the left, center, and right extents.
325 */
326STATIC int
327xfs_refcount_merge_center_extents(
328 struct xfs_btree_cur *cur,
329 struct xfs_refcount_irec *left,
330 struct xfs_refcount_irec *center,
331 struct xfs_refcount_irec *right,
332 unsigned long long extlen,
333 xfs_agblock_t *agbno,
334 xfs_extlen_t *aglen)
335{
336 int error;
337 int found_rec;
338
339 trace_xfs_refcount_merge_center_extents(cur->bc_mp,
340 cur->bc_private.a.agno, left, center, right);
341
342 /*
343 * Make sure the center and right extents are not in the btree.
344 * If the center extent was synthesized, the first delete call
345 * removes the right extent and we skip the second deletion.
346 * If center and right were in the btree, then the first delete
347 * call removes the center and the second one removes the right
348 * extent.
349 */
350 error = xfs_refcount_lookup_ge(cur, center->rc_startblock,
351 &found_rec);
352 if (error)
353 goto out_error;
354 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
355
356 error = xfs_refcount_delete(cur, &found_rec);
357 if (error)
358 goto out_error;
359 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
360
361 if (center->rc_refcount > 1) {
362 error = xfs_refcount_delete(cur, &found_rec);
363 if (error)
364 goto out_error;
365 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1,
366 out_error);
367 }
368
369 /* Enlarge the left extent. */
370 error = xfs_refcount_lookup_le(cur, left->rc_startblock,
371 &found_rec);
372 if (error)
373 goto out_error;
374 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
375
376 left->rc_blockcount = extlen;
377 error = xfs_refcount_update(cur, left);
378 if (error)
379 goto out_error;
380
381 *aglen = 0;
382 return error;
383
384out_error:
385 trace_xfs_refcount_merge_center_extents_error(cur->bc_mp,
386 cur->bc_private.a.agno, error, _RET_IP_);
387 return error;
388}
389
390/*
391 * Merge with the left extent.
392 */
393STATIC int
394xfs_refcount_merge_left_extent(
395 struct xfs_btree_cur *cur,
396 struct xfs_refcount_irec *left,
397 struct xfs_refcount_irec *cleft,
398 xfs_agblock_t *agbno,
399 xfs_extlen_t *aglen)
400{
401 int error;
402 int found_rec;
403
404 trace_xfs_refcount_merge_left_extent(cur->bc_mp,
405 cur->bc_private.a.agno, left, cleft);
406
407 /* If the extent at agbno (cleft) wasn't synthesized, remove it. */
408 if (cleft->rc_refcount > 1) {
409 error = xfs_refcount_lookup_le(cur, cleft->rc_startblock,
410 &found_rec);
411 if (error)
412 goto out_error;
413 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1,
414 out_error);
415
416 error = xfs_refcount_delete(cur, &found_rec);
417 if (error)
418 goto out_error;
419 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1,
420 out_error);
421 }
422
423 /* Enlarge the left extent. */
424 error = xfs_refcount_lookup_le(cur, left->rc_startblock,
425 &found_rec);
426 if (error)
427 goto out_error;
428 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
429
430 left->rc_blockcount += cleft->rc_blockcount;
431 error = xfs_refcount_update(cur, left);
432 if (error)
433 goto out_error;
434
435 *agbno += cleft->rc_blockcount;
436 *aglen -= cleft->rc_blockcount;
437 return error;
438
439out_error:
440 trace_xfs_refcount_merge_left_extent_error(cur->bc_mp,
441 cur->bc_private.a.agno, error, _RET_IP_);
442 return error;
443}
444
445/*
446 * Merge with the right extent.
447 */
448STATIC int
449xfs_refcount_merge_right_extent(
450 struct xfs_btree_cur *cur,
451 struct xfs_refcount_irec *right,
452 struct xfs_refcount_irec *cright,
453 xfs_agblock_t *agbno,
454 xfs_extlen_t *aglen)
455{
456 int error;
457 int found_rec;
458
459 trace_xfs_refcount_merge_right_extent(cur->bc_mp,
460 cur->bc_private.a.agno, cright, right);
461
462 /*
463 * If the extent ending at agbno+aglen (cright) wasn't synthesized,
464 * remove it.
465 */
466 if (cright->rc_refcount > 1) {
467 error = xfs_refcount_lookup_le(cur, cright->rc_startblock,
468 &found_rec);
469 if (error)
470 goto out_error;
471 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1,
472 out_error);
473
474 error = xfs_refcount_delete(cur, &found_rec);
475 if (error)
476 goto out_error;
477 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1,
478 out_error);
479 }
480
481 /* Enlarge the right extent. */
482 error = xfs_refcount_lookup_le(cur, right->rc_startblock,
483 &found_rec);
484 if (error)
485 goto out_error;
486 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
487
488 right->rc_startblock -= cright->rc_blockcount;
489 right->rc_blockcount += cright->rc_blockcount;
490 error = xfs_refcount_update(cur, right);
491 if (error)
492 goto out_error;
493
494 *aglen -= cright->rc_blockcount;
495 return error;
496
497out_error:
498 trace_xfs_refcount_merge_right_extent_error(cur->bc_mp,
499 cur->bc_private.a.agno, error, _RET_IP_);
500 return error;
501}
502
503/*
504 * Find the left extent and the one after it (cleft). This function assumes
505 * that we've already split any extent crossing agbno.
506 */
507STATIC int
508xfs_refcount_find_left_extents(
509 struct xfs_btree_cur *cur,
510 struct xfs_refcount_irec *left,
511 struct xfs_refcount_irec *cleft,
512 xfs_agblock_t agbno,
513 xfs_extlen_t aglen)
514{
515 struct xfs_refcount_irec tmp;
516 int error;
517 int found_rec;
518
519 left->rc_startblock = cleft->rc_startblock = NULLAGBLOCK;
520 error = xfs_refcount_lookup_le(cur, agbno - 1, &found_rec);
521 if (error)
522 goto out_error;
523 if (!found_rec)
524 return 0;
525
526 error = xfs_refcount_get_rec(cur, &tmp, &found_rec);
527 if (error)
528 goto out_error;
529 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
530
531 if (xfs_refc_next(&tmp) != agbno)
532 return 0;
533 /* We have a left extent; retrieve (or invent) the next right one */
534 *left = tmp;
535
536 error = xfs_btree_increment(cur, 0, &found_rec);
537 if (error)
538 goto out_error;
539 if (found_rec) {
540 error = xfs_refcount_get_rec(cur, &tmp, &found_rec);
541 if (error)
542 goto out_error;
543 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1,
544 out_error);
545
546 /* if tmp starts at the end of our range, just use that */
547 if (tmp.rc_startblock == agbno)
548 *cleft = tmp;
549 else {
550 /*
551 * There's a gap in the refcntbt at the start of the
552 * range we're interested in (refcount == 1) so
553 * synthesize the implied extent and pass it back.
554 * We assume here that the agbno/aglen range was
555 * passed in from a data fork extent mapping and
556 * therefore is allocated to exactly one owner.
557 */
558 cleft->rc_startblock = agbno;
559 cleft->rc_blockcount = min(aglen,
560 tmp.rc_startblock - agbno);
561 cleft->rc_refcount = 1;
562 }
563 } else {
564 /*
565 * No extents, so pretend that there's one covering the whole
566 * range.
567 */
568 cleft->rc_startblock = agbno;
569 cleft->rc_blockcount = aglen;
570 cleft->rc_refcount = 1;
571 }
572 trace_xfs_refcount_find_left_extent(cur->bc_mp, cur->bc_private.a.agno,
573 left, cleft, agbno);
574 return error;
575
576out_error:
577 trace_xfs_refcount_find_left_extent_error(cur->bc_mp,
578 cur->bc_private.a.agno, error, _RET_IP_);
579 return error;
580}
581
582/*
583 * Find the right extent and the one before it (cright). This function
584 * assumes that we've already split any extents crossing agbno + aglen.
585 */
586STATIC int
587xfs_refcount_find_right_extents(
588 struct xfs_btree_cur *cur,
589 struct xfs_refcount_irec *right,
590 struct xfs_refcount_irec *cright,
591 xfs_agblock_t agbno,
592 xfs_extlen_t aglen)
593{
594 struct xfs_refcount_irec tmp;
595 int error;
596 int found_rec;
597
598 right->rc_startblock = cright->rc_startblock = NULLAGBLOCK;
599 error = xfs_refcount_lookup_ge(cur, agbno + aglen, &found_rec);
600 if (error)
601 goto out_error;
602 if (!found_rec)
603 return 0;
604
605 error = xfs_refcount_get_rec(cur, &tmp, &found_rec);
606 if (error)
607 goto out_error;
608 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error);
609
610 if (tmp.rc_startblock != agbno + aglen)
611 return 0;
612 /* We have a right extent; retrieve (or invent) the next left one */
613 *right = tmp;
614
615 error = xfs_btree_decrement(cur, 0, &found_rec);
616 if (error)
617 goto out_error;
618 if (found_rec) {
619 error = xfs_refcount_get_rec(cur, &tmp, &found_rec);
620 if (error)
621 goto out_error;
622 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1,
623 out_error);
624
625 /* if tmp ends at the end of our range, just use that */
626 if (xfs_refc_next(&tmp) == agbno + aglen)
627 *cright = tmp;
628 else {
629 /*
630 * There's a gap in the refcntbt at the end of the
631 * range we're interested in (refcount == 1) so
632 * create the implied extent and pass it back.
633 * We assume here that the agbno/aglen range was
634 * passed in from a data fork extent mapping and
635 * therefore is allocated to exactly one owner.
636 */
637 cright->rc_startblock = max(agbno, xfs_refc_next(&tmp));
638 cright->rc_blockcount = right->rc_startblock -
639 cright->rc_startblock;
640 cright->rc_refcount = 1;
641 }
642 } else {
643 /*
644 * No extents, so pretend that there's one covering the whole
645 * range.
646 */
647 cright->rc_startblock = agbno;
648 cright->rc_blockcount = aglen;
649 cright->rc_refcount = 1;
650 }
651 trace_xfs_refcount_find_right_extent(cur->bc_mp, cur->bc_private.a.agno,
652 cright, right, agbno + aglen);
653 return error;
654
655out_error:
656 trace_xfs_refcount_find_right_extent_error(cur->bc_mp,
657 cur->bc_private.a.agno, error, _RET_IP_);
658 return error;
659}
660
661/* Is this extent valid? */
662static inline bool
663xfs_refc_valid(
664 struct xfs_refcount_irec *rc)
665{
666 return rc->rc_startblock != NULLAGBLOCK;
667}
668
669/*
670 * Try to merge with any extents on the boundaries of the adjustment range.
671 */
672STATIC int
673xfs_refcount_merge_extents(
674 struct xfs_btree_cur *cur,
675 xfs_agblock_t *agbno,
676 xfs_extlen_t *aglen,
677 enum xfs_refc_adjust_op adjust,
678 bool *shape_changed)
679{
680 struct xfs_refcount_irec left = {0}, cleft = {0};
681 struct xfs_refcount_irec cright = {0}, right = {0};
682 int error;
683 unsigned long long ulen;
684 bool cequal;
685
686 *shape_changed = false;
687 /*
688 * Find the extent just below agbno [left], just above agbno [cleft],
689 * just below (agbno + aglen) [cright], and just above (agbno + aglen)
690 * [right].
691 */
692 error = xfs_refcount_find_left_extents(cur, &left, &cleft, *agbno,
693 *aglen);
694 if (error)
695 return error;
696 error = xfs_refcount_find_right_extents(cur, &right, &cright, *agbno,
697 *aglen);
698 if (error)
699 return error;
700
701 /* No left or right extent to merge; exit. */
702 if (!xfs_refc_valid(&left) && !xfs_refc_valid(&right))
703 return 0;
704
705 cequal = (cleft.rc_startblock == cright.rc_startblock) &&
706 (cleft.rc_blockcount == cright.rc_blockcount);
707
708 /* Try to merge left, cleft, and right. cleft must == cright. */
709 ulen = (unsigned long long)left.rc_blockcount + cleft.rc_blockcount +
710 right.rc_blockcount;
711 if (xfs_refc_valid(&left) && xfs_refc_valid(&right) &&
712 xfs_refc_valid(&cleft) && xfs_refc_valid(&cright) && cequal &&
713 left.rc_refcount == cleft.rc_refcount + adjust &&
714 right.rc_refcount == cleft.rc_refcount + adjust &&
715 ulen < MAXREFCEXTLEN) {
716 *shape_changed = true;
717 return xfs_refcount_merge_center_extents(cur, &left, &cleft,
718 &right, ulen, agbno, aglen);
719 }
720
721 /* Try to merge left and cleft. */
722 ulen = (unsigned long long)left.rc_blockcount + cleft.rc_blockcount;
723 if (xfs_refc_valid(&left) && xfs_refc_valid(&cleft) &&
724 left.rc_refcount == cleft.rc_refcount + adjust &&
725 ulen < MAXREFCEXTLEN) {
726 *shape_changed = true;
727 error = xfs_refcount_merge_left_extent(cur, &left, &cleft,
728 agbno, aglen);
729 if (error)
730 return error;
731
732 /*
733 * If we just merged left + cleft and cleft == cright,
734 * we no longer have a cright to merge with right. We're done.
735 */
736 if (cequal)
737 return 0;
738 }
739
740 /* Try to merge cright and right. */
741 ulen = (unsigned long long)right.rc_blockcount + cright.rc_blockcount;
742 if (xfs_refc_valid(&right) && xfs_refc_valid(&cright) &&
743 right.rc_refcount == cright.rc_refcount + adjust &&
744 ulen < MAXREFCEXTLEN) {
745 *shape_changed = true;
746 return xfs_refcount_merge_right_extent(cur, &right, &cright,
747 agbno, aglen);
748 }
749
750 return error;
751}
752
753/*
754 * While we're adjusting the refcounts records of an extent, we have
755 * to keep an eye on the number of extents we're dirtying -- run too
756 * many in a single transaction and we'll exceed the transaction's
757 * reservation and crash the fs. Each record adds 12 bytes to the
758 * log (plus any key updates) so we'll conservatively assume 24 bytes
759 * per record. We must also leave space for btree splits on both ends
760 * of the range and space for the CUD and a new CUI.
761 *
762 * XXX: This is a pretty hand-wavy estimate. The penalty for guessing
763 * true incorrectly is a shutdown FS; the penalty for guessing false
764 * incorrectly is more transaction rolls than might be necessary.
765 * Be conservative here.
766 */
767static bool
768xfs_refcount_still_have_space(
769 struct xfs_btree_cur *cur)
770{
771 unsigned long overhead;
772
773 overhead = cur->bc_private.a.priv.refc.shape_changes *
774 xfs_allocfree_log_count(cur->bc_mp, 1);
775 overhead *= cur->bc_mp->m_sb.sb_blocksize;
776
777 /*
778 * Only allow 2 refcount extent updates per transaction if the
779 * refcount continue update "error" has been injected.
780 */
781 if (cur->bc_private.a.priv.refc.nr_ops > 2 &&
782 XFS_TEST_ERROR(false, cur->bc_mp,
783 XFS_ERRTAG_REFCOUNT_CONTINUE_UPDATE,
784 XFS_RANDOM_REFCOUNT_CONTINUE_UPDATE))
785 return false;
786
787 if (cur->bc_private.a.priv.refc.nr_ops == 0)
788 return true;
789 else if (overhead > cur->bc_tp->t_log_res)
790 return false;
791 return cur->bc_tp->t_log_res - overhead >
792 cur->bc_private.a.priv.refc.nr_ops * 32;
793}
794
795/*
796 * Adjust the refcounts of middle extents. At this point we should have
797 * split extents that crossed the adjustment range; merged with adjacent
798 * extents; and updated agbno/aglen to reflect the merges. Therefore,
799 * all we have to do is update the extents inside [agbno, agbno + aglen].
800 */
801STATIC int
802xfs_refcount_adjust_extents(
803 struct xfs_btree_cur *cur,
804 xfs_agblock_t *agbno,
805 xfs_extlen_t *aglen,
806 enum xfs_refc_adjust_op adj,
807 struct xfs_defer_ops *dfops,
808 struct xfs_owner_info *oinfo)
809{
810 struct xfs_refcount_irec ext, tmp;
811 int error;
812 int found_rec, found_tmp;
813 xfs_fsblock_t fsbno;
814
815 /* Merging did all the work already. */
816 if (*aglen == 0)
817 return 0;
818
819 error = xfs_refcount_lookup_ge(cur, *agbno, &found_rec);
820 if (error)
821 goto out_error;
822
823 while (*aglen > 0 && xfs_refcount_still_have_space(cur)) {
824 error = xfs_refcount_get_rec(cur, &ext, &found_rec);
825 if (error)
826 goto out_error;
827 if (!found_rec) {
828 ext.rc_startblock = cur->bc_mp->m_sb.sb_agblocks;
829 ext.rc_blockcount = 0;
830 ext.rc_refcount = 0;
831 }
832
833 /*
834 * Deal with a hole in the refcount tree; if a file maps to
835 * these blocks and there's no refcountbt record, pretend that
836 * there is one with refcount == 1.
837 */
838 if (ext.rc_startblock != *agbno) {
839 tmp.rc_startblock = *agbno;
840 tmp.rc_blockcount = min(*aglen,
841 ext.rc_startblock - *agbno);
842 tmp.rc_refcount = 1 + adj;
843 trace_xfs_refcount_modify_extent(cur->bc_mp,
844 cur->bc_private.a.agno, &tmp);
845
846 /*
847 * Either cover the hole (increment) or
848 * delete the range (decrement).
849 */
850 if (tmp.rc_refcount) {
851 error = xfs_refcount_insert(cur, &tmp,
852 &found_tmp);
853 if (error)
854 goto out_error;
855 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp,
856 found_tmp == 1, out_error);
857 cur->bc_private.a.priv.refc.nr_ops++;
858 } else {
859 fsbno = XFS_AGB_TO_FSB(cur->bc_mp,
860 cur->bc_private.a.agno,
861 tmp.rc_startblock);
862 xfs_bmap_add_free(cur->bc_mp, dfops, fsbno,
863 tmp.rc_blockcount, oinfo);
864 }
865
866 (*agbno) += tmp.rc_blockcount;
867 (*aglen) -= tmp.rc_blockcount;
868
869 error = xfs_refcount_lookup_ge(cur, *agbno,
870 &found_rec);
871 if (error)
872 goto out_error;
873 }
874
875 /* Stop if there's nothing left to modify */
876 if (*aglen == 0 || !xfs_refcount_still_have_space(cur))
877 break;
878
879 /*
880 * Adjust the reference count and either update the tree
881 * (incr) or free the blocks (decr).
882 */
883 if (ext.rc_refcount == MAXREFCOUNT)
884 goto skip;
885 ext.rc_refcount += adj;
886 trace_xfs_refcount_modify_extent(cur->bc_mp,
887 cur->bc_private.a.agno, &ext);
888 if (ext.rc_refcount > 1) {
889 error = xfs_refcount_update(cur, &ext);
890 if (error)
891 goto out_error;
892 cur->bc_private.a.priv.refc.nr_ops++;
893 } else if (ext.rc_refcount == 1) {
894 error = xfs_refcount_delete(cur, &found_rec);
895 if (error)
896 goto out_error;
897 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp,
898 found_rec == 1, out_error);
899 cur->bc_private.a.priv.refc.nr_ops++;
900 goto advloop;
901 } else {
902 fsbno = XFS_AGB_TO_FSB(cur->bc_mp,
903 cur->bc_private.a.agno,
904 ext.rc_startblock);
905 xfs_bmap_add_free(cur->bc_mp, dfops, fsbno,
906 ext.rc_blockcount, oinfo);
907 }
908
909skip:
910 error = xfs_btree_increment(cur, 0, &found_rec);
911 if (error)
912 goto out_error;
913
914advloop:
915 (*agbno) += ext.rc_blockcount;
916 (*aglen) -= ext.rc_blockcount;
917 }
918
919 return error;
920out_error:
921 trace_xfs_refcount_modify_extent_error(cur->bc_mp,
922 cur->bc_private.a.agno, error, _RET_IP_);
923 return error;
924}
925
926/* Adjust the reference count of a range of AG blocks. */
927STATIC int
928xfs_refcount_adjust(
929 struct xfs_btree_cur *cur,
930 xfs_agblock_t agbno,
931 xfs_extlen_t aglen,
932 xfs_agblock_t *new_agbno,
933 xfs_extlen_t *new_aglen,
934 enum xfs_refc_adjust_op adj,
935 struct xfs_defer_ops *dfops,
936 struct xfs_owner_info *oinfo)
937{
938 bool shape_changed;
939 int shape_changes = 0;
940 int error;
941
942 *new_agbno = agbno;
943 *new_aglen = aglen;
944 if (adj == XFS_REFCOUNT_ADJUST_INCREASE)
945 trace_xfs_refcount_increase(cur->bc_mp, cur->bc_private.a.agno,
946 agbno, aglen);
947 else
948 trace_xfs_refcount_decrease(cur->bc_mp, cur->bc_private.a.agno,
949 agbno, aglen);
950
951 /*
952 * Ensure that no rcextents cross the boundary of the adjustment range.
953 */
954 error = xfs_refcount_split_extent(cur, agbno, &shape_changed);
955 if (error)
956 goto out_error;
957 if (shape_changed)
958 shape_changes++;
959
960 error = xfs_refcount_split_extent(cur, agbno + aglen, &shape_changed);
961 if (error)
962 goto out_error;
963 if (shape_changed)
964 shape_changes++;
965
966 /*
967 * Try to merge with the left or right extents of the range.
968 */
969 error = xfs_refcount_merge_extents(cur, new_agbno, new_aglen, adj,
970 &shape_changed);
971 if (error)
972 goto out_error;
973 if (shape_changed)
974 shape_changes++;
975 if (shape_changes)
976 cur->bc_private.a.priv.refc.shape_changes++;
977
978 /* Now that we've taken care of the ends, adjust the middle extents */
979 error = xfs_refcount_adjust_extents(cur, new_agbno, new_aglen,
980 adj, dfops, oinfo);
981 if (error)
982 goto out_error;
983
984 return 0;
985
986out_error:
987 trace_xfs_refcount_adjust_error(cur->bc_mp, cur->bc_private.a.agno,
988 error, _RET_IP_);
989 return error;
990}
23a15a6c
DW
991
992/* Clean up after calling xfs_refcount_finish_one. */
993void
994xfs_refcount_finish_one_cleanup(
995 struct xfs_trans *tp,
996 struct xfs_btree_cur *rcur,
997 int error)
998{
999 struct xfs_buf *agbp;
1000
1001 if (rcur == NULL)
1002 return;
1003 agbp = rcur->bc_private.a.agbp;
1004 xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
1005 if (error)
1006 xfs_trans_brelse(tp, agbp);
1007}
1008
1009/*
1010 * Process one of the deferred refcount operations. We pass back the
1011 * btree cursor to maintain our lock on the btree between calls.
1012 * This saves time and eliminates a buffer deadlock between the
1013 * superblock and the AGF because we'll always grab them in the same
1014 * order.
1015 */
1016int
1017xfs_refcount_finish_one(
1018 struct xfs_trans *tp,
1019 struct xfs_defer_ops *dfops,
1020 enum xfs_refcount_intent_type type,
1021 xfs_fsblock_t startblock,
1022 xfs_extlen_t blockcount,
1023 xfs_fsblock_t *new_fsb,
1024 xfs_extlen_t *new_len,
1025 struct xfs_btree_cur **pcur)
1026{
1027 struct xfs_mount *mp = tp->t_mountp;
1028 struct xfs_btree_cur *rcur;
1029 struct xfs_buf *agbp = NULL;
1030 int error = 0;
1031 xfs_agnumber_t agno;
1032 xfs_agblock_t bno;
1033 xfs_agblock_t new_agbno;
1034 unsigned long nr_ops = 0;
1035 int shape_changes = 0;
1036
1037 agno = XFS_FSB_TO_AGNO(mp, startblock);
1038 ASSERT(agno != NULLAGNUMBER);
1039 bno = XFS_FSB_TO_AGBNO(mp, startblock);
1040
1041 trace_xfs_refcount_deferred(mp, XFS_FSB_TO_AGNO(mp, startblock),
1042 type, XFS_FSB_TO_AGBNO(mp, startblock),
1043 blockcount);
1044
1045 if (XFS_TEST_ERROR(false, mp,
1046 XFS_ERRTAG_REFCOUNT_FINISH_ONE,
1047 XFS_RANDOM_REFCOUNT_FINISH_ONE))
1048 return -EIO;
1049
1050 /*
1051 * If we haven't gotten a cursor or the cursor AG doesn't match
1052 * the startblock, get one now.
1053 */
1054 rcur = *pcur;
1055 if (rcur != NULL && rcur->bc_private.a.agno != agno) {
1056 nr_ops = rcur->bc_private.a.priv.refc.nr_ops;
1057 shape_changes = rcur->bc_private.a.priv.refc.shape_changes;
1058 xfs_refcount_finish_one_cleanup(tp, rcur, 0);
1059 rcur = NULL;
1060 *pcur = NULL;
1061 }
1062 if (rcur == NULL) {
1063 error = xfs_alloc_read_agf(tp->t_mountp, tp, agno,
1064 XFS_ALLOC_FLAG_FREEING, &agbp);
1065 if (error)
1066 return error;
1067 if (!agbp)
1068 return -EFSCORRUPTED;
1069
1070 rcur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno, dfops);
1071 if (!rcur) {
1072 error = -ENOMEM;
1073 goto out_cur;
1074 }
1075 rcur->bc_private.a.priv.refc.nr_ops = nr_ops;
1076 rcur->bc_private.a.priv.refc.shape_changes = shape_changes;
1077 }
1078 *pcur = rcur;
1079
1080 switch (type) {
1081 case XFS_REFCOUNT_INCREASE:
1082 error = xfs_refcount_adjust(rcur, bno, blockcount, &new_agbno,
1083 new_len, XFS_REFCOUNT_ADJUST_INCREASE, dfops, NULL);
1084 *new_fsb = XFS_AGB_TO_FSB(mp, agno, new_agbno);
1085 break;
1086 case XFS_REFCOUNT_DECREASE:
1087 error = xfs_refcount_adjust(rcur, bno, blockcount, &new_agbno,
1088 new_len, XFS_REFCOUNT_ADJUST_DECREASE, dfops, NULL);
1089 *new_fsb = XFS_AGB_TO_FSB(mp, agno, new_agbno);
1090 break;
1091 default:
1092 ASSERT(0);
1093 error = -EFSCORRUPTED;
1094 }
1095 if (!error && *new_len > 0)
1096 trace_xfs_refcount_finish_one_leftover(mp, agno, type,
1097 bno, blockcount, new_agbno, *new_len);
1098 return error;
1099
1100out_cur:
1101 xfs_trans_brelse(tp, agbp);
1102
1103 return error;
1104}
1105
1106/*
1107 * Record a refcount intent for later processing.
1108 */
1109static int
1110__xfs_refcount_add(
1111 struct xfs_mount *mp,
1112 struct xfs_defer_ops *dfops,
1113 enum xfs_refcount_intent_type type,
1114 xfs_fsblock_t startblock,
1115 xfs_extlen_t blockcount)
1116{
1117 struct xfs_refcount_intent *ri;
1118
1119 trace_xfs_refcount_defer(mp, XFS_FSB_TO_AGNO(mp, startblock),
1120 type, XFS_FSB_TO_AGBNO(mp, startblock),
1121 blockcount);
1122
1123 ri = kmem_alloc(sizeof(struct xfs_refcount_intent),
1124 KM_SLEEP | KM_NOFS);
1125 INIT_LIST_HEAD(&ri->ri_list);
1126 ri->ri_type = type;
1127 ri->ri_startblock = startblock;
1128 ri->ri_blockcount = blockcount;
1129
1130 xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_REFCOUNT, &ri->ri_list);
1131 return 0;
1132}
1133
1134/*
1135 * Increase the reference count of the blocks backing a file's extent.
1136 */
1137int
1138xfs_refcount_increase_extent(
1139 struct xfs_mount *mp,
1140 struct xfs_defer_ops *dfops,
1141 struct xfs_bmbt_irec *PREV)
1142{
1143 if (!xfs_sb_version_hasreflink(&mp->m_sb))
1144 return 0;
1145
1146 return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_INCREASE,
1147 PREV->br_startblock, PREV->br_blockcount);
1148}
1149
1150/*
1151 * Decrease the reference count of the blocks backing a file's extent.
1152 */
1153int
1154xfs_refcount_decrease_extent(
1155 struct xfs_mount *mp,
1156 struct xfs_defer_ops *dfops,
1157 struct xfs_bmbt_irec *PREV)
1158{
1159 if (!xfs_sb_version_hasreflink(&mp->m_sb))
1160 return 0;
1161
1162 return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_DECREASE,
1163 PREV->br_startblock, PREV->br_blockcount);
1164}
94097330
DW
1165
1166/*
1167 * Given an AG extent, find the lowest-numbered run of shared blocks
1168 * within that range and return the range in fbno/flen. If
1169 * find_end_of_shared is set, return the longest contiguous extent of
1170 * shared blocks; if not, just return the first extent we find. If no
1171 * shared blocks are found, fbno and flen will be set to NULLAGBLOCK
1172 * and 0, respectively.
1173 */
1174int
1175xfs_refcount_find_shared(
1176 struct xfs_btree_cur *cur,
1177 xfs_agblock_t agbno,
1178 xfs_extlen_t aglen,
1179 xfs_agblock_t *fbno,
1180 xfs_extlen_t *flen,
1181 bool find_end_of_shared)
1182{
1183 struct xfs_refcount_irec tmp;
1184 int i;
1185 int have;
1186 int error;
1187
1188 trace_xfs_refcount_find_shared(cur->bc_mp, cur->bc_private.a.agno,
1189 agbno, aglen);
1190
1191 /* By default, skip the whole range */
1192 *fbno = NULLAGBLOCK;
1193 *flen = 0;
1194
1195 /* Try to find a refcount extent that crosses the start */
1196 error = xfs_refcount_lookup_le(cur, agbno, &have);
1197 if (error)
1198 goto out_error;
1199 if (!have) {
1200 /* No left extent, look at the next one */
1201 error = xfs_btree_increment(cur, 0, &have);
1202 if (error)
1203 goto out_error;
1204 if (!have)
1205 goto done;
1206 }
1207 error = xfs_refcount_get_rec(cur, &tmp, &i);
1208 if (error)
1209 goto out_error;
1210 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, out_error);
1211
1212 /* If the extent ends before the start, look at the next one */
1213 if (tmp.rc_startblock + tmp.rc_blockcount <= agbno) {
1214 error = xfs_btree_increment(cur, 0, &have);
1215 if (error)
1216 goto out_error;
1217 if (!have)
1218 goto done;
1219 error = xfs_refcount_get_rec(cur, &tmp, &i);
1220 if (error)
1221 goto out_error;
1222 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, out_error);
1223 }
1224
1225 /* If the extent starts after the range we want, bail out */
1226 if (tmp.rc_startblock >= agbno + aglen)
1227 goto done;
1228
1229 /* We found the start of a shared extent! */
1230 if (tmp.rc_startblock < agbno) {
1231 tmp.rc_blockcount -= (agbno - tmp.rc_startblock);
1232 tmp.rc_startblock = agbno;
1233 }
1234
1235 *fbno = tmp.rc_startblock;
1236 *flen = min(tmp.rc_blockcount, agbno + aglen - *fbno);
1237 if (!find_end_of_shared)
1238 goto done;
1239
1240 /* Otherwise, find the end of this shared extent */
1241 while (*fbno + *flen < agbno + aglen) {
1242 error = xfs_btree_increment(cur, 0, &have);
1243 if (error)
1244 goto out_error;
1245 if (!have)
1246 break;
1247 error = xfs_refcount_get_rec(cur, &tmp, &i);
1248 if (error)
1249 goto out_error;
1250 XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, out_error);
1251 if (tmp.rc_startblock >= agbno + aglen ||
1252 tmp.rc_startblock != *fbno + *flen)
1253 break;
1254 *flen = min(*flen + tmp.rc_blockcount, agbno + aglen - *fbno);
1255 }
1256
1257done:
1258 trace_xfs_refcount_find_shared_result(cur->bc_mp,
1259 cur->bc_private.a.agno, *fbno, *flen);
1260
1261out_error:
1262 if (error)
1263 trace_xfs_refcount_find_shared_error(cur->bc_mp,
1264 cur->bc_private.a.agno, error, _RET_IP_);
1265 return error;
1266}