1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include "xfs.h"
19#include "xfs_fs.h"
20#include "xfs_shared.h"
21#include "xfs_format.h"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
24#include "xfs_bit.h"
25#include "xfs_sb.h"
26#include "xfs_mount.h"
27#include "xfs_defer.h"
28#include "xfs_da_format.h"
29#include "xfs_da_btree.h"
30#include "xfs_btree.h"
31#include "xfs_trans.h"
32#include "xfs_alloc.h"
33#include "xfs_rmap.h"
34#include "xfs_rmap_btree.h"
35#include "xfs_trans_space.h"
36#include "xfs_trace.h"
37#include "xfs_error.h"
38#include "xfs_extent_busy.h"
39#include "xfs_bmap.h"
40#include "xfs_inode.h"
41
42
43
44
45
46int
47xfs_rmap_lookup_le(
48 struct xfs_btree_cur *cur,
49 xfs_agblock_t bno,
50 xfs_extlen_t len,
51 uint64_t owner,
52 uint64_t offset,
53 unsigned int flags,
54 int *stat)
55{
56 cur->bc_rec.r.rm_startblock = bno;
57 cur->bc_rec.r.rm_blockcount = len;
58 cur->bc_rec.r.rm_owner = owner;
59 cur->bc_rec.r.rm_offset = offset;
60 cur->bc_rec.r.rm_flags = flags;
61 return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
62}
63
64
65
66
67
68int
69xfs_rmap_lookup_eq(
70 struct xfs_btree_cur *cur,
71 xfs_agblock_t bno,
72 xfs_extlen_t len,
73 uint64_t owner,
74 uint64_t offset,
75 unsigned int flags,
76 int *stat)
77{
78 cur->bc_rec.r.rm_startblock = bno;
79 cur->bc_rec.r.rm_blockcount = len;
80 cur->bc_rec.r.rm_owner = owner;
81 cur->bc_rec.r.rm_offset = offset;
82 cur->bc_rec.r.rm_flags = flags;
83 return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
84}
85
86
87
88
89
90
91STATIC int
92xfs_rmap_update(
93 struct xfs_btree_cur *cur,
94 struct xfs_rmap_irec *irec)
95{
96 union xfs_btree_rec rec;
97 int error;
98
99 trace_xfs_rmap_update(cur->bc_mp, cur->bc_private.a.agno,
100 irec->rm_startblock, irec->rm_blockcount,
101 irec->rm_owner, irec->rm_offset, irec->rm_flags);
102
103 rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
104 rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
105 rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
106 rec.rmap.rm_offset = cpu_to_be64(
107 xfs_rmap_irec_offset_pack(irec));
108 error = xfs_btree_update(cur, &rec);
109 if (error)
110 trace_xfs_rmap_update_error(cur->bc_mp,
111 cur->bc_private.a.agno, error, _RET_IP_);
112 return error;
113}
114
115int
116xfs_rmap_insert(
117 struct xfs_btree_cur *rcur,
118 xfs_agblock_t agbno,
119 xfs_extlen_t len,
120 uint64_t owner,
121 uint64_t offset,
122 unsigned int flags)
123{
124 int i;
125 int error;
126
127 trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
128 len, owner, offset, flags);
129
130 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
131 if (error)
132 goto done;
133 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 0, done);
134
135 rcur->bc_rec.r.rm_startblock = agbno;
136 rcur->bc_rec.r.rm_blockcount = len;
137 rcur->bc_rec.r.rm_owner = owner;
138 rcur->bc_rec.r.rm_offset = offset;
139 rcur->bc_rec.r.rm_flags = flags;
140 error = xfs_btree_insert(rcur, &i);
141 if (error)
142 goto done;
143 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
144done:
145 if (error)
146 trace_xfs_rmap_insert_error(rcur->bc_mp,
147 rcur->bc_private.a.agno, error, _RET_IP_);
148 return error;
149}
150
151static int
152xfs_rmap_btrec_to_irec(
153 union xfs_btree_rec *rec,
154 struct xfs_rmap_irec *irec)
155{
156 irec->rm_flags = 0;
157 irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
158 irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
159 irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
160 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
161 irec);
162}
163
164
165
166
167int
168xfs_rmap_get_rec(
169 struct xfs_btree_cur *cur,
170 struct xfs_rmap_irec *irec,
171 int *stat)
172{
173 union xfs_btree_rec *rec;
174 int error;
175
176 error = xfs_btree_get_rec(cur, &rec, stat);
177 if (error || !*stat)
178 return error;
179
180 return xfs_rmap_btrec_to_irec(rec, irec);
181}
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201STATIC int
202xfs_rmap_unmap(
203 struct xfs_btree_cur *cur,
204 xfs_agblock_t bno,
205 xfs_extlen_t len,
206 bool unwritten,
207 struct xfs_owner_info *oinfo)
208{
209 struct xfs_mount *mp = cur->bc_mp;
210 struct xfs_rmap_irec ltrec;
211 uint64_t ltoff;
212 int error = 0;
213 int i;
214 uint64_t owner;
215 uint64_t offset;
216 unsigned int flags;
217 bool ignore_off;
218
219 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
220 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
221 (flags & XFS_RMAP_BMBT_BLOCK);
222 if (unwritten)
223 flags |= XFS_RMAP_UNWRITTEN;
224 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
225 unwritten, oinfo);
226
227
228
229
230
231
232 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i);
233 if (error)
234 goto out_error;
235 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
236
237 error = xfs_rmap_get_rec(cur, <rec, &i);
238 if (error)
239 goto out_error;
240 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
241 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
242 cur->bc_private.a.agno, ltrec.rm_startblock,
243 ltrec.rm_blockcount, ltrec.rm_owner,
244 ltrec.rm_offset, ltrec.rm_flags);
245 ltoff = ltrec.rm_offset;
246
247
248
249
250
251
252
253
254 if (owner == XFS_RMAP_OWN_NULL) {
255 XFS_WANT_CORRUPTED_GOTO(mp, bno >= ltrec.rm_startblock +
256 ltrec.rm_blockcount, out_error);
257 goto out_done;
258 }
259
260
261 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
262 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error);
263
264
265 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
266 ltrec.rm_startblock + ltrec.rm_blockcount >=
267 bno + len, out_error);
268
269
270 XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner ||
271 XFS_RMAP_NON_INODE_OWNER(owner), out_error);
272
273
274 if (!XFS_RMAP_NON_INODE_OWNER(owner)) {
275 if (flags & XFS_RMAP_BMBT_BLOCK) {
276 XFS_WANT_CORRUPTED_GOTO(mp,
277 ltrec.rm_flags & XFS_RMAP_BMBT_BLOCK,
278 out_error);
279 } else {
280 XFS_WANT_CORRUPTED_GOTO(mp,
281 ltrec.rm_offset <= offset, out_error);
282 XFS_WANT_CORRUPTED_GOTO(mp,
283 ltoff + ltrec.rm_blockcount >= offset + len,
284 out_error);
285 }
286 }
287
288 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
289
290 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
291 ltrec.rm_startblock, ltrec.rm_blockcount,
292 ltrec.rm_owner, ltrec.rm_offset,
293 ltrec.rm_flags);
294 error = xfs_btree_delete(cur, &i);
295 if (error)
296 goto out_error;
297 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
298 } else if (ltrec.rm_startblock == bno) {
299
300
301
302
303
304
305
306
307
308
309 ltrec.rm_startblock += len;
310 ltrec.rm_blockcount -= len;
311 if (!ignore_off)
312 ltrec.rm_offset += len;
313 error = xfs_rmap_update(cur, <rec);
314 if (error)
315 goto out_error;
316 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
317
318
319
320
321
322
323
324
325
326
327 ltrec.rm_blockcount -= len;
328 error = xfs_rmap_update(cur, <rec);
329 if (error)
330 goto out_error;
331 } else {
332
333
334
335
336
337
338
339
340
341
342
343
344
345 xfs_extlen_t orig_len = ltrec.rm_blockcount;
346
347 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
348 error = xfs_rmap_update(cur, <rec);
349 if (error)
350 goto out_error;
351
352 error = xfs_btree_increment(cur, 0, &i);
353 if (error)
354 goto out_error;
355
356 cur->bc_rec.r.rm_startblock = bno + len;
357 cur->bc_rec.r.rm_blockcount = orig_len - len -
358 ltrec.rm_blockcount;
359 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
360 if (ignore_off)
361 cur->bc_rec.r.rm_offset = 0;
362 else
363 cur->bc_rec.r.rm_offset = offset + len;
364 cur->bc_rec.r.rm_flags = flags;
365 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
366 cur->bc_rec.r.rm_startblock,
367 cur->bc_rec.r.rm_blockcount,
368 cur->bc_rec.r.rm_owner,
369 cur->bc_rec.r.rm_offset,
370 cur->bc_rec.r.rm_flags);
371 error = xfs_btree_insert(cur, &i);
372 if (error)
373 goto out_error;
374 }
375
376out_done:
377 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
378 unwritten, oinfo);
379out_error:
380 if (error)
381 trace_xfs_rmap_unmap_error(mp, cur->bc_private.a.agno,
382 error, _RET_IP_);
383 return error;
384}
385
386
387
388
389int
390xfs_rmap_free(
391 struct xfs_trans *tp,
392 struct xfs_buf *agbp,
393 xfs_agnumber_t agno,
394 xfs_agblock_t bno,
395 xfs_extlen_t len,
396 struct xfs_owner_info *oinfo)
397{
398 struct xfs_mount *mp = tp->t_mountp;
399 struct xfs_btree_cur *cur;
400 int error;
401
402 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
403 return 0;
404
405 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
406
407 error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
408 if (error)
409 goto out_error;
410
411 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
412 return 0;
413
414out_error:
415 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
416 return error;
417}
418
419
420
421
422
423
424static bool
425xfs_rmap_is_mergeable(
426 struct xfs_rmap_irec *irec,
427 uint64_t owner,
428 unsigned int flags)
429{
430 if (irec->rm_owner == XFS_RMAP_OWN_NULL)
431 return false;
432 if (irec->rm_owner != owner)
433 return false;
434 if ((flags & XFS_RMAP_UNWRITTEN) ^
435 (irec->rm_flags & XFS_RMAP_UNWRITTEN))
436 return false;
437 if ((flags & XFS_RMAP_ATTR_FORK) ^
438 (irec->rm_flags & XFS_RMAP_ATTR_FORK))
439 return false;
440 if ((flags & XFS_RMAP_BMBT_BLOCK) ^
441 (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
442 return false;
443 return true;
444}
445
446
447
448
449
450
451
452STATIC int
453xfs_rmap_map(
454 struct xfs_btree_cur *cur,
455 xfs_agblock_t bno,
456 xfs_extlen_t len,
457 bool unwritten,
458 struct xfs_owner_info *oinfo)
459{
460 struct xfs_mount *mp = cur->bc_mp;
461 struct xfs_rmap_irec ltrec;
462 struct xfs_rmap_irec gtrec;
463 int have_gt;
464 int have_lt;
465 int error = 0;
466 int i;
467 uint64_t owner;
468 uint64_t offset;
469 unsigned int flags = 0;
470 bool ignore_off;
471
472 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
473 ASSERT(owner != 0);
474 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
475 (flags & XFS_RMAP_BMBT_BLOCK);
476 if (unwritten)
477 flags |= XFS_RMAP_UNWRITTEN;
478 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
479 unwritten, oinfo);
480
481
482
483
484
485
486 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
487 &have_lt);
488 if (error)
489 goto out_error;
490 XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
491
492 error = xfs_rmap_get_rec(cur, <rec, &have_lt);
493 if (error)
494 goto out_error;
495 XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
496 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
497 cur->bc_private.a.agno, ltrec.rm_startblock,
498 ltrec.rm_blockcount, ltrec.rm_owner,
499 ltrec.rm_offset, ltrec.rm_flags);
500
501 if (!xfs_rmap_is_mergeable(<rec, owner, flags))
502 have_lt = 0;
503
504 XFS_WANT_CORRUPTED_GOTO(mp,
505 have_lt == 0 ||
506 ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error);
507
508
509
510
511
512
513 error = xfs_btree_increment(cur, 0, &have_gt);
514 if (error)
515 goto out_error;
516 if (have_gt) {
517 error = xfs_rmap_get_rec(cur, >rec, &have_gt);
518 if (error)
519 goto out_error;
520 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
521 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock,
522 out_error);
523 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
524 cur->bc_private.a.agno, gtrec.rm_startblock,
525 gtrec.rm_blockcount, gtrec.rm_owner,
526 gtrec.rm_offset, gtrec.rm_flags);
527 if (!xfs_rmap_is_mergeable(>rec, owner, flags))
528 have_gt = 0;
529 }
530
531
532
533
534
535 if (have_lt &&
536 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
537 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
538
539
540
541
542
543
544
545
546
547 ltrec.rm_blockcount += len;
548 if (have_gt &&
549 bno + len == gtrec.rm_startblock &&
550 (ignore_off || offset + len == gtrec.rm_offset) &&
551 (unsigned long)ltrec.rm_blockcount + len +
552 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
553
554
555
556
557
558
559
560
561
562 ltrec.rm_blockcount += gtrec.rm_blockcount;
563 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
564 gtrec.rm_startblock,
565 gtrec.rm_blockcount,
566 gtrec.rm_owner,
567 gtrec.rm_offset,
568 gtrec.rm_flags);
569 error = xfs_btree_delete(cur, &i);
570 if (error)
571 goto out_error;
572 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
573 }
574
575
576 error = xfs_btree_decrement(cur, 0, &have_gt);
577 if (error)
578 goto out_error;
579 error = xfs_rmap_update(cur, <rec);
580 if (error)
581 goto out_error;
582 } else if (have_gt &&
583 bno + len == gtrec.rm_startblock &&
584 (ignore_off || offset + len == gtrec.rm_offset)) {
585
586
587
588
589
590
591
592
593
594 gtrec.rm_startblock = bno;
595 gtrec.rm_blockcount += len;
596 if (!ignore_off)
597 gtrec.rm_offset = offset;
598 error = xfs_rmap_update(cur, >rec);
599 if (error)
600 goto out_error;
601 } else {
602
603
604
605
606 cur->bc_rec.r.rm_startblock = bno;
607 cur->bc_rec.r.rm_blockcount = len;
608 cur->bc_rec.r.rm_owner = owner;
609 cur->bc_rec.r.rm_offset = offset;
610 cur->bc_rec.r.rm_flags = flags;
611 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
612 owner, offset, flags);
613 error = xfs_btree_insert(cur, &i);
614 if (error)
615 goto out_error;
616 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
617 }
618
619 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
620 unwritten, oinfo);
621out_error:
622 if (error)
623 trace_xfs_rmap_map_error(mp, cur->bc_private.a.agno,
624 error, _RET_IP_);
625 return error;
626}
627
628
629
630
631int
632xfs_rmap_alloc(
633 struct xfs_trans *tp,
634 struct xfs_buf *agbp,
635 xfs_agnumber_t agno,
636 xfs_agblock_t bno,
637 xfs_extlen_t len,
638 struct xfs_owner_info *oinfo)
639{
640 struct xfs_mount *mp = tp->t_mountp;
641 struct xfs_btree_cur *cur;
642 int error;
643
644 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
645 return 0;
646
647 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
648 error = xfs_rmap_map(cur, bno, len, false, oinfo);
649 if (error)
650 goto out_error;
651
652 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
653 return 0;
654
655out_error:
656 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
657 return error;
658}
659
660#define RMAP_LEFT_CONTIG (1 << 0)
661#define RMAP_RIGHT_CONTIG (1 << 1)
662#define RMAP_LEFT_FILLING (1 << 2)
663#define RMAP_RIGHT_FILLING (1 << 3)
664#define RMAP_LEFT_VALID (1 << 6)
665#define RMAP_RIGHT_VALID (1 << 7)
666
667#define LEFT r[0]
668#define RIGHT r[1]
669#define PREV r[2]
670#define NEW r[3]
671
672
673
674
675
676STATIC int
677xfs_rmap_convert(
678 struct xfs_btree_cur *cur,
679 xfs_agblock_t bno,
680 xfs_extlen_t len,
681 bool unwritten,
682 struct xfs_owner_info *oinfo)
683{
684 struct xfs_mount *mp = cur->bc_mp;
685 struct xfs_rmap_irec r[4];
686
687
688 uint64_t owner;
689 uint64_t offset;
690 uint64_t new_endoff;
691 unsigned int oldext;
692 unsigned int newext;
693 unsigned int flags = 0;
694 int i;
695 int state = 0;
696 int error;
697
698 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
699 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
700 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
701 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
702 new_endoff = offset + len;
703 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
704 unwritten, oinfo);
705
706
707
708
709
710
711 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
712 if (error)
713 goto done;
714 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
715
716 error = xfs_rmap_get_rec(cur, &PREV, &i);
717 if (error)
718 goto done;
719 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
720 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
721 cur->bc_private.a.agno, PREV.rm_startblock,
722 PREV.rm_blockcount, PREV.rm_owner,
723 PREV.rm_offset, PREV.rm_flags);
724
725 ASSERT(PREV.rm_offset <= offset);
726 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
727 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
728 newext = ~oldext & XFS_RMAP_UNWRITTEN;
729
730
731
732
733
734 if (PREV.rm_offset == offset)
735 state |= RMAP_LEFT_FILLING;
736 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
737 state |= RMAP_RIGHT_FILLING;
738
739
740
741
742
743
744 error = xfs_btree_decrement(cur, 0, &i);
745 if (error)
746 goto done;
747 if (i) {
748 state |= RMAP_LEFT_VALID;
749 error = xfs_rmap_get_rec(cur, &LEFT, &i);
750 if (error)
751 goto done;
752 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
753 XFS_WANT_CORRUPTED_GOTO(mp,
754 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
755 done);
756 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
757 cur->bc_private.a.agno, LEFT.rm_startblock,
758 LEFT.rm_blockcount, LEFT.rm_owner,
759 LEFT.rm_offset, LEFT.rm_flags);
760 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
761 LEFT.rm_offset + LEFT.rm_blockcount == offset &&
762 xfs_rmap_is_mergeable(&LEFT, owner, newext))
763 state |= RMAP_LEFT_CONTIG;
764 }
765
766
767
768
769
770
771 error = xfs_btree_increment(cur, 0, &i);
772 if (error)
773 goto done;
774 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
775 error = xfs_btree_increment(cur, 0, &i);
776 if (error)
777 goto done;
778 if (i) {
779 state |= RMAP_RIGHT_VALID;
780 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
781 if (error)
782 goto done;
783 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
784 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
785 done);
786 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
787 cur->bc_private.a.agno, RIGHT.rm_startblock,
788 RIGHT.rm_blockcount, RIGHT.rm_owner,
789 RIGHT.rm_offset, RIGHT.rm_flags);
790 if (bno + len == RIGHT.rm_startblock &&
791 offset + len == RIGHT.rm_offset &&
792 xfs_rmap_is_mergeable(&RIGHT, owner, newext))
793 state |= RMAP_RIGHT_CONTIG;
794 }
795
796
797 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
798 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
799 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
800 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
801 (unsigned long)LEFT.rm_blockcount + len +
802 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
803 state &= ~RMAP_RIGHT_CONTIG;
804
805 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
806 _RET_IP_);
807
808
809 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
810 if (error)
811 goto done;
812 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
813
814
815
816
817 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
818 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
819 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
820 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
821
822
823
824
825 error = xfs_btree_increment(cur, 0, &i);
826 if (error)
827 goto done;
828 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
829 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
830 RIGHT.rm_startblock, RIGHT.rm_blockcount,
831 RIGHT.rm_owner, RIGHT.rm_offset,
832 RIGHT.rm_flags);
833 error = xfs_btree_delete(cur, &i);
834 if (error)
835 goto done;
836 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
837 error = xfs_btree_decrement(cur, 0, &i);
838 if (error)
839 goto done;
840 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
841 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
842 PREV.rm_startblock, PREV.rm_blockcount,
843 PREV.rm_owner, PREV.rm_offset,
844 PREV.rm_flags);
845 error = xfs_btree_delete(cur, &i);
846 if (error)
847 goto done;
848 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
849 error = xfs_btree_decrement(cur, 0, &i);
850 if (error)
851 goto done;
852 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
853 NEW = LEFT;
854 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
855 error = xfs_rmap_update(cur, &NEW);
856 if (error)
857 goto done;
858 break;
859
860 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
861
862
863
864
865 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
866 PREV.rm_startblock, PREV.rm_blockcount,
867 PREV.rm_owner, PREV.rm_offset,
868 PREV.rm_flags);
869 error = xfs_btree_delete(cur, &i);
870 if (error)
871 goto done;
872 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
873 error = xfs_btree_decrement(cur, 0, &i);
874 if (error)
875 goto done;
876 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
877 NEW = LEFT;
878 NEW.rm_blockcount += PREV.rm_blockcount;
879 error = xfs_rmap_update(cur, &NEW);
880 if (error)
881 goto done;
882 break;
883
884 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
885
886
887
888
889 error = xfs_btree_increment(cur, 0, &i);
890 if (error)
891 goto done;
892 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
893 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
894 RIGHT.rm_startblock, RIGHT.rm_blockcount,
895 RIGHT.rm_owner, RIGHT.rm_offset,
896 RIGHT.rm_flags);
897 error = xfs_btree_delete(cur, &i);
898 if (error)
899 goto done;
900 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
901 error = xfs_btree_decrement(cur, 0, &i);
902 if (error)
903 goto done;
904 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
905 NEW = PREV;
906 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
907 NEW.rm_flags = newext;
908 error = xfs_rmap_update(cur, &NEW);
909 if (error)
910 goto done;
911 break;
912
913 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
914
915
916
917
918
919 NEW = PREV;
920 NEW.rm_flags = newext;
921 error = xfs_rmap_update(cur, &NEW);
922 if (error)
923 goto done;
924 break;
925
926 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
927
928
929
930
931 NEW = PREV;
932 NEW.rm_offset += len;
933 NEW.rm_startblock += len;
934 NEW.rm_blockcount -= len;
935 error = xfs_rmap_update(cur, &NEW);
936 if (error)
937 goto done;
938 error = xfs_btree_decrement(cur, 0, &i);
939 if (error)
940 goto done;
941 NEW = LEFT;
942 NEW.rm_blockcount += len;
943 error = xfs_rmap_update(cur, &NEW);
944 if (error)
945 goto done;
946 break;
947
948 case RMAP_LEFT_FILLING:
949
950
951
952
953 NEW = PREV;
954 NEW.rm_startblock += len;
955 NEW.rm_offset += len;
956 NEW.rm_blockcount -= len;
957 error = xfs_rmap_update(cur, &NEW);
958 if (error)
959 goto done;
960 NEW.rm_startblock = bno;
961 NEW.rm_owner = owner;
962 NEW.rm_offset = offset;
963 NEW.rm_blockcount = len;
964 NEW.rm_flags = newext;
965 cur->bc_rec.r = NEW;
966 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
967 len, owner, offset, newext);
968 error = xfs_btree_insert(cur, &i);
969 if (error)
970 goto done;
971 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
972 break;
973
974 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
975
976
977
978
979 NEW = PREV;
980 NEW.rm_blockcount -= len;
981 error = xfs_rmap_update(cur, &NEW);
982 if (error)
983 goto done;
984 error = xfs_btree_increment(cur, 0, &i);
985 if (error)
986 goto done;
987 NEW = RIGHT;
988 NEW.rm_offset = offset;
989 NEW.rm_startblock = bno;
990 NEW.rm_blockcount += len;
991 error = xfs_rmap_update(cur, &NEW);
992 if (error)
993 goto done;
994 break;
995
996 case RMAP_RIGHT_FILLING:
997
998
999
1000
1001 NEW = PREV;
1002 NEW.rm_blockcount -= len;
1003 error = xfs_rmap_update(cur, &NEW);
1004 if (error)
1005 goto done;
1006 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1007 oldext, &i);
1008 if (error)
1009 goto done;
1010 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1011 NEW.rm_startblock = bno;
1012 NEW.rm_owner = owner;
1013 NEW.rm_offset = offset;
1014 NEW.rm_blockcount = len;
1015 NEW.rm_flags = newext;
1016 cur->bc_rec.r = NEW;
1017 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1018 len, owner, offset, newext);
1019 error = xfs_btree_insert(cur, &i);
1020 if (error)
1021 goto done;
1022 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1023 break;
1024
1025 case 0:
1026
1027
1028
1029
1030
1031
1032 NEW.rm_startblock = bno + len;
1033 NEW.rm_owner = owner;
1034 NEW.rm_offset = new_endoff;
1035 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1036 new_endoff;
1037 NEW.rm_flags = PREV.rm_flags;
1038 error = xfs_rmap_update(cur, &NEW);
1039 if (error)
1040 goto done;
1041
1042 NEW = PREV;
1043 NEW.rm_blockcount = offset - PREV.rm_offset;
1044 cur->bc_rec.r = NEW;
1045 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
1046 NEW.rm_startblock, NEW.rm_blockcount,
1047 NEW.rm_owner, NEW.rm_offset,
1048 NEW.rm_flags);
1049 error = xfs_btree_insert(cur, &i);
1050 if (error)
1051 goto done;
1052 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1053
1054
1055
1056
1057
1058 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1059 oldext, &i);
1060 if (error)
1061 goto done;
1062 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1063
1064 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1065 cur->bc_rec.r.rm_flags |= newext;
1066 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
1067 owner, offset, newext);
1068 error = xfs_btree_insert(cur, &i);
1069 if (error)
1070 goto done;
1071 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1072 break;
1073
1074 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1075 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1076 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1077 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1078 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1079 case RMAP_LEFT_CONTIG:
1080 case RMAP_RIGHT_CONTIG:
1081
1082
1083
1084 ASSERT(0);
1085 }
1086
1087 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1088 unwritten, oinfo);
1089done:
1090 if (error)
1091 trace_xfs_rmap_convert_error(cur->bc_mp,
1092 cur->bc_private.a.agno, error, _RET_IP_);
1093 return error;
1094}
1095
1096#undef NEW
1097#undef LEFT
1098#undef RIGHT
1099#undef PREV
1100
1101struct xfs_rmap_query_range_info {
1102 xfs_rmap_query_range_fn fn;
1103 void *priv;
1104};
1105
1106
1107STATIC int
1108xfs_rmap_query_range_helper(
1109 struct xfs_btree_cur *cur,
1110 union xfs_btree_rec *rec,
1111 void *priv)
1112{
1113 struct xfs_rmap_query_range_info *query = priv;
1114 struct xfs_rmap_irec irec;
1115 int error;
1116
1117 error = xfs_rmap_btrec_to_irec(rec, &irec);
1118 if (error)
1119 return error;
1120 return query->fn(cur, &irec, query->priv);
1121}
1122
1123
1124int
1125xfs_rmap_query_range(
1126 struct xfs_btree_cur *cur,
1127 struct xfs_rmap_irec *low_rec,
1128 struct xfs_rmap_irec *high_rec,
1129 xfs_rmap_query_range_fn fn,
1130 void *priv)
1131{
1132 union xfs_btree_irec low_brec;
1133 union xfs_btree_irec high_brec;
1134 struct xfs_rmap_query_range_info query;
1135
1136 low_brec.r = *low_rec;
1137 high_brec.r = *high_rec;
1138 query.priv = priv;
1139 query.fn = fn;
1140 return xfs_btree_query_range(cur, &low_brec, &high_brec,
1141 xfs_rmap_query_range_helper, &query);
1142}
1143
1144
1145void
1146xfs_rmap_finish_one_cleanup(
1147 struct xfs_trans *tp,
1148 struct xfs_btree_cur *rcur,
1149 int error)
1150{
1151 struct xfs_buf *agbp;
1152
1153 if (rcur == NULL)
1154 return;
1155 agbp = rcur->bc_private.a.agbp;
1156 xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
1157 if (error)
1158 xfs_trans_brelse(tp, agbp);
1159}
1160
1161
1162
1163
1164
1165
1166
1167
1168int
1169xfs_rmap_finish_one(
1170 struct xfs_trans *tp,
1171 enum xfs_rmap_intent_type type,
1172 __uint64_t owner,
1173 int whichfork,
1174 xfs_fileoff_t startoff,
1175 xfs_fsblock_t startblock,
1176 xfs_filblks_t blockcount,
1177 xfs_exntst_t state,
1178 struct xfs_btree_cur **pcur)
1179{
1180 struct xfs_mount *mp = tp->t_mountp;
1181 struct xfs_btree_cur *rcur;
1182 struct xfs_buf *agbp = NULL;
1183 int error = 0;
1184 xfs_agnumber_t agno;
1185 struct xfs_owner_info oinfo;
1186 xfs_agblock_t bno;
1187 bool unwritten;
1188
1189 agno = XFS_FSB_TO_AGNO(mp, startblock);
1190 ASSERT(agno != NULLAGNUMBER);
1191 bno = XFS_FSB_TO_AGBNO(mp, startblock);
1192
1193 trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork,
1194 startoff, blockcount, state);
1195
1196 if (XFS_TEST_ERROR(false, mp,
1197 XFS_ERRTAG_RMAP_FINISH_ONE,
1198 XFS_RANDOM_RMAP_FINISH_ONE))
1199 return -EIO;
1200
1201
1202
1203
1204
1205 rcur = *pcur;
1206 if (rcur != NULL && rcur->bc_private.a.agno != agno) {
1207 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
1208 rcur = NULL;
1209 *pcur = NULL;
1210 }
1211 if (rcur == NULL) {
1212
1213
1214
1215
1216
1217 error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
1218 if (error)
1219 return error;
1220 if (!agbp)
1221 return -EFSCORRUPTED;
1222
1223 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
1224 if (!rcur) {
1225 error = -ENOMEM;
1226 goto out_cur;
1227 }
1228 }
1229 *pcur = rcur;
1230
1231 xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
1232 unwritten = state == XFS_EXT_UNWRITTEN;
1233 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
1234
1235 switch (type) {
1236 case XFS_RMAP_ALLOC:
1237 case XFS_RMAP_MAP:
1238 error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
1239 break;
1240 case XFS_RMAP_FREE:
1241 case XFS_RMAP_UNMAP:
1242 error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
1243 &oinfo);
1244 break;
1245 case XFS_RMAP_CONVERT:
1246 error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
1247 &oinfo);
1248 break;
1249 default:
1250 ASSERT(0);
1251 error = -EFSCORRUPTED;
1252 }
1253 return error;
1254
1255out_cur:
1256 xfs_trans_brelse(tp, agbp);
1257
1258 return error;
1259}
1260
1261
1262
1263
1264static bool
1265xfs_rmap_update_is_needed(
1266 struct xfs_mount *mp)
1267{
1268 return xfs_sb_version_hasrmapbt(&mp->m_sb);
1269}
1270
1271
1272
1273
1274
1275static int
1276__xfs_rmap_add(
1277 struct xfs_mount *mp,
1278 struct xfs_defer_ops *dfops,
1279 enum xfs_rmap_intent_type type,
1280 __uint64_t owner,
1281 int whichfork,
1282 struct xfs_bmbt_irec *bmap)
1283{
1284 struct xfs_rmap_intent *ri;
1285
1286 trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, bmap->br_startblock),
1287 type,
1288 XFS_FSB_TO_AGBNO(mp, bmap->br_startblock),
1289 owner, whichfork,
1290 bmap->br_startoff,
1291 bmap->br_blockcount,
1292 bmap->br_state);
1293
1294 ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_SLEEP | KM_NOFS);
1295 INIT_LIST_HEAD(&ri->ri_list);
1296 ri->ri_type = type;
1297 ri->ri_owner = owner;
1298 ri->ri_whichfork = whichfork;
1299 ri->ri_bmap = *bmap;
1300
1301 xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
1302 return 0;
1303}
1304
1305
1306int
1307xfs_rmap_map_extent(
1308 struct xfs_mount *mp,
1309 struct xfs_defer_ops *dfops,
1310 struct xfs_inode *ip,
1311 int whichfork,
1312 struct xfs_bmbt_irec *PREV)
1313{
1314 if (!xfs_rmap_update_is_needed(mp))
1315 return 0;
1316
1317 return __xfs_rmap_add(mp, dfops, XFS_RMAP_MAP, ip->i_ino,
1318 whichfork, PREV);
1319}
1320
1321
1322int
1323xfs_rmap_unmap_extent(
1324 struct xfs_mount *mp,
1325 struct xfs_defer_ops *dfops,
1326 struct xfs_inode *ip,
1327 int whichfork,
1328 struct xfs_bmbt_irec *PREV)
1329{
1330 if (!xfs_rmap_update_is_needed(mp))
1331 return 0;
1332
1333 return __xfs_rmap_add(mp, dfops, XFS_RMAP_UNMAP, ip->i_ino,
1334 whichfork, PREV);
1335}
1336
1337
1338int
1339xfs_rmap_convert_extent(
1340 struct xfs_mount *mp,
1341 struct xfs_defer_ops *dfops,
1342 struct xfs_inode *ip,
1343 int whichfork,
1344 struct xfs_bmbt_irec *PREV)
1345{
1346 if (!xfs_rmap_update_is_needed(mp))
1347 return 0;
1348
1349 return __xfs_rmap_add(mp, dfops, XFS_RMAP_CONVERT, ip->i_ino,
1350 whichfork, PREV);
1351}
1352
1353
1354int
1355xfs_rmap_alloc_extent(
1356 struct xfs_mount *mp,
1357 struct xfs_defer_ops *dfops,
1358 xfs_agnumber_t agno,
1359 xfs_agblock_t bno,
1360 xfs_extlen_t len,
1361 __uint64_t owner)
1362{
1363 struct xfs_bmbt_irec bmap;
1364
1365 if (!xfs_rmap_update_is_needed(mp))
1366 return 0;
1367
1368 bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
1369 bmap.br_blockcount = len;
1370 bmap.br_startoff = 0;
1371 bmap.br_state = XFS_EXT_NORM;
1372
1373 return __xfs_rmap_add(mp, dfops, XFS_RMAP_ALLOC, owner,
1374 XFS_DATA_FORK, &bmap);
1375}
1376
1377
1378int
1379xfs_rmap_free_extent(
1380 struct xfs_mount *mp,
1381 struct xfs_defer_ops *dfops,
1382 xfs_agnumber_t agno,
1383 xfs_agblock_t bno,
1384 xfs_extlen_t len,
1385 __uint64_t owner)
1386{
1387 struct xfs_bmbt_irec bmap;
1388
1389 if (!xfs_rmap_update_is_needed(mp))
1390 return 0;
1391
1392 bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
1393 bmap.br_blockcount = len;
1394 bmap.br_startoff = 0;
1395 bmap.br_state = XFS_EXT_NORM;
1396
1397 return __xfs_rmap_add(mp, dfops, XFS_RMAP_FREE, owner,
1398 XFS_DATA_FORK, &bmap);
1399}
1400