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