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 xfs_mount_t *mp,
763 xfs_extlen_t oblocks,
764 xfs_extlen_t nblocks,
765 xfs_inode_t *ip)
766{
767 xfs_fileoff_t bno;
768 xfs_buf_t *bp;
769 int committed;
770 xfs_daddr_t d;
771 int error;
772 xfs_fsblock_t firstblock;
773 xfs_bmap_free_t flist;
774 xfs_fsblock_t fsbno;
775 xfs_bmbt_irec_t map;
776 int nmap;
777 int resblks;
778
779
780
781
782 while (oblocks < nblocks) {
783 int cancelflags = 0;
784 xfs_trans_t *tp;
785
786 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ALLOC);
787 resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks);
788
789
790
791 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtalloc,
792 resblks, 0);
793 if (error)
794 goto error_cancel;
795 cancelflags = XFS_TRANS_RELEASE_LOG_RES;
796
797
798
799 xfs_ilock(ip, XFS_ILOCK_EXCL);
800 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
801
802 xfs_bmap_init(&flist, &firstblock);
803
804
805
806 nmap = 1;
807 cancelflags |= XFS_TRANS_ABORT;
808 error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks,
809 XFS_BMAPI_METADATA, &firstblock,
810 resblks, &map, &nmap, &flist);
811 if (!error && nmap < 1)
812 error = -ENOSPC;
813 if (error)
814 goto error_cancel;
815
816
817
818 error = xfs_bmap_finish(&tp, &flist, &committed);
819 if (error)
820 goto error_cancel;
821 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
822 if (error)
823 goto error;
824
825
826
827
828 cancelflags = 0;
829 for (bno = map.br_startoff, fsbno = map.br_startblock;
830 bno < map.br_startoff + map.br_blockcount;
831 bno++, fsbno++) {
832 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ZERO);
833
834
835
836 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtzero,
837 0, 0);
838 if (error)
839 goto error_cancel;
840
841
842
843 xfs_ilock(ip, XFS_ILOCK_EXCL);
844 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
845
846
847
848 d = XFS_FSB_TO_DADDR(mp, fsbno);
849 bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
850 mp->m_bsize, 0);
851 if (bp == NULL) {
852 error = -EIO;
853error_cancel:
854 xfs_trans_cancel(tp, cancelflags);
855 goto error;
856 }
857 memset(bp->b_addr, 0, mp->m_sb.sb_blocksize);
858 xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
859
860
861
862 error = xfs_trans_commit(tp, 0);
863 if (error)
864 goto error;
865 }
866
867
868
869 oblocks = map.br_startoff + map.br_blockcount;
870 }
871 return 0;
872
873error:
874 return error;
875}
876
877
878
879
880
881
882
883
884int
885xfs_growfs_rt(
886 xfs_mount_t *mp,
887 xfs_growfs_rt_t *in)
888{
889 xfs_rtblock_t bmbno;
890 xfs_buf_t *bp;
891 int error;
892 xfs_mount_t *nmp;
893 xfs_rfsblock_t nrblocks;
894 xfs_extlen_t nrbmblocks;
895 xfs_rtblock_t nrextents;
896 uint8_t nrextslog;
897 xfs_extlen_t nrsumblocks;
898 uint nrsumlevels;
899 uint nrsumsize;
900 xfs_sb_t *nsbp;
901 xfs_extlen_t rbmblocks;
902 xfs_extlen_t rsumblocks;
903 xfs_sb_t *sbp;
904 xfs_fsblock_t sumbno;
905
906 sbp = &mp->m_sb;
907
908
909
910 if (!capable(CAP_SYS_ADMIN))
911 return -EPERM;
912 if (mp->m_rtdev_targp == NULL || mp->m_rbmip == NULL ||
913 (nrblocks = in->newblocks) <= sbp->sb_rblocks ||
914 (sbp->sb_rblocks && (in->extsize != sbp->sb_rextsize)))
915 return -EINVAL;
916 if ((error = xfs_sb_validate_fsb_count(sbp, nrblocks)))
917 return error;
918
919
920
921 error = xfs_buf_read_uncached(mp->m_rtdev_targp,
922 XFS_FSB_TO_BB(mp, nrblocks - 1),
923 XFS_FSB_TO_BB(mp, 1), 0, &bp, NULL);
924 if (error)
925 return error;
926 xfs_buf_relse(bp);
927
928
929
930
931 nrextents = nrblocks;
932 do_div(nrextents, in->extsize);
933 nrbmblocks = howmany_64(nrextents, NBBY * sbp->sb_blocksize);
934 nrextslog = xfs_highbit32(nrextents);
935 nrsumlevels = nrextslog + 1;
936 nrsumsize = (uint)sizeof(xfs_suminfo_t) * nrsumlevels * nrbmblocks;
937 nrsumblocks = XFS_B_TO_FSB(mp, nrsumsize);
938 nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
939
940
941
942
943
944 if (nrsumblocks > (mp->m_sb.sb_logblocks >> 1))
945 return -EINVAL;
946
947
948
949
950 rbmblocks = XFS_B_TO_FSB(mp, mp->m_rbmip->i_d.di_size);
951 rsumblocks = XFS_B_TO_FSB(mp, mp->m_rsumip->i_d.di_size);
952
953
954
955 error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks, mp->m_rbmip);
956 if (error)
957 return error;
958 error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, mp->m_rsumip);
959 if (error)
960 return error;
961
962
963
964 nmp = kmem_alloc(sizeof(*nmp), KM_SLEEP);
965
966
967
968
969
970
971 for (bmbno = sbp->sb_rbmblocks -
972 ((sbp->sb_rextents & ((1 << mp->m_blkbit_log) - 1)) != 0);
973 bmbno < nrbmblocks;
974 bmbno++) {
975 xfs_trans_t *tp;
976 int cancelflags = 0;
977
978 *nmp = *mp;
979 nsbp = &nmp->m_sb;
980
981
982
983 nsbp->sb_rextsize = in->extsize;
984 nsbp->sb_rbmblocks = bmbno + 1;
985 nsbp->sb_rblocks =
986 XFS_RTMIN(nrblocks,
987 nsbp->sb_rbmblocks * NBBY *
988 nsbp->sb_blocksize * nsbp->sb_rextsize);
989 nsbp->sb_rextents = nsbp->sb_rblocks;
990 do_div(nsbp->sb_rextents, nsbp->sb_rextsize);
991 ASSERT(nsbp->sb_rextents != 0);
992 nsbp->sb_rextslog = xfs_highbit32(nsbp->sb_rextents);
993 nrsumlevels = nmp->m_rsumlevels = nsbp->sb_rextslog + 1;
994 nrsumsize =
995 (uint)sizeof(xfs_suminfo_t) * nrsumlevels *
996 nsbp->sb_rbmblocks;
997 nrsumblocks = XFS_B_TO_FSB(mp, nrsumsize);
998 nmp->m_rsumsize = nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
999
1000
1001
1002 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_FREE);
1003 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtfree,
1004 0, 0);
1005 if (error)
1006 goto error_cancel;
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 cancelflags |= XFS_TRANS_ABORT;
1019
1020
1021
1022 xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL);
1023 xfs_trans_ijoin(tp, mp->m_rsumip, XFS_ILOCK_EXCL);
1024
1025
1026
1027 mp->m_rsumip->i_d.di_size = nmp->m_rsumsize;
1028 xfs_trans_log_inode(tp, mp->m_rsumip, XFS_ILOG_CORE);
1029
1030
1031
1032
1033 if (sbp->sb_rbmblocks != nsbp->sb_rbmblocks ||
1034 mp->m_rsumlevels != nmp->m_rsumlevels) {
1035 error = xfs_rtcopy_summary(mp, nmp, tp);
1036 if (error)
1037 goto error_cancel;
1038 }
1039
1040
1041
1042 if (nsbp->sb_rextsize != sbp->sb_rextsize)
1043 xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSIZE,
1044 nsbp->sb_rextsize - sbp->sb_rextsize);
1045 if (nsbp->sb_rbmblocks != sbp->sb_rbmblocks)
1046 xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBMBLOCKS,
1047 nsbp->sb_rbmblocks - sbp->sb_rbmblocks);
1048 if (nsbp->sb_rblocks != sbp->sb_rblocks)
1049 xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBLOCKS,
1050 nsbp->sb_rblocks - sbp->sb_rblocks);
1051 if (nsbp->sb_rextents != sbp->sb_rextents)
1052 xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTENTS,
1053 nsbp->sb_rextents - sbp->sb_rextents);
1054 if (nsbp->sb_rextslog != sbp->sb_rextslog)
1055 xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSLOG,
1056 nsbp->sb_rextslog - sbp->sb_rextslog);
1057
1058
1059
1060 bp = NULL;
1061 error = xfs_rtfree_range(nmp, tp, sbp->sb_rextents,
1062 nsbp->sb_rextents - sbp->sb_rextents, &bp, &sumbno);
1063 if (error) {
1064error_cancel:
1065 xfs_trans_cancel(tp, cancelflags);
1066 break;
1067 }
1068
1069
1070
1071 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS,
1072 nsbp->sb_rextents - sbp->sb_rextents);
1073
1074
1075
1076 mp->m_rsumlevels = nrsumlevels;
1077 mp->m_rsumsize = nrsumsize;
1078
1079 error = xfs_trans_commit(tp, 0);
1080 if (error)
1081 break;
1082 }
1083
1084
1085
1086
1087 kmem_free(nmp);
1088
1089 return error;
1090}
1091
1092
1093
1094
1095
1096
1097int
1098xfs_rtallocate_extent(
1099 xfs_trans_t *tp,
1100 xfs_rtblock_t bno,
1101 xfs_extlen_t minlen,
1102 xfs_extlen_t maxlen,
1103 xfs_extlen_t *len,
1104 xfs_alloctype_t type,
1105 int wasdel,
1106 xfs_extlen_t prod,
1107 xfs_rtblock_t *rtblock)
1108{
1109 xfs_mount_t *mp = tp->t_mountp;
1110 int error;
1111 xfs_rtblock_t r;
1112 xfs_fsblock_t sb;
1113 xfs_buf_t *sumbp;
1114
1115 ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
1116 ASSERT(minlen > 0 && minlen <= maxlen);
1117
1118
1119
1120
1121 if (prod > 1) {
1122 xfs_extlen_t i;
1123
1124 if ((i = maxlen % prod))
1125 maxlen -= i;
1126 if ((i = minlen % prod))
1127 minlen += prod - i;
1128 if (maxlen < minlen) {
1129 *rtblock = NULLRTBLOCK;
1130 return 0;
1131 }
1132 }
1133
1134 sumbp = NULL;
1135
1136
1137
1138 switch (type) {
1139 case XFS_ALLOCTYPE_ANY_AG:
1140 error = xfs_rtallocate_extent_size(mp, tp, minlen, maxlen, len,
1141 &sumbp, &sb, prod, &r);
1142 break;
1143 case XFS_ALLOCTYPE_NEAR_BNO:
1144 error = xfs_rtallocate_extent_near(mp, tp, bno, minlen, maxlen,
1145 len, &sumbp, &sb, prod, &r);
1146 break;
1147 case XFS_ALLOCTYPE_THIS_BNO:
1148 error = xfs_rtallocate_extent_exact(mp, tp, bno, minlen, maxlen,
1149 len, &sumbp, &sb, prod, &r);
1150 break;
1151 default:
1152 error = -EIO;
1153 ASSERT(0);
1154 }
1155 if (error)
1156 return error;
1157
1158
1159
1160
1161 if (r != NULLRTBLOCK) {
1162 long slen = (long)*len;
1163
1164 ASSERT(*len >= minlen && *len <= maxlen);
1165 if (wasdel)
1166 xfs_trans_mod_sb(tp, XFS_TRANS_SB_RES_FREXTENTS, -slen);
1167 else
1168 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, -slen);
1169 }
1170 *rtblock = r;
1171 return 0;
1172}
1173
1174
1175
1176
1177int
1178xfs_rtmount_init(
1179 struct xfs_mount *mp)
1180{
1181 struct xfs_buf *bp;
1182 struct xfs_sb *sbp;
1183 xfs_daddr_t d;
1184 int error;
1185
1186 sbp = &mp->m_sb;
1187 if (sbp->sb_rblocks == 0)
1188 return 0;
1189 if (mp->m_rtdev_targp == NULL) {
1190 xfs_warn(mp,
1191 "Filesystem has a realtime volume, use rtdev=device option");
1192 return -ENODEV;
1193 }
1194 mp->m_rsumlevels = sbp->sb_rextslog + 1;
1195 mp->m_rsumsize =
1196 (uint)sizeof(xfs_suminfo_t) * mp->m_rsumlevels *
1197 sbp->sb_rbmblocks;
1198 mp->m_rsumsize = roundup(mp->m_rsumsize, sbp->sb_blocksize);
1199 mp->m_rbmip = mp->m_rsumip = NULL;
1200
1201
1202
1203 d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
1204 if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_rblocks) {
1205 xfs_warn(mp, "realtime mount -- %llu != %llu",
1206 (unsigned long long) XFS_BB_TO_FSB(mp, d),
1207 (unsigned long long) mp->m_sb.sb_rblocks);
1208 return -EFBIG;
1209 }
1210 error = xfs_buf_read_uncached(mp->m_rtdev_targp,
1211 d - XFS_FSB_TO_BB(mp, 1),
1212 XFS_FSB_TO_BB(mp, 1), 0, &bp, NULL);
1213 if (error) {
1214 xfs_warn(mp, "realtime device size check failed");
1215 return error;
1216 }
1217 xfs_buf_relse(bp);
1218 return 0;
1219}
1220
1221
1222
1223
1224
1225int
1226xfs_rtmount_inodes(
1227 xfs_mount_t *mp)
1228{
1229 int error;
1230 xfs_sb_t *sbp;
1231
1232 sbp = &mp->m_sb;
1233 if (sbp->sb_rbmino == NULLFSINO)
1234 return 0;
1235 error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip);
1236 if (error)
1237 return error;
1238 ASSERT(mp->m_rbmip != NULL);
1239 ASSERT(sbp->sb_rsumino != NULLFSINO);
1240 error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip);
1241 if (error) {
1242 IRELE(mp->m_rbmip);
1243 return error;
1244 }
1245 ASSERT(mp->m_rsumip != NULL);
1246 return 0;
1247}
1248
1249void
1250xfs_rtunmount_inodes(
1251 struct xfs_mount *mp)
1252{
1253 if (mp->m_rbmip)
1254 IRELE(mp->m_rbmip);
1255 if (mp->m_rsumip)
1256 IRELE(mp->m_rsumip);
1257}
1258
1259
1260
1261
1262
1263
1264
1265
1266int
1267xfs_rtpick_extent(
1268 xfs_mount_t *mp,
1269 xfs_trans_t *tp,
1270 xfs_extlen_t len,
1271 xfs_rtblock_t *pick)
1272{
1273 xfs_rtblock_t b;
1274 int log2;
1275 __uint64_t resid;
1276 __uint64_t seq;
1277 __uint64_t *seqp;
1278
1279 ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
1280
1281 seqp = (__uint64_t *)&mp->m_rbmip->i_d.di_atime;
1282 if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) {
1283 mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
1284 *seqp = 0;
1285 }
1286 seq = *seqp;
1287 if ((log2 = xfs_highbit64(seq)) == -1)
1288 b = 0;
1289 else {
1290 resid = seq - (1ULL << log2);
1291 b = (mp->m_sb.sb_rextents * ((resid << 1) + 1ULL)) >>
1292 (log2 + 1);
1293 if (b >= mp->m_sb.sb_rextents)
1294 b = do_mod(b, mp->m_sb.sb_rextents);
1295 if (b + len > mp->m_sb.sb_rextents)
1296 b = mp->m_sb.sb_rextents - len;
1297 }
1298 *seqp = seq + 1;
1299 xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
1300 *pick = b;
1301 return 0;
1302}
1303