1
2
3
4
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
27
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
49
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
71
72
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_private.a.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_private.a.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_private.a.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 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 0, done);
117
118 rcur->bc_rec.r.rm_startblock = agbno;
119 rcur->bc_rec.r.rm_blockcount = len;
120 rcur->bc_rec.r.rm_owner = owner;
121 rcur->bc_rec.r.rm_offset = offset;
122 rcur->bc_rec.r.rm_flags = flags;
123 error = xfs_btree_insert(rcur, &i);
124 if (error)
125 goto done;
126 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
127done:
128 if (error)
129 trace_xfs_rmap_insert_error(rcur->bc_mp,
130 rcur->bc_private.a.agno, error, _RET_IP_);
131 return error;
132}
133
134STATIC int
135xfs_rmap_delete(
136 struct xfs_btree_cur *rcur,
137 xfs_agblock_t agbno,
138 xfs_extlen_t len,
139 uint64_t owner,
140 uint64_t offset,
141 unsigned int flags)
142{
143 int i;
144 int error;
145
146 trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
147 len, owner, offset, flags);
148
149 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
150 if (error)
151 goto done;
152 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
153
154 error = xfs_btree_delete(rcur, &i);
155 if (error)
156 goto done;
157 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
158done:
159 if (error)
160 trace_xfs_rmap_delete_error(rcur->bc_mp,
161 rcur->bc_private.a.agno, error, _RET_IP_);
162 return error;
163}
164
165
166int
167xfs_rmap_btrec_to_irec(
168 union xfs_btree_rec *rec,
169 struct xfs_rmap_irec *irec)
170{
171 irec->rm_flags = 0;
172 irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
173 irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
174 irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
175 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
176 irec);
177}
178
179
180
181
182int
183xfs_rmap_get_rec(
184 struct xfs_btree_cur *cur,
185 struct xfs_rmap_irec *irec,
186 int *stat)
187{
188 struct xfs_mount *mp = cur->bc_mp;
189 xfs_agnumber_t agno = cur->bc_private.a.agno;
190 union xfs_btree_rec *rec;
191 int error;
192
193 error = xfs_btree_get_rec(cur, &rec, stat);
194 if (error || !*stat)
195 return error;
196
197 if (xfs_rmap_btrec_to_irec(rec, irec))
198 goto out_bad_rec;
199
200 if (irec->rm_blockcount == 0)
201 goto out_bad_rec;
202 if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
203 if (irec->rm_owner != XFS_RMAP_OWN_FS)
204 goto out_bad_rec;
205 if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
206 goto out_bad_rec;
207 } else {
208
209 if (!xfs_verify_agbno(mp, agno, irec->rm_startblock))
210 goto out_bad_rec;
211 if (irec->rm_startblock >
212 irec->rm_startblock + irec->rm_blockcount)
213 goto out_bad_rec;
214 if (!xfs_verify_agbno(mp, agno,
215 irec->rm_startblock + irec->rm_blockcount - 1))
216 goto out_bad_rec;
217 }
218
219 if (!(xfs_verify_ino(mp, irec->rm_owner) ||
220 (irec->rm_owner <= XFS_RMAP_OWN_FS &&
221 irec->rm_owner >= XFS_RMAP_OWN_MIN)))
222 goto out_bad_rec;
223
224 return 0;
225out_bad_rec:
226 xfs_warn(mp,
227 "Reverse Mapping BTree record corruption in AG %d detected!",
228 agno);
229 xfs_warn(mp,
230 "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
231 irec->rm_owner, irec->rm_flags, irec->rm_startblock,
232 irec->rm_blockcount);
233 return -EFSCORRUPTED;
234}
235
236struct xfs_find_left_neighbor_info {
237 struct xfs_rmap_irec high;
238 struct xfs_rmap_irec *irec;
239 int *stat;
240};
241
242
243STATIC int
244xfs_rmap_find_left_neighbor_helper(
245 struct xfs_btree_cur *cur,
246 struct xfs_rmap_irec *rec,
247 void *priv)
248{
249 struct xfs_find_left_neighbor_info *info = priv;
250
251 trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
252 cur->bc_private.a.agno, rec->rm_startblock,
253 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
254 rec->rm_flags);
255
256 if (rec->rm_owner != info->high.rm_owner)
257 return XFS_BTREE_QUERY_RANGE_CONTINUE;
258 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
259 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
260 rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
261 return XFS_BTREE_QUERY_RANGE_CONTINUE;
262
263 *info->irec = *rec;
264 *info->stat = 1;
265 return XFS_BTREE_QUERY_RANGE_ABORT;
266}
267
268
269
270
271
272
273int
274xfs_rmap_find_left_neighbor(
275 struct xfs_btree_cur *cur,
276 xfs_agblock_t bno,
277 uint64_t owner,
278 uint64_t offset,
279 unsigned int flags,
280 struct xfs_rmap_irec *irec,
281 int *stat)
282{
283 struct xfs_find_left_neighbor_info info;
284 int error;
285
286 *stat = 0;
287 if (bno == 0)
288 return 0;
289 info.high.rm_startblock = bno - 1;
290 info.high.rm_owner = owner;
291 if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
292 !(flags & XFS_RMAP_BMBT_BLOCK)) {
293 if (offset == 0)
294 return 0;
295 info.high.rm_offset = offset - 1;
296 } else
297 info.high.rm_offset = 0;
298 info.high.rm_flags = flags;
299 info.high.rm_blockcount = 0;
300 info.irec = irec;
301 info.stat = stat;
302
303 trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
304 cur->bc_private.a.agno, bno, 0, owner, offset, flags);
305
306 error = xfs_rmap_query_range(cur, &info.high, &info.high,
307 xfs_rmap_find_left_neighbor_helper, &info);
308 if (error == XFS_BTREE_QUERY_RANGE_ABORT)
309 error = 0;
310 if (*stat)
311 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
312 cur->bc_private.a.agno, irec->rm_startblock,
313 irec->rm_blockcount, irec->rm_owner,
314 irec->rm_offset, irec->rm_flags);
315 return error;
316}
317
318
319STATIC int
320xfs_rmap_lookup_le_range_helper(
321 struct xfs_btree_cur *cur,
322 struct xfs_rmap_irec *rec,
323 void *priv)
324{
325 struct xfs_find_left_neighbor_info *info = priv;
326
327 trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
328 cur->bc_private.a.agno, rec->rm_startblock,
329 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
330 rec->rm_flags);
331
332 if (rec->rm_owner != info->high.rm_owner)
333 return XFS_BTREE_QUERY_RANGE_CONTINUE;
334 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
335 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
336 (rec->rm_offset > info->high.rm_offset ||
337 rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
338 return XFS_BTREE_QUERY_RANGE_CONTINUE;
339
340 *info->irec = *rec;
341 *info->stat = 1;
342 return XFS_BTREE_QUERY_RANGE_ABORT;
343}
344
345
346
347
348
349
350
351int
352xfs_rmap_lookup_le_range(
353 struct xfs_btree_cur *cur,
354 xfs_agblock_t bno,
355 uint64_t owner,
356 uint64_t offset,
357 unsigned int flags,
358 struct xfs_rmap_irec *irec,
359 int *stat)
360{
361 struct xfs_find_left_neighbor_info info;
362 int error;
363
364 info.high.rm_startblock = bno;
365 info.high.rm_owner = owner;
366 if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
367 info.high.rm_offset = offset;
368 else
369 info.high.rm_offset = 0;
370 info.high.rm_flags = flags;
371 info.high.rm_blockcount = 0;
372 *stat = 0;
373 info.irec = irec;
374 info.stat = stat;
375
376 trace_xfs_rmap_lookup_le_range(cur->bc_mp,
377 cur->bc_private.a.agno, bno, 0, owner, offset, flags);
378 error = xfs_rmap_query_range(cur, &info.high, &info.high,
379 xfs_rmap_lookup_le_range_helper, &info);
380 if (error == XFS_BTREE_QUERY_RANGE_ABORT)
381 error = 0;
382 if (*stat)
383 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
384 cur->bc_private.a.agno, irec->rm_startblock,
385 irec->rm_blockcount, irec->rm_owner,
386 irec->rm_offset, irec->rm_flags);
387 return error;
388}
389
390
391
392
393
394static int
395xfs_rmap_free_check_owner(
396 struct xfs_mount *mp,
397 uint64_t ltoff,
398 struct xfs_rmap_irec *rec,
399 xfs_filblks_t len,
400 uint64_t owner,
401 uint64_t offset,
402 unsigned int flags)
403{
404 int error = 0;
405
406 if (owner == XFS_RMAP_OWN_UNKNOWN)
407 return 0;
408
409
410 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
411 (rec->rm_flags & XFS_RMAP_UNWRITTEN), out);
412
413
414 XFS_WANT_CORRUPTED_GOTO(mp, owner == rec->rm_owner, out);
415
416
417 if (XFS_RMAP_NON_INODE_OWNER(owner))
418 goto out;
419
420 if (flags & XFS_RMAP_BMBT_BLOCK) {
421 XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_flags & XFS_RMAP_BMBT_BLOCK,
422 out);
423 } else {
424 XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_offset <= offset, out);
425 XFS_WANT_CORRUPTED_GOTO(mp,
426 ltoff + rec->rm_blockcount >= offset + len,
427 out);
428 }
429
430out:
431 return error;
432}
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452STATIC int
453xfs_rmap_unmap(
454 struct xfs_btree_cur *cur,
455 xfs_agblock_t bno,
456 xfs_extlen_t len,
457 bool unwritten,
458 const struct xfs_owner_info *oinfo)
459{
460 struct xfs_mount *mp = cur->bc_mp;
461 struct xfs_rmap_irec ltrec;
462 uint64_t ltoff;
463 int error = 0;
464 int i;
465 uint64_t owner;
466 uint64_t offset;
467 unsigned int flags;
468 bool ignore_off;
469
470 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
471 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
472 (flags & XFS_RMAP_BMBT_BLOCK);
473 if (unwritten)
474 flags |= XFS_RMAP_UNWRITTEN;
475 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
476 unwritten, oinfo);
477
478
479
480
481
482
483 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i);
484 if (error)
485 goto out_error;
486 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
487
488 error = xfs_rmap_get_rec(cur, <rec, &i);
489 if (error)
490 goto out_error;
491 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
492 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
493 cur->bc_private.a.agno, ltrec.rm_startblock,
494 ltrec.rm_blockcount, ltrec.rm_owner,
495 ltrec.rm_offset, ltrec.rm_flags);
496 ltoff = ltrec.rm_offset;
497
498
499
500
501
502
503
504
505 if (owner == XFS_RMAP_OWN_NULL) {
506 XFS_WANT_CORRUPTED_GOTO(mp, bno >= ltrec.rm_startblock +
507 ltrec.rm_blockcount, out_error);
508 goto out_done;
509 }
510
511
512
513
514
515
516
517
518 if (owner == XFS_RMAP_OWN_UNKNOWN &&
519 ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
520 struct xfs_rmap_irec rtrec;
521
522 error = xfs_btree_increment(cur, 0, &i);
523 if (error)
524 goto out_error;
525 if (i == 0)
526 goto out_done;
527 error = xfs_rmap_get_rec(cur, &rtrec, &i);
528 if (error)
529 goto out_error;
530 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
531 if (rtrec.rm_startblock >= bno + len)
532 goto out_done;
533 }
534
535
536 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
537 ltrec.rm_startblock + ltrec.rm_blockcount >=
538 bno + len, out_error);
539
540
541 error = xfs_rmap_free_check_owner(mp, ltoff, <rec, len, owner,
542 offset, flags);
543 if (error)
544 goto out_error;
545
546 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
547
548 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
549 ltrec.rm_startblock, ltrec.rm_blockcount,
550 ltrec.rm_owner, ltrec.rm_offset,
551 ltrec.rm_flags);
552 error = xfs_btree_delete(cur, &i);
553 if (error)
554 goto out_error;
555 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
556 } else if (ltrec.rm_startblock == bno) {
557
558
559
560
561
562
563
564
565
566
567 ltrec.rm_startblock += len;
568 ltrec.rm_blockcount -= len;
569 if (!ignore_off)
570 ltrec.rm_offset += len;
571 error = xfs_rmap_update(cur, <rec);
572 if (error)
573 goto out_error;
574 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
575
576
577
578
579
580
581
582
583
584
585 ltrec.rm_blockcount -= len;
586 error = xfs_rmap_update(cur, <rec);
587 if (error)
588 goto out_error;
589 } else {
590
591
592
593
594
595
596
597
598
599
600
601
602
603 xfs_extlen_t orig_len = ltrec.rm_blockcount;
604
605 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
606 error = xfs_rmap_update(cur, <rec);
607 if (error)
608 goto out_error;
609
610 error = xfs_btree_increment(cur, 0, &i);
611 if (error)
612 goto out_error;
613
614 cur->bc_rec.r.rm_startblock = bno + len;
615 cur->bc_rec.r.rm_blockcount = orig_len - len -
616 ltrec.rm_blockcount;
617 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
618 if (ignore_off)
619 cur->bc_rec.r.rm_offset = 0;
620 else
621 cur->bc_rec.r.rm_offset = offset + len;
622 cur->bc_rec.r.rm_flags = flags;
623 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
624 cur->bc_rec.r.rm_startblock,
625 cur->bc_rec.r.rm_blockcount,
626 cur->bc_rec.r.rm_owner,
627 cur->bc_rec.r.rm_offset,
628 cur->bc_rec.r.rm_flags);
629 error = xfs_btree_insert(cur, &i);
630 if (error)
631 goto out_error;
632 }
633
634out_done:
635 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
636 unwritten, oinfo);
637out_error:
638 if (error)
639 trace_xfs_rmap_unmap_error(mp, cur->bc_private.a.agno,
640 error, _RET_IP_);
641 return error;
642}
643
644
645
646
647int
648xfs_rmap_free(
649 struct xfs_trans *tp,
650 struct xfs_buf *agbp,
651 xfs_agnumber_t agno,
652 xfs_agblock_t bno,
653 xfs_extlen_t len,
654 const struct xfs_owner_info *oinfo)
655{
656 struct xfs_mount *mp = tp->t_mountp;
657 struct xfs_btree_cur *cur;
658 int error;
659
660 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
661 return 0;
662
663 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
664
665 error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
666
667 xfs_btree_del_cursor(cur, error);
668 return error;
669}
670
671
672
673
674
675
676static bool
677xfs_rmap_is_mergeable(
678 struct xfs_rmap_irec *irec,
679 uint64_t owner,
680 unsigned int flags)
681{
682 if (irec->rm_owner == XFS_RMAP_OWN_NULL)
683 return false;
684 if (irec->rm_owner != owner)
685 return false;
686 if ((flags & XFS_RMAP_UNWRITTEN) ^
687 (irec->rm_flags & XFS_RMAP_UNWRITTEN))
688 return false;
689 if ((flags & XFS_RMAP_ATTR_FORK) ^
690 (irec->rm_flags & XFS_RMAP_ATTR_FORK))
691 return false;
692 if ((flags & XFS_RMAP_BMBT_BLOCK) ^
693 (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
694 return false;
695 return true;
696}
697
698
699
700
701
702
703
704STATIC int
705xfs_rmap_map(
706 struct xfs_btree_cur *cur,
707 xfs_agblock_t bno,
708 xfs_extlen_t len,
709 bool unwritten,
710 const struct xfs_owner_info *oinfo)
711{
712 struct xfs_mount *mp = cur->bc_mp;
713 struct xfs_rmap_irec ltrec;
714 struct xfs_rmap_irec gtrec;
715 int have_gt;
716 int have_lt;
717 int error = 0;
718 int i;
719 uint64_t owner;
720 uint64_t offset;
721 unsigned int flags = 0;
722 bool ignore_off;
723
724 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
725 ASSERT(owner != 0);
726 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
727 (flags & XFS_RMAP_BMBT_BLOCK);
728 if (unwritten)
729 flags |= XFS_RMAP_UNWRITTEN;
730 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
731 unwritten, oinfo);
732 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
733
734
735
736
737
738
739 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
740 &have_lt);
741 if (error)
742 goto out_error;
743 if (have_lt) {
744 error = xfs_rmap_get_rec(cur, <rec, &have_lt);
745 if (error)
746 goto out_error;
747 XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
748 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
749 cur->bc_private.a.agno, ltrec.rm_startblock,
750 ltrec.rm_blockcount, ltrec.rm_owner,
751 ltrec.rm_offset, ltrec.rm_flags);
752
753 if (!xfs_rmap_is_mergeable(<rec, owner, flags))
754 have_lt = 0;
755 }
756
757 XFS_WANT_CORRUPTED_GOTO(mp,
758 have_lt == 0 ||
759 ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error);
760
761
762
763
764
765
766 error = xfs_btree_increment(cur, 0, &have_gt);
767 if (error)
768 goto out_error;
769 if (have_gt) {
770 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
771 if (error)
772 goto out_error;
773 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
774 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock,
775 out_error);
776 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
777 cur->bc_private.a.agno, gtrec.rm_startblock,
778 gtrec.rm_blockcount, gtrec.rm_owner,
779 gtrec.rm_offset, gtrec.rm_flags);
780 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
781 have_gt = 0;
782 }
783
784
785
786
787
788 if (have_lt &&
789 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
790 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
791
792
793
794
795
796
797
798
799
800 ltrec.rm_blockcount += len;
801 if (have_gt &&
802 bno + len == gtrec.rm_startblock &&
803 (ignore_off || offset + len == gtrec.rm_offset) &&
804 (unsigned long)ltrec.rm_blockcount + len +
805 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
806
807
808
809
810
811
812
813
814
815 ltrec.rm_blockcount += gtrec.rm_blockcount;
816 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
817 gtrec.rm_startblock,
818 gtrec.rm_blockcount,
819 gtrec.rm_owner,
820 gtrec.rm_offset,
821 gtrec.rm_flags);
822 error = xfs_btree_delete(cur, &i);
823 if (error)
824 goto out_error;
825 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
826 }
827
828
829 error = xfs_btree_decrement(cur, 0, &have_gt);
830 if (error)
831 goto out_error;
832 error = xfs_rmap_update(cur, <rec);
833 if (error)
834 goto out_error;
835 } else if (have_gt &&
836 bno + len == gtrec.rm_startblock &&
837 (ignore_off || offset + len == gtrec.rm_offset)) {
838
839
840
841
842
843
844
845
846
847 gtrec.rm_startblock = bno;
848 gtrec.rm_blockcount += len;
849 if (!ignore_off)
850 gtrec.rm_offset = offset;
851 error = xfs_rmap_update(cur, >rec);
852 if (error)
853 goto out_error;
854 } else {
855
856
857
858
859 cur->bc_rec.r.rm_startblock = bno;
860 cur->bc_rec.r.rm_blockcount = len;
861 cur->bc_rec.r.rm_owner = owner;
862 cur->bc_rec.r.rm_offset = offset;
863 cur->bc_rec.r.rm_flags = flags;
864 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
865 owner, offset, flags);
866 error = xfs_btree_insert(cur, &i);
867 if (error)
868 goto out_error;
869 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
870 }
871
872 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
873 unwritten, oinfo);
874out_error:
875 if (error)
876 trace_xfs_rmap_map_error(mp, cur->bc_private.a.agno,
877 error, _RET_IP_);
878 return error;
879}
880
881
882
883
884int
885xfs_rmap_alloc(
886 struct xfs_trans *tp,
887 struct xfs_buf *agbp,
888 xfs_agnumber_t agno,
889 xfs_agblock_t bno,
890 xfs_extlen_t len,
891 const struct xfs_owner_info *oinfo)
892{
893 struct xfs_mount *mp = tp->t_mountp;
894 struct xfs_btree_cur *cur;
895 int error;
896
897 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
898 return 0;
899
900 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
901 error = xfs_rmap_map(cur, bno, len, false, oinfo);
902
903 xfs_btree_del_cursor(cur, error);
904 return error;
905}
906
907#define RMAP_LEFT_CONTIG (1 << 0)
908#define RMAP_RIGHT_CONTIG (1 << 1)
909#define RMAP_LEFT_FILLING (1 << 2)
910#define RMAP_RIGHT_FILLING (1 << 3)
911#define RMAP_LEFT_VALID (1 << 6)
912#define RMAP_RIGHT_VALID (1 << 7)
913
914#define LEFT r[0]
915#define RIGHT r[1]
916#define PREV r[2]
917#define NEW r[3]
918
919
920
921
922
923STATIC int
924xfs_rmap_convert(
925 struct xfs_btree_cur *cur,
926 xfs_agblock_t bno,
927 xfs_extlen_t len,
928 bool unwritten,
929 const struct xfs_owner_info *oinfo)
930{
931 struct xfs_mount *mp = cur->bc_mp;
932 struct xfs_rmap_irec r[4];
933
934
935 uint64_t owner;
936 uint64_t offset;
937 uint64_t new_endoff;
938 unsigned int oldext;
939 unsigned int newext;
940 unsigned int flags = 0;
941 int i;
942 int state = 0;
943 int error;
944
945 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
946 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
947 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
948 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
949 new_endoff = offset + len;
950 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
951 unwritten, oinfo);
952
953
954
955
956
957
958 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
959 if (error)
960 goto done;
961 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
962
963 error = xfs_rmap_get_rec(cur, &PREV, &i);
964 if (error)
965 goto done;
966 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
967 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
968 cur->bc_private.a.agno, PREV.rm_startblock,
969 PREV.rm_blockcount, PREV.rm_owner,
970 PREV.rm_offset, PREV.rm_flags);
971
972 ASSERT(PREV.rm_offset <= offset);
973 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
974 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
975 newext = ~oldext & XFS_RMAP_UNWRITTEN;
976
977
978
979
980
981 if (PREV.rm_offset == offset)
982 state |= RMAP_LEFT_FILLING;
983 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
984 state |= RMAP_RIGHT_FILLING;
985
986
987
988
989
990
991 error = xfs_btree_decrement(cur, 0, &i);
992 if (error)
993 goto done;
994 if (i) {
995 state |= RMAP_LEFT_VALID;
996 error = xfs_rmap_get_rec(cur, &LEFT, &i);
997 if (error)
998 goto done;
999 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1000 XFS_WANT_CORRUPTED_GOTO(mp,
1001 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
1002 done);
1003 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
1004 cur->bc_private.a.agno, LEFT.rm_startblock,
1005 LEFT.rm_blockcount, LEFT.rm_owner,
1006 LEFT.rm_offset, LEFT.rm_flags);
1007 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1008 LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1009 xfs_rmap_is_mergeable(&LEFT, owner, newext))
1010 state |= RMAP_LEFT_CONTIG;
1011 }
1012
1013
1014
1015
1016
1017
1018 error = xfs_btree_increment(cur, 0, &i);
1019 if (error)
1020 goto done;
1021 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1022 error = xfs_btree_increment(cur, 0, &i);
1023 if (error)
1024 goto done;
1025 if (i) {
1026 state |= RMAP_RIGHT_VALID;
1027 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1028 if (error)
1029 goto done;
1030 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1031 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1032 done);
1033 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1034 cur->bc_private.a.agno, RIGHT.rm_startblock,
1035 RIGHT.rm_blockcount, RIGHT.rm_owner,
1036 RIGHT.rm_offset, RIGHT.rm_flags);
1037 if (bno + len == RIGHT.rm_startblock &&
1038 offset + len == RIGHT.rm_offset &&
1039 xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1040 state |= RMAP_RIGHT_CONTIG;
1041 }
1042
1043
1044 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1045 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1046 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1047 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1048 (unsigned long)LEFT.rm_blockcount + len +
1049 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1050 state &= ~RMAP_RIGHT_CONTIG;
1051
1052 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1053 _RET_IP_);
1054
1055
1056 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1057 if (error)
1058 goto done;
1059 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1060
1061
1062
1063
1064 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1065 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1066 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1067 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1068
1069
1070
1071
1072 error = xfs_btree_increment(cur, 0, &i);
1073 if (error)
1074 goto done;
1075 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1076 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1077 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1078 RIGHT.rm_owner, RIGHT.rm_offset,
1079 RIGHT.rm_flags);
1080 error = xfs_btree_delete(cur, &i);
1081 if (error)
1082 goto done;
1083 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1084 error = xfs_btree_decrement(cur, 0, &i);
1085 if (error)
1086 goto done;
1087 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1088 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1089 PREV.rm_startblock, PREV.rm_blockcount,
1090 PREV.rm_owner, PREV.rm_offset,
1091 PREV.rm_flags);
1092 error = xfs_btree_delete(cur, &i);
1093 if (error)
1094 goto done;
1095 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1096 error = xfs_btree_decrement(cur, 0, &i);
1097 if (error)
1098 goto done;
1099 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1100 NEW = LEFT;
1101 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1102 error = xfs_rmap_update(cur, &NEW);
1103 if (error)
1104 goto done;
1105 break;
1106
1107 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1108
1109
1110
1111
1112 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1113 PREV.rm_startblock, PREV.rm_blockcount,
1114 PREV.rm_owner, PREV.rm_offset,
1115 PREV.rm_flags);
1116 error = xfs_btree_delete(cur, &i);
1117 if (error)
1118 goto done;
1119 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1120 error = xfs_btree_decrement(cur, 0, &i);
1121 if (error)
1122 goto done;
1123 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1124 NEW = LEFT;
1125 NEW.rm_blockcount += PREV.rm_blockcount;
1126 error = xfs_rmap_update(cur, &NEW);
1127 if (error)
1128 goto done;
1129 break;
1130
1131 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1132
1133
1134
1135
1136 error = xfs_btree_increment(cur, 0, &i);
1137 if (error)
1138 goto done;
1139 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1140 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1141 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1142 RIGHT.rm_owner, RIGHT.rm_offset,
1143 RIGHT.rm_flags);
1144 error = xfs_btree_delete(cur, &i);
1145 if (error)
1146 goto done;
1147 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1148 error = xfs_btree_decrement(cur, 0, &i);
1149 if (error)
1150 goto done;
1151 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1152 NEW = PREV;
1153 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1154 NEW.rm_flags = newext;
1155 error = xfs_rmap_update(cur, &NEW);
1156 if (error)
1157 goto done;
1158 break;
1159
1160 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1161
1162
1163
1164
1165
1166 NEW = PREV;
1167 NEW.rm_flags = newext;
1168 error = xfs_rmap_update(cur, &NEW);
1169 if (error)
1170 goto done;
1171 break;
1172
1173 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1174
1175
1176
1177
1178 NEW = PREV;
1179 NEW.rm_offset += len;
1180 NEW.rm_startblock += len;
1181 NEW.rm_blockcount -= len;
1182 error = xfs_rmap_update(cur, &NEW);
1183 if (error)
1184 goto done;
1185 error = xfs_btree_decrement(cur, 0, &i);
1186 if (error)
1187 goto done;
1188 NEW = LEFT;
1189 NEW.rm_blockcount += len;
1190 error = xfs_rmap_update(cur, &NEW);
1191 if (error)
1192 goto done;
1193 break;
1194
1195 case RMAP_LEFT_FILLING:
1196
1197
1198
1199
1200 NEW = PREV;
1201 NEW.rm_startblock += len;
1202 NEW.rm_offset += len;
1203 NEW.rm_blockcount -= len;
1204 error = xfs_rmap_update(cur, &NEW);
1205 if (error)
1206 goto done;
1207 NEW.rm_startblock = bno;
1208 NEW.rm_owner = owner;
1209 NEW.rm_offset = offset;
1210 NEW.rm_blockcount = len;
1211 NEW.rm_flags = newext;
1212 cur->bc_rec.r = NEW;
1213 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1214 len, owner, offset, newext);
1215 error = xfs_btree_insert(cur, &i);
1216 if (error)
1217 goto done;
1218 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1219 break;
1220
1221 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1222
1223
1224
1225
1226 NEW = PREV;
1227 NEW.rm_blockcount -= len;
1228 error = xfs_rmap_update(cur, &NEW);
1229 if (error)
1230 goto done;
1231 error = xfs_btree_increment(cur, 0, &i);
1232 if (error)
1233 goto done;
1234 NEW = RIGHT;
1235 NEW.rm_offset = offset;
1236 NEW.rm_startblock = bno;
1237 NEW.rm_blockcount += len;
1238 error = xfs_rmap_update(cur, &NEW);
1239 if (error)
1240 goto done;
1241 break;
1242
1243 case RMAP_RIGHT_FILLING:
1244
1245
1246
1247
1248 NEW = PREV;
1249 NEW.rm_blockcount -= len;
1250 error = xfs_rmap_update(cur, &NEW);
1251 if (error)
1252 goto done;
1253 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1254 oldext, &i);
1255 if (error)
1256 goto done;
1257 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1258 NEW.rm_startblock = bno;
1259 NEW.rm_owner = owner;
1260 NEW.rm_offset = offset;
1261 NEW.rm_blockcount = len;
1262 NEW.rm_flags = newext;
1263 cur->bc_rec.r = NEW;
1264 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1265 len, owner, offset, newext);
1266 error = xfs_btree_insert(cur, &i);
1267 if (error)
1268 goto done;
1269 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1270 break;
1271
1272 case 0:
1273
1274
1275
1276
1277
1278
1279 NEW.rm_startblock = bno + len;
1280 NEW.rm_owner = owner;
1281 NEW.rm_offset = new_endoff;
1282 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1283 new_endoff;
1284 NEW.rm_flags = PREV.rm_flags;
1285 error = xfs_rmap_update(cur, &NEW);
1286 if (error)
1287 goto done;
1288
1289 NEW = PREV;
1290 NEW.rm_blockcount = offset - PREV.rm_offset;
1291 cur->bc_rec.r = NEW;
1292 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
1293 NEW.rm_startblock, NEW.rm_blockcount,
1294 NEW.rm_owner, NEW.rm_offset,
1295 NEW.rm_flags);
1296 error = xfs_btree_insert(cur, &i);
1297 if (error)
1298 goto done;
1299 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1300
1301
1302
1303
1304
1305 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1306 oldext, &i);
1307 if (error)
1308 goto done;
1309 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1310
1311 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1312 cur->bc_rec.r.rm_flags |= newext;
1313 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
1314 owner, offset, newext);
1315 error = xfs_btree_insert(cur, &i);
1316 if (error)
1317 goto done;
1318 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1319 break;
1320
1321 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1322 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1323 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1324 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1325 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1326 case RMAP_LEFT_CONTIG:
1327 case RMAP_RIGHT_CONTIG:
1328
1329
1330
1331 ASSERT(0);
1332 }
1333
1334 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1335 unwritten, oinfo);
1336done:
1337 if (error)
1338 trace_xfs_rmap_convert_error(cur->bc_mp,
1339 cur->bc_private.a.agno, error, _RET_IP_);
1340 return error;
1341}
1342
1343
1344
1345
1346
1347
1348STATIC int
1349xfs_rmap_convert_shared(
1350 struct xfs_btree_cur *cur,
1351 xfs_agblock_t bno,
1352 xfs_extlen_t len,
1353 bool unwritten,
1354 const struct xfs_owner_info *oinfo)
1355{
1356 struct xfs_mount *mp = cur->bc_mp;
1357 struct xfs_rmap_irec r[4];
1358
1359
1360 uint64_t owner;
1361 uint64_t offset;
1362 uint64_t new_endoff;
1363 unsigned int oldext;
1364 unsigned int newext;
1365 unsigned int flags = 0;
1366 int i;
1367 int state = 0;
1368 int error;
1369
1370 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1371 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1372 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1373 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1374 new_endoff = offset + len;
1375 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
1376 unwritten, oinfo);
1377
1378
1379
1380
1381
1382
1383 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1384 &PREV, &i);
1385 if (error)
1386 goto done;
1387 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1388
1389 ASSERT(PREV.rm_offset <= offset);
1390 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1391 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1392 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1393
1394
1395
1396
1397
1398 if (PREV.rm_offset == offset)
1399 state |= RMAP_LEFT_FILLING;
1400 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1401 state |= RMAP_RIGHT_FILLING;
1402
1403
1404 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1405 &LEFT, &i);
1406 if (error)
1407 goto done;
1408 if (i) {
1409 state |= RMAP_LEFT_VALID;
1410 XFS_WANT_CORRUPTED_GOTO(mp,
1411 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
1412 done);
1413 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1414 state |= RMAP_LEFT_CONTIG;
1415 }
1416
1417
1418 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1419 newext, &i);
1420 if (error)
1421 goto done;
1422 if (i) {
1423 state |= RMAP_RIGHT_VALID;
1424 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1425 if (error)
1426 goto done;
1427 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1428 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1429 done);
1430 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1431 cur->bc_private.a.agno, RIGHT.rm_startblock,
1432 RIGHT.rm_blockcount, RIGHT.rm_owner,
1433 RIGHT.rm_offset, RIGHT.rm_flags);
1434 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1435 state |= RMAP_RIGHT_CONTIG;
1436 }
1437
1438
1439 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1440 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1441 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1442 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1443 (unsigned long)LEFT.rm_blockcount + len +
1444 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1445 state &= ~RMAP_RIGHT_CONTIG;
1446
1447 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1448 _RET_IP_);
1449
1450
1451
1452 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1453 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1454 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1455 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1456
1457
1458
1459
1460 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1461 RIGHT.rm_blockcount, RIGHT.rm_owner,
1462 RIGHT.rm_offset, RIGHT.rm_flags);
1463 if (error)
1464 goto done;
1465 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1466 PREV.rm_blockcount, PREV.rm_owner,
1467 PREV.rm_offset, PREV.rm_flags);
1468 if (error)
1469 goto done;
1470 NEW = LEFT;
1471 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1472 NEW.rm_blockcount, NEW.rm_owner,
1473 NEW.rm_offset, NEW.rm_flags, &i);
1474 if (error)
1475 goto done;
1476 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1477 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1478 error = xfs_rmap_update(cur, &NEW);
1479 if (error)
1480 goto done;
1481 break;
1482
1483 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1484
1485
1486
1487
1488 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1489 PREV.rm_blockcount, PREV.rm_owner,
1490 PREV.rm_offset, PREV.rm_flags);
1491 if (error)
1492 goto done;
1493 NEW = LEFT;
1494 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1495 NEW.rm_blockcount, NEW.rm_owner,
1496 NEW.rm_offset, NEW.rm_flags, &i);
1497 if (error)
1498 goto done;
1499 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1500 NEW.rm_blockcount += PREV.rm_blockcount;
1501 error = xfs_rmap_update(cur, &NEW);
1502 if (error)
1503 goto done;
1504 break;
1505
1506 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1507
1508
1509
1510
1511 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1512 RIGHT.rm_blockcount, RIGHT.rm_owner,
1513 RIGHT.rm_offset, RIGHT.rm_flags);
1514 if (error)
1515 goto done;
1516 NEW = PREV;
1517 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1518 NEW.rm_blockcount, NEW.rm_owner,
1519 NEW.rm_offset, NEW.rm_flags, &i);
1520 if (error)
1521 goto done;
1522 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1523 NEW.rm_blockcount += RIGHT.rm_blockcount;
1524 NEW.rm_flags = RIGHT.rm_flags;
1525 error = xfs_rmap_update(cur, &NEW);
1526 if (error)
1527 goto done;
1528 break;
1529
1530 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1531
1532
1533
1534
1535
1536 NEW = PREV;
1537 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1538 NEW.rm_blockcount, NEW.rm_owner,
1539 NEW.rm_offset, NEW.rm_flags, &i);
1540 if (error)
1541 goto done;
1542 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1543 NEW.rm_flags = newext;
1544 error = xfs_rmap_update(cur, &NEW);
1545 if (error)
1546 goto done;
1547 break;
1548
1549 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1550
1551
1552
1553
1554 NEW = PREV;
1555 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1556 NEW.rm_blockcount, NEW.rm_owner,
1557 NEW.rm_offset, NEW.rm_flags);
1558 if (error)
1559 goto done;
1560 NEW.rm_offset += len;
1561 NEW.rm_startblock += len;
1562 NEW.rm_blockcount -= len;
1563 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1564 NEW.rm_blockcount, NEW.rm_owner,
1565 NEW.rm_offset, NEW.rm_flags);
1566 if (error)
1567 goto done;
1568 NEW = LEFT;
1569 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1570 NEW.rm_blockcount, NEW.rm_owner,
1571 NEW.rm_offset, NEW.rm_flags, &i);
1572 if (error)
1573 goto done;
1574 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1575 NEW.rm_blockcount += len;
1576 error = xfs_rmap_update(cur, &NEW);
1577 if (error)
1578 goto done;
1579 break;
1580
1581 case RMAP_LEFT_FILLING:
1582
1583
1584
1585
1586 NEW = PREV;
1587 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1588 NEW.rm_blockcount, NEW.rm_owner,
1589 NEW.rm_offset, NEW.rm_flags);
1590 if (error)
1591 goto done;
1592 NEW.rm_offset += len;
1593 NEW.rm_startblock += len;
1594 NEW.rm_blockcount -= len;
1595 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1596 NEW.rm_blockcount, NEW.rm_owner,
1597 NEW.rm_offset, NEW.rm_flags);
1598 if (error)
1599 goto done;
1600 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1601 if (error)
1602 goto done;
1603 break;
1604
1605 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1606
1607
1608
1609
1610 NEW = PREV;
1611 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1612 NEW.rm_blockcount, NEW.rm_owner,
1613 NEW.rm_offset, NEW.rm_flags, &i);
1614 if (error)
1615 goto done;
1616 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1617 NEW.rm_blockcount = offset - NEW.rm_offset;
1618 error = xfs_rmap_update(cur, &NEW);
1619 if (error)
1620 goto done;
1621 NEW = RIGHT;
1622 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1623 NEW.rm_blockcount, NEW.rm_owner,
1624 NEW.rm_offset, NEW.rm_flags);
1625 if (error)
1626 goto done;
1627 NEW.rm_offset = offset;
1628 NEW.rm_startblock = bno;
1629 NEW.rm_blockcount += len;
1630 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1631 NEW.rm_blockcount, NEW.rm_owner,
1632 NEW.rm_offset, NEW.rm_flags);
1633 if (error)
1634 goto done;
1635 break;
1636
1637 case RMAP_RIGHT_FILLING:
1638
1639
1640
1641
1642 NEW = PREV;
1643 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1644 NEW.rm_blockcount, NEW.rm_owner,
1645 NEW.rm_offset, NEW.rm_flags, &i);
1646 if (error)
1647 goto done;
1648 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1649 NEW.rm_blockcount -= len;
1650 error = xfs_rmap_update(cur, &NEW);
1651 if (error)
1652 goto done;
1653 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1654 if (error)
1655 goto done;
1656 break;
1657
1658 case 0:
1659
1660
1661
1662
1663
1664
1665 NEW.rm_startblock = bno + len;
1666 NEW.rm_owner = owner;
1667 NEW.rm_offset = new_endoff;
1668 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1669 new_endoff;
1670 NEW.rm_flags = PREV.rm_flags;
1671 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1672 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1673 NEW.rm_flags);
1674 if (error)
1675 goto done;
1676
1677 NEW = PREV;
1678 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1679 NEW.rm_blockcount, NEW.rm_owner,
1680 NEW.rm_offset, NEW.rm_flags, &i);
1681 if (error)
1682 goto done;
1683 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1684 NEW.rm_blockcount = offset - NEW.rm_offset;
1685 error = xfs_rmap_update(cur, &NEW);
1686 if (error)
1687 goto done;
1688
1689 NEW.rm_startblock = bno;
1690 NEW.rm_blockcount = len;
1691 NEW.rm_owner = owner;
1692 NEW.rm_offset = offset;
1693 NEW.rm_flags = newext;
1694 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1695 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1696 NEW.rm_flags);
1697 if (error)
1698 goto done;
1699 break;
1700
1701 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1702 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1703 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1704 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1705 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1706 case RMAP_LEFT_CONTIG:
1707 case RMAP_RIGHT_CONTIG:
1708
1709
1710
1711 ASSERT(0);
1712 }
1713
1714 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1715 unwritten, oinfo);
1716done:
1717 if (error)
1718 trace_xfs_rmap_convert_error(cur->bc_mp,
1719 cur->bc_private.a.agno, error, _RET_IP_);
1720 return error;
1721}
1722
1723#undef NEW
1724#undef LEFT
1725#undef RIGHT
1726#undef PREV
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737STATIC int
1738xfs_rmap_unmap_shared(
1739 struct xfs_btree_cur *cur,
1740 xfs_agblock_t bno,
1741 xfs_extlen_t len,
1742 bool unwritten,
1743 const struct xfs_owner_info *oinfo)
1744{
1745 struct xfs_mount *mp = cur->bc_mp;
1746 struct xfs_rmap_irec ltrec;
1747 uint64_t ltoff;
1748 int error = 0;
1749 int i;
1750 uint64_t owner;
1751 uint64_t offset;
1752 unsigned int flags;
1753
1754 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1755 if (unwritten)
1756 flags |= XFS_RMAP_UNWRITTEN;
1757 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
1758 unwritten, oinfo);
1759
1760
1761
1762
1763
1764
1765 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1766 <rec, &i);
1767 if (error)
1768 goto out_error;
1769 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1770 ltoff = ltrec.rm_offset;
1771
1772
1773 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
1774 ltrec.rm_startblock + ltrec.rm_blockcount >=
1775 bno + len, out_error);
1776
1777
1778 XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner, out_error);
1779
1780
1781 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
1782 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error);
1783
1784
1785 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error);
1786 XFS_WANT_CORRUPTED_GOTO(mp, offset <= ltoff + ltrec.rm_blockcount,
1787 out_error);
1788
1789 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
1790
1791 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1792 ltrec.rm_blockcount, ltrec.rm_owner,
1793 ltrec.rm_offset, ltrec.rm_flags);
1794 if (error)
1795 goto out_error;
1796 } else if (ltrec.rm_startblock == bno) {
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1810 ltrec.rm_blockcount, ltrec.rm_owner,
1811 ltrec.rm_offset, ltrec.rm_flags);
1812 if (error)
1813 goto out_error;
1814
1815
1816 ltrec.rm_startblock += len;
1817 ltrec.rm_blockcount -= len;
1818 ltrec.rm_offset += len;
1819 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
1820 ltrec.rm_blockcount, ltrec.rm_owner,
1821 ltrec.rm_offset, ltrec.rm_flags);
1822 if (error)
1823 goto out_error;
1824 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1836 ltrec.rm_blockcount, ltrec.rm_owner,
1837 ltrec.rm_offset, ltrec.rm_flags, &i);
1838 if (error)
1839 goto out_error;
1840 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1841 ltrec.rm_blockcount -= len;
1842 error = xfs_rmap_update(cur, <rec);
1843 if (error)
1844 goto out_error;
1845 } else {
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858 xfs_extlen_t orig_len = ltrec.rm_blockcount;
1859
1860
1861 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1862 ltrec.rm_blockcount, ltrec.rm_owner,
1863 ltrec.rm_offset, ltrec.rm_flags, &i);
1864 if (error)
1865 goto out_error;
1866 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1867 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
1868 error = xfs_rmap_update(cur, <rec);
1869 if (error)
1870 goto out_error;
1871
1872
1873 error = xfs_rmap_insert(cur, bno + len,
1874 orig_len - len - ltrec.rm_blockcount,
1875 ltrec.rm_owner, offset + len,
1876 ltrec.rm_flags);
1877 if (error)
1878 goto out_error;
1879 }
1880
1881 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
1882 unwritten, oinfo);
1883out_error:
1884 if (error)
1885 trace_xfs_rmap_unmap_error(cur->bc_mp,
1886 cur->bc_private.a.agno, error, _RET_IP_);
1887 return error;
1888}
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899STATIC int
1900xfs_rmap_map_shared(
1901 struct xfs_btree_cur *cur,
1902 xfs_agblock_t bno,
1903 xfs_extlen_t len,
1904 bool unwritten,
1905 const struct xfs_owner_info *oinfo)
1906{
1907 struct xfs_mount *mp = cur->bc_mp;
1908 struct xfs_rmap_irec ltrec;
1909 struct xfs_rmap_irec gtrec;
1910 int have_gt;
1911 int have_lt;
1912 int error = 0;
1913 int i;
1914 uint64_t owner;
1915 uint64_t offset;
1916 unsigned int flags = 0;
1917
1918 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1919 if (unwritten)
1920 flags |= XFS_RMAP_UNWRITTEN;
1921 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
1922 unwritten, oinfo);
1923
1924
1925 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
1926 <rec, &have_lt);
1927 if (error)
1928 goto out_error;
1929 if (have_lt &&
1930 !xfs_rmap_is_mergeable(<rec, owner, flags))
1931 have_lt = 0;
1932
1933
1934 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1935 flags, &have_gt);
1936 if (error)
1937 goto out_error;
1938 if (have_gt) {
1939 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
1940 if (error)
1941 goto out_error;
1942 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
1943 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1944 cur->bc_private.a.agno, gtrec.rm_startblock,
1945 gtrec.rm_blockcount, gtrec.rm_owner,
1946 gtrec.rm_offset, gtrec.rm_flags);
1947
1948 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
1949 have_gt = 0;
1950 }
1951
1952 if (have_lt &&
1953 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
1954 ltrec.rm_offset + ltrec.rm_blockcount == offset) {
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964 ltrec.rm_blockcount += len;
1965 if (have_gt &&
1966 bno + len == gtrec.rm_startblock &&
1967 offset + len == gtrec.rm_offset) {
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977 ltrec.rm_blockcount += gtrec.rm_blockcount;
1978 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
1979 gtrec.rm_blockcount, gtrec.rm_owner,
1980 gtrec.rm_offset, gtrec.rm_flags);
1981 if (error)
1982 goto out_error;
1983 }
1984
1985
1986 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1987 ltrec.rm_blockcount, ltrec.rm_owner,
1988 ltrec.rm_offset, ltrec.rm_flags, &i);
1989 if (error)
1990 goto out_error;
1991 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1992
1993 error = xfs_rmap_update(cur, <rec);
1994 if (error)
1995 goto out_error;
1996 } else if (have_gt &&
1997 bno + len == gtrec.rm_startblock &&
1998 offset + len == gtrec.rm_offset) {
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2010 gtrec.rm_blockcount, gtrec.rm_owner,
2011 gtrec.rm_offset, gtrec.rm_flags);
2012 if (error)
2013 goto out_error;
2014
2015
2016 gtrec.rm_startblock = bno;
2017 gtrec.rm_blockcount += len;
2018 gtrec.rm_offset = offset;
2019 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2020 gtrec.rm_blockcount, gtrec.rm_owner,
2021 gtrec.rm_offset, gtrec.rm_flags);
2022 if (error)
2023 goto out_error;
2024 } else {
2025
2026
2027
2028
2029 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2030 if (error)
2031 goto out_error;
2032 }
2033
2034 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
2035 unwritten, oinfo);
2036out_error:
2037 if (error)
2038 trace_xfs_rmap_map_error(cur->bc_mp,
2039 cur->bc_private.a.agno, error, _RET_IP_);
2040 return error;
2041}
2042
2043
2044int
2045xfs_rmap_map_raw(
2046 struct xfs_btree_cur *cur,
2047 struct xfs_rmap_irec *rmap)
2048{
2049 struct xfs_owner_info oinfo;
2050
2051 oinfo.oi_owner = rmap->rm_owner;
2052 oinfo.oi_offset = rmap->rm_offset;
2053 oinfo.oi_flags = 0;
2054 if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
2055 oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
2056 if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
2057 oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
2058
2059 if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2060 return xfs_rmap_map(cur, rmap->rm_startblock,
2061 rmap->rm_blockcount,
2062 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2063 &oinfo);
2064
2065 return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2066 rmap->rm_blockcount,
2067 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2068 &oinfo);
2069}
2070
2071struct xfs_rmap_query_range_info {
2072 xfs_rmap_query_range_fn fn;
2073 void *priv;
2074};
2075
2076
2077STATIC int
2078xfs_rmap_query_range_helper(
2079 struct xfs_btree_cur *cur,
2080 union xfs_btree_rec *rec,
2081 void *priv)
2082{
2083 struct xfs_rmap_query_range_info *query = priv;
2084 struct xfs_rmap_irec irec;
2085 int error;
2086
2087 error = xfs_rmap_btrec_to_irec(rec, &irec);
2088 if (error)
2089 return error;
2090 return query->fn(cur, &irec, query->priv);
2091}
2092
2093
2094int
2095xfs_rmap_query_range(
2096 struct xfs_btree_cur *cur,
2097 struct xfs_rmap_irec *low_rec,
2098 struct xfs_rmap_irec *high_rec,
2099 xfs_rmap_query_range_fn fn,
2100 void *priv)
2101{
2102 union xfs_btree_irec low_brec;
2103 union xfs_btree_irec high_brec;
2104 struct xfs_rmap_query_range_info query;
2105
2106 low_brec.r = *low_rec;
2107 high_brec.r = *high_rec;
2108 query.priv = priv;
2109 query.fn = fn;
2110 return xfs_btree_query_range(cur, &low_brec, &high_brec,
2111 xfs_rmap_query_range_helper, &query);
2112}
2113
2114
2115int
2116xfs_rmap_query_all(
2117 struct xfs_btree_cur *cur,
2118 xfs_rmap_query_range_fn fn,
2119 void *priv)
2120{
2121 struct xfs_rmap_query_range_info query;
2122
2123 query.priv = priv;
2124 query.fn = fn;
2125 return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2126}
2127
2128
2129void
2130xfs_rmap_finish_one_cleanup(
2131 struct xfs_trans *tp,
2132 struct xfs_btree_cur *rcur,
2133 int error)
2134{
2135 struct xfs_buf *agbp;
2136
2137 if (rcur == NULL)
2138 return;
2139 agbp = rcur->bc_private.a.agbp;
2140 xfs_btree_del_cursor(rcur, error);
2141 if (error)
2142 xfs_trans_brelse(tp, agbp);
2143}
2144
2145
2146
2147
2148
2149
2150
2151
2152int
2153xfs_rmap_finish_one(
2154 struct xfs_trans *tp,
2155 enum xfs_rmap_intent_type type,
2156 uint64_t owner,
2157 int whichfork,
2158 xfs_fileoff_t startoff,
2159 xfs_fsblock_t startblock,
2160 xfs_filblks_t blockcount,
2161 xfs_exntst_t state,
2162 struct xfs_btree_cur **pcur)
2163{
2164 struct xfs_mount *mp = tp->t_mountp;
2165 struct xfs_btree_cur *rcur;
2166 struct xfs_buf *agbp = NULL;
2167 int error = 0;
2168 xfs_agnumber_t agno;
2169 struct xfs_owner_info oinfo;
2170 xfs_agblock_t bno;
2171 bool unwritten;
2172
2173 agno = XFS_FSB_TO_AGNO(mp, startblock);
2174 ASSERT(agno != NULLAGNUMBER);
2175 bno = XFS_FSB_TO_AGBNO(mp, startblock);
2176
2177 trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork,
2178 startoff, blockcount, state);
2179
2180 if (XFS_TEST_ERROR(false, mp,
2181 XFS_ERRTAG_RMAP_FINISH_ONE))
2182 return -EIO;
2183
2184
2185
2186
2187
2188 rcur = *pcur;
2189 if (rcur != NULL && rcur->bc_private.a.agno != agno) {
2190 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2191 rcur = NULL;
2192 *pcur = NULL;
2193 }
2194 if (rcur == NULL) {
2195
2196
2197
2198
2199
2200 error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
2201 if (error)
2202 return error;
2203 if (!agbp)
2204 return -EFSCORRUPTED;
2205
2206 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
2207 if (!rcur) {
2208 error = -ENOMEM;
2209 goto out_cur;
2210 }
2211 }
2212 *pcur = rcur;
2213
2214 xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2215 unwritten = state == XFS_EXT_UNWRITTEN;
2216 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2217
2218 switch (type) {
2219 case XFS_RMAP_ALLOC:
2220 case XFS_RMAP_MAP:
2221 error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2222 break;
2223 case XFS_RMAP_MAP_SHARED:
2224 error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2225 &oinfo);
2226 break;
2227 case XFS_RMAP_FREE:
2228 case XFS_RMAP_UNMAP:
2229 error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2230 &oinfo);
2231 break;
2232 case XFS_RMAP_UNMAP_SHARED:
2233 error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2234 &oinfo);
2235 break;
2236 case XFS_RMAP_CONVERT:
2237 error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2238 &oinfo);
2239 break;
2240 case XFS_RMAP_CONVERT_SHARED:
2241 error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2242 !unwritten, &oinfo);
2243 break;
2244 default:
2245 ASSERT(0);
2246 error = -EFSCORRUPTED;
2247 }
2248 return error;
2249
2250out_cur:
2251 xfs_trans_brelse(tp, agbp);
2252
2253 return error;
2254}
2255
2256
2257
2258
2259static bool
2260xfs_rmap_update_is_needed(
2261 struct xfs_mount *mp,
2262 int whichfork)
2263{
2264 return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK;
2265}
2266
2267
2268
2269
2270
2271static int
2272__xfs_rmap_add(
2273 struct xfs_trans *tp,
2274 enum xfs_rmap_intent_type type,
2275 uint64_t owner,
2276 int whichfork,
2277 struct xfs_bmbt_irec *bmap)
2278{
2279 struct xfs_rmap_intent *ri;
2280
2281 trace_xfs_rmap_defer(tp->t_mountp,
2282 XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock),
2283 type,
2284 XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock),
2285 owner, whichfork,
2286 bmap->br_startoff,
2287 bmap->br_blockcount,
2288 bmap->br_state);
2289
2290 ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_SLEEP | KM_NOFS);
2291 INIT_LIST_HEAD(&ri->ri_list);
2292 ri->ri_type = type;
2293 ri->ri_owner = owner;
2294 ri->ri_whichfork = whichfork;
2295 ri->ri_bmap = *bmap;
2296
2297 xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
2298 return 0;
2299}
2300
2301
2302int
2303xfs_rmap_map_extent(
2304 struct xfs_trans *tp,
2305 struct xfs_inode *ip,
2306 int whichfork,
2307 struct xfs_bmbt_irec *PREV)
2308{
2309 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2310 return 0;
2311
2312 return __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
2313 XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino,
2314 whichfork, PREV);
2315}
2316
2317
2318int
2319xfs_rmap_unmap_extent(
2320 struct xfs_trans *tp,
2321 struct xfs_inode *ip,
2322 int whichfork,
2323 struct xfs_bmbt_irec *PREV)
2324{
2325 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2326 return 0;
2327
2328 return __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
2329 XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino,
2330 whichfork, PREV);
2331}
2332
2333
2334
2335
2336
2337
2338
2339int
2340xfs_rmap_convert_extent(
2341 struct xfs_mount *mp,
2342 struct xfs_trans *tp,
2343 struct xfs_inode *ip,
2344 int whichfork,
2345 struct xfs_bmbt_irec *PREV)
2346{
2347 if (!xfs_rmap_update_is_needed(mp, whichfork))
2348 return 0;
2349
2350 return __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
2351 XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino,
2352 whichfork, PREV);
2353}
2354
2355
2356int
2357xfs_rmap_alloc_extent(
2358 struct xfs_trans *tp,
2359 xfs_agnumber_t agno,
2360 xfs_agblock_t bno,
2361 xfs_extlen_t len,
2362 uint64_t owner)
2363{
2364 struct xfs_bmbt_irec bmap;
2365
2366 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2367 return 0;
2368
2369 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2370 bmap.br_blockcount = len;
2371 bmap.br_startoff = 0;
2372 bmap.br_state = XFS_EXT_NORM;
2373
2374 return __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
2375}
2376
2377
2378int
2379xfs_rmap_free_extent(
2380 struct xfs_trans *tp,
2381 xfs_agnumber_t agno,
2382 xfs_agblock_t bno,
2383 xfs_extlen_t len,
2384 uint64_t owner)
2385{
2386 struct xfs_bmbt_irec bmap;
2387
2388 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2389 return 0;
2390
2391 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2392 bmap.br_blockcount = len;
2393 bmap.br_startoff = 0;
2394 bmap.br_state = XFS_EXT_NORM;
2395
2396 return __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
2397}
2398
2399
2400int
2401xfs_rmap_compare(
2402 const struct xfs_rmap_irec *a,
2403 const struct xfs_rmap_irec *b)
2404{
2405 __u64 oa;
2406 __u64 ob;
2407
2408 oa = xfs_rmap_irec_offset_pack(a);
2409 ob = xfs_rmap_irec_offset_pack(b);
2410
2411 if (a->rm_startblock < b->rm_startblock)
2412 return -1;
2413 else if (a->rm_startblock > b->rm_startblock)
2414 return 1;
2415 else if (a->rm_owner < b->rm_owner)
2416 return -1;
2417 else if (a->rm_owner > b->rm_owner)
2418 return 1;
2419 else if (oa < ob)
2420 return -1;
2421 else if (oa > ob)
2422 return 1;
2423 else
2424 return 0;
2425}
2426
2427
2428int
2429xfs_rmap_has_record(
2430 struct xfs_btree_cur *cur,
2431 xfs_agblock_t bno,
2432 xfs_extlen_t len,
2433 bool *exists)
2434{
2435 union xfs_btree_irec low;
2436 union xfs_btree_irec high;
2437
2438 memset(&low, 0, sizeof(low));
2439 low.r.rm_startblock = bno;
2440 memset(&high, 0xFF, sizeof(high));
2441 high.r.rm_startblock = bno + len - 1;
2442
2443 return xfs_btree_has_record(cur, &low, &high, exists);
2444}
2445
2446
2447
2448
2449
2450
2451
2452
2453int
2454xfs_rmap_record_exists(
2455 struct xfs_btree_cur *cur,
2456 xfs_agblock_t bno,
2457 xfs_extlen_t len,
2458 const struct xfs_owner_info *oinfo,
2459 bool *has_rmap)
2460{
2461 uint64_t owner;
2462 uint64_t offset;
2463 unsigned int flags;
2464 int has_record;
2465 struct xfs_rmap_irec irec;
2466 int error;
2467
2468 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2469 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
2470 (flags & XFS_RMAP_BMBT_BLOCK));
2471
2472 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
2473 &has_record);
2474 if (error)
2475 return error;
2476 if (!has_record) {
2477 *has_rmap = false;
2478 return 0;
2479 }
2480
2481 error = xfs_rmap_get_rec(cur, &irec, &has_record);
2482 if (error)
2483 return error;
2484 if (!has_record) {
2485 *has_rmap = false;
2486 return 0;
2487 }
2488
2489 *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
2490 irec.rm_startblock + irec.rm_blockcount >= bno + len);
2491 return 0;
2492}
2493
2494struct xfs_rmap_key_state {
2495 uint64_t owner;
2496 uint64_t offset;
2497 unsigned int flags;
2498 bool has_rmap;
2499};
2500
2501
2502STATIC int
2503xfs_rmap_has_other_keys_helper(
2504 struct xfs_btree_cur *cur,
2505 struct xfs_rmap_irec *rec,
2506 void *priv)
2507{
2508 struct xfs_rmap_key_state *rks = priv;
2509
2510 if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset &&
2511 ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags)
2512 return 0;
2513 rks->has_rmap = true;
2514 return XFS_BTREE_QUERY_RANGE_ABORT;
2515}
2516
2517
2518
2519
2520
2521int
2522xfs_rmap_has_other_keys(
2523 struct xfs_btree_cur *cur,
2524 xfs_agblock_t bno,
2525 xfs_extlen_t len,
2526 const struct xfs_owner_info *oinfo,
2527 bool *has_rmap)
2528{
2529 struct xfs_rmap_irec low = {0};
2530 struct xfs_rmap_irec high;
2531 struct xfs_rmap_key_state rks;
2532 int error;
2533
2534 xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags);
2535 rks.has_rmap = false;
2536
2537 low.rm_startblock = bno;
2538 memset(&high, 0xFF, sizeof(high));
2539 high.rm_startblock = bno + len - 1;
2540
2541 error = xfs_rmap_query_range(cur, &low, &high,
2542 xfs_rmap_has_other_keys_helper, &rks);
2543 *has_rmap = rks.has_rmap;
2544 return error;
2545}
2546
2547const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
2548 .oi_owner = XFS_RMAP_OWN_NULL,
2549};
2550const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
2551 .oi_owner = XFS_RMAP_OWN_UNKNOWN,
2552};
2553const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
2554 .oi_owner = XFS_RMAP_OWN_FS,
2555};
2556const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
2557 .oi_owner = XFS_RMAP_OWN_LOG,
2558};
2559const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
2560 .oi_owner = XFS_RMAP_OWN_AG,
2561};
2562const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
2563 .oi_owner = XFS_RMAP_OWN_INOBT,
2564};
2565const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
2566 .oi_owner = XFS_RMAP_OWN_INODES,
2567};
2568const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
2569 .oi_owner = XFS_RMAP_OWN_REFC,
2570};
2571const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
2572 .oi_owner = XFS_RMAP_OWN_COW,
2573};
2574