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