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_mount.h"
26#include "xfs_defer.h"
27#include "xfs_inode.h"
28#include "xfs_bmap.h"
29#include "xfs_bmap_util.h"
30#include "xfs_bmap_btree.h"
31#include "xfs_alloc.h"
32#include "xfs_error.h"
33#include "xfs_trans.h"
34#include "xfs_trans_space.h"
35#include "xfs_trace.h"
36#include "xfs_buf.h"
37#include "xfs_icache.h"
38#include "xfs_rtalloc.h"
39
40
41
42
43
44
45
46
47static int
48xfs_rtget_summary(
49 xfs_mount_t *mp,
50 xfs_trans_t *tp,
51 int log,
52 xfs_rtblock_t bbno,
53 xfs_buf_t **rbpp,
54 xfs_fsblock_t *rsb,
55 xfs_suminfo_t *sum)
56{
57 return xfs_rtmodify_summary_int(mp, tp, log, bbno, 0, rbpp, rsb, sum);
58}
59
60
61
62
63
64STATIC int
65xfs_rtany_summary(
66 xfs_mount_t *mp,
67 xfs_trans_t *tp,
68 int low,
69 int high,
70 xfs_rtblock_t bbno,
71 xfs_buf_t **rbpp,
72 xfs_fsblock_t *rsb,
73 int *stat)
74{
75 int error;
76 int log;
77 xfs_suminfo_t sum;
78
79
80
81
82 for (log = low; log <= high; log++) {
83
84
85
86 error = xfs_rtget_summary(mp, tp, log, bbno, rbpp, rsb, &sum);
87 if (error) {
88 return error;
89 }
90
91
92
93 if (sum) {
94 *stat = 1;
95 return 0;
96 }
97 }
98
99
100
101 *stat = 0;
102 return 0;
103}
104
105
106
107
108
109
110STATIC int
111xfs_rtcopy_summary(
112 xfs_mount_t *omp,
113 xfs_mount_t *nmp,
114 xfs_trans_t *tp)
115{
116 xfs_rtblock_t bbno;
117 xfs_buf_t *bp;
118 int error;
119 int log;
120 xfs_suminfo_t sum;
121 xfs_fsblock_t sumbno;
122
123 bp = NULL;
124 for (log = omp->m_rsumlevels - 1; log >= 0; log--) {
125 for (bbno = omp->m_sb.sb_rbmblocks - 1;
126 (xfs_srtblock_t)bbno >= 0;
127 bbno--) {
128 error = xfs_rtget_summary(omp, tp, log, bbno, &bp,
129 &sumbno, &sum);
130 if (error)
131 return error;
132 if (sum == 0)
133 continue;
134 error = xfs_rtmodify_summary(omp, tp, log, bbno, -sum,
135 &bp, &sumbno);
136 if (error)
137 return error;
138 error = xfs_rtmodify_summary(nmp, tp, log, bbno, sum,
139 &bp, &sumbno);
140 if (error)
141 return error;
142 ASSERT(sum > 0);
143 }
144 }
145 return 0;
146}
147
148
149
150
151STATIC int
152xfs_rtallocate_range(
153 xfs_mount_t *mp,
154 xfs_trans_t *tp,
155 xfs_rtblock_t start,
156 xfs_extlen_t len,
157 xfs_buf_t **rbpp,
158 xfs_fsblock_t *rsb)
159{
160 xfs_rtblock_t end;
161 int error;
162 xfs_rtblock_t postblock = 0;
163 xfs_rtblock_t preblock = 0;
164
165 end = start + len - 1;
166
167
168
169
170
171 error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
172 if (error) {
173 return error;
174 }
175
176
177
178 error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
179 &postblock);
180 if (error) {
181 return error;
182 }
183
184
185
186
187 error = xfs_rtmodify_summary(mp, tp,
188 XFS_RTBLOCKLOG(postblock + 1 - preblock),
189 XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
190 if (error) {
191 return error;
192 }
193
194
195
196
197 if (preblock < start) {
198 error = xfs_rtmodify_summary(mp, tp,
199 XFS_RTBLOCKLOG(start - preblock),
200 XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
201 if (error) {
202 return error;
203 }
204 }
205
206
207
208
209 if (postblock > end) {
210 error = xfs_rtmodify_summary(mp, tp,
211 XFS_RTBLOCKLOG(postblock - end),
212 XFS_BITTOBLOCK(mp, end + 1), 1, rbpp, rsb);
213 if (error) {
214 return error;
215 }
216 }
217
218
219
220 error = xfs_rtmodify_range(mp, tp, start, len, 0);
221 return error;
222}
223
224
225
226
227
228
229
230STATIC int
231xfs_rtallocate_extent_block(
232 xfs_mount_t *mp,
233 xfs_trans_t *tp,
234 xfs_rtblock_t bbno,
235 xfs_extlen_t minlen,
236 xfs_extlen_t maxlen,
237 xfs_extlen_t *len,
238 xfs_rtblock_t *nextp,
239 xfs_buf_t **rbpp,
240 xfs_fsblock_t *rsb,
241 xfs_extlen_t prod,
242 xfs_rtblock_t *rtblock)
243{
244 xfs_rtblock_t besti;
245 xfs_rtblock_t bestlen;
246 xfs_rtblock_t end;
247 int error;
248 xfs_rtblock_t i;
249 xfs_rtblock_t next;
250 int stat;
251
252
253
254
255
256 for (i = XFS_BLOCKTOBIT(mp, bbno), besti = -1, bestlen = 0,
257 end = XFS_BLOCKTOBIT(mp, bbno + 1) - 1;
258 i <= end;
259 i++) {
260
261
262
263
264 error = xfs_rtcheck_range(mp, tp, i, maxlen, 1, &next, &stat);
265 if (error) {
266 return error;
267 }
268 if (stat) {
269
270
271
272 error = xfs_rtallocate_range(mp, tp, i, maxlen, rbpp,
273 rsb);
274 if (error) {
275 return error;
276 }
277 *len = maxlen;
278 *rtblock = i;
279 return 0;
280 }
281
282
283
284
285
286
287 if (minlen < maxlen) {
288 xfs_rtblock_t thislen;
289
290 thislen = next - i;
291 if (thislen >= minlen && thislen > bestlen) {
292 besti = i;
293 bestlen = thislen;
294 }
295 }
296
297
298
299 if (next < end) {
300 error = xfs_rtfind_forw(mp, tp, next, end, &i);
301 if (error) {
302 return error;
303 }
304 } else
305 break;
306 }
307
308
309
310 if (minlen < maxlen && besti != -1) {
311 xfs_extlen_t p;
312
313
314
315
316 if (prod > 1 && (p = do_mod(bestlen, prod)))
317 bestlen -= p;
318
319
320
321 error = xfs_rtallocate_range(mp, tp, besti, bestlen, rbpp, rsb);
322 if (error) {
323 return error;
324 }
325 *len = bestlen;
326 *rtblock = besti;
327 return 0;
328 }
329
330
331
332 *nextp = next;
333 *rtblock = NULLRTBLOCK;
334 return 0;
335}
336
337
338
339
340
341
342
343STATIC int
344xfs_rtallocate_extent_exact(
345 xfs_mount_t *mp,
346 xfs_trans_t *tp,
347 xfs_rtblock_t bno,
348 xfs_extlen_t minlen,
349 xfs_extlen_t maxlen,
350 xfs_extlen_t *len,
351 xfs_buf_t **rbpp,
352 xfs_fsblock_t *rsb,
353 xfs_extlen_t prod,
354 xfs_rtblock_t *rtblock)
355{
356 int error;
357 xfs_extlen_t i;
358 int isfree;
359 xfs_rtblock_t next;
360
361 ASSERT(minlen % prod == 0 && maxlen % prod == 0);
362
363
364
365 error = xfs_rtcheck_range(mp, tp, bno, maxlen, 1, &next, &isfree);
366 if (error) {
367 return error;
368 }
369 if (isfree) {
370
371
372
373 error = xfs_rtallocate_range(mp, tp, bno, maxlen, rbpp, rsb);
374 if (error) {
375 return error;
376 }
377 *len = maxlen;
378 *rtblock = bno;
379 return 0;
380 }
381
382
383
384 maxlen = next - bno;
385 if (maxlen < minlen) {
386
387
388
389 *rtblock = NULLRTBLOCK;
390 return 0;
391 }
392
393
394
395 if (prod > 1 && (i = maxlen % prod)) {
396 maxlen -= i;
397 if (maxlen < minlen) {
398
399
400
401 *rtblock = NULLRTBLOCK;
402 return 0;
403 }
404 }
405
406
407
408 error = xfs_rtallocate_range(mp, tp, bno, maxlen, rbpp, rsb);
409 if (error) {
410 return error;
411 }
412 *len = maxlen;
413 *rtblock = bno;
414 return 0;
415}
416
417
418
419
420
421
422STATIC int
423xfs_rtallocate_extent_near(
424 xfs_mount_t *mp,
425 xfs_trans_t *tp,
426 xfs_rtblock_t bno,
427 xfs_extlen_t minlen,
428 xfs_extlen_t maxlen,
429 xfs_extlen_t *len,
430 xfs_buf_t **rbpp,
431 xfs_fsblock_t *rsb,
432 xfs_extlen_t prod,
433 xfs_rtblock_t *rtblock)
434{
435 int any;
436 xfs_rtblock_t bbno;
437 int error;
438 int i;
439 int j;
440 int log2len;
441 xfs_rtblock_t n;
442 xfs_rtblock_t r;
443
444 ASSERT(minlen % prod == 0 && maxlen % prod == 0);
445
446
447
448
449 if (bno >= mp->m_sb.sb_rextents)
450 bno = mp->m_sb.sb_rextents - 1;
451
452
453
454 error = xfs_rtallocate_extent_exact(mp, tp, bno, minlen, maxlen, len,
455 rbpp, rsb, prod, &r);
456 if (error) {
457 return error;
458 }
459
460
461
462 if (r != NULLRTBLOCK) {
463 *rtblock = r;
464 return 0;
465 }
466 bbno = XFS_BITTOBLOCK(mp, bno);
467 i = 0;
468 ASSERT(minlen != 0);
469 log2len = xfs_highbit32(minlen);
470
471
472
473 for (;;) {
474
475
476
477
478 error = xfs_rtany_summary(mp, tp, log2len, mp->m_rsumlevels - 1,
479 bbno + i, rbpp, rsb, &any);
480 if (error) {
481 return error;
482 }
483
484
485
486
487 if (any) {
488
489
490
491 if (i >= 0) {
492
493
494
495
496 error = xfs_rtallocate_extent_block(mp, tp,
497 bbno + i, minlen, maxlen, len, &n, rbpp,
498 rsb, prod, &r);
499 if (error) {
500 return error;
501 }
502
503
504
505 if (r != NULLRTBLOCK) {
506 *rtblock = r;
507 return 0;
508 }
509 }
510
511
512
513 else {
514
515
516
517
518
519
520 for (j = -1; j > i; j--) {
521
522
523
524
525 error = xfs_rtany_summary(mp, tp,
526 log2len, mp->m_rsumlevels - 1,
527 bbno + j, rbpp, rsb, &any);
528 if (error) {
529 return error;
530 }
531
532
533
534
535
536
537
538
539 if (any)
540 continue;
541 error = xfs_rtallocate_extent_block(mp,
542 tp, bbno + j, minlen, maxlen,
543 len, &n, rbpp, rsb, prod, &r);
544 if (error) {
545 return error;
546 }
547
548
549
550 if (r != NULLRTBLOCK) {
551 *rtblock = r;
552 return 0;
553 }
554 }
555
556
557
558
559
560
561
562
563 error = xfs_rtallocate_extent_block(mp, tp,
564 bbno + i, minlen, maxlen, len, &n, rbpp,
565 rsb, prod, &r);
566 if (error) {
567 return error;
568 }
569
570
571
572 if (r != NULLRTBLOCK) {
573 *rtblock = r;
574 return 0;
575 }
576 }
577 }
578
579
580
581
582 if (i > 0 && (int)bbno - i >= 0)
583 i = -i;
584
585
586
587
588 else if (i > 0 && (int)bbno + i < mp->m_sb.sb_rbmblocks - 1)
589 i++;
590
591
592
593
594 else if (i <= 0 && (int)bbno - i < mp->m_sb.sb_rbmblocks - 1)
595 i = 1 - i;
596
597
598
599
600 else if (i <= 0 && (int)bbno + i > 0)
601 i--;
602
603
604
605 else
606 break;
607 }
608 *rtblock = NULLRTBLOCK;
609 return 0;
610}
611
612
613
614
615
616
617STATIC int
618xfs_rtallocate_extent_size(
619 xfs_mount_t *mp,
620 xfs_trans_t *tp,
621 xfs_extlen_t minlen,
622 xfs_extlen_t maxlen,
623 xfs_extlen_t *len,
624 xfs_buf_t **rbpp,
625 xfs_fsblock_t *rsb,
626 xfs_extlen_t prod,
627 xfs_rtblock_t *rtblock)
628{
629 int error;
630 int i;
631 int l;
632 xfs_rtblock_t n;
633 xfs_rtblock_t r;
634 xfs_suminfo_t sum;
635
636 ASSERT(minlen % prod == 0 && maxlen % prod == 0);
637 ASSERT(maxlen != 0);
638
639
640
641
642
643
644
645
646 for (l = xfs_highbit32(maxlen); l < mp->m_rsumlevels; l++) {
647
648
649
650 for (i = 0; i < mp->m_sb.sb_rbmblocks; i++) {
651
652
653
654 error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb,
655 &sum);
656 if (error) {
657 return error;
658 }
659
660
661
662 if (!sum)
663 continue;
664
665
666
667 error = xfs_rtallocate_extent_block(mp, tp, i, maxlen,
668 maxlen, len, &n, rbpp, rsb, prod, &r);
669 if (error) {
670 return error;
671 }
672
673
674
675 if (r != NULLRTBLOCK) {
676 *rtblock = r;
677 return 0;
678 }
679
680
681
682
683
684 if (XFS_BITTOBLOCK(mp, n) > i + 1)
685 i = XFS_BITTOBLOCK(mp, n) - 1;
686 }
687 }
688
689
690
691
692 if (minlen > --maxlen) {
693 *rtblock = NULLRTBLOCK;
694 return 0;
695 }
696 ASSERT(minlen != 0);
697 ASSERT(maxlen != 0);
698
699
700
701
702
703
704 for (l = xfs_highbit32(maxlen); l >= xfs_highbit32(minlen); l--) {
705
706
707
708
709 for (i = 0; i < mp->m_sb.sb_rbmblocks; i++) {
710
711
712
713 error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb,
714 &sum);
715 if (error) {
716 return error;
717 }
718
719
720
721 if (!sum)
722 continue;
723
724
725
726
727
728 error = xfs_rtallocate_extent_block(mp, tp, i,
729 XFS_RTMAX(minlen, 1 << l),
730 XFS_RTMIN(maxlen, (1 << (l + 1)) - 1),
731 len, &n, rbpp, rsb, prod, &r);
732 if (error) {
733 return error;
734 }
735
736
737
738 if (r != NULLRTBLOCK) {
739 *rtblock = r;
740 return 0;
741 }
742
743
744
745
746
747 if (XFS_BITTOBLOCK(mp, n) > i + 1)
748 i = XFS_BITTOBLOCK(mp, n) - 1;
749 }
750 }
751
752
753
754 *rtblock = NULLRTBLOCK;
755 return 0;
756}
757
758
759
760
761STATIC int
762xfs_growfs_rt_alloc(
763 struct xfs_mount *mp,
764 xfs_extlen_t oblocks,
765 xfs_extlen_t nblocks,
766 struct xfs_inode *ip)
767{
768 xfs_fileoff_t bno;
769 struct xfs_buf *bp;
770 xfs_daddr_t d;
771 int error;
772 xfs_fsblock_t firstblock;
773 struct xfs_defer_ops dfops;
774 xfs_fsblock_t fsbno;
775 struct xfs_bmbt_irec map;
776 int nmap;
777 int resblks;
778 struct xfs_trans *tp;
779
780
781
782
783 while (oblocks < nblocks) {
784 resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks);
785
786
787
788 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtalloc, resblks,
789 0, 0, &tp);
790 if (error)
791 return error;
792
793
794
795 xfs_ilock(ip, XFS_ILOCK_EXCL);
796 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
797
798 xfs_defer_init(&dfops, &firstblock);
799
800
801
802 nmap = 1;
803 error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks,
804 XFS_BMAPI_METADATA, &firstblock,
805 resblks, &map, &nmap, &dfops);
806 if (!error && nmap < 1)
807 error = -ENOSPC;
808 if (error)
809 goto out_bmap_cancel;
810
811
812
813 error = xfs_defer_finish(&tp, &dfops, NULL);
814 if (error)
815 goto out_bmap_cancel;
816 error = xfs_trans_commit(tp);
817 if (error)
818 return error;
819
820
821
822
823 for (bno = map.br_startoff, fsbno = map.br_startblock;
824 bno < map.br_startoff + map.br_blockcount;
825 bno++, fsbno++) {
826
827
828
829 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtzero,
830 0, 0, 0, &tp);
831 if (error)
832 return error;
833
834
835
836 xfs_ilock(ip, XFS_ILOCK_EXCL);
837 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
838
839
840
841 d = XFS_FSB_TO_DADDR(mp, fsbno);
842 bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
843 mp->m_bsize, 0);
844 if (bp == NULL) {
845 error = -EIO;
846 goto out_trans_cancel;
847 }
848 memset(bp->b_addr, 0, mp->m_sb.sb_blocksize);
849 xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
850
851
852
853 error = xfs_trans_commit(tp);
854 if (error)
855 return error;
856 }
857
858
859
860 oblocks = map.br_startoff + map.br_blockcount;
861 }
862
863 return 0;
864
865out_bmap_cancel:
866 xfs_defer_cancel(&dfops);
867out_trans_cancel:
868 xfs_trans_cancel(tp);
869 return error;
870}
871
872
873
874
875
876
877
878
879int
880xfs_growfs_rt(
881 xfs_mount_t *mp,
882 xfs_growfs_rt_t *in)
883{
884 xfs_rtblock_t bmbno;
885 xfs_buf_t *bp;
886 int error;
887 xfs_mount_t *nmp;
888 xfs_rfsblock_t nrblocks;
889 xfs_extlen_t nrbmblocks;
890 xfs_rtblock_t nrextents;
891 uint8_t nrextslog;
892 xfs_extlen_t nrsumblocks;
893 uint nrsumlevels;
894 uint nrsumsize;
895 xfs_sb_t *nsbp;
896 xfs_extlen_t rbmblocks;
897 xfs_extlen_t rsumblocks;
898 xfs_sb_t *sbp;
899 xfs_fsblock_t sumbno;
900
901 sbp = &mp->m_sb;
902
903
904
905 if (!capable(CAP_SYS_ADMIN))
906 return -EPERM;
907 if (mp->m_rtdev_targp == NULL || mp->m_rbmip == NULL ||
908 (nrblocks = in->newblocks) <= sbp->sb_rblocks ||
909 (sbp->sb_rblocks && (in->extsize != sbp->sb_rextsize)))
910 return -EINVAL;
911 if ((error = xfs_sb_validate_fsb_count(sbp, nrblocks)))
912 return error;
913
914
915
916 error = xfs_buf_read_uncached(mp->m_rtdev_targp,
917 XFS_FSB_TO_BB(mp, nrblocks - 1),
918 XFS_FSB_TO_BB(mp, 1), 0, &bp, NULL);
919 if (error)
920 return error;
921 xfs_buf_relse(bp);
922
923
924
925
926 nrextents = nrblocks;
927 do_div(nrextents, in->extsize);
928 nrbmblocks = howmany_64(nrextents, NBBY * sbp->sb_blocksize);
929 nrextslog = xfs_highbit32(nrextents);
930 nrsumlevels = nrextslog + 1;
931 nrsumsize = (uint)sizeof(xfs_suminfo_t) * nrsumlevels * nrbmblocks;
932 nrsumblocks = XFS_B_TO_FSB(mp, nrsumsize);
933 nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
934
935
936
937
938
939 if (nrsumblocks > (mp->m_sb.sb_logblocks >> 1))
940 return -EINVAL;
941
942
943
944
945 rbmblocks = XFS_B_TO_FSB(mp, mp->m_rbmip->i_d.di_size);
946 rsumblocks = XFS_B_TO_FSB(mp, mp->m_rsumip->i_d.di_size);
947
948
949
950 error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks, mp->m_rbmip);
951 if (error)
952 return error;
953 error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, mp->m_rsumip);
954 if (error)
955 return error;
956
957
958
959 nmp = kmem_alloc(sizeof(*nmp), KM_SLEEP);
960
961
962
963
964
965
966 for (bmbno = sbp->sb_rbmblocks -
967 ((sbp->sb_rextents & ((1 << mp->m_blkbit_log) - 1)) != 0);
968 bmbno < nrbmblocks;
969 bmbno++) {
970 xfs_trans_t *tp;
971
972 *nmp = *mp;
973 nsbp = &nmp->m_sb;
974
975
976
977 nsbp->sb_rextsize = in->extsize;
978 nsbp->sb_rbmblocks = bmbno + 1;
979 nsbp->sb_rblocks =
980 XFS_RTMIN(nrblocks,
981 nsbp->sb_rbmblocks * NBBY *
982 nsbp->sb_blocksize * nsbp->sb_rextsize);
983 nsbp->sb_rextents = nsbp->sb_rblocks;
984 do_div(nsbp->sb_rextents, nsbp->sb_rextsize);
985 ASSERT(nsbp->sb_rextents != 0);
986 nsbp->sb_rextslog = xfs_highbit32(nsbp->sb_rextents);
987 nrsumlevels = nmp->m_rsumlevels = nsbp->sb_rextslog + 1;
988 nrsumsize =
989 (uint)sizeof(xfs_suminfo_t) * nrsumlevels *
990 nsbp->sb_rbmblocks;
991 nrsumblocks = XFS_B_TO_FSB(mp, nrsumsize);
992 nmp->m_rsumsize = nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
993
994
995
996 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtfree, 0, 0, 0,
997 &tp);
998 if (error)
999 break;
1000
1001
1002
1003 xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
1004 xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
1005
1006
1007
1008 mp->m_rbmip->i_d.di_size =
1009 nsbp->sb_rbmblocks * nsbp->sb_blocksize;
1010 xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
1011
1012
1013
1014 xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL);
1015 xfs_trans_ijoin(tp, mp->m_rsumip, XFS_ILOCK_EXCL);
1016
1017
1018
1019 mp->m_rsumip->i_d.di_size = nmp->m_rsumsize;
1020 xfs_trans_log_inode(tp, mp->m_rsumip, XFS_ILOG_CORE);
1021
1022
1023
1024
1025 if (sbp->sb_rbmblocks != nsbp->sb_rbmblocks ||
1026 mp->m_rsumlevels != nmp->m_rsumlevels) {
1027 error = xfs_rtcopy_summary(mp, nmp, tp);
1028 if (error)
1029 goto error_cancel;
1030 }
1031
1032
1033
1034 if (nsbp->sb_rextsize != sbp->sb_rextsize)
1035 xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSIZE,
1036 nsbp->sb_rextsize - sbp->sb_rextsize);
1037 if (nsbp->sb_rbmblocks != sbp->sb_rbmblocks)
1038 xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBMBLOCKS,
1039 nsbp->sb_rbmblocks - sbp->sb_rbmblocks);
1040 if (nsbp->sb_rblocks != sbp->sb_rblocks)
1041 xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBLOCKS,
1042 nsbp->sb_rblocks - sbp->sb_rblocks);
1043 if (nsbp->sb_rextents != sbp->sb_rextents)
1044 xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTENTS,
1045 nsbp->sb_rextents - sbp->sb_rextents);
1046 if (nsbp->sb_rextslog != sbp->sb_rextslog)
1047 xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSLOG,
1048 nsbp->sb_rextslog - sbp->sb_rextslog);
1049
1050
1051
1052 bp = NULL;
1053 error = xfs_rtfree_range(nmp, tp, sbp->sb_rextents,
1054 nsbp->sb_rextents - sbp->sb_rextents, &bp, &sumbno);
1055 if (error) {
1056error_cancel:
1057 xfs_trans_cancel(tp);
1058 break;
1059 }
1060
1061
1062
1063 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS,
1064 nsbp->sb_rextents - sbp->sb_rextents);
1065
1066
1067
1068 mp->m_rsumlevels = nrsumlevels;
1069 mp->m_rsumsize = nrsumsize;
1070
1071 error = xfs_trans_commit(tp);
1072 if (error)
1073 break;
1074 }
1075
1076
1077
1078
1079 kmem_free(nmp);
1080
1081 return error;
1082}
1083
1084
1085
1086
1087
1088
1089int
1090xfs_rtallocate_extent(
1091 xfs_trans_t *tp,
1092 xfs_rtblock_t bno,
1093 xfs_extlen_t minlen,
1094 xfs_extlen_t maxlen,
1095 xfs_extlen_t *len,
1096 xfs_alloctype_t type,
1097 int wasdel,
1098 xfs_extlen_t prod,
1099 xfs_rtblock_t *rtblock)
1100{
1101 xfs_mount_t *mp = tp->t_mountp;
1102 int error;
1103 xfs_rtblock_t r;
1104 xfs_fsblock_t sb;
1105 xfs_buf_t *sumbp;
1106
1107 ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
1108 ASSERT(minlen > 0 && minlen <= maxlen);
1109
1110
1111
1112
1113 if (prod > 1) {
1114 xfs_extlen_t i;
1115
1116 if ((i = maxlen % prod))
1117 maxlen -= i;
1118 if ((i = minlen % prod))
1119 minlen += prod - i;
1120 if (maxlen < minlen) {
1121 *rtblock = NULLRTBLOCK;
1122 return 0;
1123 }
1124 }
1125
1126 sumbp = NULL;
1127
1128
1129
1130 switch (type) {
1131 case XFS_ALLOCTYPE_ANY_AG:
1132 error = xfs_rtallocate_extent_size(mp, tp, minlen, maxlen, len,
1133 &sumbp, &sb, prod, &r);
1134 break;
1135 case XFS_ALLOCTYPE_NEAR_BNO:
1136 error = xfs_rtallocate_extent_near(mp, tp, bno, minlen, maxlen,
1137 len, &sumbp, &sb, prod, &r);
1138 break;
1139 case XFS_ALLOCTYPE_THIS_BNO:
1140 error = xfs_rtallocate_extent_exact(mp, tp, bno, minlen, maxlen,
1141 len, &sumbp, &sb, prod, &r);
1142 break;
1143 default:
1144 error = -EIO;
1145 ASSERT(0);
1146 }
1147 if (error)
1148 return error;
1149
1150
1151
1152
1153 if (r != NULLRTBLOCK) {
1154 long slen = (long)*len;
1155
1156 ASSERT(*len >= minlen && *len <= maxlen);
1157 if (wasdel)
1158 xfs_trans_mod_sb(tp, XFS_TRANS_SB_RES_FREXTENTS, -slen);
1159 else
1160 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, -slen);
1161 }
1162 *rtblock = r;
1163 return 0;
1164}
1165
1166
1167
1168
1169int
1170xfs_rtmount_init(
1171 struct xfs_mount *mp)
1172{
1173 struct xfs_buf *bp;
1174 struct xfs_sb *sbp;
1175 xfs_daddr_t d;
1176 int error;
1177
1178 sbp = &mp->m_sb;
1179 if (sbp->sb_rblocks == 0)
1180 return 0;
1181 if (mp->m_rtdev_targp == NULL) {
1182 xfs_warn(mp,
1183 "Filesystem has a realtime volume, use rtdev=device option");
1184 return -ENODEV;
1185 }
1186 mp->m_rsumlevels = sbp->sb_rextslog + 1;
1187 mp->m_rsumsize =
1188 (uint)sizeof(xfs_suminfo_t) * mp->m_rsumlevels *
1189 sbp->sb_rbmblocks;
1190 mp->m_rsumsize = roundup(mp->m_rsumsize, sbp->sb_blocksize);
1191 mp->m_rbmip = mp->m_rsumip = NULL;
1192
1193
1194
1195 d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
1196 if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_rblocks) {
1197 xfs_warn(mp, "realtime mount -- %llu != %llu",
1198 (unsigned long long) XFS_BB_TO_FSB(mp, d),
1199 (unsigned long long) mp->m_sb.sb_rblocks);
1200 return -EFBIG;
1201 }
1202 error = xfs_buf_read_uncached(mp->m_rtdev_targp,
1203 d - XFS_FSB_TO_BB(mp, 1),
1204 XFS_FSB_TO_BB(mp, 1), 0, &bp, NULL);
1205 if (error) {
1206 xfs_warn(mp, "realtime device size check failed");
1207 return error;
1208 }
1209 xfs_buf_relse(bp);
1210 return 0;
1211}
1212
1213
1214
1215
1216
1217int
1218xfs_rtmount_inodes(
1219 xfs_mount_t *mp)
1220{
1221 int error;
1222 xfs_sb_t *sbp;
1223
1224 sbp = &mp->m_sb;
1225 if (sbp->sb_rbmino == NULLFSINO)
1226 return 0;
1227 error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip);
1228 if (error)
1229 return error;
1230 ASSERT(mp->m_rbmip != NULL);
1231 ASSERT(sbp->sb_rsumino != NULLFSINO);
1232 error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip);
1233 if (error) {
1234 IRELE(mp->m_rbmip);
1235 return error;
1236 }
1237 ASSERT(mp->m_rsumip != NULL);
1238 return 0;
1239}
1240
1241void
1242xfs_rtunmount_inodes(
1243 struct xfs_mount *mp)
1244{
1245 if (mp->m_rbmip)
1246 IRELE(mp->m_rbmip);
1247 if (mp->m_rsumip)
1248 IRELE(mp->m_rsumip);
1249}
1250
1251
1252
1253
1254
1255
1256
1257
1258int
1259xfs_rtpick_extent(
1260 xfs_mount_t *mp,
1261 xfs_trans_t *tp,
1262 xfs_extlen_t len,
1263 xfs_rtblock_t *pick)
1264{
1265 xfs_rtblock_t b;
1266 int log2;
1267 __uint64_t resid;
1268 __uint64_t seq;
1269 __uint64_t *seqp;
1270
1271 ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
1272
1273 seqp = (__uint64_t *)&VFS_I(mp->m_rbmip)->i_atime;
1274 if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) {
1275 mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
1276 *seqp = 0;
1277 }
1278 seq = *seqp;
1279 if ((log2 = xfs_highbit64(seq)) == -1)
1280 b = 0;
1281 else {
1282 resid = seq - (1ULL << log2);
1283 b = (mp->m_sb.sb_rextents * ((resid << 1) + 1ULL)) >>
1284 (log2 + 1);
1285 if (b >= mp->m_sb.sb_rextents)
1286 b = do_mod(b, mp->m_sb.sb_rextents);
1287 if (b + len > mp->m_sb.sb_rextents)
1288 b = mp->m_sb.sb_rextents - len;
1289 }
1290 *seqp = seq + 1;
1291 xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
1292 *pick = b;
1293 return 0;
1294}
1295