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