Loading...
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2014 Red Hat, Inc.
4 * All Rights Reserved.
5 */
6#include "xfs.h"
7#include "xfs_fs.h"
8#include "xfs_shared.h"
9#include "xfs_format.h"
10#include "xfs_log_format.h"
11#include "xfs_trans_resv.h"
12#include "xfs_bit.h"
13#include "xfs_mount.h"
14#include "xfs_sb.h"
15#include "xfs_defer.h"
16#include "xfs_btree.h"
17#include "xfs_trans.h"
18#include "xfs_alloc.h"
19#include "xfs_rmap.h"
20#include "xfs_rmap_btree.h"
21#include "xfs_trace.h"
22#include "xfs_errortag.h"
23#include "xfs_error.h"
24#include "xfs_inode.h"
25#include "xfs_ag.h"
26
27struct kmem_cache *xfs_rmap_intent_cache;
28
29/*
30 * Lookup the first record less than or equal to [bno, len, owner, offset]
31 * in the btree given by cur.
32 */
33int
34xfs_rmap_lookup_le(
35 struct xfs_btree_cur *cur,
36 xfs_agblock_t bno,
37 uint64_t owner,
38 uint64_t offset,
39 unsigned int flags,
40 struct xfs_rmap_irec *irec,
41 int *stat)
42{
43 int get_stat = 0;
44 int error;
45
46 cur->bc_rec.r.rm_startblock = bno;
47 cur->bc_rec.r.rm_blockcount = 0;
48 cur->bc_rec.r.rm_owner = owner;
49 cur->bc_rec.r.rm_offset = offset;
50 cur->bc_rec.r.rm_flags = flags;
51
52 error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
53 if (error || !(*stat) || !irec)
54 return error;
55
56 error = xfs_rmap_get_rec(cur, irec, &get_stat);
57 if (error)
58 return error;
59 if (!get_stat)
60 return -EFSCORRUPTED;
61
62 return 0;
63}
64
65/*
66 * Lookup the record exactly matching [bno, len, owner, offset]
67 * in the btree given by cur.
68 */
69int
70xfs_rmap_lookup_eq(
71 struct xfs_btree_cur *cur,
72 xfs_agblock_t bno,
73 xfs_extlen_t len,
74 uint64_t owner,
75 uint64_t offset,
76 unsigned int flags,
77 int *stat)
78{
79 cur->bc_rec.r.rm_startblock = bno;
80 cur->bc_rec.r.rm_blockcount = len;
81 cur->bc_rec.r.rm_owner = owner;
82 cur->bc_rec.r.rm_offset = offset;
83 cur->bc_rec.r.rm_flags = flags;
84 return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
85}
86
87/*
88 * Update the record referred to by cur to the value given
89 * by [bno, len, owner, offset].
90 * This either works (return 0) or gets an EFSCORRUPTED error.
91 */
92STATIC int
93xfs_rmap_update(
94 struct xfs_btree_cur *cur,
95 struct xfs_rmap_irec *irec)
96{
97 union xfs_btree_rec rec;
98 int error;
99
100 trace_xfs_rmap_update(cur->bc_mp, cur->bc_ag.pag->pag_agno,
101 irec->rm_startblock, irec->rm_blockcount,
102 irec->rm_owner, irec->rm_offset, irec->rm_flags);
103
104 rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
105 rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
106 rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
107 rec.rmap.rm_offset = cpu_to_be64(
108 xfs_rmap_irec_offset_pack(irec));
109 error = xfs_btree_update(cur, &rec);
110 if (error)
111 trace_xfs_rmap_update_error(cur->bc_mp,
112 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
113 return error;
114}
115
116int
117xfs_rmap_insert(
118 struct xfs_btree_cur *rcur,
119 xfs_agblock_t agbno,
120 xfs_extlen_t len,
121 uint64_t owner,
122 uint64_t offset,
123 unsigned int flags)
124{
125 int i;
126 int error;
127
128 trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno,
129 len, owner, offset, flags);
130
131 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
132 if (error)
133 goto done;
134 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 0)) {
135 error = -EFSCORRUPTED;
136 goto done;
137 }
138
139 rcur->bc_rec.r.rm_startblock = agbno;
140 rcur->bc_rec.r.rm_blockcount = len;
141 rcur->bc_rec.r.rm_owner = owner;
142 rcur->bc_rec.r.rm_offset = offset;
143 rcur->bc_rec.r.rm_flags = flags;
144 error = xfs_btree_insert(rcur, &i);
145 if (error)
146 goto done;
147 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
148 error = -EFSCORRUPTED;
149 goto done;
150 }
151done:
152 if (error)
153 trace_xfs_rmap_insert_error(rcur->bc_mp,
154 rcur->bc_ag.pag->pag_agno, error, _RET_IP_);
155 return error;
156}
157
158STATIC int
159xfs_rmap_delete(
160 struct xfs_btree_cur *rcur,
161 xfs_agblock_t agbno,
162 xfs_extlen_t len,
163 uint64_t owner,
164 uint64_t offset,
165 unsigned int flags)
166{
167 int i;
168 int error;
169
170 trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno,
171 len, owner, offset, flags);
172
173 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
174 if (error)
175 goto done;
176 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
177 error = -EFSCORRUPTED;
178 goto done;
179 }
180
181 error = xfs_btree_delete(rcur, &i);
182 if (error)
183 goto done;
184 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
185 error = -EFSCORRUPTED;
186 goto done;
187 }
188done:
189 if (error)
190 trace_xfs_rmap_delete_error(rcur->bc_mp,
191 rcur->bc_ag.pag->pag_agno, error, _RET_IP_);
192 return error;
193}
194
195/* Convert an internal btree record to an rmap record. */
196xfs_failaddr_t
197xfs_rmap_btrec_to_irec(
198 const union xfs_btree_rec *rec,
199 struct xfs_rmap_irec *irec)
200{
201 irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
202 irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
203 irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
204 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
205 irec);
206}
207
208/* Simple checks for rmap records. */
209xfs_failaddr_t
210xfs_rmap_check_irec(
211 struct xfs_btree_cur *cur,
212 const struct xfs_rmap_irec *irec)
213{
214 struct xfs_mount *mp = cur->bc_mp;
215 bool is_inode;
216 bool is_unwritten;
217 bool is_bmbt;
218 bool is_attr;
219
220 if (irec->rm_blockcount == 0)
221 return __this_address;
222 if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
223 if (irec->rm_owner != XFS_RMAP_OWN_FS)
224 return __this_address;
225 if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
226 return __this_address;
227 } else {
228 /* check for valid extent range, including overflow */
229 if (!xfs_verify_agbext(cur->bc_ag.pag, irec->rm_startblock,
230 irec->rm_blockcount))
231 return __this_address;
232 }
233
234 if (!(xfs_verify_ino(mp, irec->rm_owner) ||
235 (irec->rm_owner <= XFS_RMAP_OWN_FS &&
236 irec->rm_owner >= XFS_RMAP_OWN_MIN)))
237 return __this_address;
238
239 /* Check flags. */
240 is_inode = !XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
241 is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
242 is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
243 is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
244
245 if (is_bmbt && irec->rm_offset != 0)
246 return __this_address;
247
248 if (!is_inode && irec->rm_offset != 0)
249 return __this_address;
250
251 if (is_unwritten && (is_bmbt || !is_inode || is_attr))
252 return __this_address;
253
254 if (!is_inode && (is_bmbt || is_unwritten || is_attr))
255 return __this_address;
256
257 /* Check for a valid fork offset, if applicable. */
258 if (is_inode && !is_bmbt &&
259 !xfs_verify_fileext(mp, irec->rm_offset, irec->rm_blockcount))
260 return __this_address;
261
262 return NULL;
263}
264
265static inline int
266xfs_rmap_complain_bad_rec(
267 struct xfs_btree_cur *cur,
268 xfs_failaddr_t fa,
269 const struct xfs_rmap_irec *irec)
270{
271 struct xfs_mount *mp = cur->bc_mp;
272
273 xfs_warn(mp,
274 "Reverse Mapping BTree record corruption in AG %d detected at %pS!",
275 cur->bc_ag.pag->pag_agno, fa);
276 xfs_warn(mp,
277 "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
278 irec->rm_owner, irec->rm_flags, irec->rm_startblock,
279 irec->rm_blockcount);
280 return -EFSCORRUPTED;
281}
282
283/*
284 * Get the data from the pointed-to record.
285 */
286int
287xfs_rmap_get_rec(
288 struct xfs_btree_cur *cur,
289 struct xfs_rmap_irec *irec,
290 int *stat)
291{
292 union xfs_btree_rec *rec;
293 xfs_failaddr_t fa;
294 int error;
295
296 error = xfs_btree_get_rec(cur, &rec, stat);
297 if (error || !*stat)
298 return error;
299
300 fa = xfs_rmap_btrec_to_irec(rec, irec);
301 if (!fa)
302 fa = xfs_rmap_check_irec(cur, irec);
303 if (fa)
304 return xfs_rmap_complain_bad_rec(cur, fa, irec);
305
306 return 0;
307}
308
309struct xfs_find_left_neighbor_info {
310 struct xfs_rmap_irec high;
311 struct xfs_rmap_irec *irec;
312};
313
314/* For each rmap given, figure out if it matches the key we want. */
315STATIC int
316xfs_rmap_find_left_neighbor_helper(
317 struct xfs_btree_cur *cur,
318 const struct xfs_rmap_irec *rec,
319 void *priv)
320{
321 struct xfs_find_left_neighbor_info *info = priv;
322
323 trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
324 cur->bc_ag.pag->pag_agno, rec->rm_startblock,
325 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
326 rec->rm_flags);
327
328 if (rec->rm_owner != info->high.rm_owner)
329 return 0;
330 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
331 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
332 rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
333 return 0;
334
335 *info->irec = *rec;
336 return -ECANCELED;
337}
338
339/*
340 * Find the record to the left of the given extent, being careful only to
341 * return a match with the same owner and adjacent physical and logical
342 * block ranges.
343 */
344STATIC int
345xfs_rmap_find_left_neighbor(
346 struct xfs_btree_cur *cur,
347 xfs_agblock_t bno,
348 uint64_t owner,
349 uint64_t offset,
350 unsigned int flags,
351 struct xfs_rmap_irec *irec,
352 int *stat)
353{
354 struct xfs_find_left_neighbor_info info;
355 int found = 0;
356 int error;
357
358 *stat = 0;
359 if (bno == 0)
360 return 0;
361 info.high.rm_startblock = bno - 1;
362 info.high.rm_owner = owner;
363 if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
364 !(flags & XFS_RMAP_BMBT_BLOCK)) {
365 if (offset == 0)
366 return 0;
367 info.high.rm_offset = offset - 1;
368 } else
369 info.high.rm_offset = 0;
370 info.high.rm_flags = flags;
371 info.high.rm_blockcount = 0;
372 info.irec = irec;
373
374 trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
375 cur->bc_ag.pag->pag_agno, bno, 0, owner, offset, flags);
376
377 /*
378 * Historically, we always used the range query to walk every reverse
379 * mapping that could possibly overlap the key that the caller asked
380 * for, and filter out the ones that don't. That is very slow when
381 * there are a lot of records.
382 *
383 * However, there are two scenarios where the classic btree search can
384 * produce correct results -- if the index contains a record that is an
385 * exact match for the lookup key; and if there are no other records
386 * between the record we want and the key we supplied.
387 *
388 * As an optimization, try a non-overlapped lookup first. This makes
389 * extent conversion and remap operations run a bit faster if the
390 * physical extents aren't being shared. If we don't find what we
391 * want, we fall back to the overlapped query.
392 */
393 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
394 &found);
395 if (error)
396 return error;
397 if (found)
398 error = xfs_rmap_find_left_neighbor_helper(cur, irec, &info);
399 if (!error)
400 error = xfs_rmap_query_range(cur, &info.high, &info.high,
401 xfs_rmap_find_left_neighbor_helper, &info);
402 if (error != -ECANCELED)
403 return error;
404
405 *stat = 1;
406 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
407 cur->bc_ag.pag->pag_agno, irec->rm_startblock,
408 irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
409 irec->rm_flags);
410 return 0;
411}
412
413/* For each rmap given, figure out if it matches the key we want. */
414STATIC int
415xfs_rmap_lookup_le_range_helper(
416 struct xfs_btree_cur *cur,
417 const struct xfs_rmap_irec *rec,
418 void *priv)
419{
420 struct xfs_find_left_neighbor_info *info = priv;
421
422 trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
423 cur->bc_ag.pag->pag_agno, rec->rm_startblock,
424 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
425 rec->rm_flags);
426
427 if (rec->rm_owner != info->high.rm_owner)
428 return 0;
429 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
430 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
431 (rec->rm_offset > info->high.rm_offset ||
432 rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
433 return 0;
434
435 *info->irec = *rec;
436 return -ECANCELED;
437}
438
439/*
440 * Find the record to the left of the given extent, being careful only to
441 * return a match with the same owner and overlapping physical and logical
442 * block ranges. This is the overlapping-interval version of
443 * xfs_rmap_lookup_le.
444 */
445int
446xfs_rmap_lookup_le_range(
447 struct xfs_btree_cur *cur,
448 xfs_agblock_t bno,
449 uint64_t owner,
450 uint64_t offset,
451 unsigned int flags,
452 struct xfs_rmap_irec *irec,
453 int *stat)
454{
455 struct xfs_find_left_neighbor_info info;
456 int found = 0;
457 int error;
458
459 info.high.rm_startblock = bno;
460 info.high.rm_owner = owner;
461 if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
462 info.high.rm_offset = offset;
463 else
464 info.high.rm_offset = 0;
465 info.high.rm_flags = flags;
466 info.high.rm_blockcount = 0;
467 *stat = 0;
468 info.irec = irec;
469
470 trace_xfs_rmap_lookup_le_range(cur->bc_mp, cur->bc_ag.pag->pag_agno,
471 bno, 0, owner, offset, flags);
472
473 /*
474 * Historically, we always used the range query to walk every reverse
475 * mapping that could possibly overlap the key that the caller asked
476 * for, and filter out the ones that don't. That is very slow when
477 * there are a lot of records.
478 *
479 * However, there are two scenarios where the classic btree search can
480 * produce correct results -- if the index contains a record that is an
481 * exact match for the lookup key; and if there are no other records
482 * between the record we want and the key we supplied.
483 *
484 * As an optimization, try a non-overlapped lookup first. This makes
485 * scrub run much faster on most filesystems because bmbt records are
486 * usually an exact match for rmap records. If we don't find what we
487 * want, we fall back to the overlapped query.
488 */
489 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
490 &found);
491 if (error)
492 return error;
493 if (found)
494 error = xfs_rmap_lookup_le_range_helper(cur, irec, &info);
495 if (!error)
496 error = xfs_rmap_query_range(cur, &info.high, &info.high,
497 xfs_rmap_lookup_le_range_helper, &info);
498 if (error != -ECANCELED)
499 return error;
500
501 *stat = 1;
502 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
503 cur->bc_ag.pag->pag_agno, irec->rm_startblock,
504 irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
505 irec->rm_flags);
506 return 0;
507}
508
509/*
510 * Perform all the relevant owner checks for a removal op. If we're doing an
511 * unknown-owner removal then we have no owner information to check.
512 */
513static int
514xfs_rmap_free_check_owner(
515 struct xfs_mount *mp,
516 uint64_t ltoff,
517 struct xfs_rmap_irec *rec,
518 xfs_filblks_t len,
519 uint64_t owner,
520 uint64_t offset,
521 unsigned int flags)
522{
523 int error = 0;
524
525 if (owner == XFS_RMAP_OWN_UNKNOWN)
526 return 0;
527
528 /* Make sure the unwritten flag matches. */
529 if (XFS_IS_CORRUPT(mp,
530 (flags & XFS_RMAP_UNWRITTEN) !=
531 (rec->rm_flags & XFS_RMAP_UNWRITTEN))) {
532 error = -EFSCORRUPTED;
533 goto out;
534 }
535
536 /* Make sure the owner matches what we expect to find in the tree. */
537 if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) {
538 error = -EFSCORRUPTED;
539 goto out;
540 }
541
542 /* Check the offset, if necessary. */
543 if (XFS_RMAP_NON_INODE_OWNER(owner))
544 goto out;
545
546 if (flags & XFS_RMAP_BMBT_BLOCK) {
547 if (XFS_IS_CORRUPT(mp,
548 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) {
549 error = -EFSCORRUPTED;
550 goto out;
551 }
552 } else {
553 if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) {
554 error = -EFSCORRUPTED;
555 goto out;
556 }
557 if (XFS_IS_CORRUPT(mp,
558 offset + len > ltoff + rec->rm_blockcount)) {
559 error = -EFSCORRUPTED;
560 goto out;
561 }
562 }
563
564out:
565 return error;
566}
567
568/*
569 * Find the extent in the rmap btree and remove it.
570 *
571 * The record we find should always be an exact match for the extent that we're
572 * looking for, since we insert them into the btree without modification.
573 *
574 * Special Case #1: when growing the filesystem, we "free" an extent when
575 * growing the last AG. This extent is new space and so it is not tracked as
576 * used space in the btree. The growfs code will pass in an owner of
577 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
578 * extent. We verify that - the extent lookup result in a record that does not
579 * overlap.
580 *
581 * Special Case #2: EFIs do not record the owner of the extent, so when
582 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
583 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
584 * corruption checks during log recovery.
585 */
586STATIC int
587xfs_rmap_unmap(
588 struct xfs_btree_cur *cur,
589 xfs_agblock_t bno,
590 xfs_extlen_t len,
591 bool unwritten,
592 const struct xfs_owner_info *oinfo)
593{
594 struct xfs_mount *mp = cur->bc_mp;
595 struct xfs_rmap_irec ltrec;
596 uint64_t ltoff;
597 int error = 0;
598 int i;
599 uint64_t owner;
600 uint64_t offset;
601 unsigned int flags;
602 bool ignore_off;
603
604 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
605 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
606 (flags & XFS_RMAP_BMBT_BLOCK);
607 if (unwritten)
608 flags |= XFS_RMAP_UNWRITTEN;
609 trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
610 unwritten, oinfo);
611
612 /*
613 * We should always have a left record because there's a static record
614 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
615 * will not ever be removed from the tree.
616 */
617 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, <rec, &i);
618 if (error)
619 goto out_error;
620 if (XFS_IS_CORRUPT(mp, i != 1)) {
621 error = -EFSCORRUPTED;
622 goto out_error;
623 }
624
625 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
626 cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
627 ltrec.rm_blockcount, ltrec.rm_owner,
628 ltrec.rm_offset, ltrec.rm_flags);
629 ltoff = ltrec.rm_offset;
630
631 /*
632 * For growfs, the incoming extent must be beyond the left record we
633 * just found as it is new space and won't be used by anyone. This is
634 * just a corruption check as we don't actually do anything with this
635 * extent. Note that we need to use >= instead of > because it might
636 * be the case that the "left" extent goes all the way to EOFS.
637 */
638 if (owner == XFS_RMAP_OWN_NULL) {
639 if (XFS_IS_CORRUPT(mp,
640 bno <
641 ltrec.rm_startblock + ltrec.rm_blockcount)) {
642 error = -EFSCORRUPTED;
643 goto out_error;
644 }
645 goto out_done;
646 }
647
648 /*
649 * If we're doing an unknown-owner removal for EFI recovery, we expect
650 * to find the full range in the rmapbt or nothing at all. If we
651 * don't find any rmaps overlapping either end of the range, we're
652 * done. Hopefully this means that the EFI creator already queued
653 * (and finished) a RUI to remove the rmap.
654 */
655 if (owner == XFS_RMAP_OWN_UNKNOWN &&
656 ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
657 struct xfs_rmap_irec rtrec;
658
659 error = xfs_btree_increment(cur, 0, &i);
660 if (error)
661 goto out_error;
662 if (i == 0)
663 goto out_done;
664 error = xfs_rmap_get_rec(cur, &rtrec, &i);
665 if (error)
666 goto out_error;
667 if (XFS_IS_CORRUPT(mp, i != 1)) {
668 error = -EFSCORRUPTED;
669 goto out_error;
670 }
671 if (rtrec.rm_startblock >= bno + len)
672 goto out_done;
673 }
674
675 /* Make sure the extent we found covers the entire freeing range. */
676 if (XFS_IS_CORRUPT(mp,
677 ltrec.rm_startblock > bno ||
678 ltrec.rm_startblock + ltrec.rm_blockcount <
679 bno + len)) {
680 error = -EFSCORRUPTED;
681 goto out_error;
682 }
683
684 /* Check owner information. */
685 error = xfs_rmap_free_check_owner(mp, ltoff, <rec, len, owner,
686 offset, flags);
687 if (error)
688 goto out_error;
689
690 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
691 /* exact match, simply remove the record from rmap tree */
692 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
693 ltrec.rm_startblock, ltrec.rm_blockcount,
694 ltrec.rm_owner, ltrec.rm_offset,
695 ltrec.rm_flags);
696 error = xfs_btree_delete(cur, &i);
697 if (error)
698 goto out_error;
699 if (XFS_IS_CORRUPT(mp, i != 1)) {
700 error = -EFSCORRUPTED;
701 goto out_error;
702 }
703 } else if (ltrec.rm_startblock == bno) {
704 /*
705 * overlap left hand side of extent: move the start, trim the
706 * length and update the current record.
707 *
708 * ltbno ltlen
709 * Orig: |oooooooooooooooooooo|
710 * Freeing: |fffffffff|
711 * Result: |rrrrrrrrrr|
712 * bno len
713 */
714 ltrec.rm_startblock += len;
715 ltrec.rm_blockcount -= len;
716 if (!ignore_off)
717 ltrec.rm_offset += len;
718 error = xfs_rmap_update(cur, <rec);
719 if (error)
720 goto out_error;
721 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
722 /*
723 * overlap right hand side of extent: trim the length and update
724 * the current record.
725 *
726 * ltbno ltlen
727 * Orig: |oooooooooooooooooooo|
728 * Freeing: |fffffffff|
729 * Result: |rrrrrrrrrr|
730 * bno len
731 */
732 ltrec.rm_blockcount -= len;
733 error = xfs_rmap_update(cur, <rec);
734 if (error)
735 goto out_error;
736 } else {
737
738 /*
739 * overlap middle of extent: trim the length of the existing
740 * record to the length of the new left-extent size, increment
741 * the insertion position so we can insert a new record
742 * containing the remaining right-extent space.
743 *
744 * ltbno ltlen
745 * Orig: |oooooooooooooooooooo|
746 * Freeing: |fffffffff|
747 * Result: |rrrrr| |rrrr|
748 * bno len
749 */
750 xfs_extlen_t orig_len = ltrec.rm_blockcount;
751
752 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
753 error = xfs_rmap_update(cur, <rec);
754 if (error)
755 goto out_error;
756
757 error = xfs_btree_increment(cur, 0, &i);
758 if (error)
759 goto out_error;
760
761 cur->bc_rec.r.rm_startblock = bno + len;
762 cur->bc_rec.r.rm_blockcount = orig_len - len -
763 ltrec.rm_blockcount;
764 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
765 if (ignore_off)
766 cur->bc_rec.r.rm_offset = 0;
767 else
768 cur->bc_rec.r.rm_offset = offset + len;
769 cur->bc_rec.r.rm_flags = flags;
770 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
771 cur->bc_rec.r.rm_startblock,
772 cur->bc_rec.r.rm_blockcount,
773 cur->bc_rec.r.rm_owner,
774 cur->bc_rec.r.rm_offset,
775 cur->bc_rec.r.rm_flags);
776 error = xfs_btree_insert(cur, &i);
777 if (error)
778 goto out_error;
779 }
780
781out_done:
782 trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
783 unwritten, oinfo);
784out_error:
785 if (error)
786 trace_xfs_rmap_unmap_error(mp, cur->bc_ag.pag->pag_agno,
787 error, _RET_IP_);
788 return error;
789}
790
791/*
792 * Remove a reference to an extent in the rmap btree.
793 */
794int
795xfs_rmap_free(
796 struct xfs_trans *tp,
797 struct xfs_buf *agbp,
798 struct xfs_perag *pag,
799 xfs_agblock_t bno,
800 xfs_extlen_t len,
801 const struct xfs_owner_info *oinfo)
802{
803 struct xfs_mount *mp = tp->t_mountp;
804 struct xfs_btree_cur *cur;
805 int error;
806
807 if (!xfs_has_rmapbt(mp))
808 return 0;
809
810 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
811
812 error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
813
814 xfs_btree_del_cursor(cur, error);
815 return error;
816}
817
818/*
819 * A mergeable rmap must have the same owner and the same values for
820 * the unwritten, attr_fork, and bmbt flags. The startblock and
821 * offset are checked separately.
822 */
823static bool
824xfs_rmap_is_mergeable(
825 struct xfs_rmap_irec *irec,
826 uint64_t owner,
827 unsigned int flags)
828{
829 if (irec->rm_owner == XFS_RMAP_OWN_NULL)
830 return false;
831 if (irec->rm_owner != owner)
832 return false;
833 if ((flags & XFS_RMAP_UNWRITTEN) ^
834 (irec->rm_flags & XFS_RMAP_UNWRITTEN))
835 return false;
836 if ((flags & XFS_RMAP_ATTR_FORK) ^
837 (irec->rm_flags & XFS_RMAP_ATTR_FORK))
838 return false;
839 if ((flags & XFS_RMAP_BMBT_BLOCK) ^
840 (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
841 return false;
842 return true;
843}
844
845/*
846 * When we allocate a new block, the first thing we do is add a reference to
847 * the extent in the rmap btree. This takes the form of a [agbno, length,
848 * owner, offset] record. Flags are encoded in the high bits of the offset
849 * field.
850 */
851STATIC int
852xfs_rmap_map(
853 struct xfs_btree_cur *cur,
854 xfs_agblock_t bno,
855 xfs_extlen_t len,
856 bool unwritten,
857 const struct xfs_owner_info *oinfo)
858{
859 struct xfs_mount *mp = cur->bc_mp;
860 struct xfs_rmap_irec ltrec;
861 struct xfs_rmap_irec gtrec;
862 int have_gt;
863 int have_lt;
864 int error = 0;
865 int i;
866 uint64_t owner;
867 uint64_t offset;
868 unsigned int flags = 0;
869 bool ignore_off;
870
871 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
872 ASSERT(owner != 0);
873 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
874 (flags & XFS_RMAP_BMBT_BLOCK);
875 if (unwritten)
876 flags |= XFS_RMAP_UNWRITTEN;
877 trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
878 unwritten, oinfo);
879 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
880
881 /*
882 * For the initial lookup, look for an exact match or the left-adjacent
883 * record for our insertion point. This will also give us the record for
884 * start block contiguity tests.
885 */
886 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, <rec,
887 &have_lt);
888 if (error)
889 goto out_error;
890 if (have_lt) {
891 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
892 cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
893 ltrec.rm_blockcount, ltrec.rm_owner,
894 ltrec.rm_offset, ltrec.rm_flags);
895
896 if (!xfs_rmap_is_mergeable(<rec, owner, flags))
897 have_lt = 0;
898 }
899
900 if (XFS_IS_CORRUPT(mp,
901 have_lt != 0 &&
902 ltrec.rm_startblock + ltrec.rm_blockcount > bno)) {
903 error = -EFSCORRUPTED;
904 goto out_error;
905 }
906
907 /*
908 * Increment the cursor to see if we have a right-adjacent record to our
909 * insertion point. This will give us the record for end block
910 * contiguity tests.
911 */
912 error = xfs_btree_increment(cur, 0, &have_gt);
913 if (error)
914 goto out_error;
915 if (have_gt) {
916 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
917 if (error)
918 goto out_error;
919 if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
920 error = -EFSCORRUPTED;
921 goto out_error;
922 }
923 if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) {
924 error = -EFSCORRUPTED;
925 goto out_error;
926 }
927 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
928 cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
929 gtrec.rm_blockcount, gtrec.rm_owner,
930 gtrec.rm_offset, gtrec.rm_flags);
931 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
932 have_gt = 0;
933 }
934
935 /*
936 * Note: cursor currently points one record to the right of ltrec, even
937 * if there is no record in the tree to the right.
938 */
939 if (have_lt &&
940 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
941 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
942 /*
943 * left edge contiguous, merge into left record.
944 *
945 * ltbno ltlen
946 * orig: |ooooooooo|
947 * adding: |aaaaaaaaa|
948 * result: |rrrrrrrrrrrrrrrrrrr|
949 * bno len
950 */
951 ltrec.rm_blockcount += len;
952 if (have_gt &&
953 bno + len == gtrec.rm_startblock &&
954 (ignore_off || offset + len == gtrec.rm_offset) &&
955 (unsigned long)ltrec.rm_blockcount + len +
956 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
957 /*
958 * right edge also contiguous, delete right record
959 * and merge into left record.
960 *
961 * ltbno ltlen gtbno gtlen
962 * orig: |ooooooooo| |ooooooooo|
963 * adding: |aaaaaaaaa|
964 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
965 */
966 ltrec.rm_blockcount += gtrec.rm_blockcount;
967 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
968 gtrec.rm_startblock,
969 gtrec.rm_blockcount,
970 gtrec.rm_owner,
971 gtrec.rm_offset,
972 gtrec.rm_flags);
973 error = xfs_btree_delete(cur, &i);
974 if (error)
975 goto out_error;
976 if (XFS_IS_CORRUPT(mp, i != 1)) {
977 error = -EFSCORRUPTED;
978 goto out_error;
979 }
980 }
981
982 /* point the cursor back to the left record and update */
983 error = xfs_btree_decrement(cur, 0, &have_gt);
984 if (error)
985 goto out_error;
986 error = xfs_rmap_update(cur, <rec);
987 if (error)
988 goto out_error;
989 } else if (have_gt &&
990 bno + len == gtrec.rm_startblock &&
991 (ignore_off || offset + len == gtrec.rm_offset)) {
992 /*
993 * right edge contiguous, merge into right record.
994 *
995 * gtbno gtlen
996 * Orig: |ooooooooo|
997 * adding: |aaaaaaaaa|
998 * Result: |rrrrrrrrrrrrrrrrrrr|
999 * bno len
1000 */
1001 gtrec.rm_startblock = bno;
1002 gtrec.rm_blockcount += len;
1003 if (!ignore_off)
1004 gtrec.rm_offset = offset;
1005 error = xfs_rmap_update(cur, >rec);
1006 if (error)
1007 goto out_error;
1008 } else {
1009 /*
1010 * no contiguous edge with identical owner, insert
1011 * new record at current cursor position.
1012 */
1013 cur->bc_rec.r.rm_startblock = bno;
1014 cur->bc_rec.r.rm_blockcount = len;
1015 cur->bc_rec.r.rm_owner = owner;
1016 cur->bc_rec.r.rm_offset = offset;
1017 cur->bc_rec.r.rm_flags = flags;
1018 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1019 owner, offset, flags);
1020 error = xfs_btree_insert(cur, &i);
1021 if (error)
1022 goto out_error;
1023 if (XFS_IS_CORRUPT(mp, i != 1)) {
1024 error = -EFSCORRUPTED;
1025 goto out_error;
1026 }
1027 }
1028
1029 trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1030 unwritten, oinfo);
1031out_error:
1032 if (error)
1033 trace_xfs_rmap_map_error(mp, cur->bc_ag.pag->pag_agno,
1034 error, _RET_IP_);
1035 return error;
1036}
1037
1038/*
1039 * Add a reference to an extent in the rmap btree.
1040 */
1041int
1042xfs_rmap_alloc(
1043 struct xfs_trans *tp,
1044 struct xfs_buf *agbp,
1045 struct xfs_perag *pag,
1046 xfs_agblock_t bno,
1047 xfs_extlen_t len,
1048 const struct xfs_owner_info *oinfo)
1049{
1050 struct xfs_mount *mp = tp->t_mountp;
1051 struct xfs_btree_cur *cur;
1052 int error;
1053
1054 if (!xfs_has_rmapbt(mp))
1055 return 0;
1056
1057 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
1058 error = xfs_rmap_map(cur, bno, len, false, oinfo);
1059
1060 xfs_btree_del_cursor(cur, error);
1061 return error;
1062}
1063
1064#define RMAP_LEFT_CONTIG (1 << 0)
1065#define RMAP_RIGHT_CONTIG (1 << 1)
1066#define RMAP_LEFT_FILLING (1 << 2)
1067#define RMAP_RIGHT_FILLING (1 << 3)
1068#define RMAP_LEFT_VALID (1 << 6)
1069#define RMAP_RIGHT_VALID (1 << 7)
1070
1071#define LEFT r[0]
1072#define RIGHT r[1]
1073#define PREV r[2]
1074#define NEW r[3]
1075
1076/*
1077 * Convert an unwritten extent to a real extent or vice versa.
1078 * Does not handle overlapping extents.
1079 */
1080STATIC int
1081xfs_rmap_convert(
1082 struct xfs_btree_cur *cur,
1083 xfs_agblock_t bno,
1084 xfs_extlen_t len,
1085 bool unwritten,
1086 const struct xfs_owner_info *oinfo)
1087{
1088 struct xfs_mount *mp = cur->bc_mp;
1089 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1090 /* left is 0, right is 1, */
1091 /* prev is 2, new is 3 */
1092 uint64_t owner;
1093 uint64_t offset;
1094 uint64_t new_endoff;
1095 unsigned int oldext;
1096 unsigned int newext;
1097 unsigned int flags = 0;
1098 int i;
1099 int state = 0;
1100 int error;
1101
1102 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1103 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1104 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1105 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1106 new_endoff = offset + len;
1107 trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1108 unwritten, oinfo);
1109
1110 /*
1111 * For the initial lookup, look for an exact match or the left-adjacent
1112 * record for our insertion point. This will also give us the record for
1113 * start block contiguity tests.
1114 */
1115 error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, &PREV, &i);
1116 if (error)
1117 goto done;
1118 if (XFS_IS_CORRUPT(mp, i != 1)) {
1119 error = -EFSCORRUPTED;
1120 goto done;
1121 }
1122
1123 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
1124 cur->bc_ag.pag->pag_agno, PREV.rm_startblock,
1125 PREV.rm_blockcount, PREV.rm_owner,
1126 PREV.rm_offset, PREV.rm_flags);
1127
1128 ASSERT(PREV.rm_offset <= offset);
1129 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1130 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1131 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1132
1133 /*
1134 * Set flags determining what part of the previous oldext allocation
1135 * extent is being replaced by a newext allocation.
1136 */
1137 if (PREV.rm_offset == offset)
1138 state |= RMAP_LEFT_FILLING;
1139 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1140 state |= RMAP_RIGHT_FILLING;
1141
1142 /*
1143 * Decrement the cursor to see if we have a left-adjacent record to our
1144 * insertion point. This will give us the record for end block
1145 * contiguity tests.
1146 */
1147 error = xfs_btree_decrement(cur, 0, &i);
1148 if (error)
1149 goto done;
1150 if (i) {
1151 state |= RMAP_LEFT_VALID;
1152 error = xfs_rmap_get_rec(cur, &LEFT, &i);
1153 if (error)
1154 goto done;
1155 if (XFS_IS_CORRUPT(mp, i != 1)) {
1156 error = -EFSCORRUPTED;
1157 goto done;
1158 }
1159 if (XFS_IS_CORRUPT(mp,
1160 LEFT.rm_startblock + LEFT.rm_blockcount >
1161 bno)) {
1162 error = -EFSCORRUPTED;
1163 goto done;
1164 }
1165 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
1166 cur->bc_ag.pag->pag_agno, LEFT.rm_startblock,
1167 LEFT.rm_blockcount, LEFT.rm_owner,
1168 LEFT.rm_offset, LEFT.rm_flags);
1169 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1170 LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1171 xfs_rmap_is_mergeable(&LEFT, owner, newext))
1172 state |= RMAP_LEFT_CONTIG;
1173 }
1174
1175 /*
1176 * Increment the cursor to see if we have a right-adjacent record to our
1177 * insertion point. This will give us the record for end block
1178 * contiguity tests.
1179 */
1180 error = xfs_btree_increment(cur, 0, &i);
1181 if (error)
1182 goto done;
1183 if (XFS_IS_CORRUPT(mp, i != 1)) {
1184 error = -EFSCORRUPTED;
1185 goto done;
1186 }
1187 error = xfs_btree_increment(cur, 0, &i);
1188 if (error)
1189 goto done;
1190 if (i) {
1191 state |= RMAP_RIGHT_VALID;
1192 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1193 if (error)
1194 goto done;
1195 if (XFS_IS_CORRUPT(mp, i != 1)) {
1196 error = -EFSCORRUPTED;
1197 goto done;
1198 }
1199 if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1200 error = -EFSCORRUPTED;
1201 goto done;
1202 }
1203 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1204 cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
1205 RIGHT.rm_blockcount, RIGHT.rm_owner,
1206 RIGHT.rm_offset, RIGHT.rm_flags);
1207 if (bno + len == RIGHT.rm_startblock &&
1208 offset + len == RIGHT.rm_offset &&
1209 xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1210 state |= RMAP_RIGHT_CONTIG;
1211 }
1212
1213 /* check that left + prev + right is not too long */
1214 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1215 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1216 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1217 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1218 (unsigned long)LEFT.rm_blockcount + len +
1219 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1220 state &= ~RMAP_RIGHT_CONTIG;
1221
1222 trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
1223 _RET_IP_);
1224
1225 /* reset the cursor back to PREV */
1226 error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, NULL, &i);
1227 if (error)
1228 goto done;
1229 if (XFS_IS_CORRUPT(mp, i != 1)) {
1230 error = -EFSCORRUPTED;
1231 goto done;
1232 }
1233
1234 /*
1235 * Switch out based on the FILLING and CONTIG state bits.
1236 */
1237 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1238 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1239 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1240 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1241 /*
1242 * Setting all of a previous oldext extent to newext.
1243 * The left and right neighbors are both contiguous with new.
1244 */
1245 error = xfs_btree_increment(cur, 0, &i);
1246 if (error)
1247 goto done;
1248 if (XFS_IS_CORRUPT(mp, i != 1)) {
1249 error = -EFSCORRUPTED;
1250 goto done;
1251 }
1252 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1253 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1254 RIGHT.rm_owner, RIGHT.rm_offset,
1255 RIGHT.rm_flags);
1256 error = xfs_btree_delete(cur, &i);
1257 if (error)
1258 goto done;
1259 if (XFS_IS_CORRUPT(mp, i != 1)) {
1260 error = -EFSCORRUPTED;
1261 goto done;
1262 }
1263 error = xfs_btree_decrement(cur, 0, &i);
1264 if (error)
1265 goto done;
1266 if (XFS_IS_CORRUPT(mp, i != 1)) {
1267 error = -EFSCORRUPTED;
1268 goto done;
1269 }
1270 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1271 PREV.rm_startblock, PREV.rm_blockcount,
1272 PREV.rm_owner, PREV.rm_offset,
1273 PREV.rm_flags);
1274 error = xfs_btree_delete(cur, &i);
1275 if (error)
1276 goto done;
1277 if (XFS_IS_CORRUPT(mp, i != 1)) {
1278 error = -EFSCORRUPTED;
1279 goto done;
1280 }
1281 error = xfs_btree_decrement(cur, 0, &i);
1282 if (error)
1283 goto done;
1284 if (XFS_IS_CORRUPT(mp, i != 1)) {
1285 error = -EFSCORRUPTED;
1286 goto done;
1287 }
1288 NEW = LEFT;
1289 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1290 error = xfs_rmap_update(cur, &NEW);
1291 if (error)
1292 goto done;
1293 break;
1294
1295 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1296 /*
1297 * Setting all of a previous oldext extent to newext.
1298 * The left neighbor is contiguous, the right is not.
1299 */
1300 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1301 PREV.rm_startblock, PREV.rm_blockcount,
1302 PREV.rm_owner, PREV.rm_offset,
1303 PREV.rm_flags);
1304 error = xfs_btree_delete(cur, &i);
1305 if (error)
1306 goto done;
1307 if (XFS_IS_CORRUPT(mp, i != 1)) {
1308 error = -EFSCORRUPTED;
1309 goto done;
1310 }
1311 error = xfs_btree_decrement(cur, 0, &i);
1312 if (error)
1313 goto done;
1314 if (XFS_IS_CORRUPT(mp, i != 1)) {
1315 error = -EFSCORRUPTED;
1316 goto done;
1317 }
1318 NEW = LEFT;
1319 NEW.rm_blockcount += PREV.rm_blockcount;
1320 error = xfs_rmap_update(cur, &NEW);
1321 if (error)
1322 goto done;
1323 break;
1324
1325 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1326 /*
1327 * Setting all of a previous oldext extent to newext.
1328 * The right neighbor is contiguous, the left is not.
1329 */
1330 error = xfs_btree_increment(cur, 0, &i);
1331 if (error)
1332 goto done;
1333 if (XFS_IS_CORRUPT(mp, i != 1)) {
1334 error = -EFSCORRUPTED;
1335 goto done;
1336 }
1337 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1338 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1339 RIGHT.rm_owner, RIGHT.rm_offset,
1340 RIGHT.rm_flags);
1341 error = xfs_btree_delete(cur, &i);
1342 if (error)
1343 goto done;
1344 if (XFS_IS_CORRUPT(mp, i != 1)) {
1345 error = -EFSCORRUPTED;
1346 goto done;
1347 }
1348 error = xfs_btree_decrement(cur, 0, &i);
1349 if (error)
1350 goto done;
1351 if (XFS_IS_CORRUPT(mp, i != 1)) {
1352 error = -EFSCORRUPTED;
1353 goto done;
1354 }
1355 NEW = PREV;
1356 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1357 NEW.rm_flags = newext;
1358 error = xfs_rmap_update(cur, &NEW);
1359 if (error)
1360 goto done;
1361 break;
1362
1363 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1364 /*
1365 * Setting all of a previous oldext extent to newext.
1366 * Neither the left nor right neighbors are contiguous with
1367 * the new one.
1368 */
1369 NEW = PREV;
1370 NEW.rm_flags = newext;
1371 error = xfs_rmap_update(cur, &NEW);
1372 if (error)
1373 goto done;
1374 break;
1375
1376 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1377 /*
1378 * Setting the first part of a previous oldext extent to newext.
1379 * The left neighbor is contiguous.
1380 */
1381 NEW = PREV;
1382 NEW.rm_offset += len;
1383 NEW.rm_startblock += len;
1384 NEW.rm_blockcount -= len;
1385 error = xfs_rmap_update(cur, &NEW);
1386 if (error)
1387 goto done;
1388 error = xfs_btree_decrement(cur, 0, &i);
1389 if (error)
1390 goto done;
1391 NEW = LEFT;
1392 NEW.rm_blockcount += len;
1393 error = xfs_rmap_update(cur, &NEW);
1394 if (error)
1395 goto done;
1396 break;
1397
1398 case RMAP_LEFT_FILLING:
1399 /*
1400 * Setting the first part of a previous oldext extent to newext.
1401 * The left neighbor is not contiguous.
1402 */
1403 NEW = PREV;
1404 NEW.rm_startblock += len;
1405 NEW.rm_offset += len;
1406 NEW.rm_blockcount -= len;
1407 error = xfs_rmap_update(cur, &NEW);
1408 if (error)
1409 goto done;
1410 NEW.rm_startblock = bno;
1411 NEW.rm_owner = owner;
1412 NEW.rm_offset = offset;
1413 NEW.rm_blockcount = len;
1414 NEW.rm_flags = newext;
1415 cur->bc_rec.r = NEW;
1416 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
1417 len, owner, offset, newext);
1418 error = xfs_btree_insert(cur, &i);
1419 if (error)
1420 goto done;
1421 if (XFS_IS_CORRUPT(mp, i != 1)) {
1422 error = -EFSCORRUPTED;
1423 goto done;
1424 }
1425 break;
1426
1427 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1428 /*
1429 * Setting the last part of a previous oldext extent to newext.
1430 * The right neighbor is contiguous with the new allocation.
1431 */
1432 NEW = PREV;
1433 NEW.rm_blockcount -= len;
1434 error = xfs_rmap_update(cur, &NEW);
1435 if (error)
1436 goto done;
1437 error = xfs_btree_increment(cur, 0, &i);
1438 if (error)
1439 goto done;
1440 NEW = RIGHT;
1441 NEW.rm_offset = offset;
1442 NEW.rm_startblock = bno;
1443 NEW.rm_blockcount += len;
1444 error = xfs_rmap_update(cur, &NEW);
1445 if (error)
1446 goto done;
1447 break;
1448
1449 case RMAP_RIGHT_FILLING:
1450 /*
1451 * Setting the last part of a previous oldext extent to newext.
1452 * The right neighbor is not contiguous.
1453 */
1454 NEW = PREV;
1455 NEW.rm_blockcount -= len;
1456 error = xfs_rmap_update(cur, &NEW);
1457 if (error)
1458 goto done;
1459 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1460 oldext, &i);
1461 if (error)
1462 goto done;
1463 if (XFS_IS_CORRUPT(mp, i != 0)) {
1464 error = -EFSCORRUPTED;
1465 goto done;
1466 }
1467 NEW.rm_startblock = bno;
1468 NEW.rm_owner = owner;
1469 NEW.rm_offset = offset;
1470 NEW.rm_blockcount = len;
1471 NEW.rm_flags = newext;
1472 cur->bc_rec.r = NEW;
1473 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
1474 len, owner, offset, newext);
1475 error = xfs_btree_insert(cur, &i);
1476 if (error)
1477 goto done;
1478 if (XFS_IS_CORRUPT(mp, i != 1)) {
1479 error = -EFSCORRUPTED;
1480 goto done;
1481 }
1482 break;
1483
1484 case 0:
1485 /*
1486 * Setting the middle part of a previous oldext extent to
1487 * newext. Contiguity is impossible here.
1488 * One extent becomes three extents.
1489 */
1490 /* new right extent - oldext */
1491 NEW.rm_startblock = bno + len;
1492 NEW.rm_owner = owner;
1493 NEW.rm_offset = new_endoff;
1494 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1495 new_endoff;
1496 NEW.rm_flags = PREV.rm_flags;
1497 error = xfs_rmap_update(cur, &NEW);
1498 if (error)
1499 goto done;
1500 /* new left extent - oldext */
1501 NEW = PREV;
1502 NEW.rm_blockcount = offset - PREV.rm_offset;
1503 cur->bc_rec.r = NEW;
1504 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
1505 NEW.rm_startblock, NEW.rm_blockcount,
1506 NEW.rm_owner, NEW.rm_offset,
1507 NEW.rm_flags);
1508 error = xfs_btree_insert(cur, &i);
1509 if (error)
1510 goto done;
1511 if (XFS_IS_CORRUPT(mp, i != 1)) {
1512 error = -EFSCORRUPTED;
1513 goto done;
1514 }
1515 /*
1516 * Reset the cursor to the position of the new extent
1517 * we are about to insert as we can't trust it after
1518 * the previous insert.
1519 */
1520 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1521 oldext, &i);
1522 if (error)
1523 goto done;
1524 if (XFS_IS_CORRUPT(mp, i != 0)) {
1525 error = -EFSCORRUPTED;
1526 goto done;
1527 }
1528 /* new middle extent - newext */
1529 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1530 cur->bc_rec.r.rm_flags |= newext;
1531 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1532 owner, offset, newext);
1533 error = xfs_btree_insert(cur, &i);
1534 if (error)
1535 goto done;
1536 if (XFS_IS_CORRUPT(mp, i != 1)) {
1537 error = -EFSCORRUPTED;
1538 goto done;
1539 }
1540 break;
1541
1542 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1543 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1544 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1545 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1546 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1547 case RMAP_LEFT_CONTIG:
1548 case RMAP_RIGHT_CONTIG:
1549 /*
1550 * These cases are all impossible.
1551 */
1552 ASSERT(0);
1553 }
1554
1555 trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1556 unwritten, oinfo);
1557done:
1558 if (error)
1559 trace_xfs_rmap_convert_error(cur->bc_mp,
1560 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
1561 return error;
1562}
1563
1564/*
1565 * Convert an unwritten extent to a real extent or vice versa. If there is no
1566 * possibility of overlapping extents, delegate to the simpler convert
1567 * function.
1568 */
1569STATIC int
1570xfs_rmap_convert_shared(
1571 struct xfs_btree_cur *cur,
1572 xfs_agblock_t bno,
1573 xfs_extlen_t len,
1574 bool unwritten,
1575 const struct xfs_owner_info *oinfo)
1576{
1577 struct xfs_mount *mp = cur->bc_mp;
1578 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1579 /* left is 0, right is 1, */
1580 /* prev is 2, new is 3 */
1581 uint64_t owner;
1582 uint64_t offset;
1583 uint64_t new_endoff;
1584 unsigned int oldext;
1585 unsigned int newext;
1586 unsigned int flags = 0;
1587 int i;
1588 int state = 0;
1589 int error;
1590
1591 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1592 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1593 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1594 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1595 new_endoff = offset + len;
1596 trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1597 unwritten, oinfo);
1598
1599 /*
1600 * For the initial lookup, look for and exact match or the left-adjacent
1601 * record for our insertion point. This will also give us the record for
1602 * start block contiguity tests.
1603 */
1604 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, oldext,
1605 &PREV, &i);
1606 if (error)
1607 goto done;
1608 if (XFS_IS_CORRUPT(mp, i != 1)) {
1609 error = -EFSCORRUPTED;
1610 goto done;
1611 }
1612
1613 ASSERT(PREV.rm_offset <= offset);
1614 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1615 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1616 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1617
1618 /*
1619 * Set flags determining what part of the previous oldext allocation
1620 * extent is being replaced by a newext allocation.
1621 */
1622 if (PREV.rm_offset == offset)
1623 state |= RMAP_LEFT_FILLING;
1624 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1625 state |= RMAP_RIGHT_FILLING;
1626
1627 /* Is there a left record that abuts our range? */
1628 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1629 &LEFT, &i);
1630 if (error)
1631 goto done;
1632 if (i) {
1633 state |= RMAP_LEFT_VALID;
1634 if (XFS_IS_CORRUPT(mp,
1635 LEFT.rm_startblock + LEFT.rm_blockcount >
1636 bno)) {
1637 error = -EFSCORRUPTED;
1638 goto done;
1639 }
1640 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1641 state |= RMAP_LEFT_CONTIG;
1642 }
1643
1644 /* Is there a right record that abuts our range? */
1645 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1646 newext, &i);
1647 if (error)
1648 goto done;
1649 if (i) {
1650 state |= RMAP_RIGHT_VALID;
1651 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1652 if (error)
1653 goto done;
1654 if (XFS_IS_CORRUPT(mp, i != 1)) {
1655 error = -EFSCORRUPTED;
1656 goto done;
1657 }
1658 if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1659 error = -EFSCORRUPTED;
1660 goto done;
1661 }
1662 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1663 cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
1664 RIGHT.rm_blockcount, RIGHT.rm_owner,
1665 RIGHT.rm_offset, RIGHT.rm_flags);
1666 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1667 state |= RMAP_RIGHT_CONTIG;
1668 }
1669
1670 /* check that left + prev + right is not too long */
1671 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1672 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1673 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1674 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1675 (unsigned long)LEFT.rm_blockcount + len +
1676 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1677 state &= ~RMAP_RIGHT_CONTIG;
1678
1679 trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
1680 _RET_IP_);
1681 /*
1682 * Switch out based on the FILLING and CONTIG state bits.
1683 */
1684 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1685 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1686 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1687 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1688 /*
1689 * Setting all of a previous oldext extent to newext.
1690 * The left and right neighbors are both contiguous with new.
1691 */
1692 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1693 RIGHT.rm_blockcount, RIGHT.rm_owner,
1694 RIGHT.rm_offset, RIGHT.rm_flags);
1695 if (error)
1696 goto done;
1697 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1698 PREV.rm_blockcount, PREV.rm_owner,
1699 PREV.rm_offset, PREV.rm_flags);
1700 if (error)
1701 goto done;
1702 NEW = LEFT;
1703 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1704 NEW.rm_blockcount, NEW.rm_owner,
1705 NEW.rm_offset, NEW.rm_flags, &i);
1706 if (error)
1707 goto done;
1708 if (XFS_IS_CORRUPT(mp, i != 1)) {
1709 error = -EFSCORRUPTED;
1710 goto done;
1711 }
1712 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1713 error = xfs_rmap_update(cur, &NEW);
1714 if (error)
1715 goto done;
1716 break;
1717
1718 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1719 /*
1720 * Setting all of a previous oldext extent to newext.
1721 * The left neighbor is contiguous, the right is not.
1722 */
1723 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1724 PREV.rm_blockcount, PREV.rm_owner,
1725 PREV.rm_offset, PREV.rm_flags);
1726 if (error)
1727 goto done;
1728 NEW = LEFT;
1729 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1730 NEW.rm_blockcount, NEW.rm_owner,
1731 NEW.rm_offset, NEW.rm_flags, &i);
1732 if (error)
1733 goto done;
1734 if (XFS_IS_CORRUPT(mp, i != 1)) {
1735 error = -EFSCORRUPTED;
1736 goto done;
1737 }
1738 NEW.rm_blockcount += PREV.rm_blockcount;
1739 error = xfs_rmap_update(cur, &NEW);
1740 if (error)
1741 goto done;
1742 break;
1743
1744 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1745 /*
1746 * Setting all of a previous oldext extent to newext.
1747 * The right neighbor is contiguous, the left is not.
1748 */
1749 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1750 RIGHT.rm_blockcount, RIGHT.rm_owner,
1751 RIGHT.rm_offset, RIGHT.rm_flags);
1752 if (error)
1753 goto done;
1754 NEW = PREV;
1755 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1756 NEW.rm_blockcount, NEW.rm_owner,
1757 NEW.rm_offset, NEW.rm_flags, &i);
1758 if (error)
1759 goto done;
1760 if (XFS_IS_CORRUPT(mp, i != 1)) {
1761 error = -EFSCORRUPTED;
1762 goto done;
1763 }
1764 NEW.rm_blockcount += RIGHT.rm_blockcount;
1765 NEW.rm_flags = RIGHT.rm_flags;
1766 error = xfs_rmap_update(cur, &NEW);
1767 if (error)
1768 goto done;
1769 break;
1770
1771 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1772 /*
1773 * Setting all of a previous oldext extent to newext.
1774 * Neither the left nor right neighbors are contiguous with
1775 * the new one.
1776 */
1777 NEW = PREV;
1778 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1779 NEW.rm_blockcount, NEW.rm_owner,
1780 NEW.rm_offset, NEW.rm_flags, &i);
1781 if (error)
1782 goto done;
1783 if (XFS_IS_CORRUPT(mp, i != 1)) {
1784 error = -EFSCORRUPTED;
1785 goto done;
1786 }
1787 NEW.rm_flags = newext;
1788 error = xfs_rmap_update(cur, &NEW);
1789 if (error)
1790 goto done;
1791 break;
1792
1793 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1794 /*
1795 * Setting the first part of a previous oldext extent to newext.
1796 * The left neighbor is contiguous.
1797 */
1798 NEW = PREV;
1799 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1800 NEW.rm_blockcount, NEW.rm_owner,
1801 NEW.rm_offset, NEW.rm_flags);
1802 if (error)
1803 goto done;
1804 NEW.rm_offset += len;
1805 NEW.rm_startblock += len;
1806 NEW.rm_blockcount -= len;
1807 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1808 NEW.rm_blockcount, NEW.rm_owner,
1809 NEW.rm_offset, NEW.rm_flags);
1810 if (error)
1811 goto done;
1812 NEW = LEFT;
1813 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1814 NEW.rm_blockcount, NEW.rm_owner,
1815 NEW.rm_offset, NEW.rm_flags, &i);
1816 if (error)
1817 goto done;
1818 if (XFS_IS_CORRUPT(mp, i != 1)) {
1819 error = -EFSCORRUPTED;
1820 goto done;
1821 }
1822 NEW.rm_blockcount += len;
1823 error = xfs_rmap_update(cur, &NEW);
1824 if (error)
1825 goto done;
1826 break;
1827
1828 case RMAP_LEFT_FILLING:
1829 /*
1830 * Setting the first part of a previous oldext extent to newext.
1831 * The left neighbor is not contiguous.
1832 */
1833 NEW = PREV;
1834 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1835 NEW.rm_blockcount, NEW.rm_owner,
1836 NEW.rm_offset, NEW.rm_flags);
1837 if (error)
1838 goto done;
1839 NEW.rm_offset += len;
1840 NEW.rm_startblock += len;
1841 NEW.rm_blockcount -= len;
1842 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1843 NEW.rm_blockcount, NEW.rm_owner,
1844 NEW.rm_offset, NEW.rm_flags);
1845 if (error)
1846 goto done;
1847 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1848 if (error)
1849 goto done;
1850 break;
1851
1852 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1853 /*
1854 * Setting the last part of a previous oldext extent to newext.
1855 * The right neighbor is contiguous with the new allocation.
1856 */
1857 NEW = PREV;
1858 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1859 NEW.rm_blockcount, NEW.rm_owner,
1860 NEW.rm_offset, NEW.rm_flags, &i);
1861 if (error)
1862 goto done;
1863 if (XFS_IS_CORRUPT(mp, i != 1)) {
1864 error = -EFSCORRUPTED;
1865 goto done;
1866 }
1867 NEW.rm_blockcount = offset - NEW.rm_offset;
1868 error = xfs_rmap_update(cur, &NEW);
1869 if (error)
1870 goto done;
1871 NEW = RIGHT;
1872 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1873 NEW.rm_blockcount, NEW.rm_owner,
1874 NEW.rm_offset, NEW.rm_flags);
1875 if (error)
1876 goto done;
1877 NEW.rm_offset = offset;
1878 NEW.rm_startblock = bno;
1879 NEW.rm_blockcount += len;
1880 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1881 NEW.rm_blockcount, NEW.rm_owner,
1882 NEW.rm_offset, NEW.rm_flags);
1883 if (error)
1884 goto done;
1885 break;
1886
1887 case RMAP_RIGHT_FILLING:
1888 /*
1889 * Setting the last part of a previous oldext extent to newext.
1890 * The right neighbor is not contiguous.
1891 */
1892 NEW = PREV;
1893 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1894 NEW.rm_blockcount, NEW.rm_owner,
1895 NEW.rm_offset, NEW.rm_flags, &i);
1896 if (error)
1897 goto done;
1898 if (XFS_IS_CORRUPT(mp, i != 1)) {
1899 error = -EFSCORRUPTED;
1900 goto done;
1901 }
1902 NEW.rm_blockcount -= len;
1903 error = xfs_rmap_update(cur, &NEW);
1904 if (error)
1905 goto done;
1906 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1907 if (error)
1908 goto done;
1909 break;
1910
1911 case 0:
1912 /*
1913 * Setting the middle part of a previous oldext extent to
1914 * newext. Contiguity is impossible here.
1915 * One extent becomes three extents.
1916 */
1917 /* new right extent - oldext */
1918 NEW.rm_startblock = bno + len;
1919 NEW.rm_owner = owner;
1920 NEW.rm_offset = new_endoff;
1921 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1922 new_endoff;
1923 NEW.rm_flags = PREV.rm_flags;
1924 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1925 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1926 NEW.rm_flags);
1927 if (error)
1928 goto done;
1929 /* new left extent - oldext */
1930 NEW = PREV;
1931 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1932 NEW.rm_blockcount, NEW.rm_owner,
1933 NEW.rm_offset, NEW.rm_flags, &i);
1934 if (error)
1935 goto done;
1936 if (XFS_IS_CORRUPT(mp, i != 1)) {
1937 error = -EFSCORRUPTED;
1938 goto done;
1939 }
1940 NEW.rm_blockcount = offset - NEW.rm_offset;
1941 error = xfs_rmap_update(cur, &NEW);
1942 if (error)
1943 goto done;
1944 /* new middle extent - newext */
1945 NEW.rm_startblock = bno;
1946 NEW.rm_blockcount = len;
1947 NEW.rm_owner = owner;
1948 NEW.rm_offset = offset;
1949 NEW.rm_flags = newext;
1950 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1951 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1952 NEW.rm_flags);
1953 if (error)
1954 goto done;
1955 break;
1956
1957 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1958 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1959 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1960 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1961 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1962 case RMAP_LEFT_CONTIG:
1963 case RMAP_RIGHT_CONTIG:
1964 /*
1965 * These cases are all impossible.
1966 */
1967 ASSERT(0);
1968 }
1969
1970 trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1971 unwritten, oinfo);
1972done:
1973 if (error)
1974 trace_xfs_rmap_convert_error(cur->bc_mp,
1975 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
1976 return error;
1977}
1978
1979#undef NEW
1980#undef LEFT
1981#undef RIGHT
1982#undef PREV
1983
1984/*
1985 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1986 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1987 * that the prev/next records in the btree might belong to another owner.
1988 * Therefore we must use delete+insert to alter any of the key fields.
1989 *
1990 * For every other situation there can only be one owner for a given extent,
1991 * so we can call the regular _free function.
1992 */
1993STATIC int
1994xfs_rmap_unmap_shared(
1995 struct xfs_btree_cur *cur,
1996 xfs_agblock_t bno,
1997 xfs_extlen_t len,
1998 bool unwritten,
1999 const struct xfs_owner_info *oinfo)
2000{
2001 struct xfs_mount *mp = cur->bc_mp;
2002 struct xfs_rmap_irec ltrec;
2003 uint64_t ltoff;
2004 int error = 0;
2005 int i;
2006 uint64_t owner;
2007 uint64_t offset;
2008 unsigned int flags;
2009
2010 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2011 if (unwritten)
2012 flags |= XFS_RMAP_UNWRITTEN;
2013 trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
2014 unwritten, oinfo);
2015
2016 /*
2017 * We should always have a left record because there's a static record
2018 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
2019 * will not ever be removed from the tree.
2020 */
2021 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
2022 <rec, &i);
2023 if (error)
2024 goto out_error;
2025 if (XFS_IS_CORRUPT(mp, i != 1)) {
2026 error = -EFSCORRUPTED;
2027 goto out_error;
2028 }
2029 ltoff = ltrec.rm_offset;
2030
2031 /* Make sure the extent we found covers the entire freeing range. */
2032 if (XFS_IS_CORRUPT(mp,
2033 ltrec.rm_startblock > bno ||
2034 ltrec.rm_startblock + ltrec.rm_blockcount <
2035 bno + len)) {
2036 error = -EFSCORRUPTED;
2037 goto out_error;
2038 }
2039
2040 /* Make sure the owner matches what we expect to find in the tree. */
2041 if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) {
2042 error = -EFSCORRUPTED;
2043 goto out_error;
2044 }
2045
2046 /* Make sure the unwritten flag matches. */
2047 if (XFS_IS_CORRUPT(mp,
2048 (flags & XFS_RMAP_UNWRITTEN) !=
2049 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) {
2050 error = -EFSCORRUPTED;
2051 goto out_error;
2052 }
2053
2054 /* Check the offset. */
2055 if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) {
2056 error = -EFSCORRUPTED;
2057 goto out_error;
2058 }
2059 if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) {
2060 error = -EFSCORRUPTED;
2061 goto out_error;
2062 }
2063
2064 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
2065 /* Exact match, simply remove the record from rmap tree. */
2066 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2067 ltrec.rm_blockcount, ltrec.rm_owner,
2068 ltrec.rm_offset, ltrec.rm_flags);
2069 if (error)
2070 goto out_error;
2071 } else if (ltrec.rm_startblock == bno) {
2072 /*
2073 * Overlap left hand side of extent: move the start, trim the
2074 * length and update the current record.
2075 *
2076 * ltbno ltlen
2077 * Orig: |oooooooooooooooooooo|
2078 * Freeing: |fffffffff|
2079 * Result: |rrrrrrrrrr|
2080 * bno len
2081 */
2082
2083 /* Delete prev rmap. */
2084 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2085 ltrec.rm_blockcount, ltrec.rm_owner,
2086 ltrec.rm_offset, ltrec.rm_flags);
2087 if (error)
2088 goto out_error;
2089
2090 /* Add an rmap at the new offset. */
2091 ltrec.rm_startblock += len;
2092 ltrec.rm_blockcount -= len;
2093 ltrec.rm_offset += len;
2094 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
2095 ltrec.rm_blockcount, ltrec.rm_owner,
2096 ltrec.rm_offset, ltrec.rm_flags);
2097 if (error)
2098 goto out_error;
2099 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
2100 /*
2101 * Overlap right hand side of extent: trim the length and
2102 * update the current record.
2103 *
2104 * ltbno ltlen
2105 * Orig: |oooooooooooooooooooo|
2106 * Freeing: |fffffffff|
2107 * Result: |rrrrrrrrrr|
2108 * bno len
2109 */
2110 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2111 ltrec.rm_blockcount, ltrec.rm_owner,
2112 ltrec.rm_offset, ltrec.rm_flags, &i);
2113 if (error)
2114 goto out_error;
2115 if (XFS_IS_CORRUPT(mp, i != 1)) {
2116 error = -EFSCORRUPTED;
2117 goto out_error;
2118 }
2119 ltrec.rm_blockcount -= len;
2120 error = xfs_rmap_update(cur, <rec);
2121 if (error)
2122 goto out_error;
2123 } else {
2124 /*
2125 * Overlap middle of extent: trim the length of the existing
2126 * record to the length of the new left-extent size, increment
2127 * the insertion position so we can insert a new record
2128 * containing the remaining right-extent space.
2129 *
2130 * ltbno ltlen
2131 * Orig: |oooooooooooooooooooo|
2132 * Freeing: |fffffffff|
2133 * Result: |rrrrr| |rrrr|
2134 * bno len
2135 */
2136 xfs_extlen_t orig_len = ltrec.rm_blockcount;
2137
2138 /* Shrink the left side of the rmap */
2139 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2140 ltrec.rm_blockcount, ltrec.rm_owner,
2141 ltrec.rm_offset, ltrec.rm_flags, &i);
2142 if (error)
2143 goto out_error;
2144 if (XFS_IS_CORRUPT(mp, i != 1)) {
2145 error = -EFSCORRUPTED;
2146 goto out_error;
2147 }
2148 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
2149 error = xfs_rmap_update(cur, <rec);
2150 if (error)
2151 goto out_error;
2152
2153 /* Add an rmap at the new offset */
2154 error = xfs_rmap_insert(cur, bno + len,
2155 orig_len - len - ltrec.rm_blockcount,
2156 ltrec.rm_owner, offset + len,
2157 ltrec.rm_flags);
2158 if (error)
2159 goto out_error;
2160 }
2161
2162 trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2163 unwritten, oinfo);
2164out_error:
2165 if (error)
2166 trace_xfs_rmap_unmap_error(cur->bc_mp,
2167 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2168 return error;
2169}
2170
2171/*
2172 * Find an extent in the rmap btree and map it. For rmap extent types that
2173 * can overlap (data fork rmaps on reflink filesystems) we must be careful
2174 * that the prev/next records in the btree might belong to another owner.
2175 * Therefore we must use delete+insert to alter any of the key fields.
2176 *
2177 * For every other situation there can only be one owner for a given extent,
2178 * so we can call the regular _alloc function.
2179 */
2180STATIC int
2181xfs_rmap_map_shared(
2182 struct xfs_btree_cur *cur,
2183 xfs_agblock_t bno,
2184 xfs_extlen_t len,
2185 bool unwritten,
2186 const struct xfs_owner_info *oinfo)
2187{
2188 struct xfs_mount *mp = cur->bc_mp;
2189 struct xfs_rmap_irec ltrec;
2190 struct xfs_rmap_irec gtrec;
2191 int have_gt;
2192 int have_lt;
2193 int error = 0;
2194 int i;
2195 uint64_t owner;
2196 uint64_t offset;
2197 unsigned int flags = 0;
2198
2199 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2200 if (unwritten)
2201 flags |= XFS_RMAP_UNWRITTEN;
2202 trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
2203 unwritten, oinfo);
2204
2205 /* Is there a left record that abuts our range? */
2206 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
2207 <rec, &have_lt);
2208 if (error)
2209 goto out_error;
2210 if (have_lt &&
2211 !xfs_rmap_is_mergeable(<rec, owner, flags))
2212 have_lt = 0;
2213
2214 /* Is there a right record that abuts our range? */
2215 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
2216 flags, &have_gt);
2217 if (error)
2218 goto out_error;
2219 if (have_gt) {
2220 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
2221 if (error)
2222 goto out_error;
2223 if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
2224 error = -EFSCORRUPTED;
2225 goto out_error;
2226 }
2227 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
2228 cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
2229 gtrec.rm_blockcount, gtrec.rm_owner,
2230 gtrec.rm_offset, gtrec.rm_flags);
2231
2232 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
2233 have_gt = 0;
2234 }
2235
2236 if (have_lt &&
2237 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
2238 ltrec.rm_offset + ltrec.rm_blockcount == offset) {
2239 /*
2240 * Left edge contiguous, merge into left record.
2241 *
2242 * ltbno ltlen
2243 * orig: |ooooooooo|
2244 * adding: |aaaaaaaaa|
2245 * result: |rrrrrrrrrrrrrrrrrrr|
2246 * bno len
2247 */
2248 ltrec.rm_blockcount += len;
2249 if (have_gt &&
2250 bno + len == gtrec.rm_startblock &&
2251 offset + len == gtrec.rm_offset) {
2252 /*
2253 * Right edge also contiguous, delete right record
2254 * and merge into left record.
2255 *
2256 * ltbno ltlen gtbno gtlen
2257 * orig: |ooooooooo| |ooooooooo|
2258 * adding: |aaaaaaaaa|
2259 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
2260 */
2261 ltrec.rm_blockcount += gtrec.rm_blockcount;
2262 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2263 gtrec.rm_blockcount, gtrec.rm_owner,
2264 gtrec.rm_offset, gtrec.rm_flags);
2265 if (error)
2266 goto out_error;
2267 }
2268
2269 /* Point the cursor back to the left record and update. */
2270 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2271 ltrec.rm_blockcount, ltrec.rm_owner,
2272 ltrec.rm_offset, ltrec.rm_flags, &i);
2273 if (error)
2274 goto out_error;
2275 if (XFS_IS_CORRUPT(mp, i != 1)) {
2276 error = -EFSCORRUPTED;
2277 goto out_error;
2278 }
2279
2280 error = xfs_rmap_update(cur, <rec);
2281 if (error)
2282 goto out_error;
2283 } else if (have_gt &&
2284 bno + len == gtrec.rm_startblock &&
2285 offset + len == gtrec.rm_offset) {
2286 /*
2287 * Right edge contiguous, merge into right record.
2288 *
2289 * gtbno gtlen
2290 * Orig: |ooooooooo|
2291 * adding: |aaaaaaaaa|
2292 * Result: |rrrrrrrrrrrrrrrrrrr|
2293 * bno len
2294 */
2295 /* Delete the old record. */
2296 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2297 gtrec.rm_blockcount, gtrec.rm_owner,
2298 gtrec.rm_offset, gtrec.rm_flags);
2299 if (error)
2300 goto out_error;
2301
2302 /* Move the start and re-add it. */
2303 gtrec.rm_startblock = bno;
2304 gtrec.rm_blockcount += len;
2305 gtrec.rm_offset = offset;
2306 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2307 gtrec.rm_blockcount, gtrec.rm_owner,
2308 gtrec.rm_offset, gtrec.rm_flags);
2309 if (error)
2310 goto out_error;
2311 } else {
2312 /*
2313 * No contiguous edge with identical owner, insert
2314 * new record at current cursor position.
2315 */
2316 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2317 if (error)
2318 goto out_error;
2319 }
2320
2321 trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2322 unwritten, oinfo);
2323out_error:
2324 if (error)
2325 trace_xfs_rmap_map_error(cur->bc_mp,
2326 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2327 return error;
2328}
2329
2330/* Insert a raw rmap into the rmapbt. */
2331int
2332xfs_rmap_map_raw(
2333 struct xfs_btree_cur *cur,
2334 struct xfs_rmap_irec *rmap)
2335{
2336 struct xfs_owner_info oinfo;
2337
2338 oinfo.oi_owner = rmap->rm_owner;
2339 oinfo.oi_offset = rmap->rm_offset;
2340 oinfo.oi_flags = 0;
2341 if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
2342 oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
2343 if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
2344 oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
2345
2346 if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2347 return xfs_rmap_map(cur, rmap->rm_startblock,
2348 rmap->rm_blockcount,
2349 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2350 &oinfo);
2351
2352 return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2353 rmap->rm_blockcount,
2354 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2355 &oinfo);
2356}
2357
2358struct xfs_rmap_query_range_info {
2359 xfs_rmap_query_range_fn fn;
2360 void *priv;
2361};
2362
2363/* Format btree record and pass to our callback. */
2364STATIC int
2365xfs_rmap_query_range_helper(
2366 struct xfs_btree_cur *cur,
2367 const union xfs_btree_rec *rec,
2368 void *priv)
2369{
2370 struct xfs_rmap_query_range_info *query = priv;
2371 struct xfs_rmap_irec irec;
2372 xfs_failaddr_t fa;
2373
2374 fa = xfs_rmap_btrec_to_irec(rec, &irec);
2375 if (!fa)
2376 fa = xfs_rmap_check_irec(cur, &irec);
2377 if (fa)
2378 return xfs_rmap_complain_bad_rec(cur, fa, &irec);
2379
2380 return query->fn(cur, &irec, query->priv);
2381}
2382
2383/* Find all rmaps between two keys. */
2384int
2385xfs_rmap_query_range(
2386 struct xfs_btree_cur *cur,
2387 const struct xfs_rmap_irec *low_rec,
2388 const struct xfs_rmap_irec *high_rec,
2389 xfs_rmap_query_range_fn fn,
2390 void *priv)
2391{
2392 union xfs_btree_irec low_brec = { .r = *low_rec };
2393 union xfs_btree_irec high_brec = { .r = *high_rec };
2394 struct xfs_rmap_query_range_info query = { .priv = priv, .fn = fn };
2395
2396 return xfs_btree_query_range(cur, &low_brec, &high_brec,
2397 xfs_rmap_query_range_helper, &query);
2398}
2399
2400/* Find all rmaps. */
2401int
2402xfs_rmap_query_all(
2403 struct xfs_btree_cur *cur,
2404 xfs_rmap_query_range_fn fn,
2405 void *priv)
2406{
2407 struct xfs_rmap_query_range_info query;
2408
2409 query.priv = priv;
2410 query.fn = fn;
2411 return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2412}
2413
2414/* Clean up after calling xfs_rmap_finish_one. */
2415void
2416xfs_rmap_finish_one_cleanup(
2417 struct xfs_trans *tp,
2418 struct xfs_btree_cur *rcur,
2419 int error)
2420{
2421 struct xfs_buf *agbp;
2422
2423 if (rcur == NULL)
2424 return;
2425 agbp = rcur->bc_ag.agbp;
2426 xfs_btree_del_cursor(rcur, error);
2427 if (error)
2428 xfs_trans_brelse(tp, agbp);
2429}
2430
2431/*
2432 * Process one of the deferred rmap operations. We pass back the
2433 * btree cursor to maintain our lock on the rmapbt between calls.
2434 * This saves time and eliminates a buffer deadlock between the
2435 * superblock and the AGF because we'll always grab them in the same
2436 * order.
2437 */
2438int
2439xfs_rmap_finish_one(
2440 struct xfs_trans *tp,
2441 struct xfs_rmap_intent *ri,
2442 struct xfs_btree_cur **pcur)
2443{
2444 struct xfs_mount *mp = tp->t_mountp;
2445 struct xfs_btree_cur *rcur;
2446 struct xfs_buf *agbp = NULL;
2447 int error = 0;
2448 struct xfs_owner_info oinfo;
2449 xfs_agblock_t bno;
2450 bool unwritten;
2451
2452 bno = XFS_FSB_TO_AGBNO(mp, ri->ri_bmap.br_startblock);
2453
2454 trace_xfs_rmap_deferred(mp, ri->ri_pag->pag_agno, ri->ri_type, bno,
2455 ri->ri_owner, ri->ri_whichfork,
2456 ri->ri_bmap.br_startoff, ri->ri_bmap.br_blockcount,
2457 ri->ri_bmap.br_state);
2458
2459 if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE))
2460 return -EIO;
2461
2462 /*
2463 * If we haven't gotten a cursor or the cursor AG doesn't match
2464 * the startblock, get one now.
2465 */
2466 rcur = *pcur;
2467 if (rcur != NULL && rcur->bc_ag.pag != ri->ri_pag) {
2468 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2469 rcur = NULL;
2470 *pcur = NULL;
2471 }
2472 if (rcur == NULL) {
2473 /*
2474 * Refresh the freelist before we start changing the
2475 * rmapbt, because a shape change could cause us to
2476 * allocate blocks.
2477 */
2478 error = xfs_free_extent_fix_freelist(tp, ri->ri_pag, &agbp);
2479 if (error)
2480 return error;
2481 if (XFS_IS_CORRUPT(tp->t_mountp, !agbp))
2482 return -EFSCORRUPTED;
2483
2484 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, ri->ri_pag);
2485 }
2486 *pcur = rcur;
2487
2488 xfs_rmap_ino_owner(&oinfo, ri->ri_owner, ri->ri_whichfork,
2489 ri->ri_bmap.br_startoff);
2490 unwritten = ri->ri_bmap.br_state == XFS_EXT_UNWRITTEN;
2491 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, ri->ri_bmap.br_startblock);
2492
2493 switch (ri->ri_type) {
2494 case XFS_RMAP_ALLOC:
2495 case XFS_RMAP_MAP:
2496 error = xfs_rmap_map(rcur, bno, ri->ri_bmap.br_blockcount,
2497 unwritten, &oinfo);
2498 break;
2499 case XFS_RMAP_MAP_SHARED:
2500 error = xfs_rmap_map_shared(rcur, bno,
2501 ri->ri_bmap.br_blockcount, unwritten, &oinfo);
2502 break;
2503 case XFS_RMAP_FREE:
2504 case XFS_RMAP_UNMAP:
2505 error = xfs_rmap_unmap(rcur, bno, ri->ri_bmap.br_blockcount,
2506 unwritten, &oinfo);
2507 break;
2508 case XFS_RMAP_UNMAP_SHARED:
2509 error = xfs_rmap_unmap_shared(rcur, bno,
2510 ri->ri_bmap.br_blockcount, unwritten, &oinfo);
2511 break;
2512 case XFS_RMAP_CONVERT:
2513 error = xfs_rmap_convert(rcur, bno, ri->ri_bmap.br_blockcount,
2514 !unwritten, &oinfo);
2515 break;
2516 case XFS_RMAP_CONVERT_SHARED:
2517 error = xfs_rmap_convert_shared(rcur, bno,
2518 ri->ri_bmap.br_blockcount, !unwritten, &oinfo);
2519 break;
2520 default:
2521 ASSERT(0);
2522 error = -EFSCORRUPTED;
2523 }
2524
2525 return error;
2526}
2527
2528/*
2529 * Don't defer an rmap if we aren't an rmap filesystem.
2530 */
2531static bool
2532xfs_rmap_update_is_needed(
2533 struct xfs_mount *mp,
2534 int whichfork)
2535{
2536 return xfs_has_rmapbt(mp) && whichfork != XFS_COW_FORK;
2537}
2538
2539/*
2540 * Record a rmap intent; the list is kept sorted first by AG and then by
2541 * increasing age.
2542 */
2543static void
2544__xfs_rmap_add(
2545 struct xfs_trans *tp,
2546 enum xfs_rmap_intent_type type,
2547 uint64_t owner,
2548 int whichfork,
2549 struct xfs_bmbt_irec *bmap)
2550{
2551 struct xfs_rmap_intent *ri;
2552
2553 trace_xfs_rmap_defer(tp->t_mountp,
2554 XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock),
2555 type,
2556 XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock),
2557 owner, whichfork,
2558 bmap->br_startoff,
2559 bmap->br_blockcount,
2560 bmap->br_state);
2561
2562 ri = kmem_cache_alloc(xfs_rmap_intent_cache, GFP_NOFS | __GFP_NOFAIL);
2563 INIT_LIST_HEAD(&ri->ri_list);
2564 ri->ri_type = type;
2565 ri->ri_owner = owner;
2566 ri->ri_whichfork = whichfork;
2567 ri->ri_bmap = *bmap;
2568
2569 xfs_rmap_update_get_group(tp->t_mountp, ri);
2570 xfs_defer_add(tp, &ri->ri_list, &xfs_rmap_update_defer_type);
2571}
2572
2573/* Map an extent into a file. */
2574void
2575xfs_rmap_map_extent(
2576 struct xfs_trans *tp,
2577 struct xfs_inode *ip,
2578 int whichfork,
2579 struct xfs_bmbt_irec *PREV)
2580{
2581 enum xfs_rmap_intent_type type = XFS_RMAP_MAP;
2582
2583 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2584 return;
2585
2586 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2587 type = XFS_RMAP_MAP_SHARED;
2588
2589 __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2590}
2591
2592/* Unmap an extent out of a file. */
2593void
2594xfs_rmap_unmap_extent(
2595 struct xfs_trans *tp,
2596 struct xfs_inode *ip,
2597 int whichfork,
2598 struct xfs_bmbt_irec *PREV)
2599{
2600 enum xfs_rmap_intent_type type = XFS_RMAP_UNMAP;
2601
2602 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2603 return;
2604
2605 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2606 type = XFS_RMAP_UNMAP_SHARED;
2607
2608 __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2609}
2610
2611/*
2612 * Convert a data fork extent from unwritten to real or vice versa.
2613 *
2614 * Note that tp can be NULL here as no transaction is used for COW fork
2615 * unwritten conversion.
2616 */
2617void
2618xfs_rmap_convert_extent(
2619 struct xfs_mount *mp,
2620 struct xfs_trans *tp,
2621 struct xfs_inode *ip,
2622 int whichfork,
2623 struct xfs_bmbt_irec *PREV)
2624{
2625 enum xfs_rmap_intent_type type = XFS_RMAP_CONVERT;
2626
2627 if (!xfs_rmap_update_is_needed(mp, whichfork))
2628 return;
2629
2630 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2631 type = XFS_RMAP_CONVERT_SHARED;
2632
2633 __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2634}
2635
2636/* Schedule the creation of an rmap for non-file data. */
2637void
2638xfs_rmap_alloc_extent(
2639 struct xfs_trans *tp,
2640 xfs_agnumber_t agno,
2641 xfs_agblock_t bno,
2642 xfs_extlen_t len,
2643 uint64_t owner)
2644{
2645 struct xfs_bmbt_irec bmap;
2646
2647 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2648 return;
2649
2650 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2651 bmap.br_blockcount = len;
2652 bmap.br_startoff = 0;
2653 bmap.br_state = XFS_EXT_NORM;
2654
2655 __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
2656}
2657
2658/* Schedule the deletion of an rmap for non-file data. */
2659void
2660xfs_rmap_free_extent(
2661 struct xfs_trans *tp,
2662 xfs_agnumber_t agno,
2663 xfs_agblock_t bno,
2664 xfs_extlen_t len,
2665 uint64_t owner)
2666{
2667 struct xfs_bmbt_irec bmap;
2668
2669 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2670 return;
2671
2672 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2673 bmap.br_blockcount = len;
2674 bmap.br_startoff = 0;
2675 bmap.br_state = XFS_EXT_NORM;
2676
2677 __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
2678}
2679
2680/* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2681int
2682xfs_rmap_compare(
2683 const struct xfs_rmap_irec *a,
2684 const struct xfs_rmap_irec *b)
2685{
2686 __u64 oa;
2687 __u64 ob;
2688
2689 oa = xfs_rmap_irec_offset_pack(a);
2690 ob = xfs_rmap_irec_offset_pack(b);
2691
2692 if (a->rm_startblock < b->rm_startblock)
2693 return -1;
2694 else if (a->rm_startblock > b->rm_startblock)
2695 return 1;
2696 else if (a->rm_owner < b->rm_owner)
2697 return -1;
2698 else if (a->rm_owner > b->rm_owner)
2699 return 1;
2700 else if (oa < ob)
2701 return -1;
2702 else if (oa > ob)
2703 return 1;
2704 else
2705 return 0;
2706}
2707
2708/*
2709 * Scan the physical storage part of the keyspace of the reverse mapping index
2710 * and tell us if the area has no records, is fully mapped by records, or is
2711 * partially filled.
2712 */
2713int
2714xfs_rmap_has_records(
2715 struct xfs_btree_cur *cur,
2716 xfs_agblock_t bno,
2717 xfs_extlen_t len,
2718 enum xbtree_recpacking *outcome)
2719{
2720 union xfs_btree_key mask = {
2721 .rmap.rm_startblock = cpu_to_be32(-1U),
2722 };
2723 union xfs_btree_irec low;
2724 union xfs_btree_irec high;
2725
2726 memset(&low, 0, sizeof(low));
2727 low.r.rm_startblock = bno;
2728 memset(&high, 0xFF, sizeof(high));
2729 high.r.rm_startblock = bno + len - 1;
2730
2731 return xfs_btree_has_records(cur, &low, &high, &mask, outcome);
2732}
2733
2734struct xfs_rmap_ownercount {
2735 /* Owner that we're looking for. */
2736 struct xfs_rmap_irec good;
2737
2738 /* rmap search keys */
2739 struct xfs_rmap_irec low;
2740 struct xfs_rmap_irec high;
2741
2742 struct xfs_rmap_matches *results;
2743
2744 /* Stop early if we find a nonmatch? */
2745 bool stop_on_nonmatch;
2746};
2747
2748/* Does this rmap represent space that can have multiple owners? */
2749static inline bool
2750xfs_rmap_shareable(
2751 struct xfs_mount *mp,
2752 const struct xfs_rmap_irec *rmap)
2753{
2754 if (!xfs_has_reflink(mp))
2755 return false;
2756 if (XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2757 return false;
2758 if (rmap->rm_flags & (XFS_RMAP_ATTR_FORK |
2759 XFS_RMAP_BMBT_BLOCK))
2760 return false;
2761 return true;
2762}
2763
2764static inline void
2765xfs_rmap_ownercount_init(
2766 struct xfs_rmap_ownercount *roc,
2767 xfs_agblock_t bno,
2768 xfs_extlen_t len,
2769 const struct xfs_owner_info *oinfo,
2770 struct xfs_rmap_matches *results)
2771{
2772 memset(roc, 0, sizeof(*roc));
2773 roc->results = results;
2774
2775 roc->low.rm_startblock = bno;
2776 memset(&roc->high, 0xFF, sizeof(roc->high));
2777 roc->high.rm_startblock = bno + len - 1;
2778
2779 memset(results, 0, sizeof(*results));
2780 roc->good.rm_startblock = bno;
2781 roc->good.rm_blockcount = len;
2782 roc->good.rm_owner = oinfo->oi_owner;
2783 roc->good.rm_offset = oinfo->oi_offset;
2784 if (oinfo->oi_flags & XFS_OWNER_INFO_ATTR_FORK)
2785 roc->good.rm_flags |= XFS_RMAP_ATTR_FORK;
2786 if (oinfo->oi_flags & XFS_OWNER_INFO_BMBT_BLOCK)
2787 roc->good.rm_flags |= XFS_RMAP_BMBT_BLOCK;
2788}
2789
2790/* Figure out if this is a match for the owner. */
2791STATIC int
2792xfs_rmap_count_owners_helper(
2793 struct xfs_btree_cur *cur,
2794 const struct xfs_rmap_irec *rec,
2795 void *priv)
2796{
2797 struct xfs_rmap_ownercount *roc = priv;
2798 struct xfs_rmap_irec check = *rec;
2799 unsigned int keyflags;
2800 bool filedata;
2801 int64_t delta;
2802
2803 filedata = !XFS_RMAP_NON_INODE_OWNER(check.rm_owner) &&
2804 !(check.rm_flags & XFS_RMAP_BMBT_BLOCK);
2805
2806 /* Trim the part of check that comes before the comparison range. */
2807 delta = (int64_t)roc->good.rm_startblock - check.rm_startblock;
2808 if (delta > 0) {
2809 check.rm_startblock += delta;
2810 check.rm_blockcount -= delta;
2811 if (filedata)
2812 check.rm_offset += delta;
2813 }
2814
2815 /* Trim the part of check that comes after the comparison range. */
2816 delta = (check.rm_startblock + check.rm_blockcount) -
2817 (roc->good.rm_startblock + roc->good.rm_blockcount);
2818 if (delta > 0)
2819 check.rm_blockcount -= delta;
2820
2821 /* Don't care about unwritten status for establishing ownership. */
2822 keyflags = check.rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK);
2823
2824 if (check.rm_startblock == roc->good.rm_startblock &&
2825 check.rm_blockcount == roc->good.rm_blockcount &&
2826 check.rm_owner == roc->good.rm_owner &&
2827 check.rm_offset == roc->good.rm_offset &&
2828 keyflags == roc->good.rm_flags) {
2829 roc->results->matches++;
2830 } else {
2831 roc->results->non_owner_matches++;
2832 if (xfs_rmap_shareable(cur->bc_mp, &roc->good) ^
2833 xfs_rmap_shareable(cur->bc_mp, &check))
2834 roc->results->bad_non_owner_matches++;
2835 }
2836
2837 if (roc->results->non_owner_matches && roc->stop_on_nonmatch)
2838 return -ECANCELED;
2839
2840 return 0;
2841}
2842
2843/* Count the number of owners and non-owners of this range of blocks. */
2844int
2845xfs_rmap_count_owners(
2846 struct xfs_btree_cur *cur,
2847 xfs_agblock_t bno,
2848 xfs_extlen_t len,
2849 const struct xfs_owner_info *oinfo,
2850 struct xfs_rmap_matches *results)
2851{
2852 struct xfs_rmap_ownercount roc;
2853 int error;
2854
2855 xfs_rmap_ownercount_init(&roc, bno, len, oinfo, results);
2856 error = xfs_rmap_query_range(cur, &roc.low, &roc.high,
2857 xfs_rmap_count_owners_helper, &roc);
2858 if (error)
2859 return error;
2860
2861 /*
2862 * There can't be any non-owner rmaps that conflict with the given
2863 * owner if we didn't find any rmaps matching the owner.
2864 */
2865 if (!results->matches)
2866 results->bad_non_owner_matches = 0;
2867
2868 return 0;
2869}
2870
2871/*
2872 * Given an extent and some owner info, can we find records overlapping
2873 * the extent whose owner info does not match the given owner?
2874 */
2875int
2876xfs_rmap_has_other_keys(
2877 struct xfs_btree_cur *cur,
2878 xfs_agblock_t bno,
2879 xfs_extlen_t len,
2880 const struct xfs_owner_info *oinfo,
2881 bool *has_other)
2882{
2883 struct xfs_rmap_matches res;
2884 struct xfs_rmap_ownercount roc;
2885 int error;
2886
2887 xfs_rmap_ownercount_init(&roc, bno, len, oinfo, &res);
2888 roc.stop_on_nonmatch = true;
2889
2890 error = xfs_rmap_query_range(cur, &roc.low, &roc.high,
2891 xfs_rmap_count_owners_helper, &roc);
2892 if (error == -ECANCELED) {
2893 *has_other = true;
2894 return 0;
2895 }
2896 if (error)
2897 return error;
2898
2899 *has_other = false;
2900 return 0;
2901}
2902
2903const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
2904 .oi_owner = XFS_RMAP_OWN_NULL,
2905};
2906const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
2907 .oi_owner = XFS_RMAP_OWN_UNKNOWN,
2908};
2909const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
2910 .oi_owner = XFS_RMAP_OWN_FS,
2911};
2912const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
2913 .oi_owner = XFS_RMAP_OWN_LOG,
2914};
2915const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
2916 .oi_owner = XFS_RMAP_OWN_AG,
2917};
2918const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
2919 .oi_owner = XFS_RMAP_OWN_INOBT,
2920};
2921const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
2922 .oi_owner = XFS_RMAP_OWN_INODES,
2923};
2924const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
2925 .oi_owner = XFS_RMAP_OWN_REFC,
2926};
2927const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
2928 .oi_owner = XFS_RMAP_OWN_COW,
2929};
2930
2931int __init
2932xfs_rmap_intent_init_cache(void)
2933{
2934 xfs_rmap_intent_cache = kmem_cache_create("xfs_rmap_intent",
2935 sizeof(struct xfs_rmap_intent),
2936 0, 0, NULL);
2937
2938 return xfs_rmap_intent_cache != NULL ? 0 : -ENOMEM;
2939}
2940
2941void
2942xfs_rmap_intent_destroy_cache(void)
2943{
2944 kmem_cache_destroy(xfs_rmap_intent_cache);
2945 xfs_rmap_intent_cache = NULL;
2946}
1/*
2 * Copyright (c) 2014 Red Hat, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18#include "xfs.h"
19#include "xfs_fs.h"
20#include "xfs_shared.h"
21#include "xfs_format.h"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
24#include "xfs_bit.h"
25#include "xfs_sb.h"
26#include "xfs_mount.h"
27#include "xfs_defer.h"
28#include "xfs_da_format.h"
29#include "xfs_da_btree.h"
30#include "xfs_btree.h"
31#include "xfs_trans.h"
32#include "xfs_alloc.h"
33#include "xfs_rmap.h"
34#include "xfs_rmap_btree.h"
35#include "xfs_trans_space.h"
36#include "xfs_trace.h"
37#include "xfs_error.h"
38#include "xfs_extent_busy.h"
39#include "xfs_bmap.h"
40#include "xfs_inode.h"
41
42/*
43 * Lookup the first record less than or equal to [bno, len, owner, offset]
44 * in the btree given by cur.
45 */
46int
47xfs_rmap_lookup_le(
48 struct xfs_btree_cur *cur,
49 xfs_agblock_t bno,
50 xfs_extlen_t len,
51 uint64_t owner,
52 uint64_t offset,
53 unsigned int flags,
54 int *stat)
55{
56 cur->bc_rec.r.rm_startblock = bno;
57 cur->bc_rec.r.rm_blockcount = len;
58 cur->bc_rec.r.rm_owner = owner;
59 cur->bc_rec.r.rm_offset = offset;
60 cur->bc_rec.r.rm_flags = flags;
61 return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
62}
63
64/*
65 * Lookup the record exactly matching [bno, len, owner, offset]
66 * in the btree given by cur.
67 */
68int
69xfs_rmap_lookup_eq(
70 struct xfs_btree_cur *cur,
71 xfs_agblock_t bno,
72 xfs_extlen_t len,
73 uint64_t owner,
74 uint64_t offset,
75 unsigned int flags,
76 int *stat)
77{
78 cur->bc_rec.r.rm_startblock = bno;
79 cur->bc_rec.r.rm_blockcount = len;
80 cur->bc_rec.r.rm_owner = owner;
81 cur->bc_rec.r.rm_offset = offset;
82 cur->bc_rec.r.rm_flags = flags;
83 return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
84}
85
86/*
87 * Update the record referred to by cur to the value given
88 * by [bno, len, owner, offset].
89 * This either works (return 0) or gets an EFSCORRUPTED error.
90 */
91STATIC int
92xfs_rmap_update(
93 struct xfs_btree_cur *cur,
94 struct xfs_rmap_irec *irec)
95{
96 union xfs_btree_rec rec;
97 int error;
98
99 trace_xfs_rmap_update(cur->bc_mp, cur->bc_private.a.agno,
100 irec->rm_startblock, irec->rm_blockcount,
101 irec->rm_owner, irec->rm_offset, irec->rm_flags);
102
103 rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
104 rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
105 rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
106 rec.rmap.rm_offset = cpu_to_be64(
107 xfs_rmap_irec_offset_pack(irec));
108 error = xfs_btree_update(cur, &rec);
109 if (error)
110 trace_xfs_rmap_update_error(cur->bc_mp,
111 cur->bc_private.a.agno, error, _RET_IP_);
112 return error;
113}
114
115int
116xfs_rmap_insert(
117 struct xfs_btree_cur *rcur,
118 xfs_agblock_t agbno,
119 xfs_extlen_t len,
120 uint64_t owner,
121 uint64_t offset,
122 unsigned int flags)
123{
124 int i;
125 int error;
126
127 trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
128 len, owner, offset, flags);
129
130 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
131 if (error)
132 goto done;
133 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 0, done);
134
135 rcur->bc_rec.r.rm_startblock = agbno;
136 rcur->bc_rec.r.rm_blockcount = len;
137 rcur->bc_rec.r.rm_owner = owner;
138 rcur->bc_rec.r.rm_offset = offset;
139 rcur->bc_rec.r.rm_flags = flags;
140 error = xfs_btree_insert(rcur, &i);
141 if (error)
142 goto done;
143 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
144done:
145 if (error)
146 trace_xfs_rmap_insert_error(rcur->bc_mp,
147 rcur->bc_private.a.agno, error, _RET_IP_);
148 return error;
149}
150
151STATIC int
152xfs_rmap_delete(
153 struct xfs_btree_cur *rcur,
154 xfs_agblock_t agbno,
155 xfs_extlen_t len,
156 uint64_t owner,
157 uint64_t offset,
158 unsigned int flags)
159{
160 int i;
161 int error;
162
163 trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
164 len, owner, offset, flags);
165
166 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
167 if (error)
168 goto done;
169 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
170
171 error = xfs_btree_delete(rcur, &i);
172 if (error)
173 goto done;
174 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
175done:
176 if (error)
177 trace_xfs_rmap_delete_error(rcur->bc_mp,
178 rcur->bc_private.a.agno, error, _RET_IP_);
179 return error;
180}
181
182static int
183xfs_rmap_btrec_to_irec(
184 union xfs_btree_rec *rec,
185 struct xfs_rmap_irec *irec)
186{
187 irec->rm_flags = 0;
188 irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
189 irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
190 irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
191 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
192 irec);
193}
194
195/*
196 * Get the data from the pointed-to record.
197 */
198int
199xfs_rmap_get_rec(
200 struct xfs_btree_cur *cur,
201 struct xfs_rmap_irec *irec,
202 int *stat)
203{
204 union xfs_btree_rec *rec;
205 int error;
206
207 error = xfs_btree_get_rec(cur, &rec, stat);
208 if (error || !*stat)
209 return error;
210
211 return xfs_rmap_btrec_to_irec(rec, irec);
212}
213
214struct xfs_find_left_neighbor_info {
215 struct xfs_rmap_irec high;
216 struct xfs_rmap_irec *irec;
217 int *stat;
218};
219
220/* For each rmap given, figure out if it matches the key we want. */
221STATIC int
222xfs_rmap_find_left_neighbor_helper(
223 struct xfs_btree_cur *cur,
224 struct xfs_rmap_irec *rec,
225 void *priv)
226{
227 struct xfs_find_left_neighbor_info *info = priv;
228
229 trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
230 cur->bc_private.a.agno, rec->rm_startblock,
231 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
232 rec->rm_flags);
233
234 if (rec->rm_owner != info->high.rm_owner)
235 return XFS_BTREE_QUERY_RANGE_CONTINUE;
236 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
237 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
238 rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
239 return XFS_BTREE_QUERY_RANGE_CONTINUE;
240
241 *info->irec = *rec;
242 *info->stat = 1;
243 return XFS_BTREE_QUERY_RANGE_ABORT;
244}
245
246/*
247 * Find the record to the left of the given extent, being careful only to
248 * return a match with the same owner and adjacent physical and logical
249 * block ranges.
250 */
251int
252xfs_rmap_find_left_neighbor(
253 struct xfs_btree_cur *cur,
254 xfs_agblock_t bno,
255 uint64_t owner,
256 uint64_t offset,
257 unsigned int flags,
258 struct xfs_rmap_irec *irec,
259 int *stat)
260{
261 struct xfs_find_left_neighbor_info info;
262 int error;
263
264 *stat = 0;
265 if (bno == 0)
266 return 0;
267 info.high.rm_startblock = bno - 1;
268 info.high.rm_owner = owner;
269 if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
270 !(flags & XFS_RMAP_BMBT_BLOCK)) {
271 if (offset == 0)
272 return 0;
273 info.high.rm_offset = offset - 1;
274 } else
275 info.high.rm_offset = 0;
276 info.high.rm_flags = flags;
277 info.high.rm_blockcount = 0;
278 info.irec = irec;
279 info.stat = stat;
280
281 trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
282 cur->bc_private.a.agno, bno, 0, owner, offset, flags);
283
284 error = xfs_rmap_query_range(cur, &info.high, &info.high,
285 xfs_rmap_find_left_neighbor_helper, &info);
286 if (error == XFS_BTREE_QUERY_RANGE_ABORT)
287 error = 0;
288 if (*stat)
289 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
290 cur->bc_private.a.agno, irec->rm_startblock,
291 irec->rm_blockcount, irec->rm_owner,
292 irec->rm_offset, irec->rm_flags);
293 return error;
294}
295
296/* For each rmap given, figure out if it matches the key we want. */
297STATIC int
298xfs_rmap_lookup_le_range_helper(
299 struct xfs_btree_cur *cur,
300 struct xfs_rmap_irec *rec,
301 void *priv)
302{
303 struct xfs_find_left_neighbor_info *info = priv;
304
305 trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
306 cur->bc_private.a.agno, rec->rm_startblock,
307 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
308 rec->rm_flags);
309
310 if (rec->rm_owner != info->high.rm_owner)
311 return XFS_BTREE_QUERY_RANGE_CONTINUE;
312 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
313 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
314 (rec->rm_offset > info->high.rm_offset ||
315 rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
316 return XFS_BTREE_QUERY_RANGE_CONTINUE;
317
318 *info->irec = *rec;
319 *info->stat = 1;
320 return XFS_BTREE_QUERY_RANGE_ABORT;
321}
322
323/*
324 * Find the record to the left of the given extent, being careful only to
325 * return a match with the same owner and overlapping physical and logical
326 * block ranges. This is the overlapping-interval version of
327 * xfs_rmap_lookup_le.
328 */
329int
330xfs_rmap_lookup_le_range(
331 struct xfs_btree_cur *cur,
332 xfs_agblock_t bno,
333 uint64_t owner,
334 uint64_t offset,
335 unsigned int flags,
336 struct xfs_rmap_irec *irec,
337 int *stat)
338{
339 struct xfs_find_left_neighbor_info info;
340 int error;
341
342 info.high.rm_startblock = bno;
343 info.high.rm_owner = owner;
344 if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
345 info.high.rm_offset = offset;
346 else
347 info.high.rm_offset = 0;
348 info.high.rm_flags = flags;
349 info.high.rm_blockcount = 0;
350 *stat = 0;
351 info.irec = irec;
352 info.stat = stat;
353
354 trace_xfs_rmap_lookup_le_range(cur->bc_mp,
355 cur->bc_private.a.agno, bno, 0, owner, offset, flags);
356 error = xfs_rmap_query_range(cur, &info.high, &info.high,
357 xfs_rmap_lookup_le_range_helper, &info);
358 if (error == XFS_BTREE_QUERY_RANGE_ABORT)
359 error = 0;
360 if (*stat)
361 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
362 cur->bc_private.a.agno, irec->rm_startblock,
363 irec->rm_blockcount, irec->rm_owner,
364 irec->rm_offset, irec->rm_flags);
365 return error;
366}
367
368/*
369 * Find the extent in the rmap btree and remove it.
370 *
371 * The record we find should always be an exact match for the extent that we're
372 * looking for, since we insert them into the btree without modification.
373 *
374 * Special Case #1: when growing the filesystem, we "free" an extent when
375 * growing the last AG. This extent is new space and so it is not tracked as
376 * used space in the btree. The growfs code will pass in an owner of
377 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
378 * extent. We verify that - the extent lookup result in a record that does not
379 * overlap.
380 *
381 * Special Case #2: EFIs do not record the owner of the extent, so when
382 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
383 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
384 * corruption checks during log recovery.
385 */
386STATIC int
387xfs_rmap_unmap(
388 struct xfs_btree_cur *cur,
389 xfs_agblock_t bno,
390 xfs_extlen_t len,
391 bool unwritten,
392 struct xfs_owner_info *oinfo)
393{
394 struct xfs_mount *mp = cur->bc_mp;
395 struct xfs_rmap_irec ltrec;
396 uint64_t ltoff;
397 int error = 0;
398 int i;
399 uint64_t owner;
400 uint64_t offset;
401 unsigned int flags;
402 bool ignore_off;
403
404 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
405 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
406 (flags & XFS_RMAP_BMBT_BLOCK);
407 if (unwritten)
408 flags |= XFS_RMAP_UNWRITTEN;
409 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
410 unwritten, oinfo);
411
412 /*
413 * We should always have a left record because there's a static record
414 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
415 * will not ever be removed from the tree.
416 */
417 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i);
418 if (error)
419 goto out_error;
420 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
421
422 error = xfs_rmap_get_rec(cur, <rec, &i);
423 if (error)
424 goto out_error;
425 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
426 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
427 cur->bc_private.a.agno, ltrec.rm_startblock,
428 ltrec.rm_blockcount, ltrec.rm_owner,
429 ltrec.rm_offset, ltrec.rm_flags);
430 ltoff = ltrec.rm_offset;
431
432 /*
433 * For growfs, the incoming extent must be beyond the left record we
434 * just found as it is new space and won't be used by anyone. This is
435 * just a corruption check as we don't actually do anything with this
436 * extent. Note that we need to use >= instead of > because it might
437 * be the case that the "left" extent goes all the way to EOFS.
438 */
439 if (owner == XFS_RMAP_OWN_NULL) {
440 XFS_WANT_CORRUPTED_GOTO(mp, bno >= ltrec.rm_startblock +
441 ltrec.rm_blockcount, out_error);
442 goto out_done;
443 }
444
445 /* Make sure the unwritten flag matches. */
446 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
447 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error);
448
449 /* Make sure the extent we found covers the entire freeing range. */
450 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
451 ltrec.rm_startblock + ltrec.rm_blockcount >=
452 bno + len, out_error);
453
454 /* Make sure the owner matches what we expect to find in the tree. */
455 XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner ||
456 XFS_RMAP_NON_INODE_OWNER(owner), out_error);
457
458 /* Check the offset, if necessary. */
459 if (!XFS_RMAP_NON_INODE_OWNER(owner)) {
460 if (flags & XFS_RMAP_BMBT_BLOCK) {
461 XFS_WANT_CORRUPTED_GOTO(mp,
462 ltrec.rm_flags & XFS_RMAP_BMBT_BLOCK,
463 out_error);
464 } else {
465 XFS_WANT_CORRUPTED_GOTO(mp,
466 ltrec.rm_offset <= offset, out_error);
467 XFS_WANT_CORRUPTED_GOTO(mp,
468 ltoff + ltrec.rm_blockcount >= offset + len,
469 out_error);
470 }
471 }
472
473 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
474 /* exact match, simply remove the record from rmap tree */
475 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
476 ltrec.rm_startblock, ltrec.rm_blockcount,
477 ltrec.rm_owner, ltrec.rm_offset,
478 ltrec.rm_flags);
479 error = xfs_btree_delete(cur, &i);
480 if (error)
481 goto out_error;
482 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
483 } else if (ltrec.rm_startblock == bno) {
484 /*
485 * overlap left hand side of extent: move the start, trim the
486 * length and update the current record.
487 *
488 * ltbno ltlen
489 * Orig: |oooooooooooooooooooo|
490 * Freeing: |fffffffff|
491 * Result: |rrrrrrrrrr|
492 * bno len
493 */
494 ltrec.rm_startblock += len;
495 ltrec.rm_blockcount -= len;
496 if (!ignore_off)
497 ltrec.rm_offset += len;
498 error = xfs_rmap_update(cur, <rec);
499 if (error)
500 goto out_error;
501 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
502 /*
503 * overlap right hand side of extent: trim the length and update
504 * the current record.
505 *
506 * ltbno ltlen
507 * Orig: |oooooooooooooooooooo|
508 * Freeing: |fffffffff|
509 * Result: |rrrrrrrrrr|
510 * bno len
511 */
512 ltrec.rm_blockcount -= len;
513 error = xfs_rmap_update(cur, <rec);
514 if (error)
515 goto out_error;
516 } else {
517
518 /*
519 * overlap middle of extent: trim the length of the existing
520 * record to the length of the new left-extent size, increment
521 * the insertion position so we can insert a new record
522 * containing the remaining right-extent space.
523 *
524 * ltbno ltlen
525 * Orig: |oooooooooooooooooooo|
526 * Freeing: |fffffffff|
527 * Result: |rrrrr| |rrrr|
528 * bno len
529 */
530 xfs_extlen_t orig_len = ltrec.rm_blockcount;
531
532 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
533 error = xfs_rmap_update(cur, <rec);
534 if (error)
535 goto out_error;
536
537 error = xfs_btree_increment(cur, 0, &i);
538 if (error)
539 goto out_error;
540
541 cur->bc_rec.r.rm_startblock = bno + len;
542 cur->bc_rec.r.rm_blockcount = orig_len - len -
543 ltrec.rm_blockcount;
544 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
545 if (ignore_off)
546 cur->bc_rec.r.rm_offset = 0;
547 else
548 cur->bc_rec.r.rm_offset = offset + len;
549 cur->bc_rec.r.rm_flags = flags;
550 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
551 cur->bc_rec.r.rm_startblock,
552 cur->bc_rec.r.rm_blockcount,
553 cur->bc_rec.r.rm_owner,
554 cur->bc_rec.r.rm_offset,
555 cur->bc_rec.r.rm_flags);
556 error = xfs_btree_insert(cur, &i);
557 if (error)
558 goto out_error;
559 }
560
561out_done:
562 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
563 unwritten, oinfo);
564out_error:
565 if (error)
566 trace_xfs_rmap_unmap_error(mp, cur->bc_private.a.agno,
567 error, _RET_IP_);
568 return error;
569}
570
571/*
572 * Remove a reference to an extent in the rmap btree.
573 */
574int
575xfs_rmap_free(
576 struct xfs_trans *tp,
577 struct xfs_buf *agbp,
578 xfs_agnumber_t agno,
579 xfs_agblock_t bno,
580 xfs_extlen_t len,
581 struct xfs_owner_info *oinfo)
582{
583 struct xfs_mount *mp = tp->t_mountp;
584 struct xfs_btree_cur *cur;
585 int error;
586
587 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
588 return 0;
589
590 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
591
592 error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
593 if (error)
594 goto out_error;
595
596 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
597 return 0;
598
599out_error:
600 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
601 return error;
602}
603
604/*
605 * A mergeable rmap must have the same owner and the same values for
606 * the unwritten, attr_fork, and bmbt flags. The startblock and
607 * offset are checked separately.
608 */
609static bool
610xfs_rmap_is_mergeable(
611 struct xfs_rmap_irec *irec,
612 uint64_t owner,
613 unsigned int flags)
614{
615 if (irec->rm_owner == XFS_RMAP_OWN_NULL)
616 return false;
617 if (irec->rm_owner != owner)
618 return false;
619 if ((flags & XFS_RMAP_UNWRITTEN) ^
620 (irec->rm_flags & XFS_RMAP_UNWRITTEN))
621 return false;
622 if ((flags & XFS_RMAP_ATTR_FORK) ^
623 (irec->rm_flags & XFS_RMAP_ATTR_FORK))
624 return false;
625 if ((flags & XFS_RMAP_BMBT_BLOCK) ^
626 (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
627 return false;
628 return true;
629}
630
631/*
632 * When we allocate a new block, the first thing we do is add a reference to
633 * the extent in the rmap btree. This takes the form of a [agbno, length,
634 * owner, offset] record. Flags are encoded in the high bits of the offset
635 * field.
636 */
637STATIC int
638xfs_rmap_map(
639 struct xfs_btree_cur *cur,
640 xfs_agblock_t bno,
641 xfs_extlen_t len,
642 bool unwritten,
643 struct xfs_owner_info *oinfo)
644{
645 struct xfs_mount *mp = cur->bc_mp;
646 struct xfs_rmap_irec ltrec;
647 struct xfs_rmap_irec gtrec;
648 int have_gt;
649 int have_lt;
650 int error = 0;
651 int i;
652 uint64_t owner;
653 uint64_t offset;
654 unsigned int flags = 0;
655 bool ignore_off;
656
657 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
658 ASSERT(owner != 0);
659 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
660 (flags & XFS_RMAP_BMBT_BLOCK);
661 if (unwritten)
662 flags |= XFS_RMAP_UNWRITTEN;
663 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
664 unwritten, oinfo);
665
666 /*
667 * For the initial lookup, look for an exact match or the left-adjacent
668 * record for our insertion point. This will also give us the record for
669 * start block contiguity tests.
670 */
671 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
672 &have_lt);
673 if (error)
674 goto out_error;
675 XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
676
677 error = xfs_rmap_get_rec(cur, <rec, &have_lt);
678 if (error)
679 goto out_error;
680 XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
681 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
682 cur->bc_private.a.agno, ltrec.rm_startblock,
683 ltrec.rm_blockcount, ltrec.rm_owner,
684 ltrec.rm_offset, ltrec.rm_flags);
685
686 if (!xfs_rmap_is_mergeable(<rec, owner, flags))
687 have_lt = 0;
688
689 XFS_WANT_CORRUPTED_GOTO(mp,
690 have_lt == 0 ||
691 ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error);
692
693 /*
694 * Increment the cursor to see if we have a right-adjacent record to our
695 * insertion point. This will give us the record for end block
696 * contiguity tests.
697 */
698 error = xfs_btree_increment(cur, 0, &have_gt);
699 if (error)
700 goto out_error;
701 if (have_gt) {
702 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
703 if (error)
704 goto out_error;
705 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
706 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock,
707 out_error);
708 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
709 cur->bc_private.a.agno, gtrec.rm_startblock,
710 gtrec.rm_blockcount, gtrec.rm_owner,
711 gtrec.rm_offset, gtrec.rm_flags);
712 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
713 have_gt = 0;
714 }
715
716 /*
717 * Note: cursor currently points one record to the right of ltrec, even
718 * if there is no record in the tree to the right.
719 */
720 if (have_lt &&
721 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
722 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
723 /*
724 * left edge contiguous, merge into left record.
725 *
726 * ltbno ltlen
727 * orig: |ooooooooo|
728 * adding: |aaaaaaaaa|
729 * result: |rrrrrrrrrrrrrrrrrrr|
730 * bno len
731 */
732 ltrec.rm_blockcount += len;
733 if (have_gt &&
734 bno + len == gtrec.rm_startblock &&
735 (ignore_off || offset + len == gtrec.rm_offset) &&
736 (unsigned long)ltrec.rm_blockcount + len +
737 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
738 /*
739 * right edge also contiguous, delete right record
740 * and merge into left record.
741 *
742 * ltbno ltlen gtbno gtlen
743 * orig: |ooooooooo| |ooooooooo|
744 * adding: |aaaaaaaaa|
745 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
746 */
747 ltrec.rm_blockcount += gtrec.rm_blockcount;
748 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
749 gtrec.rm_startblock,
750 gtrec.rm_blockcount,
751 gtrec.rm_owner,
752 gtrec.rm_offset,
753 gtrec.rm_flags);
754 error = xfs_btree_delete(cur, &i);
755 if (error)
756 goto out_error;
757 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
758 }
759
760 /* point the cursor back to the left record and update */
761 error = xfs_btree_decrement(cur, 0, &have_gt);
762 if (error)
763 goto out_error;
764 error = xfs_rmap_update(cur, <rec);
765 if (error)
766 goto out_error;
767 } else if (have_gt &&
768 bno + len == gtrec.rm_startblock &&
769 (ignore_off || offset + len == gtrec.rm_offset)) {
770 /*
771 * right edge contiguous, merge into right record.
772 *
773 * gtbno gtlen
774 * Orig: |ooooooooo|
775 * adding: |aaaaaaaaa|
776 * Result: |rrrrrrrrrrrrrrrrrrr|
777 * bno len
778 */
779 gtrec.rm_startblock = bno;
780 gtrec.rm_blockcount += len;
781 if (!ignore_off)
782 gtrec.rm_offset = offset;
783 error = xfs_rmap_update(cur, >rec);
784 if (error)
785 goto out_error;
786 } else {
787 /*
788 * no contiguous edge with identical owner, insert
789 * new record at current cursor position.
790 */
791 cur->bc_rec.r.rm_startblock = bno;
792 cur->bc_rec.r.rm_blockcount = len;
793 cur->bc_rec.r.rm_owner = owner;
794 cur->bc_rec.r.rm_offset = offset;
795 cur->bc_rec.r.rm_flags = flags;
796 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
797 owner, offset, flags);
798 error = xfs_btree_insert(cur, &i);
799 if (error)
800 goto out_error;
801 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
802 }
803
804 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
805 unwritten, oinfo);
806out_error:
807 if (error)
808 trace_xfs_rmap_map_error(mp, cur->bc_private.a.agno,
809 error, _RET_IP_);
810 return error;
811}
812
813/*
814 * Add a reference to an extent in the rmap btree.
815 */
816int
817xfs_rmap_alloc(
818 struct xfs_trans *tp,
819 struct xfs_buf *agbp,
820 xfs_agnumber_t agno,
821 xfs_agblock_t bno,
822 xfs_extlen_t len,
823 struct xfs_owner_info *oinfo)
824{
825 struct xfs_mount *mp = tp->t_mountp;
826 struct xfs_btree_cur *cur;
827 int error;
828
829 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
830 return 0;
831
832 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
833 error = xfs_rmap_map(cur, bno, len, false, oinfo);
834 if (error)
835 goto out_error;
836
837 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
838 return 0;
839
840out_error:
841 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
842 return error;
843}
844
845#define RMAP_LEFT_CONTIG (1 << 0)
846#define RMAP_RIGHT_CONTIG (1 << 1)
847#define RMAP_LEFT_FILLING (1 << 2)
848#define RMAP_RIGHT_FILLING (1 << 3)
849#define RMAP_LEFT_VALID (1 << 6)
850#define RMAP_RIGHT_VALID (1 << 7)
851
852#define LEFT r[0]
853#define RIGHT r[1]
854#define PREV r[2]
855#define NEW r[3]
856
857/*
858 * Convert an unwritten extent to a real extent or vice versa.
859 * Does not handle overlapping extents.
860 */
861STATIC int
862xfs_rmap_convert(
863 struct xfs_btree_cur *cur,
864 xfs_agblock_t bno,
865 xfs_extlen_t len,
866 bool unwritten,
867 struct xfs_owner_info *oinfo)
868{
869 struct xfs_mount *mp = cur->bc_mp;
870 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
871 /* left is 0, right is 1, prev is 2 */
872 /* new is 3 */
873 uint64_t owner;
874 uint64_t offset;
875 uint64_t new_endoff;
876 unsigned int oldext;
877 unsigned int newext;
878 unsigned int flags = 0;
879 int i;
880 int state = 0;
881 int error;
882
883 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
884 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
885 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
886 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
887 new_endoff = offset + len;
888 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
889 unwritten, oinfo);
890
891 /*
892 * For the initial lookup, look for an exact match or the left-adjacent
893 * record for our insertion point. This will also give us the record for
894 * start block contiguity tests.
895 */
896 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
897 if (error)
898 goto done;
899 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
900
901 error = xfs_rmap_get_rec(cur, &PREV, &i);
902 if (error)
903 goto done;
904 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
905 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
906 cur->bc_private.a.agno, PREV.rm_startblock,
907 PREV.rm_blockcount, PREV.rm_owner,
908 PREV.rm_offset, PREV.rm_flags);
909
910 ASSERT(PREV.rm_offset <= offset);
911 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
912 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
913 newext = ~oldext & XFS_RMAP_UNWRITTEN;
914
915 /*
916 * Set flags determining what part of the previous oldext allocation
917 * extent is being replaced by a newext allocation.
918 */
919 if (PREV.rm_offset == offset)
920 state |= RMAP_LEFT_FILLING;
921 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
922 state |= RMAP_RIGHT_FILLING;
923
924 /*
925 * Decrement the cursor to see if we have a left-adjacent record to our
926 * insertion point. This will give us the record for end block
927 * contiguity tests.
928 */
929 error = xfs_btree_decrement(cur, 0, &i);
930 if (error)
931 goto done;
932 if (i) {
933 state |= RMAP_LEFT_VALID;
934 error = xfs_rmap_get_rec(cur, &LEFT, &i);
935 if (error)
936 goto done;
937 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
938 XFS_WANT_CORRUPTED_GOTO(mp,
939 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
940 done);
941 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
942 cur->bc_private.a.agno, LEFT.rm_startblock,
943 LEFT.rm_blockcount, LEFT.rm_owner,
944 LEFT.rm_offset, LEFT.rm_flags);
945 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
946 LEFT.rm_offset + LEFT.rm_blockcount == offset &&
947 xfs_rmap_is_mergeable(&LEFT, owner, newext))
948 state |= RMAP_LEFT_CONTIG;
949 }
950
951 /*
952 * Increment the cursor to see if we have a right-adjacent record to our
953 * insertion point. This will give us the record for end block
954 * contiguity tests.
955 */
956 error = xfs_btree_increment(cur, 0, &i);
957 if (error)
958 goto done;
959 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
960 error = xfs_btree_increment(cur, 0, &i);
961 if (error)
962 goto done;
963 if (i) {
964 state |= RMAP_RIGHT_VALID;
965 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
966 if (error)
967 goto done;
968 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
969 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
970 done);
971 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
972 cur->bc_private.a.agno, RIGHT.rm_startblock,
973 RIGHT.rm_blockcount, RIGHT.rm_owner,
974 RIGHT.rm_offset, RIGHT.rm_flags);
975 if (bno + len == RIGHT.rm_startblock &&
976 offset + len == RIGHT.rm_offset &&
977 xfs_rmap_is_mergeable(&RIGHT, owner, newext))
978 state |= RMAP_RIGHT_CONTIG;
979 }
980
981 /* check that left + prev + right is not too long */
982 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
983 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
984 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
985 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
986 (unsigned long)LEFT.rm_blockcount + len +
987 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
988 state &= ~RMAP_RIGHT_CONTIG;
989
990 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
991 _RET_IP_);
992
993 /* reset the cursor back to PREV */
994 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
995 if (error)
996 goto done;
997 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
998
999 /*
1000 * Switch out based on the FILLING and CONTIG state bits.
1001 */
1002 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1003 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1004 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1005 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1006 /*
1007 * Setting all of a previous oldext extent to newext.
1008 * The left and right neighbors are both contiguous with new.
1009 */
1010 error = xfs_btree_increment(cur, 0, &i);
1011 if (error)
1012 goto done;
1013 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1014 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1015 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1016 RIGHT.rm_owner, RIGHT.rm_offset,
1017 RIGHT.rm_flags);
1018 error = xfs_btree_delete(cur, &i);
1019 if (error)
1020 goto done;
1021 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1022 error = xfs_btree_decrement(cur, 0, &i);
1023 if (error)
1024 goto done;
1025 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1026 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1027 PREV.rm_startblock, PREV.rm_blockcount,
1028 PREV.rm_owner, PREV.rm_offset,
1029 PREV.rm_flags);
1030 error = xfs_btree_delete(cur, &i);
1031 if (error)
1032 goto done;
1033 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1034 error = xfs_btree_decrement(cur, 0, &i);
1035 if (error)
1036 goto done;
1037 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1038 NEW = LEFT;
1039 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1040 error = xfs_rmap_update(cur, &NEW);
1041 if (error)
1042 goto done;
1043 break;
1044
1045 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1046 /*
1047 * Setting all of a previous oldext extent to newext.
1048 * The left neighbor is contiguous, the right is not.
1049 */
1050 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1051 PREV.rm_startblock, PREV.rm_blockcount,
1052 PREV.rm_owner, PREV.rm_offset,
1053 PREV.rm_flags);
1054 error = xfs_btree_delete(cur, &i);
1055 if (error)
1056 goto done;
1057 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1058 error = xfs_btree_decrement(cur, 0, &i);
1059 if (error)
1060 goto done;
1061 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1062 NEW = LEFT;
1063 NEW.rm_blockcount += PREV.rm_blockcount;
1064 error = xfs_rmap_update(cur, &NEW);
1065 if (error)
1066 goto done;
1067 break;
1068
1069 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1070 /*
1071 * Setting all of a previous oldext extent to newext.
1072 * The right neighbor is contiguous, the left is not.
1073 */
1074 error = xfs_btree_increment(cur, 0, &i);
1075 if (error)
1076 goto done;
1077 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1078 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1079 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1080 RIGHT.rm_owner, RIGHT.rm_offset,
1081 RIGHT.rm_flags);
1082 error = xfs_btree_delete(cur, &i);
1083 if (error)
1084 goto done;
1085 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1086 error = xfs_btree_decrement(cur, 0, &i);
1087 if (error)
1088 goto done;
1089 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1090 NEW = PREV;
1091 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1092 NEW.rm_flags = newext;
1093 error = xfs_rmap_update(cur, &NEW);
1094 if (error)
1095 goto done;
1096 break;
1097
1098 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1099 /*
1100 * Setting all of a previous oldext extent to newext.
1101 * Neither the left nor right neighbors are contiguous with
1102 * the new one.
1103 */
1104 NEW = PREV;
1105 NEW.rm_flags = newext;
1106 error = xfs_rmap_update(cur, &NEW);
1107 if (error)
1108 goto done;
1109 break;
1110
1111 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1112 /*
1113 * Setting the first part of a previous oldext extent to newext.
1114 * The left neighbor is contiguous.
1115 */
1116 NEW = PREV;
1117 NEW.rm_offset += len;
1118 NEW.rm_startblock += len;
1119 NEW.rm_blockcount -= len;
1120 error = xfs_rmap_update(cur, &NEW);
1121 if (error)
1122 goto done;
1123 error = xfs_btree_decrement(cur, 0, &i);
1124 if (error)
1125 goto done;
1126 NEW = LEFT;
1127 NEW.rm_blockcount += len;
1128 error = xfs_rmap_update(cur, &NEW);
1129 if (error)
1130 goto done;
1131 break;
1132
1133 case RMAP_LEFT_FILLING:
1134 /*
1135 * Setting the first part of a previous oldext extent to newext.
1136 * The left neighbor is not contiguous.
1137 */
1138 NEW = PREV;
1139 NEW.rm_startblock += len;
1140 NEW.rm_offset += len;
1141 NEW.rm_blockcount -= len;
1142 error = xfs_rmap_update(cur, &NEW);
1143 if (error)
1144 goto done;
1145 NEW.rm_startblock = bno;
1146 NEW.rm_owner = owner;
1147 NEW.rm_offset = offset;
1148 NEW.rm_blockcount = len;
1149 NEW.rm_flags = newext;
1150 cur->bc_rec.r = NEW;
1151 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1152 len, owner, offset, newext);
1153 error = xfs_btree_insert(cur, &i);
1154 if (error)
1155 goto done;
1156 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1157 break;
1158
1159 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1160 /*
1161 * Setting the last part of a previous oldext extent to newext.
1162 * The right neighbor is contiguous with the new allocation.
1163 */
1164 NEW = PREV;
1165 NEW.rm_blockcount -= len;
1166 error = xfs_rmap_update(cur, &NEW);
1167 if (error)
1168 goto done;
1169 error = xfs_btree_increment(cur, 0, &i);
1170 if (error)
1171 goto done;
1172 NEW = RIGHT;
1173 NEW.rm_offset = offset;
1174 NEW.rm_startblock = bno;
1175 NEW.rm_blockcount += len;
1176 error = xfs_rmap_update(cur, &NEW);
1177 if (error)
1178 goto done;
1179 break;
1180
1181 case RMAP_RIGHT_FILLING:
1182 /*
1183 * Setting the last part of a previous oldext extent to newext.
1184 * The right neighbor is not contiguous.
1185 */
1186 NEW = PREV;
1187 NEW.rm_blockcount -= len;
1188 error = xfs_rmap_update(cur, &NEW);
1189 if (error)
1190 goto done;
1191 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1192 oldext, &i);
1193 if (error)
1194 goto done;
1195 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1196 NEW.rm_startblock = bno;
1197 NEW.rm_owner = owner;
1198 NEW.rm_offset = offset;
1199 NEW.rm_blockcount = len;
1200 NEW.rm_flags = newext;
1201 cur->bc_rec.r = NEW;
1202 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1203 len, owner, offset, newext);
1204 error = xfs_btree_insert(cur, &i);
1205 if (error)
1206 goto done;
1207 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1208 break;
1209
1210 case 0:
1211 /*
1212 * Setting the middle part of a previous oldext extent to
1213 * newext. Contiguity is impossible here.
1214 * One extent becomes three extents.
1215 */
1216 /* new right extent - oldext */
1217 NEW.rm_startblock = bno + len;
1218 NEW.rm_owner = owner;
1219 NEW.rm_offset = new_endoff;
1220 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1221 new_endoff;
1222 NEW.rm_flags = PREV.rm_flags;
1223 error = xfs_rmap_update(cur, &NEW);
1224 if (error)
1225 goto done;
1226 /* new left extent - oldext */
1227 NEW = PREV;
1228 NEW.rm_blockcount = offset - PREV.rm_offset;
1229 cur->bc_rec.r = NEW;
1230 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
1231 NEW.rm_startblock, NEW.rm_blockcount,
1232 NEW.rm_owner, NEW.rm_offset,
1233 NEW.rm_flags);
1234 error = xfs_btree_insert(cur, &i);
1235 if (error)
1236 goto done;
1237 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1238 /*
1239 * Reset the cursor to the position of the new extent
1240 * we are about to insert as we can't trust it after
1241 * the previous insert.
1242 */
1243 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1244 oldext, &i);
1245 if (error)
1246 goto done;
1247 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1248 /* new middle extent - newext */
1249 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1250 cur->bc_rec.r.rm_flags |= newext;
1251 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
1252 owner, offset, newext);
1253 error = xfs_btree_insert(cur, &i);
1254 if (error)
1255 goto done;
1256 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1257 break;
1258
1259 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1260 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1261 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1262 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1263 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1264 case RMAP_LEFT_CONTIG:
1265 case RMAP_RIGHT_CONTIG:
1266 /*
1267 * These cases are all impossible.
1268 */
1269 ASSERT(0);
1270 }
1271
1272 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1273 unwritten, oinfo);
1274done:
1275 if (error)
1276 trace_xfs_rmap_convert_error(cur->bc_mp,
1277 cur->bc_private.a.agno, error, _RET_IP_);
1278 return error;
1279}
1280
1281/*
1282 * Convert an unwritten extent to a real extent or vice versa. If there is no
1283 * possibility of overlapping extents, delegate to the simpler convert
1284 * function.
1285 */
1286STATIC int
1287xfs_rmap_convert_shared(
1288 struct xfs_btree_cur *cur,
1289 xfs_agblock_t bno,
1290 xfs_extlen_t len,
1291 bool unwritten,
1292 struct xfs_owner_info *oinfo)
1293{
1294 struct xfs_mount *mp = cur->bc_mp;
1295 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1296 /* left is 0, right is 1, prev is 2 */
1297 /* new is 3 */
1298 uint64_t owner;
1299 uint64_t offset;
1300 uint64_t new_endoff;
1301 unsigned int oldext;
1302 unsigned int newext;
1303 unsigned int flags = 0;
1304 int i;
1305 int state = 0;
1306 int error;
1307
1308 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1309 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1310 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1311 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1312 new_endoff = offset + len;
1313 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
1314 unwritten, oinfo);
1315
1316 /*
1317 * For the initial lookup, look for and exact match or the left-adjacent
1318 * record for our insertion point. This will also give us the record for
1319 * start block contiguity tests.
1320 */
1321 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1322 &PREV, &i);
1323 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1324
1325 ASSERT(PREV.rm_offset <= offset);
1326 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1327 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1328 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1329
1330 /*
1331 * Set flags determining what part of the previous oldext allocation
1332 * extent is being replaced by a newext allocation.
1333 */
1334 if (PREV.rm_offset == offset)
1335 state |= RMAP_LEFT_FILLING;
1336 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1337 state |= RMAP_RIGHT_FILLING;
1338
1339 /* Is there a left record that abuts our range? */
1340 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1341 &LEFT, &i);
1342 if (error)
1343 goto done;
1344 if (i) {
1345 state |= RMAP_LEFT_VALID;
1346 XFS_WANT_CORRUPTED_GOTO(mp,
1347 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
1348 done);
1349 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1350 state |= RMAP_LEFT_CONTIG;
1351 }
1352
1353 /* Is there a right record that abuts our range? */
1354 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1355 newext, &i);
1356 if (error)
1357 goto done;
1358 if (i) {
1359 state |= RMAP_RIGHT_VALID;
1360 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1361 if (error)
1362 goto done;
1363 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1364 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1365 done);
1366 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1367 cur->bc_private.a.agno, RIGHT.rm_startblock,
1368 RIGHT.rm_blockcount, RIGHT.rm_owner,
1369 RIGHT.rm_offset, RIGHT.rm_flags);
1370 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1371 state |= RMAP_RIGHT_CONTIG;
1372 }
1373
1374 /* check that left + prev + right is not too long */
1375 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1376 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1377 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1378 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1379 (unsigned long)LEFT.rm_blockcount + len +
1380 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1381 state &= ~RMAP_RIGHT_CONTIG;
1382
1383 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1384 _RET_IP_);
1385 /*
1386 * Switch out based on the FILLING and CONTIG state bits.
1387 */
1388 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1389 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1390 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1391 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1392 /*
1393 * Setting all of a previous oldext extent to newext.
1394 * The left and right neighbors are both contiguous with new.
1395 */
1396 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1397 RIGHT.rm_blockcount, RIGHT.rm_owner,
1398 RIGHT.rm_offset, RIGHT.rm_flags);
1399 if (error)
1400 goto done;
1401 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1402 PREV.rm_blockcount, PREV.rm_owner,
1403 PREV.rm_offset, PREV.rm_flags);
1404 if (error)
1405 goto done;
1406 NEW = LEFT;
1407 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1408 NEW.rm_blockcount, NEW.rm_owner,
1409 NEW.rm_offset, NEW.rm_flags, &i);
1410 if (error)
1411 goto done;
1412 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1413 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1414 error = xfs_rmap_update(cur, &NEW);
1415 if (error)
1416 goto done;
1417 break;
1418
1419 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1420 /*
1421 * Setting all of a previous oldext extent to newext.
1422 * The left neighbor is contiguous, the right is not.
1423 */
1424 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1425 PREV.rm_blockcount, PREV.rm_owner,
1426 PREV.rm_offset, PREV.rm_flags);
1427 if (error)
1428 goto done;
1429 NEW = LEFT;
1430 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1431 NEW.rm_blockcount, NEW.rm_owner,
1432 NEW.rm_offset, NEW.rm_flags, &i);
1433 if (error)
1434 goto done;
1435 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1436 NEW.rm_blockcount += PREV.rm_blockcount;
1437 error = xfs_rmap_update(cur, &NEW);
1438 if (error)
1439 goto done;
1440 break;
1441
1442 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1443 /*
1444 * Setting all of a previous oldext extent to newext.
1445 * The right neighbor is contiguous, the left is not.
1446 */
1447 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1448 RIGHT.rm_blockcount, RIGHT.rm_owner,
1449 RIGHT.rm_offset, RIGHT.rm_flags);
1450 if (error)
1451 goto done;
1452 NEW = PREV;
1453 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1454 NEW.rm_blockcount, NEW.rm_owner,
1455 NEW.rm_offset, NEW.rm_flags, &i);
1456 if (error)
1457 goto done;
1458 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1459 NEW.rm_blockcount += RIGHT.rm_blockcount;
1460 NEW.rm_flags = RIGHT.rm_flags;
1461 error = xfs_rmap_update(cur, &NEW);
1462 if (error)
1463 goto done;
1464 break;
1465
1466 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1467 /*
1468 * Setting all of a previous oldext extent to newext.
1469 * Neither the left nor right neighbors are contiguous with
1470 * the new one.
1471 */
1472 NEW = PREV;
1473 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1474 NEW.rm_blockcount, NEW.rm_owner,
1475 NEW.rm_offset, NEW.rm_flags, &i);
1476 if (error)
1477 goto done;
1478 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1479 NEW.rm_flags = newext;
1480 error = xfs_rmap_update(cur, &NEW);
1481 if (error)
1482 goto done;
1483 break;
1484
1485 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1486 /*
1487 * Setting the first part of a previous oldext extent to newext.
1488 * The left neighbor is contiguous.
1489 */
1490 NEW = PREV;
1491 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1492 NEW.rm_blockcount, NEW.rm_owner,
1493 NEW.rm_offset, NEW.rm_flags);
1494 if (error)
1495 goto done;
1496 NEW.rm_offset += len;
1497 NEW.rm_startblock += len;
1498 NEW.rm_blockcount -= len;
1499 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1500 NEW.rm_blockcount, NEW.rm_owner,
1501 NEW.rm_offset, NEW.rm_flags);
1502 if (error)
1503 goto done;
1504 NEW = LEFT;
1505 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1506 NEW.rm_blockcount, NEW.rm_owner,
1507 NEW.rm_offset, NEW.rm_flags, &i);
1508 if (error)
1509 goto done;
1510 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1511 NEW.rm_blockcount += len;
1512 error = xfs_rmap_update(cur, &NEW);
1513 if (error)
1514 goto done;
1515 break;
1516
1517 case RMAP_LEFT_FILLING:
1518 /*
1519 * Setting the first part of a previous oldext extent to newext.
1520 * The left neighbor is not contiguous.
1521 */
1522 NEW = PREV;
1523 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1524 NEW.rm_blockcount, NEW.rm_owner,
1525 NEW.rm_offset, NEW.rm_flags);
1526 if (error)
1527 goto done;
1528 NEW.rm_offset += len;
1529 NEW.rm_startblock += len;
1530 NEW.rm_blockcount -= len;
1531 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1532 NEW.rm_blockcount, NEW.rm_owner,
1533 NEW.rm_offset, NEW.rm_flags);
1534 if (error)
1535 goto done;
1536 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1537 if (error)
1538 goto done;
1539 break;
1540
1541 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1542 /*
1543 * Setting the last part of a previous oldext extent to newext.
1544 * The right neighbor is contiguous with the new allocation.
1545 */
1546 NEW = PREV;
1547 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1548 NEW.rm_blockcount, NEW.rm_owner,
1549 NEW.rm_offset, NEW.rm_flags, &i);
1550 if (error)
1551 goto done;
1552 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1553 NEW.rm_blockcount = offset - NEW.rm_offset;
1554 error = xfs_rmap_update(cur, &NEW);
1555 if (error)
1556 goto done;
1557 NEW = RIGHT;
1558 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1559 NEW.rm_blockcount, NEW.rm_owner,
1560 NEW.rm_offset, NEW.rm_flags);
1561 if (error)
1562 goto done;
1563 NEW.rm_offset = offset;
1564 NEW.rm_startblock = bno;
1565 NEW.rm_blockcount += len;
1566 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1567 NEW.rm_blockcount, NEW.rm_owner,
1568 NEW.rm_offset, NEW.rm_flags);
1569 if (error)
1570 goto done;
1571 break;
1572
1573 case RMAP_RIGHT_FILLING:
1574 /*
1575 * Setting the last part of a previous oldext extent to newext.
1576 * The right neighbor is not contiguous.
1577 */
1578 NEW = PREV;
1579 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1580 NEW.rm_blockcount, NEW.rm_owner,
1581 NEW.rm_offset, NEW.rm_flags, &i);
1582 if (error)
1583 goto done;
1584 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1585 NEW.rm_blockcount -= len;
1586 error = xfs_rmap_update(cur, &NEW);
1587 if (error)
1588 goto done;
1589 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1590 if (error)
1591 goto done;
1592 break;
1593
1594 case 0:
1595 /*
1596 * Setting the middle part of a previous oldext extent to
1597 * newext. Contiguity is impossible here.
1598 * One extent becomes three extents.
1599 */
1600 /* new right extent - oldext */
1601 NEW.rm_startblock = bno + len;
1602 NEW.rm_owner = owner;
1603 NEW.rm_offset = new_endoff;
1604 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1605 new_endoff;
1606 NEW.rm_flags = PREV.rm_flags;
1607 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1608 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1609 NEW.rm_flags);
1610 if (error)
1611 goto done;
1612 /* new left extent - oldext */
1613 NEW = PREV;
1614 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1615 NEW.rm_blockcount, NEW.rm_owner,
1616 NEW.rm_offset, NEW.rm_flags, &i);
1617 if (error)
1618 goto done;
1619 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1620 NEW.rm_blockcount = offset - NEW.rm_offset;
1621 error = xfs_rmap_update(cur, &NEW);
1622 if (error)
1623 goto done;
1624 /* new middle extent - newext */
1625 NEW.rm_startblock = bno;
1626 NEW.rm_blockcount = len;
1627 NEW.rm_owner = owner;
1628 NEW.rm_offset = offset;
1629 NEW.rm_flags = newext;
1630 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1631 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1632 NEW.rm_flags);
1633 if (error)
1634 goto done;
1635 break;
1636
1637 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1638 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1639 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1640 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1641 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1642 case RMAP_LEFT_CONTIG:
1643 case RMAP_RIGHT_CONTIG:
1644 /*
1645 * These cases are all impossible.
1646 */
1647 ASSERT(0);
1648 }
1649
1650 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1651 unwritten, oinfo);
1652done:
1653 if (error)
1654 trace_xfs_rmap_convert_error(cur->bc_mp,
1655 cur->bc_private.a.agno, error, _RET_IP_);
1656 return error;
1657}
1658
1659#undef NEW
1660#undef LEFT
1661#undef RIGHT
1662#undef PREV
1663
1664/*
1665 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1666 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1667 * that the prev/next records in the btree might belong to another owner.
1668 * Therefore we must use delete+insert to alter any of the key fields.
1669 *
1670 * For every other situation there can only be one owner for a given extent,
1671 * so we can call the regular _free function.
1672 */
1673STATIC int
1674xfs_rmap_unmap_shared(
1675 struct xfs_btree_cur *cur,
1676 xfs_agblock_t bno,
1677 xfs_extlen_t len,
1678 bool unwritten,
1679 struct xfs_owner_info *oinfo)
1680{
1681 struct xfs_mount *mp = cur->bc_mp;
1682 struct xfs_rmap_irec ltrec;
1683 uint64_t ltoff;
1684 int error = 0;
1685 int i;
1686 uint64_t owner;
1687 uint64_t offset;
1688 unsigned int flags;
1689
1690 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1691 if (unwritten)
1692 flags |= XFS_RMAP_UNWRITTEN;
1693 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
1694 unwritten, oinfo);
1695
1696 /*
1697 * We should always have a left record because there's a static record
1698 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1699 * will not ever be removed from the tree.
1700 */
1701 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1702 <rec, &i);
1703 if (error)
1704 goto out_error;
1705 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1706 ltoff = ltrec.rm_offset;
1707
1708 /* Make sure the extent we found covers the entire freeing range. */
1709 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
1710 ltrec.rm_startblock + ltrec.rm_blockcount >=
1711 bno + len, out_error);
1712
1713 /* Make sure the owner matches what we expect to find in the tree. */
1714 XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner, out_error);
1715
1716 /* Make sure the unwritten flag matches. */
1717 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
1718 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error);
1719
1720 /* Check the offset. */
1721 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error);
1722 XFS_WANT_CORRUPTED_GOTO(mp, offset <= ltoff + ltrec.rm_blockcount,
1723 out_error);
1724
1725 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
1726 /* Exact match, simply remove the record from rmap tree. */
1727 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1728 ltrec.rm_blockcount, ltrec.rm_owner,
1729 ltrec.rm_offset, ltrec.rm_flags);
1730 if (error)
1731 goto out_error;
1732 } else if (ltrec.rm_startblock == bno) {
1733 /*
1734 * Overlap left hand side of extent: move the start, trim the
1735 * length and update the current record.
1736 *
1737 * ltbno ltlen
1738 * Orig: |oooooooooooooooooooo|
1739 * Freeing: |fffffffff|
1740 * Result: |rrrrrrrrrr|
1741 * bno len
1742 */
1743
1744 /* Delete prev rmap. */
1745 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1746 ltrec.rm_blockcount, ltrec.rm_owner,
1747 ltrec.rm_offset, ltrec.rm_flags);
1748 if (error)
1749 goto out_error;
1750
1751 /* Add an rmap at the new offset. */
1752 ltrec.rm_startblock += len;
1753 ltrec.rm_blockcount -= len;
1754 ltrec.rm_offset += len;
1755 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
1756 ltrec.rm_blockcount, ltrec.rm_owner,
1757 ltrec.rm_offset, ltrec.rm_flags);
1758 if (error)
1759 goto out_error;
1760 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
1761 /*
1762 * Overlap right hand side of extent: trim the length and
1763 * update the current record.
1764 *
1765 * ltbno ltlen
1766 * Orig: |oooooooooooooooooooo|
1767 * Freeing: |fffffffff|
1768 * Result: |rrrrrrrrrr|
1769 * bno len
1770 */
1771 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1772 ltrec.rm_blockcount, ltrec.rm_owner,
1773 ltrec.rm_offset, ltrec.rm_flags, &i);
1774 if (error)
1775 goto out_error;
1776 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1777 ltrec.rm_blockcount -= len;
1778 error = xfs_rmap_update(cur, <rec);
1779 if (error)
1780 goto out_error;
1781 } else {
1782 /*
1783 * Overlap middle of extent: trim the length of the existing
1784 * record to the length of the new left-extent size, increment
1785 * the insertion position so we can insert a new record
1786 * containing the remaining right-extent space.
1787 *
1788 * ltbno ltlen
1789 * Orig: |oooooooooooooooooooo|
1790 * Freeing: |fffffffff|
1791 * Result: |rrrrr| |rrrr|
1792 * bno len
1793 */
1794 xfs_extlen_t orig_len = ltrec.rm_blockcount;
1795
1796 /* Shrink the left side of the rmap */
1797 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1798 ltrec.rm_blockcount, ltrec.rm_owner,
1799 ltrec.rm_offset, ltrec.rm_flags, &i);
1800 if (error)
1801 goto out_error;
1802 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1803 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
1804 error = xfs_rmap_update(cur, <rec);
1805 if (error)
1806 goto out_error;
1807
1808 /* Add an rmap at the new offset */
1809 error = xfs_rmap_insert(cur, bno + len,
1810 orig_len - len - ltrec.rm_blockcount,
1811 ltrec.rm_owner, offset + len,
1812 ltrec.rm_flags);
1813 if (error)
1814 goto out_error;
1815 }
1816
1817 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
1818 unwritten, oinfo);
1819out_error:
1820 if (error)
1821 trace_xfs_rmap_unmap_error(cur->bc_mp,
1822 cur->bc_private.a.agno, error, _RET_IP_);
1823 return error;
1824}
1825
1826/*
1827 * Find an extent in the rmap btree and map it. For rmap extent types that
1828 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1829 * that the prev/next records in the btree might belong to another owner.
1830 * Therefore we must use delete+insert to alter any of the key fields.
1831 *
1832 * For every other situation there can only be one owner for a given extent,
1833 * so we can call the regular _alloc function.
1834 */
1835STATIC int
1836xfs_rmap_map_shared(
1837 struct xfs_btree_cur *cur,
1838 xfs_agblock_t bno,
1839 xfs_extlen_t len,
1840 bool unwritten,
1841 struct xfs_owner_info *oinfo)
1842{
1843 struct xfs_mount *mp = cur->bc_mp;
1844 struct xfs_rmap_irec ltrec;
1845 struct xfs_rmap_irec gtrec;
1846 int have_gt;
1847 int have_lt;
1848 int error = 0;
1849 int i;
1850 uint64_t owner;
1851 uint64_t offset;
1852 unsigned int flags = 0;
1853
1854 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1855 if (unwritten)
1856 flags |= XFS_RMAP_UNWRITTEN;
1857 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
1858 unwritten, oinfo);
1859
1860 /* Is there a left record that abuts our range? */
1861 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
1862 <rec, &have_lt);
1863 if (error)
1864 goto out_error;
1865 if (have_lt &&
1866 !xfs_rmap_is_mergeable(<rec, owner, flags))
1867 have_lt = 0;
1868
1869 /* Is there a right record that abuts our range? */
1870 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1871 flags, &have_gt);
1872 if (error)
1873 goto out_error;
1874 if (have_gt) {
1875 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
1876 if (error)
1877 goto out_error;
1878 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
1879 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1880 cur->bc_private.a.agno, gtrec.rm_startblock,
1881 gtrec.rm_blockcount, gtrec.rm_owner,
1882 gtrec.rm_offset, gtrec.rm_flags);
1883
1884 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
1885 have_gt = 0;
1886 }
1887
1888 if (have_lt &&
1889 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
1890 ltrec.rm_offset + ltrec.rm_blockcount == offset) {
1891 /*
1892 * Left edge contiguous, merge into left record.
1893 *
1894 * ltbno ltlen
1895 * orig: |ooooooooo|
1896 * adding: |aaaaaaaaa|
1897 * result: |rrrrrrrrrrrrrrrrrrr|
1898 * bno len
1899 */
1900 ltrec.rm_blockcount += len;
1901 if (have_gt &&
1902 bno + len == gtrec.rm_startblock &&
1903 offset + len == gtrec.rm_offset) {
1904 /*
1905 * Right edge also contiguous, delete right record
1906 * and merge into left record.
1907 *
1908 * ltbno ltlen gtbno gtlen
1909 * orig: |ooooooooo| |ooooooooo|
1910 * adding: |aaaaaaaaa|
1911 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1912 */
1913 ltrec.rm_blockcount += gtrec.rm_blockcount;
1914 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
1915 gtrec.rm_blockcount, gtrec.rm_owner,
1916 gtrec.rm_offset, gtrec.rm_flags);
1917 if (error)
1918 goto out_error;
1919 }
1920
1921 /* Point the cursor back to the left record and update. */
1922 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1923 ltrec.rm_blockcount, ltrec.rm_owner,
1924 ltrec.rm_offset, ltrec.rm_flags, &i);
1925 if (error)
1926 goto out_error;
1927 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1928
1929 error = xfs_rmap_update(cur, <rec);
1930 if (error)
1931 goto out_error;
1932 } else if (have_gt &&
1933 bno + len == gtrec.rm_startblock &&
1934 offset + len == gtrec.rm_offset) {
1935 /*
1936 * Right edge contiguous, merge into right record.
1937 *
1938 * gtbno gtlen
1939 * Orig: |ooooooooo|
1940 * adding: |aaaaaaaaa|
1941 * Result: |rrrrrrrrrrrrrrrrrrr|
1942 * bno len
1943 */
1944 /* Delete the old record. */
1945 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
1946 gtrec.rm_blockcount, gtrec.rm_owner,
1947 gtrec.rm_offset, gtrec.rm_flags);
1948 if (error)
1949 goto out_error;
1950
1951 /* Move the start and re-add it. */
1952 gtrec.rm_startblock = bno;
1953 gtrec.rm_blockcount += len;
1954 gtrec.rm_offset = offset;
1955 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
1956 gtrec.rm_blockcount, gtrec.rm_owner,
1957 gtrec.rm_offset, gtrec.rm_flags);
1958 if (error)
1959 goto out_error;
1960 } else {
1961 /*
1962 * No contiguous edge with identical owner, insert
1963 * new record at current cursor position.
1964 */
1965 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
1966 if (error)
1967 goto out_error;
1968 }
1969
1970 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
1971 unwritten, oinfo);
1972out_error:
1973 if (error)
1974 trace_xfs_rmap_map_error(cur->bc_mp,
1975 cur->bc_private.a.agno, error, _RET_IP_);
1976 return error;
1977}
1978
1979struct xfs_rmap_query_range_info {
1980 xfs_rmap_query_range_fn fn;
1981 void *priv;
1982};
1983
1984/* Format btree record and pass to our callback. */
1985STATIC int
1986xfs_rmap_query_range_helper(
1987 struct xfs_btree_cur *cur,
1988 union xfs_btree_rec *rec,
1989 void *priv)
1990{
1991 struct xfs_rmap_query_range_info *query = priv;
1992 struct xfs_rmap_irec irec;
1993 int error;
1994
1995 error = xfs_rmap_btrec_to_irec(rec, &irec);
1996 if (error)
1997 return error;
1998 return query->fn(cur, &irec, query->priv);
1999}
2000
2001/* Find all rmaps between two keys. */
2002int
2003xfs_rmap_query_range(
2004 struct xfs_btree_cur *cur,
2005 struct xfs_rmap_irec *low_rec,
2006 struct xfs_rmap_irec *high_rec,
2007 xfs_rmap_query_range_fn fn,
2008 void *priv)
2009{
2010 union xfs_btree_irec low_brec;
2011 union xfs_btree_irec high_brec;
2012 struct xfs_rmap_query_range_info query;
2013
2014 low_brec.r = *low_rec;
2015 high_brec.r = *high_rec;
2016 query.priv = priv;
2017 query.fn = fn;
2018 return xfs_btree_query_range(cur, &low_brec, &high_brec,
2019 xfs_rmap_query_range_helper, &query);
2020}
2021
2022/* Clean up after calling xfs_rmap_finish_one. */
2023void
2024xfs_rmap_finish_one_cleanup(
2025 struct xfs_trans *tp,
2026 struct xfs_btree_cur *rcur,
2027 int error)
2028{
2029 struct xfs_buf *agbp;
2030
2031 if (rcur == NULL)
2032 return;
2033 agbp = rcur->bc_private.a.agbp;
2034 xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
2035 if (error)
2036 xfs_trans_brelse(tp, agbp);
2037}
2038
2039/*
2040 * Process one of the deferred rmap operations. We pass back the
2041 * btree cursor to maintain our lock on the rmapbt between calls.
2042 * This saves time and eliminates a buffer deadlock between the
2043 * superblock and the AGF because we'll always grab them in the same
2044 * order.
2045 */
2046int
2047xfs_rmap_finish_one(
2048 struct xfs_trans *tp,
2049 enum xfs_rmap_intent_type type,
2050 __uint64_t owner,
2051 int whichfork,
2052 xfs_fileoff_t startoff,
2053 xfs_fsblock_t startblock,
2054 xfs_filblks_t blockcount,
2055 xfs_exntst_t state,
2056 struct xfs_btree_cur **pcur)
2057{
2058 struct xfs_mount *mp = tp->t_mountp;
2059 struct xfs_btree_cur *rcur;
2060 struct xfs_buf *agbp = NULL;
2061 int error = 0;
2062 xfs_agnumber_t agno;
2063 struct xfs_owner_info oinfo;
2064 xfs_agblock_t bno;
2065 bool unwritten;
2066
2067 agno = XFS_FSB_TO_AGNO(mp, startblock);
2068 ASSERT(agno != NULLAGNUMBER);
2069 bno = XFS_FSB_TO_AGBNO(mp, startblock);
2070
2071 trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork,
2072 startoff, blockcount, state);
2073
2074 if (XFS_TEST_ERROR(false, mp,
2075 XFS_ERRTAG_RMAP_FINISH_ONE,
2076 XFS_RANDOM_RMAP_FINISH_ONE))
2077 return -EIO;
2078
2079 /*
2080 * If we haven't gotten a cursor or the cursor AG doesn't match
2081 * the startblock, get one now.
2082 */
2083 rcur = *pcur;
2084 if (rcur != NULL && rcur->bc_private.a.agno != agno) {
2085 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2086 rcur = NULL;
2087 *pcur = NULL;
2088 }
2089 if (rcur == NULL) {
2090 /*
2091 * Refresh the freelist before we start changing the
2092 * rmapbt, because a shape change could cause us to
2093 * allocate blocks.
2094 */
2095 error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
2096 if (error)
2097 return error;
2098 if (!agbp)
2099 return -EFSCORRUPTED;
2100
2101 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
2102 if (!rcur) {
2103 error = -ENOMEM;
2104 goto out_cur;
2105 }
2106 }
2107 *pcur = rcur;
2108
2109 xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2110 unwritten = state == XFS_EXT_UNWRITTEN;
2111 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2112
2113 switch (type) {
2114 case XFS_RMAP_ALLOC:
2115 case XFS_RMAP_MAP:
2116 error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2117 break;
2118 case XFS_RMAP_MAP_SHARED:
2119 error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2120 &oinfo);
2121 break;
2122 case XFS_RMAP_FREE:
2123 case XFS_RMAP_UNMAP:
2124 error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2125 &oinfo);
2126 break;
2127 case XFS_RMAP_UNMAP_SHARED:
2128 error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2129 &oinfo);
2130 break;
2131 case XFS_RMAP_CONVERT:
2132 error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2133 &oinfo);
2134 break;
2135 case XFS_RMAP_CONVERT_SHARED:
2136 error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2137 !unwritten, &oinfo);
2138 break;
2139 default:
2140 ASSERT(0);
2141 error = -EFSCORRUPTED;
2142 }
2143 return error;
2144
2145out_cur:
2146 xfs_trans_brelse(tp, agbp);
2147
2148 return error;
2149}
2150
2151/*
2152 * Don't defer an rmap if we aren't an rmap filesystem.
2153 */
2154static bool
2155xfs_rmap_update_is_needed(
2156 struct xfs_mount *mp,
2157 int whichfork)
2158{
2159 return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK;
2160}
2161
2162/*
2163 * Record a rmap intent; the list is kept sorted first by AG and then by
2164 * increasing age.
2165 */
2166static int
2167__xfs_rmap_add(
2168 struct xfs_mount *mp,
2169 struct xfs_defer_ops *dfops,
2170 enum xfs_rmap_intent_type type,
2171 __uint64_t owner,
2172 int whichfork,
2173 struct xfs_bmbt_irec *bmap)
2174{
2175 struct xfs_rmap_intent *ri;
2176
2177 trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, bmap->br_startblock),
2178 type,
2179 XFS_FSB_TO_AGBNO(mp, bmap->br_startblock),
2180 owner, whichfork,
2181 bmap->br_startoff,
2182 bmap->br_blockcount,
2183 bmap->br_state);
2184
2185 ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_SLEEP | KM_NOFS);
2186 INIT_LIST_HEAD(&ri->ri_list);
2187 ri->ri_type = type;
2188 ri->ri_owner = owner;
2189 ri->ri_whichfork = whichfork;
2190 ri->ri_bmap = *bmap;
2191
2192 xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
2193 return 0;
2194}
2195
2196/* Map an extent into a file. */
2197int
2198xfs_rmap_map_extent(
2199 struct xfs_mount *mp,
2200 struct xfs_defer_ops *dfops,
2201 struct xfs_inode *ip,
2202 int whichfork,
2203 struct xfs_bmbt_irec *PREV)
2204{
2205 if (!xfs_rmap_update_is_needed(mp, whichfork))
2206 return 0;
2207
2208 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2209 XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino,
2210 whichfork, PREV);
2211}
2212
2213/* Unmap an extent out of a file. */
2214int
2215xfs_rmap_unmap_extent(
2216 struct xfs_mount *mp,
2217 struct xfs_defer_ops *dfops,
2218 struct xfs_inode *ip,
2219 int whichfork,
2220 struct xfs_bmbt_irec *PREV)
2221{
2222 if (!xfs_rmap_update_is_needed(mp, whichfork))
2223 return 0;
2224
2225 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2226 XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino,
2227 whichfork, PREV);
2228}
2229
2230/* Convert a data fork extent from unwritten to real or vice versa. */
2231int
2232xfs_rmap_convert_extent(
2233 struct xfs_mount *mp,
2234 struct xfs_defer_ops *dfops,
2235 struct xfs_inode *ip,
2236 int whichfork,
2237 struct xfs_bmbt_irec *PREV)
2238{
2239 if (!xfs_rmap_update_is_needed(mp, whichfork))
2240 return 0;
2241
2242 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2243 XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino,
2244 whichfork, PREV);
2245}
2246
2247/* Schedule the creation of an rmap for non-file data. */
2248int
2249xfs_rmap_alloc_extent(
2250 struct xfs_mount *mp,
2251 struct xfs_defer_ops *dfops,
2252 xfs_agnumber_t agno,
2253 xfs_agblock_t bno,
2254 xfs_extlen_t len,
2255 __uint64_t owner)
2256{
2257 struct xfs_bmbt_irec bmap;
2258
2259 if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
2260 return 0;
2261
2262 bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
2263 bmap.br_blockcount = len;
2264 bmap.br_startoff = 0;
2265 bmap.br_state = XFS_EXT_NORM;
2266
2267 return __xfs_rmap_add(mp, dfops, XFS_RMAP_ALLOC, owner,
2268 XFS_DATA_FORK, &bmap);
2269}
2270
2271/* Schedule the deletion of an rmap for non-file data. */
2272int
2273xfs_rmap_free_extent(
2274 struct xfs_mount *mp,
2275 struct xfs_defer_ops *dfops,
2276 xfs_agnumber_t agno,
2277 xfs_agblock_t bno,
2278 xfs_extlen_t len,
2279 __uint64_t owner)
2280{
2281 struct xfs_bmbt_irec bmap;
2282
2283 if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
2284 return 0;
2285
2286 bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
2287 bmap.br_blockcount = len;
2288 bmap.br_startoff = 0;
2289 bmap.br_state = XFS_EXT_NORM;
2290
2291 return __xfs_rmap_add(mp, dfops, XFS_RMAP_FREE, owner,
2292 XFS_DATA_FORK, &bmap);
2293}