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_ag.h"
27#include "xfs_mount.h"
28#include "xfs_inode.h"
29#include "xfs_bmap.h"
30#include "xfs_bmap_util.h"
31#include "xfs_bmap_btree.h"
32#include "xfs_alloc.h"
33#include "xfs_error.h"
34#include "xfs_trans.h"
35#include "xfs_trans_space.h"
36#include "xfs_trace.h"
37#include "xfs_buf.h"
38#include "xfs_icache.h"
39#include "xfs_dinode.h"
40#include "xfs_rtalloc.h"
41
42
43
44
45
46
47
48
49
50
51int
52xfs_rtbuf_get(
53 xfs_mount_t *mp,
54 xfs_trans_t *tp,
55 xfs_rtblock_t block,
56 int issum,
57 xfs_buf_t **bpp)
58{
59 xfs_buf_t *bp;
60 xfs_inode_t *ip;
61 xfs_bmbt_irec_t map;
62 int nmap = 1;
63 int error;
64
65 ip = issum ? mp->m_rsumip : mp->m_rbmip;
66
67 error = xfs_bmapi_read(ip, block, 1, &map, &nmap, XFS_DATA_FORK);
68 if (error)
69 return error;
70
71 ASSERT(map.br_startblock != NULLFSBLOCK);
72 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
73 XFS_FSB_TO_DADDR(mp, map.br_startblock),
74 mp->m_bsize, 0, &bp, NULL);
75 if (error)
76 return error;
77 ASSERT(!xfs_buf_geterror(bp));
78 *bpp = bp;
79 return 0;
80}
81
82
83
84
85
86int
87xfs_rtfind_back(
88 xfs_mount_t *mp,
89 xfs_trans_t *tp,
90 xfs_rtblock_t start,
91 xfs_rtblock_t limit,
92 xfs_rtblock_t *rtblock)
93{
94 xfs_rtword_t *b;
95 int bit;
96 xfs_rtblock_t block;
97 xfs_buf_t *bp;
98 xfs_rtword_t *bufp;
99 int error;
100 xfs_rtblock_t firstbit;
101 xfs_rtblock_t i;
102 xfs_rtblock_t len;
103 xfs_rtword_t mask;
104 xfs_rtword_t want;
105 xfs_rtword_t wdiff;
106 int word;
107
108
109
110
111 block = XFS_BITTOBLOCK(mp, start);
112 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
113 if (error) {
114 return error;
115 }
116 bufp = bp->b_addr;
117
118
119
120 word = XFS_BITTOWORD(mp, start);
121 b = &bufp[word];
122 bit = (int)(start & (XFS_NBWORD - 1));
123 len = start - limit + 1;
124
125
126
127
128 want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
129
130
131
132
133 if (bit < XFS_NBWORD - 1) {
134
135
136
137
138 firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
139 mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
140 firstbit;
141
142
143
144
145 if ((wdiff = (*b ^ want) & mask)) {
146
147
148
149 xfs_trans_brelse(tp, bp);
150 i = bit - XFS_RTHIBIT(wdiff);
151 *rtblock = start - i + 1;
152 return 0;
153 }
154 i = bit - firstbit + 1;
155
156
157
158
159 if (--word == -1 && i < len) {
160
161
162
163 xfs_trans_brelse(tp, bp);
164 error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
165 if (error) {
166 return error;
167 }
168 bufp = bp->b_addr;
169 word = XFS_BLOCKWMASK(mp);
170 b = &bufp[word];
171 } else {
172
173
174
175 b--;
176 }
177 } else {
178
179
180
181 i = 0;
182 }
183
184
185
186
187 while (len - i >= XFS_NBWORD) {
188
189
190
191 if ((wdiff = *b ^ want)) {
192
193
194
195 xfs_trans_brelse(tp, bp);
196 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
197 *rtblock = start - i + 1;
198 return 0;
199 }
200 i += XFS_NBWORD;
201
202
203
204
205 if (--word == -1 && i < len) {
206
207
208
209 xfs_trans_brelse(tp, bp);
210 error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
211 if (error) {
212 return error;
213 }
214 bufp = bp->b_addr;
215 word = XFS_BLOCKWMASK(mp);
216 b = &bufp[word];
217 } else {
218
219
220
221 b--;
222 }
223 }
224
225
226
227
228 if (len - i) {
229
230
231
232
233 firstbit = XFS_NBWORD - (len - i);
234 mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
235
236
237
238 if ((wdiff = (*b ^ want) & mask)) {
239
240
241
242 xfs_trans_brelse(tp, bp);
243 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
244 *rtblock = start - i + 1;
245 return 0;
246 } else
247 i = len;
248 }
249
250
251
252 xfs_trans_brelse(tp, bp);
253 *rtblock = start - i + 1;
254 return 0;
255}
256
257
258
259
260
261int
262xfs_rtfind_forw(
263 xfs_mount_t *mp,
264 xfs_trans_t *tp,
265 xfs_rtblock_t start,
266 xfs_rtblock_t limit,
267 xfs_rtblock_t *rtblock)
268{
269 xfs_rtword_t *b;
270 int bit;
271 xfs_rtblock_t block;
272 xfs_buf_t *bp;
273 xfs_rtword_t *bufp;
274 int error;
275 xfs_rtblock_t i;
276 xfs_rtblock_t lastbit;
277 xfs_rtblock_t len;
278 xfs_rtword_t mask;
279 xfs_rtword_t want;
280 xfs_rtword_t wdiff;
281 int word;
282
283
284
285
286 block = XFS_BITTOBLOCK(mp, start);
287 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
288 if (error) {
289 return error;
290 }
291 bufp = bp->b_addr;
292
293
294
295 word = XFS_BITTOWORD(mp, start);
296 b = &bufp[word];
297 bit = (int)(start & (XFS_NBWORD - 1));
298 len = limit - start + 1;
299
300
301
302
303 want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
304
305
306
307
308 if (bit) {
309
310
311
312
313 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
314 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
315
316
317
318
319 if ((wdiff = (*b ^ want) & mask)) {
320
321
322
323 xfs_trans_brelse(tp, bp);
324 i = XFS_RTLOBIT(wdiff) - bit;
325 *rtblock = start + i - 1;
326 return 0;
327 }
328 i = lastbit - bit;
329
330
331
332
333 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
334
335
336
337 xfs_trans_brelse(tp, bp);
338 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
339 if (error) {
340 return error;
341 }
342 b = bufp = bp->b_addr;
343 word = 0;
344 } else {
345
346
347
348 b++;
349 }
350 } else {
351
352
353
354 i = 0;
355 }
356
357
358
359
360 while (len - i >= XFS_NBWORD) {
361
362
363
364 if ((wdiff = *b ^ want)) {
365
366
367
368 xfs_trans_brelse(tp, bp);
369 i += XFS_RTLOBIT(wdiff);
370 *rtblock = start + i - 1;
371 return 0;
372 }
373 i += XFS_NBWORD;
374
375
376
377
378 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
379
380
381
382 xfs_trans_brelse(tp, bp);
383 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
384 if (error) {
385 return error;
386 }
387 b = bufp = bp->b_addr;
388 word = 0;
389 } else {
390
391
392
393 b++;
394 }
395 }
396
397
398
399
400 if ((lastbit = len - i)) {
401
402
403
404 mask = ((xfs_rtword_t)1 << lastbit) - 1;
405
406
407
408 if ((wdiff = (*b ^ want) & mask)) {
409
410
411
412 xfs_trans_brelse(tp, bp);
413 i += XFS_RTLOBIT(wdiff);
414 *rtblock = start + i - 1;
415 return 0;
416 } else
417 i = len;
418 }
419
420
421
422 xfs_trans_brelse(tp, bp);
423 *rtblock = start + i - 1;
424 return 0;
425}
426
427
428
429
430
431
432
433int
434xfs_rtmodify_summary(
435 xfs_mount_t *mp,
436 xfs_trans_t *tp,
437 int log,
438 xfs_rtblock_t bbno,
439 int delta,
440 xfs_buf_t **rbpp,
441 xfs_fsblock_t *rsb)
442{
443 xfs_buf_t *bp;
444 int error;
445 xfs_fsblock_t sb;
446 int so;
447 xfs_suminfo_t *sp;
448
449
450
451
452 so = XFS_SUMOFFS(mp, log, bbno);
453
454
455
456 sb = XFS_SUMOFFSTOBLOCK(mp, so);
457
458
459
460 if (rbpp && *rbpp && *rsb == sb)
461 bp = *rbpp;
462
463
464
465 else {
466
467
468
469 if (rbpp && *rbpp)
470 xfs_trans_brelse(tp, *rbpp);
471 error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
472 if (error) {
473 return error;
474 }
475
476
477
478 if (rbpp) {
479 *rbpp = bp;
480 *rsb = sb;
481 }
482 }
483
484
485
486 sp = XFS_SUMPTR(mp, bp, so);
487 *sp += delta;
488 xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)bp->b_addr),
489 (uint)((char *)sp - (char *)bp->b_addr + sizeof(*sp) - 1));
490 return 0;
491}
492
493
494
495
496
497int
498xfs_rtmodify_range(
499 xfs_mount_t *mp,
500 xfs_trans_t *tp,
501 xfs_rtblock_t start,
502 xfs_extlen_t len,
503 int val)
504{
505 xfs_rtword_t *b;
506 int bit;
507 xfs_rtblock_t block;
508 xfs_buf_t *bp;
509 xfs_rtword_t *bufp;
510 int error;
511 xfs_rtword_t *first;
512 int i;
513 int lastbit;
514 xfs_rtword_t mask;
515 int word;
516
517
518
519
520 block = XFS_BITTOBLOCK(mp, start);
521
522
523
524 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
525 if (error) {
526 return error;
527 }
528 bufp = bp->b_addr;
529
530
531
532 word = XFS_BITTOWORD(mp, start);
533 first = b = &bufp[word];
534 bit = (int)(start & (XFS_NBWORD - 1));
535
536
537
538 val = -val;
539
540
541
542
543 if (bit) {
544
545
546
547 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
548 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
549
550
551
552 if (val)
553 *b |= mask;
554 else
555 *b &= ~mask;
556 i = lastbit - bit;
557
558
559
560
561 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
562
563
564
565
566 xfs_trans_log_buf(tp, bp,
567 (uint)((char *)first - (char *)bufp),
568 (uint)((char *)b - (char *)bufp));
569 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
570 if (error) {
571 return error;
572 }
573 first = b = bufp = bp->b_addr;
574 word = 0;
575 } else {
576
577
578
579 b++;
580 }
581 } else {
582
583
584
585 i = 0;
586 }
587
588
589
590
591 while (len - i >= XFS_NBWORD) {
592
593
594
595 *b = val;
596 i += XFS_NBWORD;
597
598
599
600
601 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
602
603
604
605
606 xfs_trans_log_buf(tp, bp,
607 (uint)((char *)first - (char *)bufp),
608 (uint)((char *)b - (char *)bufp));
609 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
610 if (error) {
611 return error;
612 }
613 first = b = bufp = bp->b_addr;
614 word = 0;
615 } else {
616
617
618
619 b++;
620 }
621 }
622
623
624
625
626 if ((lastbit = len - i)) {
627
628
629
630 bit = 0;
631 mask = ((xfs_rtword_t)1 << lastbit) - 1;
632
633
634
635 if (val)
636 *b |= mask;
637 else
638 *b &= ~mask;
639 b++;
640 }
641
642
643
644 if (b > first)
645 xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
646 (uint)((char *)b - (char *)bufp - 1));
647 return 0;
648}
649
650
651
652
653
654int
655xfs_rtfree_range(
656 xfs_mount_t *mp,
657 xfs_trans_t *tp,
658 xfs_rtblock_t start,
659 xfs_extlen_t len,
660 xfs_buf_t **rbpp,
661 xfs_fsblock_t *rsb)
662{
663 xfs_rtblock_t end;
664 int error;
665 xfs_rtblock_t postblock;
666 xfs_rtblock_t preblock;
667
668 end = start + len - 1;
669
670
671
672 error = xfs_rtmodify_range(mp, tp, start, len, 1);
673 if (error) {
674 return error;
675 }
676
677
678
679
680
681 error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
682 if (error) {
683 return error;
684 }
685
686
687
688 error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
689 &postblock);
690 if (error)
691 return error;
692
693
694
695
696 if (preblock < start) {
697 error = xfs_rtmodify_summary(mp, tp,
698 XFS_RTBLOCKLOG(start - preblock),
699 XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
700 if (error) {
701 return error;
702 }
703 }
704
705
706
707
708 if (postblock > end) {
709 error = xfs_rtmodify_summary(mp, tp,
710 XFS_RTBLOCKLOG(postblock - end),
711 XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
712 if (error) {
713 return error;
714 }
715 }
716
717
718
719
720 error = xfs_rtmodify_summary(mp, tp,
721 XFS_RTBLOCKLOG(postblock + 1 - preblock),
722 XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
723 return error;
724}
725
726
727
728
729
730int
731xfs_rtcheck_range(
732 xfs_mount_t *mp,
733 xfs_trans_t *tp,
734 xfs_rtblock_t start,
735 xfs_extlen_t len,
736 int val,
737 xfs_rtblock_t *new,
738 int *stat)
739{
740 xfs_rtword_t *b;
741 int bit;
742 xfs_rtblock_t block;
743 xfs_buf_t *bp;
744 xfs_rtword_t *bufp;
745 int error;
746 xfs_rtblock_t i;
747 xfs_rtblock_t lastbit;
748 xfs_rtword_t mask;
749 xfs_rtword_t wdiff;
750 int word;
751
752
753
754
755 block = XFS_BITTOBLOCK(mp, start);
756
757
758
759 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
760 if (error) {
761 return error;
762 }
763 bufp = bp->b_addr;
764
765
766
767 word = XFS_BITTOWORD(mp, start);
768 b = &bufp[word];
769 bit = (int)(start & (XFS_NBWORD - 1));
770
771
772
773 val = -val;
774
775
776
777
778 if (bit) {
779
780
781
782 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
783
784
785
786 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
787
788
789
790 if ((wdiff = (*b ^ val) & mask)) {
791
792
793
794 xfs_trans_brelse(tp, bp);
795 i = XFS_RTLOBIT(wdiff) - bit;
796 *new = start + i;
797 *stat = 0;
798 return 0;
799 }
800 i = lastbit - bit;
801
802
803
804
805 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
806
807
808
809 xfs_trans_brelse(tp, bp);
810 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
811 if (error) {
812 return error;
813 }
814 b = bufp = bp->b_addr;
815 word = 0;
816 } else {
817
818
819
820 b++;
821 }
822 } else {
823
824
825
826 i = 0;
827 }
828
829
830
831
832 while (len - i >= XFS_NBWORD) {
833
834
835
836 if ((wdiff = *b ^ val)) {
837
838
839
840 xfs_trans_brelse(tp, bp);
841 i += XFS_RTLOBIT(wdiff);
842 *new = start + i;
843 *stat = 0;
844 return 0;
845 }
846 i += XFS_NBWORD;
847
848
849
850
851 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
852
853
854
855 xfs_trans_brelse(tp, bp);
856 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
857 if (error) {
858 return error;
859 }
860 b = bufp = bp->b_addr;
861 word = 0;
862 } else {
863
864
865
866 b++;
867 }
868 }
869
870
871
872
873 if ((lastbit = len - i)) {
874
875
876
877 mask = ((xfs_rtword_t)1 << lastbit) - 1;
878
879
880
881 if ((wdiff = (*b ^ val) & mask)) {
882
883
884
885 xfs_trans_brelse(tp, bp);
886 i += XFS_RTLOBIT(wdiff);
887 *new = start + i;
888 *stat = 0;
889 return 0;
890 } else
891 i = len;
892 }
893
894
895
896 xfs_trans_brelse(tp, bp);
897 *new = start + i;
898 *stat = 1;
899 return 0;
900}
901
902#ifdef DEBUG
903
904
905
906STATIC int
907xfs_rtcheck_alloc_range(
908 xfs_mount_t *mp,
909 xfs_trans_t *tp,
910 xfs_rtblock_t bno,
911 xfs_extlen_t len)
912{
913 xfs_rtblock_t new;
914 int stat;
915 int error;
916
917 error = xfs_rtcheck_range(mp, tp, bno, len, 0, &new, &stat);
918 if (error)
919 return error;
920 ASSERT(stat);
921 return 0;
922}
923#else
924#define xfs_rtcheck_alloc_range(m,t,b,l) (0)
925#endif
926
927
928
929
930int
931xfs_rtfree_extent(
932 xfs_trans_t *tp,
933 xfs_rtblock_t bno,
934 xfs_extlen_t len)
935{
936 int error;
937 xfs_mount_t *mp;
938 xfs_fsblock_t sb;
939 xfs_buf_t *sumbp = NULL;
940
941 mp = tp->t_mountp;
942
943 ASSERT(mp->m_rbmip->i_itemp != NULL);
944 ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
945
946 error = xfs_rtcheck_alloc_range(mp, tp, bno, len);
947 if (error)
948 return error;
949
950
951
952
953 error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
954 if (error) {
955 return error;
956 }
957
958
959
960 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
961
962
963
964
965 if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
966 mp->m_sb.sb_rextents) {
967 if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
968 mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
969 *(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0;
970 xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
971 }
972 return 0;
973}
974
975