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