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