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);
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 int wasdel,
1097 xfs_extlen_t prod,
1098 xfs_rtblock_t *rtblock)
1099{
1100 xfs_mount_t *mp = tp->t_mountp;
1101 int error;
1102 xfs_rtblock_t r;
1103 xfs_fsblock_t sb;
1104 xfs_buf_t *sumbp;
1105
1106 ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
1107 ASSERT(minlen > 0 && minlen <= maxlen);
1108
1109
1110
1111
1112 if (prod > 1) {
1113 xfs_extlen_t i;
1114
1115 if ((i = maxlen % prod))
1116 maxlen -= i;
1117 if ((i = minlen % prod))
1118 minlen += prod - i;
1119 if (maxlen < minlen) {
1120 *rtblock = NULLRTBLOCK;
1121 return 0;
1122 }
1123 }
1124
1125retry:
1126 sumbp = NULL;
1127 if (bno == 0) {
1128 error = xfs_rtallocate_extent_size(mp, tp, minlen, maxlen, len,
1129 &sumbp, &sb, prod, &r);
1130 } else {
1131 error = xfs_rtallocate_extent_near(mp, tp, bno, minlen, maxlen,
1132 len, &sumbp, &sb, prod, &r);
1133 }
1134
1135 if (error)
1136 return error;
1137
1138
1139
1140
1141 if (r != NULLRTBLOCK) {
1142 long slen = (long)*len;
1143
1144 ASSERT(*len >= minlen && *len <= maxlen);
1145 if (wasdel)
1146 xfs_trans_mod_sb(tp, XFS_TRANS_SB_RES_FREXTENTS, -slen);
1147 else
1148 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, -slen);
1149 } else if (prod > 1) {
1150 prod = 1;
1151 goto retry;
1152 }
1153
1154 *rtblock = r;
1155 return 0;
1156}
1157
1158
1159
1160
1161int
1162xfs_rtmount_init(
1163 struct xfs_mount *mp)
1164{
1165 struct xfs_buf *bp;
1166 struct xfs_sb *sbp;
1167 xfs_daddr_t d;
1168 int error;
1169
1170 sbp = &mp->m_sb;
1171 if (sbp->sb_rblocks == 0)
1172 return 0;
1173 if (mp->m_rtdev_targp == NULL) {
1174 xfs_warn(mp,
1175 "Filesystem has a realtime volume, use rtdev=device option");
1176 return -ENODEV;
1177 }
1178 mp->m_rsumlevels = sbp->sb_rextslog + 1;
1179 mp->m_rsumsize =
1180 (uint)sizeof(xfs_suminfo_t) * mp->m_rsumlevels *
1181 sbp->sb_rbmblocks;
1182 mp->m_rsumsize = roundup(mp->m_rsumsize, sbp->sb_blocksize);
1183 mp->m_rbmip = mp->m_rsumip = NULL;
1184
1185
1186
1187 d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
1188 if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_rblocks) {
1189 xfs_warn(mp, "realtime mount -- %llu != %llu",
1190 (unsigned long long) XFS_BB_TO_FSB(mp, d),
1191 (unsigned long long) mp->m_sb.sb_rblocks);
1192 return -EFBIG;
1193 }
1194 error = xfs_buf_read_uncached(mp->m_rtdev_targp,
1195 d - XFS_FSB_TO_BB(mp, 1),
1196 XFS_FSB_TO_BB(mp, 1), 0, &bp, NULL);
1197 if (error) {
1198 xfs_warn(mp, "realtime device size check failed");
1199 return error;
1200 }
1201 xfs_buf_relse(bp);
1202 return 0;
1203}
1204
1205
1206
1207
1208
1209int
1210xfs_rtmount_inodes(
1211 xfs_mount_t *mp)
1212{
1213 int error;
1214 xfs_sb_t *sbp;
1215
1216 sbp = &mp->m_sb;
1217 if (sbp->sb_rbmino == NULLFSINO)
1218 return 0;
1219 error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip);
1220 if (error)
1221 return error;
1222 ASSERT(mp->m_rbmip != NULL);
1223 ASSERT(sbp->sb_rsumino != NULLFSINO);
1224 error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip);
1225 if (error) {
1226 IRELE(mp->m_rbmip);
1227 return error;
1228 }
1229 ASSERT(mp->m_rsumip != NULL);
1230 return 0;
1231}
1232
1233void
1234xfs_rtunmount_inodes(
1235 struct xfs_mount *mp)
1236{
1237 if (mp->m_rbmip)
1238 IRELE(mp->m_rbmip);
1239 if (mp->m_rsumip)
1240 IRELE(mp->m_rsumip);
1241}
1242
1243
1244
1245
1246
1247
1248
1249
1250int
1251xfs_rtpick_extent(
1252 xfs_mount_t *mp,
1253 xfs_trans_t *tp,
1254 xfs_extlen_t len,
1255 xfs_rtblock_t *pick)
1256{
1257 xfs_rtblock_t b;
1258 int log2;
1259 uint64_t resid;
1260 uint64_t seq;
1261 uint64_t *seqp;
1262
1263 ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
1264
1265 seqp = (uint64_t *)&VFS_I(mp->m_rbmip)->i_atime;
1266 if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) {
1267 mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
1268 *seqp = 0;
1269 }
1270 seq = *seqp;
1271 if ((log2 = xfs_highbit64(seq)) == -1)
1272 b = 0;
1273 else {
1274 resid = seq - (1ULL << log2);
1275 b = (mp->m_sb.sb_rextents * ((resid << 1) + 1ULL)) >>
1276 (log2 + 1);
1277 if (b >= mp->m_sb.sb_rextents)
1278 b = do_mod(b, mp->m_sb.sb_rextents);
1279 if (b + len > mp->m_sb.sb_rextents)
1280 b = mp->m_sb.sb_rextents - len;
1281 }
1282 *seqp = seq + 1;
1283 xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
1284 *pick = b;
1285 return 0;
1286}
1287