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