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