1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#include "xfs.h"
38#include "xfs_macros.h"
39#include "xfs_types.h"
40#include "xfs_inum.h"
41#include "xfs_log.h"
42#include "xfs_trans.h"
43#include "xfs_sb.h"
44#include "xfs_ag.h"
45#include "xfs_dir.h"
46#include "xfs_dir2.h"
47#include "xfs_dmapi.h"
48#include "xfs_mount.h"
49#include "xfs_alloc_btree.h"
50#include "xfs_bmap_btree.h"
51#include "xfs_ialloc_btree.h"
52#include "xfs_btree.h"
53#include "xfs_ialloc.h"
54#include "xfs_attr_sf.h"
55#include "xfs_dir_sf.h"
56#include "xfs_dir2_sf.h"
57#include "xfs_dinode.h"
58#include "xfs_inode.h"
59#include "xfs_alloc.h"
60#include "xfs_bmap.h"
61#include "xfs_bit.h"
62#include "xfs_rtalloc.h"
63#include "xfs_fsops.h"
64#include "xfs_error.h"
65#include "xfs_rw.h"
66#include "xfs_inode_item.h"
67#include "xfs_trans_space.h"
68
69
70
71
72
73
74
75STATIC int xfs_rtallocate_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
76 xfs_extlen_t, xfs_buf_t **, xfs_fsblock_t *);
77STATIC int xfs_rtany_summary(xfs_mount_t *, xfs_trans_t *, int, int,
78 xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, int *);
79STATIC int xfs_rtcheck_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
80 xfs_extlen_t, int, xfs_rtblock_t *, int *);
81STATIC int xfs_rtfind_back(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
82 xfs_rtblock_t, xfs_rtblock_t *);
83STATIC int xfs_rtfind_forw(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
84 xfs_rtblock_t, xfs_rtblock_t *);
85STATIC int xfs_rtget_summary( xfs_mount_t *, xfs_trans_t *, int,
86 xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, xfs_suminfo_t *);
87STATIC int xfs_rtmodify_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
88 xfs_extlen_t, int);
89STATIC int xfs_rtmodify_summary(xfs_mount_t *, xfs_trans_t *, int,
90 xfs_rtblock_t, int, xfs_buf_t **, xfs_fsblock_t *);
91
92
93
94
95
96
97
98
99STATIC int
100xfs_lowbit32(
101 __uint32_t v)
102{
103 if (v)
104 return ffs(v) - 1;
105 return -1;
106}
107
108
109
110
111STATIC int
112xfs_growfs_rt_alloc(
113 xfs_mount_t *mp,
114 xfs_extlen_t oblocks,
115 xfs_extlen_t nblocks,
116 xfs_ino_t ino)
117{
118 xfs_fileoff_t bno;
119 xfs_buf_t *bp;
120 int cancelflags;
121 int committed;
122 xfs_daddr_t d;
123 int error;
124 xfs_fsblock_t firstblock;
125 xfs_bmap_free_t flist;
126 xfs_fsblock_t fsbno;
127 xfs_inode_t *ip;
128 xfs_bmbt_irec_t map;
129 int nmap;
130 int resblks;
131 xfs_trans_t *tp;
132
133
134
135
136 while (oblocks < nblocks) {
137 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ALLOC);
138 resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks);
139 cancelflags = 0;
140
141
142
143 if ((error = xfs_trans_reserve(tp, resblks,
144 XFS_GROWRTALLOC_LOG_RES(mp), 0,
145 XFS_TRANS_PERM_LOG_RES,
146 XFS_DEFAULT_PERM_LOG_COUNT)))
147 goto error_exit;
148 cancelflags = XFS_TRANS_RELEASE_LOG_RES;
149
150
151
152 if ((error = xfs_trans_iget(mp, tp, ino, 0, XFS_ILOCK_EXCL, &ip)))
153 goto error_exit;
154 XFS_BMAP_INIT(&flist, &firstblock);
155
156
157
158 nmap = 1;
159 cancelflags |= XFS_TRANS_ABORT;
160 error = xfs_bmapi(tp, ip, oblocks, nblocks - oblocks,
161 XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, &firstblock,
162 resblks, &map, &nmap, &flist);
163 if (!error && nmap < 1)
164 error = XFS_ERROR(ENOSPC);
165 if (error)
166 goto error_exit;
167
168
169
170 error = xfs_bmap_finish(&tp, &flist, firstblock, &committed);
171 if (error)
172 goto error_exit;
173 xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
174
175
176
177
178 cancelflags = 0;
179 for (bno = map.br_startoff, fsbno = map.br_startblock;
180 bno < map.br_startoff + map.br_blockcount;
181 bno++, fsbno++) {
182 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ZERO);
183
184
185
186 if ((error = xfs_trans_reserve(tp, 0,
187 XFS_GROWRTZERO_LOG_RES(mp), 0, 0, 0)))
188 goto error_exit;
189
190
191
192 if ((error = xfs_trans_iget(mp, tp, ino, 0, XFS_ILOCK_EXCL,
193 &ip)))
194 goto error_exit;
195
196
197
198 d = XFS_FSB_TO_DADDR(mp, fsbno);
199 bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
200 mp->m_bsize, 0);
201 if (bp == NULL) {
202 error = XFS_ERROR(EIO);
203 goto error_exit;
204 }
205 memset(XFS_BUF_PTR(bp), 0, mp->m_sb.sb_blocksize);
206 xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
207
208
209
210 xfs_trans_commit(tp, 0, NULL);
211 }
212
213
214
215 oblocks = map.br_startoff + map.br_blockcount;
216 }
217 return 0;
218error_exit:
219 xfs_trans_cancel(tp, cancelflags);
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 log2len = xfs_highbit32(minlen);
468
469
470
471 for (;;) {
472
473
474
475
476 error = xfs_rtany_summary(mp, tp, log2len, mp->m_rsumlevels - 1,
477 bbno + i, rbpp, rsb, &any);
478 if (error) {
479 return error;
480 }
481
482
483
484
485 if (any) {
486
487
488
489 if (i >= 0) {
490
491
492
493
494 error = xfs_rtallocate_extent_block(mp, tp,
495 bbno + i, minlen, maxlen, len, &n, rbpp,
496 rsb, prod, &r);
497 if (error) {
498 return error;
499 }
500
501
502
503 if (r != NULLRTBLOCK) {
504 *rtblock = r;
505 return 0;
506 }
507 }
508
509
510
511 else {
512
513
514
515
516
517
518 for (j = -1; j > i; j--) {
519
520
521
522
523 error = xfs_rtany_summary(mp, tp,
524 log2len, mp->m_rsumlevels - 1,
525 bbno + j, rbpp, rsb, &any);
526 if (error) {
527 return error;
528 }
529
530
531
532
533
534
535
536
537 if (any)
538 continue;
539 error = xfs_rtallocate_extent_block(mp,
540 tp, bbno + j, minlen, maxlen,
541 len, &n, rbpp, rsb, prod, &r);
542 if (error) {
543 return error;
544 }
545
546
547
548 if (r != NULLRTBLOCK) {
549 *rtblock = r;
550 return 0;
551 }
552 }
553
554
555
556
557
558
559
560
561 error = xfs_rtallocate_extent_block(mp, tp,
562 bbno + i, minlen, maxlen, len, &n, rbpp,
563 rsb, prod, &r);
564 if (error) {
565 return error;
566 }
567
568
569
570 if (r != NULLRTBLOCK) {
571 *rtblock = r;
572 return 0;
573 }
574 }
575 }
576
577
578
579
580 if (i > 0 && (int)bbno - i >= 0)
581 i = -i;
582
583
584
585
586 else if (i > 0 && (int)bbno + i < mp->m_sb.sb_rbmblocks - 1)
587 i++;
588
589
590
591
592 else if (i <= 0 && (int)bbno - i < mp->m_sb.sb_rbmblocks - 1)
593 i = 1 - i;
594
595
596
597
598 else if (i <= 0 && (int)bbno + i > 0)
599 i--;
600
601
602
603 else
604 break;
605 }
606 *rtblock = NULLRTBLOCK;
607 return 0;
608}
609
610
611
612
613
614
615STATIC int
616xfs_rtallocate_extent_size(
617 xfs_mount_t *mp,
618 xfs_trans_t *tp,
619 xfs_extlen_t minlen,
620 xfs_extlen_t maxlen,
621 xfs_extlen_t *len,
622 xfs_buf_t **rbpp,
623 xfs_fsblock_t *rsb,
624 xfs_extlen_t prod,
625 xfs_rtblock_t *rtblock)
626{
627 int error;
628 int i;
629 int l;
630 xfs_rtblock_t n;
631 xfs_rtblock_t r;
632 xfs_suminfo_t sum;
633
634 ASSERT(minlen % prod == 0 && maxlen % prod == 0);
635
636
637
638
639
640
641
642 for (l = xfs_highbit32(maxlen); l < mp->m_rsumlevels; l++) {
643
644
645
646 for (i = 0; i < mp->m_sb.sb_rbmblocks; i++) {
647
648
649
650 error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb,
651 &sum);
652 if (error) {
653 return error;
654 }
655
656
657
658 if (!sum)
659 continue;
660
661
662
663 error = xfs_rtallocate_extent_block(mp, tp, i, maxlen,
664 maxlen, len, &n, rbpp, rsb, prod, &r);
665 if (error) {
666 return error;
667 }
668
669
670
671 if (r != NULLRTBLOCK) {
672 *rtblock = r;
673 return 0;
674 }
675
676
677
678
679
680 if (XFS_BITTOBLOCK(mp, n) > i + 1)
681 i = XFS_BITTOBLOCK(mp, n) - 1;
682 }
683 }
684
685
686
687
688 if (minlen > --maxlen) {
689 *rtblock = NULLRTBLOCK;
690 return 0;
691 }
692
693
694
695
696
697 for (l = xfs_highbit32(maxlen); l >= xfs_highbit32(minlen); l--) {
698
699
700
701
702 for (i = 0; i < mp->m_sb.sb_rbmblocks; i++) {
703
704
705
706 error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb,
707 &sum);
708 if (error) {
709 return error;
710 }
711
712
713
714 if (!sum)
715 continue;
716
717
718
719
720
721 error = xfs_rtallocate_extent_block(mp, tp, i,
722 XFS_RTMAX(minlen, 1 << l),
723 XFS_RTMIN(maxlen, (1 << (l + 1)) - 1),
724 len, &n, rbpp, rsb, prod, &r);
725 if (error) {
726 return error;
727 }
728
729
730
731 if (r != NULLRTBLOCK) {
732 *rtblock = r;
733 return 0;
734 }
735
736
737
738
739
740 if (XFS_BITTOBLOCK(mp, n) > i + 1)
741 i = XFS_BITTOBLOCK(mp, n) - 1;
742 }
743 }
744
745
746
747 *rtblock = NULLRTBLOCK;
748 return 0;
749}
750
751
752
753
754
755STATIC int
756xfs_rtallocate_range(
757 xfs_mount_t *mp,
758 xfs_trans_t *tp,
759 xfs_rtblock_t start,
760 xfs_extlen_t len,
761 xfs_buf_t **rbpp,
762 xfs_fsblock_t *rsb)
763{
764 xfs_rtblock_t end;
765 int error;
766 xfs_rtblock_t postblock;
767 xfs_rtblock_t preblock;
768
769 end = start + len - 1;
770
771
772
773
774
775 error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
776 if (error) {
777 return error;
778 }
779
780
781
782 error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
783 &postblock);
784 if (error) {
785 return error;
786 }
787
788
789
790
791 error = xfs_rtmodify_summary(mp, tp,
792 XFS_RTBLOCKLOG(postblock + 1 - preblock),
793 XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
794 if (error) {
795 return error;
796 }
797
798
799
800
801 if (preblock < start) {
802 error = xfs_rtmodify_summary(mp, tp,
803 XFS_RTBLOCKLOG(start - preblock),
804 XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
805 if (error) {
806 return error;
807 }
808 }
809
810
811
812
813 if (postblock > end) {
814 error = xfs_rtmodify_summary(mp, tp,
815 XFS_RTBLOCKLOG(postblock - end),
816 XFS_BITTOBLOCK(mp, end + 1), 1, rbpp, rsb);
817 if (error) {
818 return error;
819 }
820 }
821
822
823
824 error = xfs_rtmodify_range(mp, tp, start, len, 0);
825 return error;
826}
827
828
829
830
831
832STATIC int
833xfs_rtany_summary(
834 xfs_mount_t *mp,
835 xfs_trans_t *tp,
836 int low,
837 int high,
838 xfs_rtblock_t bbno,
839 xfs_buf_t **rbpp,
840 xfs_fsblock_t *rsb,
841 int *stat)
842{
843 int error;
844 int log;
845 xfs_suminfo_t sum;
846
847
848
849
850 for (log = low; log <= high; log++) {
851
852
853
854 error = xfs_rtget_summary(mp, tp, log, bbno, rbpp, rsb, &sum);
855 if (error) {
856 return error;
857 }
858
859
860
861 if (sum) {
862 *stat = 1;
863 return 0;
864 }
865 }
866
867
868
869 *stat = 0;
870 return 0;
871}
872
873
874
875
876
877STATIC int
878xfs_rtbuf_get(
879 xfs_mount_t *mp,
880 xfs_trans_t *tp,
881 xfs_rtblock_t block,
882 int issum,
883 xfs_buf_t **bpp)
884{
885 xfs_buf_t *bp;
886 xfs_daddr_t d;
887 int error;
888 xfs_fsblock_t fsb;
889 xfs_inode_t *ip;
890
891 ip = issum ? mp->m_rsumip : mp->m_rbmip;
892
893
894
895
896 error = xfs_bmapi_single(tp, ip, XFS_DATA_FORK, &fsb, block);
897 if (error) {
898 return error;
899 }
900 ASSERT(fsb != NULLFSBLOCK);
901
902
903
904 d = XFS_FSB_TO_DADDR(mp, fsb);
905
906
907
908 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,
909 mp->m_bsize, 0, &bp);
910 if (error) {
911 return error;
912 }
913 ASSERT(bp && !XFS_BUF_GETERROR(bp));
914 *bpp = bp;
915 return 0;
916}
917
918#ifdef DEBUG
919
920
921
922STATIC int
923xfs_rtcheck_alloc_range(
924 xfs_mount_t *mp,
925 xfs_trans_t *tp,
926 xfs_rtblock_t bno,
927 xfs_extlen_t len,
928 int *stat)
929{
930 xfs_rtblock_t new;
931
932 return xfs_rtcheck_range(mp, tp, bno, len, 0, &new, stat);
933}
934#endif
935
936#ifdef DEBUG
937
938
939
940STATIC int
941xfs_rtcheck_bit(
942 xfs_mount_t *mp,
943 xfs_trans_t *tp,
944 xfs_rtblock_t start,
945 int val)
946{
947 int bit;
948 xfs_rtblock_t block;
949 xfs_buf_t *bp;
950 xfs_rtword_t *bufp;
951
952 int error;
953 xfs_rtword_t wdiff;
954 int word;
955 xfs_rtword_t wval;
956
957 block = XFS_BITTOBLOCK(mp, start);
958 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
959 bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
960 word = XFS_BITTOWORD(mp, start);
961 bit = (int)(start & (XFS_NBWORD - 1));
962 wval = bufp[word];
963 xfs_trans_brelse(tp, bp);
964 wdiff = (wval ^ -val) & ((xfs_rtword_t)1 << bit);
965 return !wdiff;
966}
967#endif
968
969#if 0
970
971
972
973STATIC int
974xfs_rtcheck_free_range(
975 xfs_mount_t *mp,
976 xfs_trans_t *tp,
977 xfs_rtblock_t bno,
978 xfs_extlen_t len,
979 int *stat)
980{
981 xfs_rtblock_t new;
982
983 return xfs_rtcheck_range(mp, tp, bno, len, 1, &new, stat);
984}
985#endif
986
987
988
989
990
991STATIC int
992xfs_rtcheck_range(
993 xfs_mount_t *mp,
994 xfs_trans_t *tp,
995 xfs_rtblock_t start,
996 xfs_extlen_t len,
997 int val,
998 xfs_rtblock_t *new,
999 int *stat)
1000{
1001 xfs_rtword_t *b;
1002 int bit;
1003 xfs_rtblock_t block;
1004 xfs_buf_t *bp;
1005 xfs_rtword_t *bufp;
1006 int error;
1007 xfs_rtblock_t i;
1008 xfs_rtblock_t lastbit;
1009 xfs_rtword_t mask;
1010 xfs_rtword_t wdiff;
1011 int word;
1012
1013
1014
1015
1016 block = XFS_BITTOBLOCK(mp, start);
1017
1018
1019
1020 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
1021 if (error) {
1022 return error;
1023 }
1024 bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1025
1026
1027
1028 word = XFS_BITTOWORD(mp, start);
1029 b = &bufp[word];
1030 bit = (int)(start & (XFS_NBWORD - 1));
1031
1032
1033
1034 val = -val;
1035
1036
1037
1038
1039 if (bit) {
1040
1041
1042
1043 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
1044
1045
1046
1047 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
1048
1049
1050
1051 if ((wdiff = (*b ^ val) & mask)) {
1052
1053
1054
1055 xfs_trans_brelse(tp, bp);
1056 i = XFS_RTLOBIT(wdiff) - bit;
1057 *new = start + i;
1058 *stat = 0;
1059 return 0;
1060 }
1061 i = lastbit - bit;
1062
1063
1064
1065
1066 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1067
1068
1069
1070 xfs_trans_brelse(tp, bp);
1071 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1072 if (error) {
1073 return error;
1074 }
1075 b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1076 word = 0;
1077 } else {
1078
1079
1080
1081 b++;
1082 }
1083 } else {
1084
1085
1086
1087 i = 0;
1088 }
1089
1090
1091
1092
1093 while (len - i >= XFS_NBWORD) {
1094
1095
1096
1097 if ((wdiff = *b ^ val)) {
1098
1099
1100
1101 xfs_trans_brelse(tp, bp);
1102 i += XFS_RTLOBIT(wdiff);
1103 *new = start + i;
1104 *stat = 0;
1105 return 0;
1106 }
1107 i += XFS_NBWORD;
1108
1109
1110
1111
1112 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1113
1114
1115
1116 xfs_trans_brelse(tp, bp);
1117 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1118 if (error) {
1119 return error;
1120 }
1121 b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1122 word = 0;
1123 } else {
1124
1125
1126
1127 b++;
1128 }
1129 }
1130
1131
1132
1133
1134 if ((lastbit = len - i)) {
1135
1136
1137
1138 mask = ((xfs_rtword_t)1 << lastbit) - 1;
1139
1140
1141
1142 if ((wdiff = (*b ^ val) & mask)) {
1143
1144
1145
1146 xfs_trans_brelse(tp, bp);
1147 i += XFS_RTLOBIT(wdiff);
1148 *new = start + i;
1149 *stat = 0;
1150 return 0;
1151 } else
1152 i = len;
1153 }
1154
1155
1156
1157 xfs_trans_brelse(tp, bp);
1158 *new = start + i;
1159 *stat = 1;
1160 return 0;
1161}
1162
1163
1164
1165
1166
1167STATIC int
1168xfs_rtcopy_summary(
1169 xfs_mount_t *omp,
1170 xfs_mount_t *nmp,
1171 xfs_trans_t *tp)
1172{
1173 xfs_rtblock_t bbno;
1174 xfs_buf_t *bp;
1175 int error;
1176 int log;
1177 xfs_suminfo_t sum;
1178 xfs_fsblock_t sumbno;
1179
1180 bp = NULL;
1181 for (log = omp->m_rsumlevels - 1; log >= 0; log--) {
1182 for (bbno = omp->m_sb.sb_rbmblocks - 1;
1183 (xfs_srtblock_t)bbno >= 0;
1184 bbno--) {
1185 error = xfs_rtget_summary(omp, tp, log, bbno, &bp,
1186 &sumbno, &sum);
1187 if (error)
1188 return error;
1189 if (sum == 0)
1190 continue;
1191 error = xfs_rtmodify_summary(omp, tp, log, bbno, -sum,
1192 &bp, &sumbno);
1193 if (error)
1194 return error;
1195 error = xfs_rtmodify_summary(nmp, tp, log, bbno, sum,
1196 &bp, &sumbno);
1197 if (error)
1198 return error;
1199 ASSERT(sum > 0);
1200 }
1201 }
1202 return 0;
1203}
1204
1205
1206
1207
1208
1209STATIC int
1210xfs_rtfind_back(
1211 xfs_mount_t *mp,
1212 xfs_trans_t *tp,
1213 xfs_rtblock_t start,
1214 xfs_rtblock_t limit,
1215 xfs_rtblock_t *rtblock)
1216{
1217 xfs_rtword_t *b;
1218 int bit;
1219 xfs_rtblock_t block;
1220 xfs_buf_t *bp;
1221 xfs_rtword_t *bufp;
1222 int error;
1223 xfs_rtblock_t firstbit;
1224 xfs_rtblock_t i;
1225 xfs_rtblock_t len;
1226 xfs_rtword_t mask;
1227 xfs_rtword_t want;
1228 xfs_rtword_t wdiff;
1229 int word;
1230
1231
1232
1233
1234 block = XFS_BITTOBLOCK(mp, start);
1235 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
1236 if (error) {
1237 return error;
1238 }
1239 bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1240
1241
1242
1243 word = XFS_BITTOWORD(mp, start);
1244 b = &bufp[word];
1245 bit = (int)(start & (XFS_NBWORD - 1));
1246 len = start - limit + 1;
1247
1248
1249
1250
1251 want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
1252
1253
1254
1255
1256 if (bit < XFS_NBWORD - 1) {
1257
1258
1259
1260
1261 firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
1262 mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
1263 firstbit;
1264
1265
1266
1267
1268 if ((wdiff = (*b ^ want) & mask)) {
1269
1270
1271
1272 xfs_trans_brelse(tp, bp);
1273 i = bit - XFS_RTHIBIT(wdiff);
1274 *rtblock = start - i + 1;
1275 return 0;
1276 }
1277 i = bit - firstbit + 1;
1278
1279
1280
1281
1282 if (--word == -1 && i < len) {
1283
1284
1285
1286 xfs_trans_brelse(tp, bp);
1287 error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
1288 if (error) {
1289 return error;
1290 }
1291 bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1292 word = XFS_BLOCKWMASK(mp);
1293 b = &bufp[word];
1294 } else {
1295
1296
1297
1298 b--;
1299 }
1300 } else {
1301
1302
1303
1304 i = 0;
1305 }
1306
1307
1308
1309
1310 while (len - i >= XFS_NBWORD) {
1311
1312
1313
1314 if ((wdiff = *b ^ want)) {
1315
1316
1317
1318 xfs_trans_brelse(tp, bp);
1319 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
1320 *rtblock = start - i + 1;
1321 return 0;
1322 }
1323 i += XFS_NBWORD;
1324
1325
1326
1327
1328 if (--word == -1 && i < len) {
1329
1330
1331
1332 xfs_trans_brelse(tp, bp);
1333 error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
1334 if (error) {
1335 return error;
1336 }
1337 bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1338 word = XFS_BLOCKWMASK(mp);
1339 b = &bufp[word];
1340 } else {
1341
1342
1343
1344 b--;
1345 }
1346 }
1347
1348
1349
1350
1351 if (len - i) {
1352
1353
1354
1355
1356 firstbit = XFS_NBWORD - (len - i);
1357 mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
1358
1359
1360
1361 if ((wdiff = (*b ^ want) & mask)) {
1362
1363
1364
1365 xfs_trans_brelse(tp, bp);
1366 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
1367 *rtblock = start - i + 1;
1368 return 0;
1369 } else
1370 i = len;
1371 }
1372
1373
1374
1375 xfs_trans_brelse(tp, bp);
1376 *rtblock = start - i + 1;
1377 return 0;
1378}
1379
1380
1381
1382
1383
1384STATIC int
1385xfs_rtfind_forw(
1386 xfs_mount_t *mp,
1387 xfs_trans_t *tp,
1388 xfs_rtblock_t start,
1389 xfs_rtblock_t limit,
1390 xfs_rtblock_t *rtblock)
1391{
1392 xfs_rtword_t *b;
1393 int bit;
1394 xfs_rtblock_t block;
1395 xfs_buf_t *bp;
1396 xfs_rtword_t *bufp;
1397 int error;
1398 xfs_rtblock_t i;
1399 xfs_rtblock_t lastbit;
1400 xfs_rtblock_t len;
1401 xfs_rtword_t mask;
1402 xfs_rtword_t want;
1403 xfs_rtword_t wdiff;
1404 int word;
1405
1406
1407
1408
1409 block = XFS_BITTOBLOCK(mp, start);
1410 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
1411 if (error) {
1412 return error;
1413 }
1414 bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1415
1416
1417
1418 word = XFS_BITTOWORD(mp, start);
1419 b = &bufp[word];
1420 bit = (int)(start & (XFS_NBWORD - 1));
1421 len = limit - start + 1;
1422
1423
1424
1425
1426 want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
1427
1428
1429
1430
1431 if (bit) {
1432
1433
1434
1435
1436 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
1437 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
1438
1439
1440
1441
1442 if ((wdiff = (*b ^ want) & mask)) {
1443
1444
1445
1446 xfs_trans_brelse(tp, bp);
1447 i = XFS_RTLOBIT(wdiff) - bit;
1448 *rtblock = start + i - 1;
1449 return 0;
1450 }
1451 i = lastbit - bit;
1452
1453
1454
1455
1456 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1457
1458
1459
1460 xfs_trans_brelse(tp, bp);
1461 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1462 if (error) {
1463 return error;
1464 }
1465 b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1466 word = 0;
1467 } else {
1468
1469
1470
1471 b++;
1472 }
1473 } else {
1474
1475
1476
1477 i = 0;
1478 }
1479
1480
1481
1482
1483 while (len - i >= XFS_NBWORD) {
1484
1485
1486
1487 if ((wdiff = *b ^ want)) {
1488
1489
1490
1491 xfs_trans_brelse(tp, bp);
1492 i += XFS_RTLOBIT(wdiff);
1493 *rtblock = start + i - 1;
1494 return 0;
1495 }
1496 i += XFS_NBWORD;
1497
1498
1499
1500
1501 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1502
1503
1504
1505 xfs_trans_brelse(tp, bp);
1506 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1507 if (error) {
1508 return error;
1509 }
1510 b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1511 word = 0;
1512 } else {
1513
1514
1515
1516 b++;
1517 }
1518 }
1519
1520
1521
1522
1523 if ((lastbit = len - i)) {
1524
1525
1526
1527 mask = ((xfs_rtword_t)1 << lastbit) - 1;
1528
1529
1530
1531 if ((wdiff = (*b ^ want) & mask)) {
1532
1533
1534
1535 xfs_trans_brelse(tp, bp);
1536 i += XFS_RTLOBIT(wdiff);
1537 *rtblock = start + i - 1;
1538 return 0;
1539 } else
1540 i = len;
1541 }
1542
1543
1544
1545 xfs_trans_brelse(tp, bp);
1546 *rtblock = start + i - 1;
1547 return 0;
1548}
1549
1550
1551
1552
1553
1554STATIC int
1555xfs_rtfree_range(
1556 xfs_mount_t *mp,
1557 xfs_trans_t *tp,
1558 xfs_rtblock_t start,
1559 xfs_extlen_t len,
1560 xfs_buf_t **rbpp,
1561 xfs_fsblock_t *rsb)
1562{
1563 xfs_rtblock_t end;
1564 int error;
1565 xfs_rtblock_t postblock;
1566 xfs_rtblock_t preblock;
1567
1568 end = start + len - 1;
1569
1570
1571
1572 error = xfs_rtmodify_range(mp, tp, start, len, 1);
1573 if (error) {
1574 return error;
1575 }
1576
1577
1578
1579
1580
1581 error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
1582 if (error) {
1583 return error;
1584 }
1585
1586
1587
1588 error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
1589 &postblock);
1590
1591
1592
1593
1594 if (preblock < start) {
1595 error = xfs_rtmodify_summary(mp, tp,
1596 XFS_RTBLOCKLOG(start - preblock),
1597 XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
1598 if (error) {
1599 return error;
1600 }
1601 }
1602
1603
1604
1605
1606 if (postblock > end) {
1607 error = xfs_rtmodify_summary(mp, tp,
1608 XFS_RTBLOCKLOG(postblock - end),
1609 XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
1610 if (error) {
1611 return error;
1612 }
1613 }
1614
1615
1616
1617
1618 error = xfs_rtmodify_summary(mp, tp,
1619 XFS_RTBLOCKLOG(postblock + 1 - preblock),
1620 XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
1621 return error;
1622}
1623
1624
1625
1626
1627
1628
1629
1630STATIC int
1631xfs_rtget_summary(
1632 xfs_mount_t *mp,
1633 xfs_trans_t *tp,
1634 int log,
1635 xfs_rtblock_t bbno,
1636 xfs_buf_t **rbpp,
1637 xfs_fsblock_t *rsb,
1638 xfs_suminfo_t *sum)
1639{
1640 xfs_buf_t *bp;
1641 int error;
1642 xfs_fsblock_t sb;
1643 int so;
1644 xfs_suminfo_t *sp;
1645
1646
1647
1648
1649 so = XFS_SUMOFFS(mp, log, bbno);
1650
1651
1652
1653 sb = XFS_SUMOFFSTOBLOCK(mp, so);
1654
1655
1656
1657 if (rbpp && *rbpp && *rsb == sb)
1658 bp = *rbpp;
1659
1660
1661
1662 else {
1663
1664
1665
1666 if (rbpp && *rbpp)
1667 xfs_trans_brelse(tp, *rbpp);
1668 error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
1669 if (error) {
1670 return error;
1671 }
1672
1673
1674
1675 if (rbpp) {
1676 *rbpp = bp;
1677 *rsb = sb;
1678 }
1679 }
1680
1681
1682
1683 sp = XFS_SUMPTR(mp, bp, so);
1684 *sum = *sp;
1685
1686
1687
1688 if (!rbpp)
1689 xfs_trans_brelse(tp, bp);
1690 return 0;
1691}
1692
1693
1694
1695
1696
1697STATIC int
1698xfs_rtmodify_range(
1699 xfs_mount_t *mp,
1700 xfs_trans_t *tp,
1701 xfs_rtblock_t start,
1702 xfs_extlen_t len,
1703 int val)
1704{
1705 xfs_rtword_t *b;
1706 int bit;
1707 xfs_rtblock_t block;
1708 xfs_buf_t *bp;
1709 xfs_rtword_t *bufp;
1710 int error;
1711 xfs_rtword_t *first;
1712 int i;
1713 int lastbit;
1714 xfs_rtword_t mask;
1715 int word;
1716
1717
1718
1719
1720 block = XFS_BITTOBLOCK(mp, start);
1721
1722
1723
1724 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
1725 if (error) {
1726 return error;
1727 }
1728 bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1729
1730
1731
1732 word = XFS_BITTOWORD(mp, start);
1733 first = b = &bufp[word];
1734 bit = (int)(start & (XFS_NBWORD - 1));
1735
1736
1737
1738 val = -val;
1739
1740
1741
1742
1743 if (bit) {
1744
1745
1746
1747 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
1748 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
1749
1750
1751
1752 if (val)
1753 *b |= mask;
1754 else
1755 *b &= ~mask;
1756 i = lastbit - bit;
1757
1758
1759
1760
1761 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1762
1763
1764
1765
1766 xfs_trans_log_buf(tp, bp,
1767 (uint)((char *)first - (char *)bufp),
1768 (uint)((char *)b - (char *)bufp));
1769 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1770 if (error) {
1771 return error;
1772 }
1773 first = b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1774 word = 0;
1775 } else {
1776
1777
1778
1779 b++;
1780 }
1781 } else {
1782
1783
1784
1785 i = 0;
1786 }
1787
1788
1789
1790
1791 while (len - i >= XFS_NBWORD) {
1792
1793
1794
1795 *b = val;
1796 i += XFS_NBWORD;
1797
1798
1799
1800
1801 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1802
1803
1804
1805
1806 xfs_trans_log_buf(tp, bp,
1807 (uint)((char *)first - (char *)bufp),
1808 (uint)((char *)b - (char *)bufp));
1809 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1810 if (error) {
1811 return error;
1812 }
1813 first = b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
1814 word = 0;
1815 } else {
1816
1817
1818
1819 b++;
1820 }
1821 }
1822
1823
1824
1825
1826 if ((lastbit = len - i)) {
1827
1828
1829
1830 bit = 0;
1831 mask = ((xfs_rtword_t)1 << lastbit) - 1;
1832
1833
1834
1835 if (val)
1836 *b |= mask;
1837 else
1838 *b &= ~mask;
1839 b++;
1840 }
1841
1842
1843
1844 if (b > first)
1845 xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
1846 (uint)((char *)b - (char *)bufp - 1));
1847 return 0;
1848}
1849
1850
1851
1852
1853
1854
1855
1856STATIC int
1857xfs_rtmodify_summary(
1858 xfs_mount_t *mp,
1859 xfs_trans_t *tp,
1860 int log,
1861 xfs_rtblock_t bbno,
1862 int delta,
1863 xfs_buf_t **rbpp,
1864 xfs_fsblock_t *rsb)
1865{
1866 xfs_buf_t *bp;
1867 int error;
1868 xfs_fsblock_t sb;
1869 int so;
1870 xfs_suminfo_t *sp;
1871
1872
1873
1874
1875 so = XFS_SUMOFFS(mp, log, bbno);
1876
1877
1878
1879 sb = XFS_SUMOFFSTOBLOCK(mp, so);
1880
1881
1882
1883 if (rbpp && *rbpp && *rsb == sb)
1884 bp = *rbpp;
1885
1886
1887
1888 else {
1889
1890
1891
1892 if (rbpp && *rbpp)
1893 xfs_trans_brelse(tp, *rbpp);
1894 error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
1895 if (error) {
1896 return error;
1897 }
1898
1899
1900
1901 if (rbpp) {
1902 *rbpp = bp;
1903 *rsb = sb;
1904 }
1905 }
1906
1907
1908
1909 sp = XFS_SUMPTR(mp, bp, so);
1910 *sp += delta;
1911 xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)XFS_BUF_PTR(bp)),
1912 (uint)((char *)sp - (char *)XFS_BUF_PTR(bp) + sizeof(*sp) - 1));
1913 return 0;
1914}
1915
1916
1917
1918
1919
1920
1921
1922
1923int
1924xfs_growfs_rt(
1925 xfs_mount_t *mp,
1926 xfs_growfs_rt_t *in)
1927{
1928 xfs_rtblock_t bmbno;
1929 xfs_buf_t *bp;
1930 int cancelflags;
1931 int error;
1932 xfs_inode_t *ip;
1933 xfs_mount_t *nmp;
1934 xfs_drfsbno_t nrblocks;
1935 xfs_extlen_t nrbmblocks;
1936 xfs_drtbno_t nrextents;
1937 uint8_t nrextslog;
1938 xfs_extlen_t nrsumblocks;
1939 uint nrsumlevels;
1940 uint nrsumsize;
1941 xfs_sb_t *nsbp;
1942 xfs_extlen_t rbmblocks;
1943 xfs_extlen_t rsumblocks;
1944 xfs_sb_t *sbp;
1945 xfs_fsblock_t sumbno;
1946 xfs_trans_t *tp;
1947
1948 sbp = &mp->m_sb;
1949
1950
1951
1952 if (mp->m_rtdev_targp || mp->m_rbmip == NULL ||
1953 (nrblocks = in->newblocks) <= sbp->sb_rblocks ||
1954 (sbp->sb_rblocks && (in->extsize != sbp->sb_rextsize)))
1955 return XFS_ERROR(EINVAL);
1956
1957
1958
1959 error = xfs_read_buf(mp, mp->m_rtdev_targp,
1960 XFS_FSB_TO_BB(mp, in->newblocks - 1),
1961 XFS_FSB_TO_BB(mp, 1), 0, &bp);
1962 if (error)
1963 return error;
1964 ASSERT(bp);
1965 xfs_buf_relse(bp);
1966
1967
1968
1969 nrextents = nrblocks;
1970 do_div(nrextents, in->extsize);
1971 nrbmblocks = roundup_64(nrextents, NBBY * sbp->sb_blocksize);
1972 nrextslog = xfs_highbit32(nrextents);
1973 nrsumlevels = nrextslog + 1;
1974 nrsumsize = (uint)sizeof(xfs_suminfo_t) * nrsumlevels * nrbmblocks;
1975 nrsumblocks = XFS_B_TO_FSB(mp, nrsumsize);
1976 nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
1977
1978
1979
1980
1981
1982 if (nrsumblocks > (mp->m_sb.sb_logblocks >> 1))
1983 return XFS_ERROR(EINVAL);
1984
1985
1986
1987
1988 rbmblocks = XFS_B_TO_FSB(mp, mp->m_rbmip->i_d.di_size);
1989 rsumblocks = XFS_B_TO_FSB(mp, mp->m_rsumip->i_d.di_size);
1990
1991
1992
1993 if ((error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks,
1994 mp->m_sb.sb_rbmino)))
1995 return error;
1996 if ((error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks,
1997 mp->m_sb.sb_rsumino)))
1998 return error;
1999 nmp = NULL;
2000
2001
2002
2003
2004
2005
2006 for (bmbno = sbp->sb_rbmblocks -
2007 ((sbp->sb_rextents & ((1 << mp->m_blkbit_log) - 1)) != 0);
2008 bmbno < nrbmblocks;
2009 bmbno++) {
2010
2011
2012
2013 nmp = kmem_alloc(sizeof(*nmp), KM_SLEEP);
2014 *nmp = *mp;
2015 nsbp = &nmp->m_sb;
2016
2017
2018
2019 nsbp->sb_rextsize = in->extsize;
2020 nsbp->sb_rbmblocks = bmbno + 1;
2021 nsbp->sb_rblocks =
2022 XFS_RTMIN(nrblocks,
2023 nsbp->sb_rbmblocks * NBBY *
2024 nsbp->sb_blocksize * nsbp->sb_rextsize);
2025 nsbp->sb_rextents = nsbp->sb_rblocks;
2026 do_div(nsbp->sb_rextents, nsbp->sb_rextsize);
2027 nsbp->sb_rextslog = xfs_highbit32(nsbp->sb_rextents);
2028 nrsumlevels = nmp->m_rsumlevels = nsbp->sb_rextslog + 1;
2029 nrsumsize =
2030 (uint)sizeof(xfs_suminfo_t) * nrsumlevels *
2031 nsbp->sb_rbmblocks;
2032 nrsumblocks = XFS_B_TO_FSB(mp, nrsumsize);
2033 nmp->m_rsumsize = nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
2034
2035
2036
2037 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_FREE);
2038 cancelflags = 0;
2039 if ((error = xfs_trans_reserve(tp, 0,
2040 XFS_GROWRTFREE_LOG_RES(nmp), 0, 0, 0)))
2041 goto error_exit;
2042
2043
2044
2045 if ((error = xfs_trans_iget(mp, tp, 0, mp->m_sb.sb_rbmino,
2046 XFS_ILOCK_EXCL, &ip)))
2047 goto error_exit;
2048 ASSERT(ip == mp->m_rbmip);
2049
2050
2051
2052 mp->m_rbmip->i_d.di_size =
2053 nsbp->sb_rbmblocks * nsbp->sb_blocksize;
2054 xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
2055 cancelflags |= XFS_TRANS_ABORT;
2056
2057
2058
2059 if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino,
2060 0, XFS_ILOCK_EXCL, &ip)))
2061 goto error_exit;
2062 ASSERT(ip == mp->m_rsumip);
2063
2064
2065
2066 mp->m_rsumip->i_d.di_size = nmp->m_rsumsize;
2067 xfs_trans_log_inode(tp, mp->m_rsumip, XFS_ILOG_CORE);
2068
2069
2070
2071
2072 if (sbp->sb_rbmblocks != nsbp->sb_rbmblocks ||
2073 mp->m_rsumlevels != nmp->m_rsumlevels) {
2074 error = xfs_rtcopy_summary(mp, nmp, tp);
2075 if (error)
2076 goto error_exit;
2077 }
2078
2079
2080
2081 if (nsbp->sb_rextsize != sbp->sb_rextsize)
2082 xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSIZE,
2083 nsbp->sb_rextsize - sbp->sb_rextsize);
2084 if (nsbp->sb_rbmblocks != sbp->sb_rbmblocks)
2085 xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBMBLOCKS,
2086 nsbp->sb_rbmblocks - sbp->sb_rbmblocks);
2087 if (nsbp->sb_rblocks != sbp->sb_rblocks)
2088 xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBLOCKS,
2089 nsbp->sb_rblocks - sbp->sb_rblocks);
2090 if (nsbp->sb_rextents != sbp->sb_rextents)
2091 xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTENTS,
2092 nsbp->sb_rextents - sbp->sb_rextents);
2093 if (nsbp->sb_rextslog != sbp->sb_rextslog)
2094 xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSLOG,
2095 nsbp->sb_rextslog - sbp->sb_rextslog);
2096
2097
2098
2099 bp = NULL;
2100 error = xfs_rtfree_range(nmp, tp, sbp->sb_rextents,
2101 nsbp->sb_rextents - sbp->sb_rextents, &bp, &sumbno);
2102 if (error)
2103 goto error_exit;
2104
2105
2106
2107 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS,
2108 nsbp->sb_rextents - sbp->sb_rextents);
2109
2110
2111
2112 kmem_free(nmp, sizeof(*nmp));
2113 nmp = NULL;
2114
2115
2116
2117 mp->m_rsumlevels = nrsumlevels;
2118 mp->m_rsumsize = nrsumsize;
2119
2120
2121
2122 xfs_trans_commit(tp, 0, NULL);
2123 }
2124 return 0;
2125
2126
2127
2128
2129error_exit:
2130 if (nmp)
2131 kmem_free(nmp, sizeof(*nmp));
2132 xfs_trans_cancel(tp, cancelflags);
2133 return error;
2134}
2135
2136
2137
2138
2139
2140
2141int
2142xfs_rtallocate_extent(
2143 xfs_trans_t *tp,
2144 xfs_rtblock_t bno,
2145 xfs_extlen_t minlen,
2146 xfs_extlen_t maxlen,
2147 xfs_extlen_t *len,
2148 xfs_alloctype_t type,
2149 int wasdel,
2150 xfs_extlen_t prod,
2151 xfs_rtblock_t *rtblock)
2152{
2153 int error;
2154 xfs_inode_t *ip;
2155 xfs_mount_t *mp;
2156 xfs_rtblock_t r;
2157 xfs_fsblock_t sb;
2158 xfs_buf_t *sumbp;
2159
2160 ASSERT(minlen > 0 && minlen <= maxlen);
2161 mp = tp->t_mountp;
2162
2163
2164
2165 if (prod > 1) {
2166 xfs_extlen_t i;
2167
2168 if ((i = maxlen % prod))
2169 maxlen -= i;
2170 if ((i = minlen % prod))
2171 minlen += prod - i;
2172 if (maxlen < minlen) {
2173 *rtblock = NULLRTBLOCK;
2174 return 0;
2175 }
2176 }
2177
2178
2179
2180 error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, XFS_ILOCK_EXCL, &ip);
2181 if (error) {
2182 return error;
2183 }
2184 sumbp = NULL;
2185
2186
2187
2188 switch (type) {
2189 case XFS_ALLOCTYPE_ANY_AG:
2190 error = xfs_rtallocate_extent_size(mp, tp, minlen, maxlen, len,
2191 &sumbp, &sb, prod, &r);
2192 break;
2193 case XFS_ALLOCTYPE_NEAR_BNO:
2194 error = xfs_rtallocate_extent_near(mp, tp, bno, minlen, maxlen,
2195 len, &sumbp, &sb, prod, &r);
2196 break;
2197 case XFS_ALLOCTYPE_THIS_BNO:
2198 error = xfs_rtallocate_extent_exact(mp, tp, bno, minlen, maxlen,
2199 len, &sumbp, &sb, prod, &r);
2200 break;
2201 default:
2202 ASSERT(0);
2203 }
2204 if (error) {
2205 return error;
2206 }
2207
2208
2209
2210 if (r != NULLRTBLOCK) {
2211 long slen = (long)*len;
2212
2213 ASSERT(*len >= minlen && *len <= maxlen);
2214 if (wasdel)
2215 xfs_trans_mod_sb(tp, XFS_TRANS_SB_RES_FREXTENTS, -slen);
2216 else
2217 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, -slen);
2218 }
2219 *rtblock = r;
2220 return 0;
2221}
2222
2223
2224
2225
2226
2227int
2228xfs_rtfree_extent(
2229 xfs_trans_t *tp,
2230 xfs_rtblock_t bno,
2231 xfs_extlen_t len)
2232{
2233 int error;
2234 xfs_inode_t *ip;
2235 xfs_mount_t *mp;
2236 xfs_fsblock_t sb;
2237 xfs_buf_t *sumbp;
2238
2239 mp = tp->t_mountp;
2240
2241
2242
2243 error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, XFS_ILOCK_EXCL, &ip);
2244 if (error) {
2245 return error;
2246 }
2247#if defined(__KERNEL__) && defined(DEBUG)
2248
2249
2250
2251 {
2252 int stat;
2253
2254 error = xfs_rtcheck_alloc_range(mp, tp, bno, len, &stat);
2255 if (error) {
2256 return error;
2257 }
2258 ASSERT(stat);
2259 }
2260#endif
2261 sumbp = NULL;
2262
2263
2264
2265 error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
2266 if (error) {
2267 return error;
2268 }
2269
2270
2271
2272 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
2273
2274
2275
2276
2277 if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
2278 mp->m_sb.sb_rextents) {
2279 if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
2280 ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
2281 *(__uint64_t *)&ip->i_d.di_atime = 0;
2282 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
2283 }
2284 return 0;
2285}
2286
2287
2288
2289
2290int
2291xfs_rtmount_init(
2292 xfs_mount_t *mp)
2293{
2294 xfs_buf_t *bp;
2295 xfs_daddr_t d;
2296 int error;
2297 xfs_sb_t *sbp;
2298
2299 sbp = &mp->m_sb;
2300 if (sbp->sb_rblocks == 0)
2301 return 0;
2302 if (mp->m_rtdev_targp == NULL) {
2303 cmn_err(CE_WARN,
2304 "XFS: This filesystem has a realtime volume, use rtdev=device option");
2305 return XFS_ERROR(ENODEV);
2306 }
2307 mp->m_rsumlevels = sbp->sb_rextslog + 1;
2308 mp->m_rsumsize =
2309 (uint)sizeof(xfs_suminfo_t) * mp->m_rsumlevels *
2310 sbp->sb_rbmblocks;
2311 mp->m_rsumsize = roundup(mp->m_rsumsize, sbp->sb_blocksize);
2312 mp->m_rbmip = mp->m_rsumip = NULL;
2313
2314
2315
2316 d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
2317 if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_rblocks) {
2318 cmn_err(CE_WARN, "XFS: realtime mount -- %llu != %llu",
2319 (unsigned long long) XFS_BB_TO_FSB(mp, d),
2320 (unsigned long long) mp->m_sb.sb_rblocks);
2321 return XFS_ERROR(E2BIG);
2322 }
2323 error = xfs_read_buf(mp, mp->m_rtdev_targp,
2324 d - XFS_FSB_TO_BB(mp, 1),
2325 XFS_FSB_TO_BB(mp, 1), 0, &bp);
2326 if (error) {
2327 cmn_err(CE_WARN,
2328 "XFS: realtime mount -- xfs_read_buf failed, returned %d", error);
2329 if (error == ENOSPC)
2330 return XFS_ERROR(E2BIG);
2331 return error;
2332 }
2333 xfs_buf_relse(bp);
2334 return 0;
2335}
2336
2337
2338
2339
2340
2341int
2342xfs_rtmount_inodes(
2343 xfs_mount_t *mp)
2344{
2345 int error;
2346 xfs_sb_t *sbp;
2347
2348 sbp = &mp->m_sb;
2349 if (sbp->sb_rbmino == NULLFSINO)
2350 return 0;
2351 error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip, 0);
2352 if (error)
2353 return error;
2354 ASSERT(mp->m_rbmip != NULL);
2355 ASSERT(sbp->sb_rsumino != NULLFSINO);
2356 error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip, 0);
2357 if (error) {
2358 VN_RELE(XFS_ITOV(mp->m_rbmip));
2359 return error;
2360 }
2361 ASSERT(mp->m_rsumip != NULL);
2362 return 0;
2363}
2364
2365
2366
2367
2368
2369
2370
2371
2372int
2373xfs_rtpick_extent(
2374 xfs_mount_t *mp,
2375 xfs_trans_t *tp,
2376 xfs_extlen_t len,
2377 xfs_rtblock_t *pick)
2378{
2379 xfs_rtblock_t b;
2380 int error;
2381 xfs_inode_t *ip;
2382 int log2;
2383 __uint64_t resid;
2384 __uint64_t seq;
2385 __uint64_t *seqp;
2386
2387 error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, XFS_ILOCK_EXCL, &ip);
2388 if (error)
2389 return error;
2390 ASSERT(ip == mp->m_rbmip);
2391 seqp = (__uint64_t *)&ip->i_d.di_atime;
2392 if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) {
2393 ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
2394 *seqp = 0;
2395 }
2396 seq = *seqp;
2397 if ((log2 = xfs_highbit64(seq)) == -1)
2398 b = 0;
2399 else {
2400 resid = seq - (1ULL << log2);
2401 b = (mp->m_sb.sb_rextents * ((resid << 1) + 1ULL)) >>
2402 (log2 + 1);
2403 if (b >= mp->m_sb.sb_rextents)
2404 b = do_mod(b, mp->m_sb.sb_rextents);
2405 if (b + len > mp->m_sb.sb_rextents)
2406 b = mp->m_sb.sb_rextents - len;
2407 }
2408 *seqp = seq + 1;
2409 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
2410 *pick = b;
2411 return 0;
2412}
2413
2414#ifdef DEBUG
2415
2416
2417
2418void
2419xfs_rtprint_range(
2420 xfs_mount_t *mp,
2421 xfs_trans_t *tp,
2422 xfs_rtblock_t start,
2423 xfs_extlen_t len)
2424{
2425 xfs_extlen_t i;
2426
2427 printk("%Ld: ", (long long)start);
2428 for (i = 0; i < len; i++)
2429 printk("%d", xfs_rtcheck_bit(mp, tp, start + i, 1));
2430 printk("\n");
2431}
2432
2433
2434
2435
2436void
2437xfs_rtprint_summary(
2438 xfs_mount_t *mp,
2439 xfs_trans_t *tp)
2440{
2441 xfs_suminfo_t c;
2442 xfs_rtblock_t i;
2443 int l;
2444 int p;
2445 xfs_fsblock_t sb;
2446 xfs_buf_t *sumbp;
2447
2448 sumbp = NULL;
2449 for (l = 0; l < mp->m_rsumlevels; l++) {
2450 for (p = 0, i = 0; i < mp->m_sb.sb_rbmblocks; i++) {
2451 (void)xfs_rtget_summary(mp, tp, l, i, &sumbp, &sb, &c);
2452 if (c) {
2453 if (!p) {
2454 printk("%Ld-%Ld:", 1LL << l,
2455 XFS_RTMIN((1LL << l) +
2456 ((1LL << l) - 1LL),
2457 mp->m_sb.sb_rextents));
2458 p = 1;
2459 }
2460 printk(" %Ld:%d", (long long)i, c);
2461 }
2462 }
2463 if (p)
2464 printk("\n");
2465 }
2466 if (sumbp)
2467 xfs_trans_brelse(tp, sumbp);
2468}
2469#endif
2470