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_types.h"
21#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h"
25#include "xfs_ag.h"
26#include "xfs_dir2.h"
27#include "xfs_mount.h"
28#include "xfs_bmap_btree.h"
29#include "xfs_dinode.h"
30#include "xfs_inode.h"
31#include "xfs_alloc.h"
32#include "xfs_bmap.h"
33#include "xfs_rtalloc.h"
34#include "xfs_fsops.h"
35#include "xfs_error.h"
36#include "xfs_inode_item.h"
37#include "xfs_trans_space.h"
38#include "xfs_utils.h"
39#include "xfs_trace.h"
40#include "xfs_buf.h"
41#include "xfs_icache.h"
42
43
44
45
46
47
48
49STATIC int xfs_rtallocate_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
50 xfs_extlen_t, xfs_buf_t **, xfs_fsblock_t *);
51STATIC int xfs_rtany_summary(xfs_mount_t *, xfs_trans_t *, int, int,
52 xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, int *);
53STATIC int xfs_rtcheck_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
54 xfs_extlen_t, int, xfs_rtblock_t *, int *);
55STATIC int xfs_rtfind_back(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
56 xfs_rtblock_t, xfs_rtblock_t *);
57STATIC int xfs_rtfind_forw(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
58 xfs_rtblock_t, xfs_rtblock_t *);
59STATIC int xfs_rtget_summary( xfs_mount_t *, xfs_trans_t *, int,
60 xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, xfs_suminfo_t *);
61STATIC int xfs_rtmodify_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
62 xfs_extlen_t, int);
63STATIC int xfs_rtmodify_summary(xfs_mount_t *, xfs_trans_t *, int,
64 xfs_rtblock_t, int, xfs_buf_t **, xfs_fsblock_t *);
65
66
67
68
69
70
71
72
73STATIC int
74xfs_growfs_rt_alloc(
75 xfs_mount_t *mp,
76 xfs_extlen_t oblocks,
77 xfs_extlen_t nblocks,
78 xfs_inode_t *ip)
79{
80 xfs_fileoff_t bno;
81 xfs_buf_t *bp;
82 int committed;
83 xfs_daddr_t d;
84 int error;
85 xfs_fsblock_t firstblock;
86 xfs_bmap_free_t flist;
87 xfs_fsblock_t fsbno;
88 xfs_bmbt_irec_t map;
89 int nmap;
90 int resblks;
91
92
93
94
95 while (oblocks < nblocks) {
96 int cancelflags = 0;
97 xfs_trans_t *tp;
98
99 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ALLOC);
100 resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks);
101
102
103
104 if ((error = xfs_trans_reserve(tp, resblks,
105 XFS_GROWRTALLOC_LOG_RES(mp), 0,
106 XFS_TRANS_PERM_LOG_RES,
107 XFS_DEFAULT_PERM_LOG_COUNT)))
108 goto error_cancel;
109 cancelflags = XFS_TRANS_RELEASE_LOG_RES;
110
111
112
113 xfs_ilock(ip, XFS_ILOCK_EXCL);
114 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
115
116 xfs_bmap_init(&flist, &firstblock);
117
118
119
120 nmap = 1;
121 cancelflags |= XFS_TRANS_ABORT;
122 error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks,
123 XFS_BMAPI_METADATA, &firstblock,
124 resblks, &map, &nmap, &flist);
125 if (!error && nmap < 1)
126 error = XFS_ERROR(ENOSPC);
127 if (error)
128 goto error_cancel;
129
130
131
132 error = xfs_bmap_finish(&tp, &flist, &committed);
133 if (error)
134 goto error_cancel;
135 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
136 if (error)
137 goto error;
138
139
140
141
142 cancelflags = 0;
143 for (bno = map.br_startoff, fsbno = map.br_startblock;
144 bno < map.br_startoff + map.br_blockcount;
145 bno++, fsbno++) {
146 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ZERO);
147
148
149
150 if ((error = xfs_trans_reserve(tp, 0,
151 XFS_GROWRTZERO_LOG_RES(mp), 0, 0, 0)))
152 goto error_cancel;
153
154
155
156 xfs_ilock(ip, XFS_ILOCK_EXCL);
157 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
158
159
160
161 d = XFS_FSB_TO_DADDR(mp, fsbno);
162 bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
163 mp->m_bsize, 0);
164 if (bp == NULL) {
165 error = XFS_ERROR(EIO);
166error_cancel:
167 xfs_trans_cancel(tp, cancelflags);
168 goto error;
169 }
170 memset(bp->b_addr, 0, mp->m_sb.sb_blocksize);
171 xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
172
173
174
175 error = xfs_trans_commit(tp, 0);
176 if (error)
177 goto error;
178 }
179
180
181
182 oblocks = map.br_startoff + map.br_blockcount;
183 }
184 return 0;
185
186error:
187 return error;
188}
189
190
191
192
193
194
195
196STATIC int
197xfs_rtallocate_extent_block(
198 xfs_mount_t *mp,
199 xfs_trans_t *tp,
200 xfs_rtblock_t bbno,
201 xfs_extlen_t minlen,
202 xfs_extlen_t maxlen,
203 xfs_extlen_t *len,
204 xfs_rtblock_t *nextp,
205 xfs_buf_t **rbpp,
206 xfs_fsblock_t *rsb,
207 xfs_extlen_t prod,
208 xfs_rtblock_t *rtblock)
209{
210 xfs_rtblock_t besti;
211 xfs_rtblock_t bestlen;
212 xfs_rtblock_t end;
213 int error;
214 xfs_rtblock_t i;
215 xfs_rtblock_t next;
216 int stat;
217
218
219
220
221
222 for (i = XFS_BLOCKTOBIT(mp, bbno), besti = -1, bestlen = 0,
223 end = XFS_BLOCKTOBIT(mp, bbno + 1) - 1;
224 i <= end;
225 i++) {
226
227
228
229
230 error = xfs_rtcheck_range(mp, tp, i, maxlen, 1, &next, &stat);
231 if (error) {
232 return error;
233 }
234 if (stat) {
235
236
237
238 error = xfs_rtallocate_range(mp, tp, i, maxlen, rbpp,
239 rsb);
240 if (error) {
241 return error;
242 }
243 *len = maxlen;
244 *rtblock = i;
245 return 0;
246 }
247
248
249
250
251
252
253 if (minlen < maxlen) {
254 xfs_rtblock_t thislen;
255
256 thislen = next - i;
257 if (thislen >= minlen && thislen > bestlen) {
258 besti = i;
259 bestlen = thislen;
260 }
261 }
262
263
264
265 if (next < end) {
266 error = xfs_rtfind_forw(mp, tp, next, end, &i);
267 if (error) {
268 return error;
269 }
270 } else
271 break;
272 }
273
274
275
276 if (minlen < maxlen && besti != -1) {
277 xfs_extlen_t p;
278
279
280
281
282 if (prod > 1 && (p = do_mod(bestlen, prod)))
283 bestlen -= p;
284
285
286
287 error = xfs_rtallocate_range(mp, tp, besti, bestlen, rbpp, rsb);
288 if (error) {
289 return error;
290 }
291 *len = bestlen;
292 *rtblock = besti;
293 return 0;
294 }
295
296
297
298 *nextp = next;
299 *rtblock = NULLRTBLOCK;
300 return 0;
301}
302
303
304
305
306
307
308
309STATIC int
310xfs_rtallocate_extent_exact(
311 xfs_mount_t *mp,
312 xfs_trans_t *tp,
313 xfs_rtblock_t bno,
314 xfs_extlen_t minlen,
315 xfs_extlen_t maxlen,
316 xfs_extlen_t *len,
317 xfs_buf_t **rbpp,
318 xfs_fsblock_t *rsb,
319 xfs_extlen_t prod,
320 xfs_rtblock_t *rtblock)
321{
322 int error;
323 xfs_extlen_t i;
324 int isfree;
325 xfs_rtblock_t next;
326
327 ASSERT(minlen % prod == 0 && maxlen % prod == 0);
328
329
330
331 error = xfs_rtcheck_range(mp, tp, bno, maxlen, 1, &next, &isfree);
332 if (error) {
333 return error;
334 }
335 if (isfree) {
336
337
338
339 error = xfs_rtallocate_range(mp, tp, bno, maxlen, rbpp, rsb);
340 if (error) {
341 return error;
342 }
343 *len = maxlen;
344 *rtblock = bno;
345 return 0;
346 }
347
348
349
350 maxlen = next - bno;
351 if (maxlen < minlen) {
352
353
354
355 *rtblock = NULLRTBLOCK;
356 return 0;
357 }
358
359
360
361 if (prod > 1 && (i = maxlen % prod)) {
362 maxlen -= i;
363 if (maxlen < minlen) {
364
365
366
367 *rtblock = NULLRTBLOCK;
368 return 0;
369 }
370 }
371
372
373
374 error = xfs_rtallocate_range(mp, tp, bno, maxlen, rbpp, rsb);
375 if (error) {
376 return error;
377 }
378 *len = maxlen;
379 *rtblock = bno;
380 return 0;
381}
382
383
384
385
386
387
388STATIC int
389xfs_rtallocate_extent_near(
390 xfs_mount_t *mp,
391 xfs_trans_t *tp,
392 xfs_rtblock_t bno,
393 xfs_extlen_t minlen,
394 xfs_extlen_t maxlen,
395 xfs_extlen_t *len,
396 xfs_buf_t **rbpp,
397 xfs_fsblock_t *rsb,
398 xfs_extlen_t prod,
399 xfs_rtblock_t *rtblock)
400{
401 int any;
402 xfs_rtblock_t bbno;
403 int error;
404 int i;
405 int j;
406 int log2len;
407 xfs_rtblock_t n;
408 xfs_rtblock_t r;
409
410 ASSERT(minlen % prod == 0 && maxlen % prod == 0);
411
412
413
414
415 if (bno >= mp->m_sb.sb_rextents)
416 bno = mp->m_sb.sb_rextents - 1;
417
418
419
420 error = xfs_rtallocate_extent_exact(mp, tp, bno, minlen, maxlen, len,
421 rbpp, rsb, prod, &r);
422 if (error) {
423 return error;
424 }
425
426
427
428 if (r != NULLRTBLOCK) {
429 *rtblock = r;
430 return 0;
431 }
432 bbno = XFS_BITTOBLOCK(mp, bno);
433 i = 0;
434 ASSERT(minlen != 0);
435 log2len = xfs_highbit32(minlen);
436
437
438
439 for (;;) {
440
441
442
443
444 error = xfs_rtany_summary(mp, tp, log2len, mp->m_rsumlevels - 1,
445 bbno + i, rbpp, rsb, &any);
446 if (error) {
447 return error;
448 }
449
450
451
452
453 if (any) {
454
455
456
457 if (i >= 0) {
458
459
460
461
462 error = xfs_rtallocate_extent_block(mp, tp,
463 bbno + i, minlen, maxlen, len, &n, rbpp,
464 rsb, prod, &r);
465 if (error) {
466 return error;
467 }
468
469
470
471 if (r != NULLRTBLOCK) {
472 *rtblock = r;
473 return 0;
474 }
475 }
476
477
478
479 else {
480
481
482
483
484
485
486 for (j = -1; j > i; j--) {
487
488
489
490
491 error = xfs_rtany_summary(mp, tp,
492 log2len, mp->m_rsumlevels - 1,
493 bbno + j, rbpp, rsb, &any);
494 if (error) {
495 return error;
496 }
497
498
499
500
501
502
503
504
505 if (any)
506 continue;
507 error = xfs_rtallocate_extent_block(mp,
508 tp, bbno + j, minlen, maxlen,
509 len, &n, rbpp, rsb, prod, &r);
510 if (error) {
511 return error;
512 }
513
514
515
516 if (r != NULLRTBLOCK) {
517 *rtblock = r;
518 return 0;
519 }
520 }
521
522
523
524
525
526
527
528
529 error = xfs_rtallocate_extent_block(mp, tp,
530 bbno + i, minlen, maxlen, len, &n, rbpp,
531 rsb, prod, &r);
532 if (error) {
533 return error;
534 }
535
536
537
538 if (r != NULLRTBLOCK) {
539 *rtblock = r;
540 return 0;
541 }
542 }
543 }
544
545
546
547
548 if (i > 0 && (int)bbno - i >= 0)
549 i = -i;
550
551
552
553
554 else if (i > 0 && (int)bbno + i < mp->m_sb.sb_rbmblocks - 1)
555 i++;
556
557
558
559
560 else if (i <= 0 && (int)bbno - i < mp->m_sb.sb_rbmblocks - 1)
561 i = 1 - i;
562
563
564
565
566 else if (i <= 0 && (int)bbno + i > 0)
567 i--;
568
569
570
571 else
572 break;
573 }
574 *rtblock = NULLRTBLOCK;
575 return 0;
576}
577
578
579
580
581
582
583STATIC int
584xfs_rtallocate_extent_size(
585 xfs_mount_t *mp,
586 xfs_trans_t *tp,
587 xfs_extlen_t minlen,
588 xfs_extlen_t maxlen,
589 xfs_extlen_t *len,
590 xfs_buf_t **rbpp,
591 xfs_fsblock_t *rsb,
592 xfs_extlen_t prod,
593 xfs_rtblock_t *rtblock)
594{
595 int error;
596 int i;
597 int l;
598 xfs_rtblock_t n;
599 xfs_rtblock_t r;
600 xfs_suminfo_t sum;
601
602 ASSERT(minlen % prod == 0 && maxlen % prod == 0);
603 ASSERT(maxlen != 0);
604
605
606
607
608
609
610
611
612 for (l = xfs_highbit32(maxlen); l < mp->m_rsumlevels; l++) {
613
614
615
616 for (i = 0; i < mp->m_sb.sb_rbmblocks; i++) {
617
618
619
620 error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb,
621 &sum);
622 if (error) {
623 return error;
624 }
625
626
627
628 if (!sum)
629 continue;
630
631
632
633 error = xfs_rtallocate_extent_block(mp, tp, i, maxlen,
634 maxlen, len, &n, rbpp, rsb, prod, &r);
635 if (error) {
636 return error;
637 }
638
639
640
641 if (r != NULLRTBLOCK) {
642 *rtblock = r;
643 return 0;
644 }
645
646
647
648
649
650 if (XFS_BITTOBLOCK(mp, n) > i + 1)
651 i = XFS_BITTOBLOCK(mp, n) - 1;
652 }
653 }
654
655
656
657
658 if (minlen > --maxlen) {
659 *rtblock = NULLRTBLOCK;
660 return 0;
661 }
662 ASSERT(minlen != 0);
663 ASSERT(maxlen != 0);
664
665
666
667
668
669
670 for (l = xfs_highbit32(maxlen); l >= xfs_highbit32(minlen); l--) {
671
672
673
674
675 for (i = 0; i < mp->m_sb.sb_rbmblocks; i++) {
676
677
678
679 error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb,
680 &sum);
681 if (error) {
682 return error;
683 }
684
685
686
687 if (!sum)
688 continue;
689
690
691
692
693
694 error = xfs_rtallocate_extent_block(mp, tp, i,
695 XFS_RTMAX(minlen, 1 << l),
696 XFS_RTMIN(maxlen, (1 << (l + 1)) - 1),
697 len, &n, rbpp, rsb, prod, &r);
698 if (error) {
699 return error;
700 }
701
702
703
704 if (r != NULLRTBLOCK) {
705 *rtblock = r;
706 return 0;
707 }
708
709
710
711
712
713 if (XFS_BITTOBLOCK(mp, n) > i + 1)
714 i = XFS_BITTOBLOCK(mp, n) - 1;
715 }
716 }
717
718
719
720 *rtblock = NULLRTBLOCK;
721 return 0;
722}
723
724
725
726
727
728STATIC int
729xfs_rtallocate_range(
730 xfs_mount_t *mp,
731 xfs_trans_t *tp,
732 xfs_rtblock_t start,
733 xfs_extlen_t len,
734 xfs_buf_t **rbpp,
735 xfs_fsblock_t *rsb)
736{
737 xfs_rtblock_t end;
738 int error;
739 xfs_rtblock_t postblock;
740 xfs_rtblock_t preblock;
741
742 end = start + len - 1;
743
744
745
746
747
748 error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
749 if (error) {
750 return error;
751 }
752
753
754
755 error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
756 &postblock);
757 if (error) {
758 return error;
759 }
760
761
762
763
764 error = xfs_rtmodify_summary(mp, tp,
765 XFS_RTBLOCKLOG(postblock + 1 - preblock),
766 XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
767 if (error) {
768 return error;
769 }
770
771
772
773
774 if (preblock < start) {
775 error = xfs_rtmodify_summary(mp, tp,
776 XFS_RTBLOCKLOG(start - preblock),
777 XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
778 if (error) {
779 return error;
780 }
781 }
782
783
784
785
786 if (postblock > end) {
787 error = xfs_rtmodify_summary(mp, tp,
788 XFS_RTBLOCKLOG(postblock - end),
789 XFS_BITTOBLOCK(mp, end + 1), 1, rbpp, rsb);
790 if (error) {
791 return error;
792 }
793 }
794
795
796
797 error = xfs_rtmodify_range(mp, tp, start, len, 0);
798 return error;
799}
800
801
802
803
804
805STATIC int
806xfs_rtany_summary(
807 xfs_mount_t *mp,
808 xfs_trans_t *tp,
809 int low,
810 int high,
811 xfs_rtblock_t bbno,
812 xfs_buf_t **rbpp,
813 xfs_fsblock_t *rsb,
814 int *stat)
815{
816 int error;
817 int log;
818 xfs_suminfo_t sum;
819
820
821
822
823 for (log = low; log <= high; log++) {
824
825
826
827 error = xfs_rtget_summary(mp, tp, log, bbno, rbpp, rsb, &sum);
828 if (error) {
829 return error;
830 }
831
832
833
834 if (sum) {
835 *stat = 1;
836 return 0;
837 }
838 }
839
840
841
842 *stat = 0;
843 return 0;
844}
845
846
847
848
849
850STATIC int
851xfs_rtbuf_get(
852 xfs_mount_t *mp,
853 xfs_trans_t *tp,
854 xfs_rtblock_t block,
855 int issum,
856 xfs_buf_t **bpp)
857{
858 xfs_buf_t *bp;
859 xfs_inode_t *ip;
860 xfs_bmbt_irec_t map;
861 int nmap = 1;
862 int error;
863
864 ip = issum ? mp->m_rsumip : mp->m_rbmip;
865
866 error = xfs_bmapi_read(ip, block, 1, &map, &nmap, XFS_DATA_FORK);
867 if (error)
868 return error;
869
870 ASSERT(map.br_startblock != NULLFSBLOCK);
871 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
872 XFS_FSB_TO_DADDR(mp, map.br_startblock),
873 mp->m_bsize, 0, &bp, NULL);
874 if (error)
875 return error;
876 ASSERT(!xfs_buf_geterror(bp));
877 *bpp = bp;
878 return 0;
879}
880
881#ifdef DEBUG
882
883
884
885STATIC int
886xfs_rtcheck_alloc_range(
887 xfs_mount_t *mp,
888 xfs_trans_t *tp,
889 xfs_rtblock_t bno,
890 xfs_extlen_t len,
891 int *stat)
892{
893 xfs_rtblock_t new;
894
895 return xfs_rtcheck_range(mp, tp, bno, len, 0, &new, stat);
896}
897#endif
898
899
900
901
902
903STATIC int
904xfs_rtcheck_range(
905 xfs_mount_t *mp,
906 xfs_trans_t *tp,
907 xfs_rtblock_t start,
908 xfs_extlen_t len,
909 int val,
910 xfs_rtblock_t *new,
911 int *stat)
912{
913 xfs_rtword_t *b;
914 int bit;
915 xfs_rtblock_t block;
916 xfs_buf_t *bp;
917 xfs_rtword_t *bufp;
918 int error;
919 xfs_rtblock_t i;
920 xfs_rtblock_t lastbit;
921 xfs_rtword_t mask;
922 xfs_rtword_t wdiff;
923 int word;
924
925
926
927
928 block = XFS_BITTOBLOCK(mp, start);
929
930
931
932 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
933 if (error) {
934 return error;
935 }
936 bufp = bp->b_addr;
937
938
939
940 word = XFS_BITTOWORD(mp, start);
941 b = &bufp[word];
942 bit = (int)(start & (XFS_NBWORD - 1));
943
944
945
946 val = -val;
947
948
949
950
951 if (bit) {
952
953
954
955 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
956
957
958
959 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
960
961
962
963 if ((wdiff = (*b ^ val) & mask)) {
964
965
966
967 xfs_trans_brelse(tp, bp);
968 i = XFS_RTLOBIT(wdiff) - bit;
969 *new = start + i;
970 *stat = 0;
971 return 0;
972 }
973 i = lastbit - bit;
974
975
976
977
978 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
979
980
981
982 xfs_trans_brelse(tp, bp);
983 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
984 if (error) {
985 return error;
986 }
987 b = bufp = bp->b_addr;
988 word = 0;
989 } else {
990
991
992
993 b++;
994 }
995 } else {
996
997
998
999 i = 0;
1000 }
1001
1002
1003
1004
1005 while (len - i >= XFS_NBWORD) {
1006
1007
1008
1009 if ((wdiff = *b ^ val)) {
1010
1011
1012
1013 xfs_trans_brelse(tp, bp);
1014 i += XFS_RTLOBIT(wdiff);
1015 *new = start + i;
1016 *stat = 0;
1017 return 0;
1018 }
1019 i += XFS_NBWORD;
1020
1021
1022
1023
1024 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1025
1026
1027
1028 xfs_trans_brelse(tp, bp);
1029 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1030 if (error) {
1031 return error;
1032 }
1033 b = bufp = bp->b_addr;
1034 word = 0;
1035 } else {
1036
1037
1038
1039 b++;
1040 }
1041 }
1042
1043
1044
1045
1046 if ((lastbit = len - i)) {
1047
1048
1049
1050 mask = ((xfs_rtword_t)1 << lastbit) - 1;
1051
1052
1053
1054 if ((wdiff = (*b ^ val) & mask)) {
1055
1056
1057
1058 xfs_trans_brelse(tp, bp);
1059 i += XFS_RTLOBIT(wdiff);
1060 *new = start + i;
1061 *stat = 0;
1062 return 0;
1063 } else
1064 i = len;
1065 }
1066
1067
1068
1069 xfs_trans_brelse(tp, bp);
1070 *new = start + i;
1071 *stat = 1;
1072 return 0;
1073}
1074
1075
1076
1077
1078
1079STATIC int
1080xfs_rtcopy_summary(
1081 xfs_mount_t *omp,
1082 xfs_mount_t *nmp,
1083 xfs_trans_t *tp)
1084{
1085 xfs_rtblock_t bbno;
1086 xfs_buf_t *bp;
1087 int error;
1088 int log;
1089 xfs_suminfo_t sum;
1090 xfs_fsblock_t sumbno;
1091
1092 bp = NULL;
1093 for (log = omp->m_rsumlevels - 1; log >= 0; log--) {
1094 for (bbno = omp->m_sb.sb_rbmblocks - 1;
1095 (xfs_srtblock_t)bbno >= 0;
1096 bbno--) {
1097 error = xfs_rtget_summary(omp, tp, log, bbno, &bp,
1098 &sumbno, &sum);
1099 if (error)
1100 return error;
1101 if (sum == 0)
1102 continue;
1103 error = xfs_rtmodify_summary(omp, tp, log, bbno, -sum,
1104 &bp, &sumbno);
1105 if (error)
1106 return error;
1107 error = xfs_rtmodify_summary(nmp, tp, log, bbno, sum,
1108 &bp, &sumbno);
1109 if (error)
1110 return error;
1111 ASSERT(sum > 0);
1112 }
1113 }
1114 return 0;
1115}
1116
1117
1118
1119
1120
1121STATIC int
1122xfs_rtfind_back(
1123 xfs_mount_t *mp,
1124 xfs_trans_t *tp,
1125 xfs_rtblock_t start,
1126 xfs_rtblock_t limit,
1127 xfs_rtblock_t *rtblock)
1128{
1129 xfs_rtword_t *b;
1130 int bit;
1131 xfs_rtblock_t block;
1132 xfs_buf_t *bp;
1133 xfs_rtword_t *bufp;
1134 int error;
1135 xfs_rtblock_t firstbit;
1136 xfs_rtblock_t i;
1137 xfs_rtblock_t len;
1138 xfs_rtword_t mask;
1139 xfs_rtword_t want;
1140 xfs_rtword_t wdiff;
1141 int word;
1142
1143
1144
1145
1146 block = XFS_BITTOBLOCK(mp, start);
1147 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
1148 if (error) {
1149 return error;
1150 }
1151 bufp = bp->b_addr;
1152
1153
1154
1155 word = XFS_BITTOWORD(mp, start);
1156 b = &bufp[word];
1157 bit = (int)(start & (XFS_NBWORD - 1));
1158 len = start - limit + 1;
1159
1160
1161
1162
1163 want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
1164
1165
1166
1167
1168 if (bit < XFS_NBWORD - 1) {
1169
1170
1171
1172
1173 firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
1174 mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
1175 firstbit;
1176
1177
1178
1179
1180 if ((wdiff = (*b ^ want) & mask)) {
1181
1182
1183
1184 xfs_trans_brelse(tp, bp);
1185 i = bit - XFS_RTHIBIT(wdiff);
1186 *rtblock = start - i + 1;
1187 return 0;
1188 }
1189 i = bit - firstbit + 1;
1190
1191
1192
1193
1194 if (--word == -1 && i < len) {
1195
1196
1197
1198 xfs_trans_brelse(tp, bp);
1199 error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
1200 if (error) {
1201 return error;
1202 }
1203 bufp = bp->b_addr;
1204 word = XFS_BLOCKWMASK(mp);
1205 b = &bufp[word];
1206 } else {
1207
1208
1209
1210 b--;
1211 }
1212 } else {
1213
1214
1215
1216 i = 0;
1217 }
1218
1219
1220
1221
1222 while (len - i >= XFS_NBWORD) {
1223
1224
1225
1226 if ((wdiff = *b ^ want)) {
1227
1228
1229
1230 xfs_trans_brelse(tp, bp);
1231 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
1232 *rtblock = start - i + 1;
1233 return 0;
1234 }
1235 i += XFS_NBWORD;
1236
1237
1238
1239
1240 if (--word == -1 && i < len) {
1241
1242
1243
1244 xfs_trans_brelse(tp, bp);
1245 error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
1246 if (error) {
1247 return error;
1248 }
1249 bufp = bp->b_addr;
1250 word = XFS_BLOCKWMASK(mp);
1251 b = &bufp[word];
1252 } else {
1253
1254
1255
1256 b--;
1257 }
1258 }
1259
1260
1261
1262
1263 if (len - i) {
1264
1265
1266
1267
1268 firstbit = XFS_NBWORD - (len - i);
1269 mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
1270
1271
1272
1273 if ((wdiff = (*b ^ want) & mask)) {
1274
1275
1276
1277 xfs_trans_brelse(tp, bp);
1278 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
1279 *rtblock = start - i + 1;
1280 return 0;
1281 } else
1282 i = len;
1283 }
1284
1285
1286
1287 xfs_trans_brelse(tp, bp);
1288 *rtblock = start - i + 1;
1289 return 0;
1290}
1291
1292
1293
1294
1295
1296STATIC int
1297xfs_rtfind_forw(
1298 xfs_mount_t *mp,
1299 xfs_trans_t *tp,
1300 xfs_rtblock_t start,
1301 xfs_rtblock_t limit,
1302 xfs_rtblock_t *rtblock)
1303{
1304 xfs_rtword_t *b;
1305 int bit;
1306 xfs_rtblock_t block;
1307 xfs_buf_t *bp;
1308 xfs_rtword_t *bufp;
1309 int error;
1310 xfs_rtblock_t i;
1311 xfs_rtblock_t lastbit;
1312 xfs_rtblock_t len;
1313 xfs_rtword_t mask;
1314 xfs_rtword_t want;
1315 xfs_rtword_t wdiff;
1316 int word;
1317
1318
1319
1320
1321 block = XFS_BITTOBLOCK(mp, start);
1322 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
1323 if (error) {
1324 return error;
1325 }
1326 bufp = bp->b_addr;
1327
1328
1329
1330 word = XFS_BITTOWORD(mp, start);
1331 b = &bufp[word];
1332 bit = (int)(start & (XFS_NBWORD - 1));
1333 len = limit - start + 1;
1334
1335
1336
1337
1338 want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
1339
1340
1341
1342
1343 if (bit) {
1344
1345
1346
1347
1348 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
1349 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
1350
1351
1352
1353
1354 if ((wdiff = (*b ^ want) & mask)) {
1355
1356
1357
1358 xfs_trans_brelse(tp, bp);
1359 i = XFS_RTLOBIT(wdiff) - bit;
1360 *rtblock = start + i - 1;
1361 return 0;
1362 }
1363 i = lastbit - bit;
1364
1365
1366
1367
1368 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1369
1370
1371
1372 xfs_trans_brelse(tp, bp);
1373 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1374 if (error) {
1375 return error;
1376 }
1377 b = bufp = bp->b_addr;
1378 word = 0;
1379 } else {
1380
1381
1382
1383 b++;
1384 }
1385 } else {
1386
1387
1388
1389 i = 0;
1390 }
1391
1392
1393
1394
1395 while (len - i >= XFS_NBWORD) {
1396
1397
1398
1399 if ((wdiff = *b ^ want)) {
1400
1401
1402
1403 xfs_trans_brelse(tp, bp);
1404 i += XFS_RTLOBIT(wdiff);
1405 *rtblock = start + i - 1;
1406 return 0;
1407 }
1408 i += XFS_NBWORD;
1409
1410
1411
1412
1413 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1414
1415
1416
1417 xfs_trans_brelse(tp, bp);
1418 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1419 if (error) {
1420 return error;
1421 }
1422 b = bufp = bp->b_addr;
1423 word = 0;
1424 } else {
1425
1426
1427
1428 b++;
1429 }
1430 }
1431
1432
1433
1434
1435 if ((lastbit = len - i)) {
1436
1437
1438
1439 mask = ((xfs_rtword_t)1 << lastbit) - 1;
1440
1441
1442
1443 if ((wdiff = (*b ^ want) & mask)) {
1444
1445
1446
1447 xfs_trans_brelse(tp, bp);
1448 i += XFS_RTLOBIT(wdiff);
1449 *rtblock = start + i - 1;
1450 return 0;
1451 } else
1452 i = len;
1453 }
1454
1455
1456
1457 xfs_trans_brelse(tp, bp);
1458 *rtblock = start + i - 1;
1459 return 0;
1460}
1461
1462
1463
1464
1465
1466STATIC int
1467xfs_rtfree_range(
1468 xfs_mount_t *mp,
1469 xfs_trans_t *tp,
1470 xfs_rtblock_t start,
1471 xfs_extlen_t len,
1472 xfs_buf_t **rbpp,
1473 xfs_fsblock_t *rsb)
1474{
1475 xfs_rtblock_t end;
1476 int error;
1477 xfs_rtblock_t postblock;
1478 xfs_rtblock_t preblock;
1479
1480 end = start + len - 1;
1481
1482
1483
1484 error = xfs_rtmodify_range(mp, tp, start, len, 1);
1485 if (error) {
1486 return error;
1487 }
1488
1489
1490
1491
1492
1493 error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
1494 if (error) {
1495 return error;
1496 }
1497
1498
1499
1500 error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
1501 &postblock);
1502 if (error)
1503 return error;
1504
1505
1506
1507
1508 if (preblock < start) {
1509 error = xfs_rtmodify_summary(mp, tp,
1510 XFS_RTBLOCKLOG(start - preblock),
1511 XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
1512 if (error) {
1513 return error;
1514 }
1515 }
1516
1517
1518
1519
1520 if (postblock > end) {
1521 error = xfs_rtmodify_summary(mp, tp,
1522 XFS_RTBLOCKLOG(postblock - end),
1523 XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
1524 if (error) {
1525 return error;
1526 }
1527 }
1528
1529
1530
1531
1532 error = xfs_rtmodify_summary(mp, tp,
1533 XFS_RTBLOCKLOG(postblock + 1 - preblock),
1534 XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
1535 return error;
1536}
1537
1538
1539
1540
1541
1542
1543
1544STATIC int
1545xfs_rtget_summary(
1546 xfs_mount_t *mp,
1547 xfs_trans_t *tp,
1548 int log,
1549 xfs_rtblock_t bbno,
1550 xfs_buf_t **rbpp,
1551 xfs_fsblock_t *rsb,
1552 xfs_suminfo_t *sum)
1553{
1554 xfs_buf_t *bp;
1555 int error;
1556 xfs_fsblock_t sb;
1557 int so;
1558 xfs_suminfo_t *sp;
1559
1560
1561
1562
1563 so = XFS_SUMOFFS(mp, log, bbno);
1564
1565
1566
1567 sb = XFS_SUMOFFSTOBLOCK(mp, so);
1568
1569
1570
1571 if (rbpp && *rbpp && *rsb == sb)
1572 bp = *rbpp;
1573
1574
1575
1576 else {
1577
1578
1579
1580 if (rbpp && *rbpp)
1581 xfs_trans_brelse(tp, *rbpp);
1582 error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
1583 if (error) {
1584 return error;
1585 }
1586
1587
1588
1589 if (rbpp) {
1590 *rbpp = bp;
1591 *rsb = sb;
1592 }
1593 }
1594
1595
1596
1597 sp = XFS_SUMPTR(mp, bp, so);
1598 *sum = *sp;
1599
1600
1601
1602 if (!rbpp)
1603 xfs_trans_brelse(tp, bp);
1604 return 0;
1605}
1606
1607
1608
1609
1610
1611STATIC int
1612xfs_rtmodify_range(
1613 xfs_mount_t *mp,
1614 xfs_trans_t *tp,
1615 xfs_rtblock_t start,
1616 xfs_extlen_t len,
1617 int val)
1618{
1619 xfs_rtword_t *b;
1620 int bit;
1621 xfs_rtblock_t block;
1622 xfs_buf_t *bp;
1623 xfs_rtword_t *bufp;
1624 int error;
1625 xfs_rtword_t *first;
1626 int i;
1627 int lastbit;
1628 xfs_rtword_t mask;
1629 int word;
1630
1631
1632
1633
1634 block = XFS_BITTOBLOCK(mp, start);
1635
1636
1637
1638 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
1639 if (error) {
1640 return error;
1641 }
1642 bufp = bp->b_addr;
1643
1644
1645
1646 word = XFS_BITTOWORD(mp, start);
1647 first = b = &bufp[word];
1648 bit = (int)(start & (XFS_NBWORD - 1));
1649
1650
1651
1652 val = -val;
1653
1654
1655
1656
1657 if (bit) {
1658
1659
1660
1661 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
1662 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
1663
1664
1665
1666 if (val)
1667 *b |= mask;
1668 else
1669 *b &= ~mask;
1670 i = lastbit - bit;
1671
1672
1673
1674
1675 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1676
1677
1678
1679
1680 xfs_trans_log_buf(tp, bp,
1681 (uint)((char *)first - (char *)bufp),
1682 (uint)((char *)b - (char *)bufp));
1683 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1684 if (error) {
1685 return error;
1686 }
1687 first = b = bufp = bp->b_addr;
1688 word = 0;
1689 } else {
1690
1691
1692
1693 b++;
1694 }
1695 } else {
1696
1697
1698
1699 i = 0;
1700 }
1701
1702
1703
1704
1705 while (len - i >= XFS_NBWORD) {
1706
1707
1708
1709 *b = val;
1710 i += XFS_NBWORD;
1711
1712
1713
1714
1715 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1716
1717
1718
1719
1720 xfs_trans_log_buf(tp, bp,
1721 (uint)((char *)first - (char *)bufp),
1722 (uint)((char *)b - (char *)bufp));
1723 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1724 if (error) {
1725 return error;
1726 }
1727 first = b = bufp = bp->b_addr;
1728 word = 0;
1729 } else {
1730
1731
1732
1733 b++;
1734 }
1735 }
1736
1737
1738
1739
1740 if ((lastbit = len - i)) {
1741
1742
1743
1744 bit = 0;
1745 mask = ((xfs_rtword_t)1 << lastbit) - 1;
1746
1747
1748
1749 if (val)
1750 *b |= mask;
1751 else
1752 *b &= ~mask;
1753 b++;
1754 }
1755
1756
1757
1758 if (b > first)
1759 xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
1760 (uint)((char *)b - (char *)bufp - 1));
1761 return 0;
1762}
1763
1764
1765
1766
1767
1768
1769
1770STATIC int
1771xfs_rtmodify_summary(
1772 xfs_mount_t *mp,
1773 xfs_trans_t *tp,
1774 int log,
1775 xfs_rtblock_t bbno,
1776 int delta,
1777 xfs_buf_t **rbpp,
1778 xfs_fsblock_t *rsb)
1779{
1780 xfs_buf_t *bp;
1781 int error;
1782 xfs_fsblock_t sb;
1783 int so;
1784 xfs_suminfo_t *sp;
1785
1786
1787
1788
1789 so = XFS_SUMOFFS(mp, log, bbno);
1790
1791
1792
1793 sb = XFS_SUMOFFSTOBLOCK(mp, so);
1794
1795
1796
1797 if (rbpp && *rbpp && *rsb == sb)
1798 bp = *rbpp;
1799
1800
1801
1802 else {
1803
1804
1805
1806 if (rbpp && *rbpp)
1807 xfs_trans_brelse(tp, *rbpp);
1808 error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
1809 if (error) {
1810 return error;
1811 }
1812
1813
1814
1815 if (rbpp) {
1816 *rbpp = bp;
1817 *rsb = sb;
1818 }
1819 }
1820
1821
1822
1823 sp = XFS_SUMPTR(mp, bp, so);
1824 *sp += delta;
1825 xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)bp->b_addr),
1826 (uint)((char *)sp - (char *)bp->b_addr + sizeof(*sp) - 1));
1827 return 0;
1828}
1829
1830
1831
1832
1833
1834
1835
1836
1837int
1838xfs_growfs_rt(
1839 xfs_mount_t *mp,
1840 xfs_growfs_rt_t *in)
1841{
1842 xfs_rtblock_t bmbno;
1843 xfs_buf_t *bp;
1844 int error;
1845 xfs_mount_t *nmp;
1846 xfs_drfsbno_t nrblocks;
1847 xfs_extlen_t nrbmblocks;
1848 xfs_drtbno_t nrextents;
1849 uint8_t nrextslog;
1850 xfs_extlen_t nrsumblocks;
1851 uint nrsumlevels;
1852 uint nrsumsize;
1853 xfs_sb_t *nsbp;
1854 xfs_extlen_t rbmblocks;
1855 xfs_extlen_t rsumblocks;
1856 xfs_sb_t *sbp;
1857 xfs_fsblock_t sumbno;
1858
1859 sbp = &mp->m_sb;
1860
1861
1862
1863 if (!capable(CAP_SYS_ADMIN))
1864 return XFS_ERROR(EPERM);
1865 if (mp->m_rtdev_targp == NULL || mp->m_rbmip == NULL ||
1866 (nrblocks = in->newblocks) <= sbp->sb_rblocks ||
1867 (sbp->sb_rblocks && (in->extsize != sbp->sb_rextsize)))
1868 return XFS_ERROR(EINVAL);
1869 if ((error = xfs_sb_validate_fsb_count(sbp, nrblocks)))
1870 return error;
1871
1872
1873
1874 bp = xfs_buf_read_uncached(mp->m_rtdev_targp,
1875 XFS_FSB_TO_BB(mp, nrblocks - 1),
1876 XFS_FSB_TO_BB(mp, 1), 0, NULL);
1877 if (!bp)
1878 return EIO;
1879 if (bp->b_error) {
1880 error = bp->b_error;
1881 xfs_buf_relse(bp);
1882 return error;
1883 }
1884 xfs_buf_relse(bp);
1885
1886
1887
1888
1889 nrextents = nrblocks;
1890 do_div(nrextents, in->extsize);
1891 nrbmblocks = howmany_64(nrextents, NBBY * sbp->sb_blocksize);
1892 nrextslog = xfs_highbit32(nrextents);
1893 nrsumlevels = nrextslog + 1;
1894 nrsumsize = (uint)sizeof(xfs_suminfo_t) * nrsumlevels * nrbmblocks;
1895 nrsumblocks = XFS_B_TO_FSB(mp, nrsumsize);
1896 nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
1897
1898
1899
1900
1901
1902 if (nrsumblocks > (mp->m_sb.sb_logblocks >> 1))
1903 return XFS_ERROR(EINVAL);
1904
1905
1906
1907
1908 rbmblocks = XFS_B_TO_FSB(mp, mp->m_rbmip->i_d.di_size);
1909 rsumblocks = XFS_B_TO_FSB(mp, mp->m_rsumip->i_d.di_size);
1910
1911
1912
1913 error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks, mp->m_rbmip);
1914 if (error)
1915 return error;
1916 error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, mp->m_rsumip);
1917 if (error)
1918 return error;
1919
1920
1921
1922 nmp = kmem_alloc(sizeof(*nmp), KM_SLEEP);
1923
1924
1925
1926
1927
1928
1929 for (bmbno = sbp->sb_rbmblocks -
1930 ((sbp->sb_rextents & ((1 << mp->m_blkbit_log) - 1)) != 0);
1931 bmbno < nrbmblocks;
1932 bmbno++) {
1933 xfs_trans_t *tp;
1934 int cancelflags = 0;
1935
1936 *nmp = *mp;
1937 nsbp = &nmp->m_sb;
1938
1939
1940
1941 nsbp->sb_rextsize = in->extsize;
1942 nsbp->sb_rbmblocks = bmbno + 1;
1943 nsbp->sb_rblocks =
1944 XFS_RTMIN(nrblocks,
1945 nsbp->sb_rbmblocks * NBBY *
1946 nsbp->sb_blocksize * nsbp->sb_rextsize);
1947 nsbp->sb_rextents = nsbp->sb_rblocks;
1948 do_div(nsbp->sb_rextents, nsbp->sb_rextsize);
1949 ASSERT(nsbp->sb_rextents != 0);
1950 nsbp->sb_rextslog = xfs_highbit32(nsbp->sb_rextents);
1951 nrsumlevels = nmp->m_rsumlevels = nsbp->sb_rextslog + 1;
1952 nrsumsize =
1953 (uint)sizeof(xfs_suminfo_t) * nrsumlevels *
1954 nsbp->sb_rbmblocks;
1955 nrsumblocks = XFS_B_TO_FSB(mp, nrsumsize);
1956 nmp->m_rsumsize = nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
1957
1958
1959
1960 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_FREE);
1961 if ((error = xfs_trans_reserve(tp, 0,
1962 XFS_GROWRTFREE_LOG_RES(nmp), 0, 0, 0)))
1963 goto error_cancel;
1964
1965
1966
1967 xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
1968 xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
1969
1970
1971
1972 mp->m_rbmip->i_d.di_size =
1973 nsbp->sb_rbmblocks * nsbp->sb_blocksize;
1974 xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
1975 cancelflags |= XFS_TRANS_ABORT;
1976
1977
1978
1979 xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL);
1980 xfs_trans_ijoin(tp, mp->m_rsumip, XFS_ILOCK_EXCL);
1981
1982
1983
1984 mp->m_rsumip->i_d.di_size = nmp->m_rsumsize;
1985 xfs_trans_log_inode(tp, mp->m_rsumip, XFS_ILOG_CORE);
1986
1987
1988
1989
1990 if (sbp->sb_rbmblocks != nsbp->sb_rbmblocks ||
1991 mp->m_rsumlevels != nmp->m_rsumlevels) {
1992 error = xfs_rtcopy_summary(mp, nmp, tp);
1993 if (error)
1994 goto error_cancel;
1995 }
1996
1997
1998
1999 if (nsbp->sb_rextsize != sbp->sb_rextsize)
2000 xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSIZE,
2001 nsbp->sb_rextsize - sbp->sb_rextsize);
2002 if (nsbp->sb_rbmblocks != sbp->sb_rbmblocks)
2003 xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBMBLOCKS,
2004 nsbp->sb_rbmblocks - sbp->sb_rbmblocks);
2005 if (nsbp->sb_rblocks != sbp->sb_rblocks)
2006 xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBLOCKS,
2007 nsbp->sb_rblocks - sbp->sb_rblocks);
2008 if (nsbp->sb_rextents != sbp->sb_rextents)
2009 xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTENTS,
2010 nsbp->sb_rextents - sbp->sb_rextents);
2011 if (nsbp->sb_rextslog != sbp->sb_rextslog)
2012 xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSLOG,
2013 nsbp->sb_rextslog - sbp->sb_rextslog);
2014
2015
2016
2017 bp = NULL;
2018 error = xfs_rtfree_range(nmp, tp, sbp->sb_rextents,
2019 nsbp->sb_rextents - sbp->sb_rextents, &bp, &sumbno);
2020 if (error) {
2021error_cancel:
2022 xfs_trans_cancel(tp, cancelflags);
2023 break;
2024 }
2025
2026
2027
2028 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS,
2029 nsbp->sb_rextents - sbp->sb_rextents);
2030
2031
2032
2033 mp->m_rsumlevels = nrsumlevels;
2034 mp->m_rsumsize = nrsumsize;
2035
2036 error = xfs_trans_commit(tp, 0);
2037 if (error)
2038 break;
2039 }
2040
2041
2042
2043
2044 kmem_free(nmp);
2045
2046 return error;
2047}
2048
2049
2050
2051
2052
2053
2054int
2055xfs_rtallocate_extent(
2056 xfs_trans_t *tp,
2057 xfs_rtblock_t bno,
2058 xfs_extlen_t minlen,
2059 xfs_extlen_t maxlen,
2060 xfs_extlen_t *len,
2061 xfs_alloctype_t type,
2062 int wasdel,
2063 xfs_extlen_t prod,
2064 xfs_rtblock_t *rtblock)
2065{
2066 xfs_mount_t *mp = tp->t_mountp;
2067 int error;
2068 xfs_rtblock_t r;
2069 xfs_fsblock_t sb;
2070 xfs_buf_t *sumbp;
2071
2072 ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
2073 ASSERT(minlen > 0 && minlen <= maxlen);
2074
2075
2076
2077
2078 if (prod > 1) {
2079 xfs_extlen_t i;
2080
2081 if ((i = maxlen % prod))
2082 maxlen -= i;
2083 if ((i = minlen % prod))
2084 minlen += prod - i;
2085 if (maxlen < minlen) {
2086 *rtblock = NULLRTBLOCK;
2087 return 0;
2088 }
2089 }
2090
2091 sumbp = NULL;
2092
2093
2094
2095 switch (type) {
2096 case XFS_ALLOCTYPE_ANY_AG:
2097 error = xfs_rtallocate_extent_size(mp, tp, minlen, maxlen, len,
2098 &sumbp, &sb, prod, &r);
2099 break;
2100 case XFS_ALLOCTYPE_NEAR_BNO:
2101 error = xfs_rtallocate_extent_near(mp, tp, bno, minlen, maxlen,
2102 len, &sumbp, &sb, prod, &r);
2103 break;
2104 case XFS_ALLOCTYPE_THIS_BNO:
2105 error = xfs_rtallocate_extent_exact(mp, tp, bno, minlen, maxlen,
2106 len, &sumbp, &sb, prod, &r);
2107 break;
2108 default:
2109 error = EIO;
2110 ASSERT(0);
2111 }
2112 if (error)
2113 return error;
2114
2115
2116
2117
2118 if (r != NULLRTBLOCK) {
2119 long slen = (long)*len;
2120
2121 ASSERT(*len >= minlen && *len <= maxlen);
2122 if (wasdel)
2123 xfs_trans_mod_sb(tp, XFS_TRANS_SB_RES_FREXTENTS, -slen);
2124 else
2125 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, -slen);
2126 }
2127 *rtblock = r;
2128 return 0;
2129}
2130
2131
2132
2133
2134
2135int
2136xfs_rtfree_extent(
2137 xfs_trans_t *tp,
2138 xfs_rtblock_t bno,
2139 xfs_extlen_t len)
2140{
2141 int error;
2142 xfs_mount_t *mp;
2143 xfs_fsblock_t sb;
2144 xfs_buf_t *sumbp;
2145
2146 mp = tp->t_mountp;
2147
2148 ASSERT(mp->m_rbmip->i_itemp != NULL);
2149 ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
2150
2151#if defined(__KERNEL__) && defined(DEBUG)
2152
2153
2154
2155 {
2156 int stat;
2157
2158 error = xfs_rtcheck_alloc_range(mp, tp, bno, len, &stat);
2159 if (error) {
2160 return error;
2161 }
2162 ASSERT(stat);
2163 }
2164#endif
2165 sumbp = NULL;
2166
2167
2168
2169 error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
2170 if (error) {
2171 return error;
2172 }
2173
2174
2175
2176 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
2177
2178
2179
2180
2181 if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
2182 mp->m_sb.sb_rextents) {
2183 if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
2184 mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
2185 *(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0;
2186 xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
2187 }
2188 return 0;
2189}
2190
2191
2192
2193
2194int
2195xfs_rtmount_init(
2196 xfs_mount_t *mp)
2197{
2198 xfs_buf_t *bp;
2199 xfs_daddr_t d;
2200 xfs_sb_t *sbp;
2201
2202 sbp = &mp->m_sb;
2203 if (sbp->sb_rblocks == 0)
2204 return 0;
2205 if (mp->m_rtdev_targp == NULL) {
2206 xfs_warn(mp,
2207 "Filesystem has a realtime volume, use rtdev=device option");
2208 return XFS_ERROR(ENODEV);
2209 }
2210 mp->m_rsumlevels = sbp->sb_rextslog + 1;
2211 mp->m_rsumsize =
2212 (uint)sizeof(xfs_suminfo_t) * mp->m_rsumlevels *
2213 sbp->sb_rbmblocks;
2214 mp->m_rsumsize = roundup(mp->m_rsumsize, sbp->sb_blocksize);
2215 mp->m_rbmip = mp->m_rsumip = NULL;
2216
2217
2218
2219 d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
2220 if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_rblocks) {
2221 xfs_warn(mp, "realtime mount -- %llu != %llu",
2222 (unsigned long long) XFS_BB_TO_FSB(mp, d),
2223 (unsigned long long) mp->m_sb.sb_rblocks);
2224 return XFS_ERROR(EFBIG);
2225 }
2226 bp = xfs_buf_read_uncached(mp->m_rtdev_targp,
2227 d - XFS_FSB_TO_BB(mp, 1),
2228 XFS_FSB_TO_BB(mp, 1), 0, NULL);
2229 if (!bp || bp->b_error) {
2230 xfs_warn(mp, "realtime device size check failed");
2231 if (bp)
2232 xfs_buf_relse(bp);
2233 return EIO;
2234 }
2235 xfs_buf_relse(bp);
2236 return 0;
2237}
2238
2239
2240
2241
2242
2243int
2244xfs_rtmount_inodes(
2245 xfs_mount_t *mp)
2246{
2247 int error;
2248 xfs_sb_t *sbp;
2249
2250 sbp = &mp->m_sb;
2251 if (sbp->sb_rbmino == NULLFSINO)
2252 return 0;
2253 error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip);
2254 if (error)
2255 return error;
2256 ASSERT(mp->m_rbmip != NULL);
2257 ASSERT(sbp->sb_rsumino != NULLFSINO);
2258 error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip);
2259 if (error) {
2260 IRELE(mp->m_rbmip);
2261 return error;
2262 }
2263 ASSERT(mp->m_rsumip != NULL);
2264 return 0;
2265}
2266
2267void
2268xfs_rtunmount_inodes(
2269 struct xfs_mount *mp)
2270{
2271 if (mp->m_rbmip)
2272 IRELE(mp->m_rbmip);
2273 if (mp->m_rsumip)
2274 IRELE(mp->m_rsumip);
2275}
2276
2277
2278
2279
2280
2281
2282
2283
2284int
2285xfs_rtpick_extent(
2286 xfs_mount_t *mp,
2287 xfs_trans_t *tp,
2288 xfs_extlen_t len,
2289 xfs_rtblock_t *pick)
2290{
2291 xfs_rtblock_t b;
2292 int log2;
2293 __uint64_t resid;
2294 __uint64_t seq;
2295 __uint64_t *seqp;
2296
2297 ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
2298
2299 seqp = (__uint64_t *)&mp->m_rbmip->i_d.di_atime;
2300 if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) {
2301 mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
2302 *seqp = 0;
2303 }
2304 seq = *seqp;
2305 if ((log2 = xfs_highbit64(seq)) == -1)
2306 b = 0;
2307 else {
2308 resid = seq - (1ULL << log2);
2309 b = (mp->m_sb.sb_rextents * ((resid << 1) + 1ULL)) >>
2310 (log2 + 1);
2311 if (b >= mp->m_sb.sb_rextents)
2312 b = do_mod(b, mp->m_sb.sb_rextents);
2313 if (b + len > mp->m_sb.sb_rextents)
2314 b = mp->m_sb.sb_rextents - len;
2315 }
2316 *seqp = seq + 1;
2317 xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
2318 *pick = b;
2319 return 0;
2320}
2321