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