1
2
3
4
5
6#include "xfs.h"
7#include "xfs_fs.h"
8#include "xfs_shared.h"
9#include "xfs_format.h"
10#include "xfs_log_format.h"
11#include "xfs_trans_resv.h"
12#include "xfs_bit.h"
13#include "xfs_mount.h"
14#include "xfs_inode.h"
15#include "xfs_bmap.h"
16#include "xfs_trans.h"
17#include "xfs_rtalloc.h"
18#include "xfs_error.h"
19
20
21
22
23
24
25
26
27
28
29static void
30xfs_rtbuf_verify_read(
31 struct xfs_buf *bp)
32{
33 return;
34}
35
36static void
37xfs_rtbuf_verify_write(
38 struct xfs_buf *bp)
39{
40 return;
41}
42
43const struct xfs_buf_ops xfs_rtbuf_ops = {
44 .name = "rtbuf",
45 .verify_read = xfs_rtbuf_verify_read,
46 .verify_write = xfs_rtbuf_verify_write,
47};
48
49
50
51
52
53int
54xfs_rtbuf_get(
55 xfs_mount_t *mp,
56 xfs_trans_t *tp,
57 xfs_rtblock_t block,
58 int issum,
59 struct xfs_buf **bpp)
60{
61 struct xfs_buf *bp;
62 xfs_inode_t *ip;
63 xfs_bmbt_irec_t map;
64 int nmap = 1;
65 int error;
66
67 ip = issum ? mp->m_rsumip : mp->m_rbmip;
68
69 error = xfs_bmapi_read(ip, block, 1, &map, &nmap, 0);
70 if (error)
71 return error;
72
73 if (XFS_IS_CORRUPT(mp, nmap == 0 || !xfs_bmap_is_written_extent(&map)))
74 return -EFSCORRUPTED;
75
76 ASSERT(map.br_startblock != NULLFSBLOCK);
77 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
78 XFS_FSB_TO_DADDR(mp, map.br_startblock),
79 mp->m_bsize, 0, &bp, &xfs_rtbuf_ops);
80 if (error)
81 return error;
82
83 xfs_trans_buf_set_type(tp, bp, issum ? XFS_BLFT_RTSUMMARY_BUF
84 : XFS_BLFT_RTBITMAP_BUF);
85 *bpp = bp;
86 return 0;
87}
88
89
90
91
92
93int
94xfs_rtfind_back(
95 xfs_mount_t *mp,
96 xfs_trans_t *tp,
97 xfs_rtblock_t start,
98 xfs_rtblock_t limit,
99 xfs_rtblock_t *rtblock)
100{
101 xfs_rtword_t *b;
102 int bit;
103 xfs_rtblock_t block;
104 struct xfs_buf *bp;
105 xfs_rtword_t *bufp;
106 int error;
107 xfs_rtblock_t firstbit;
108 xfs_rtblock_t i;
109 xfs_rtblock_t len;
110 xfs_rtword_t mask;
111 xfs_rtword_t want;
112 xfs_rtword_t wdiff;
113 int word;
114
115
116
117
118 block = XFS_BITTOBLOCK(mp, start);
119 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
120 if (error) {
121 return error;
122 }
123 bufp = bp->b_addr;
124
125
126
127 word = XFS_BITTOWORD(mp, start);
128 b = &bufp[word];
129 bit = (int)(start & (XFS_NBWORD - 1));
130 len = start - limit + 1;
131
132
133
134
135 want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
136
137
138
139
140 if (bit < XFS_NBWORD - 1) {
141
142
143
144
145 firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
146 mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
147 firstbit;
148
149
150
151
152 if ((wdiff = (*b ^ want) & mask)) {
153
154
155
156 xfs_trans_brelse(tp, bp);
157 i = bit - XFS_RTHIBIT(wdiff);
158 *rtblock = start - i + 1;
159 return 0;
160 }
161 i = bit - firstbit + 1;
162
163
164
165
166 if (--word == -1 && i < len) {
167
168
169
170 xfs_trans_brelse(tp, bp);
171 error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
172 if (error) {
173 return error;
174 }
175 bufp = bp->b_addr;
176 word = XFS_BLOCKWMASK(mp);
177 b = &bufp[word];
178 } else {
179
180
181
182 b--;
183 }
184 } else {
185
186
187
188 i = 0;
189 }
190
191
192
193
194 while (len - i >= XFS_NBWORD) {
195
196
197
198 if ((wdiff = *b ^ want)) {
199
200
201
202 xfs_trans_brelse(tp, bp);
203 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
204 *rtblock = start - i + 1;
205 return 0;
206 }
207 i += XFS_NBWORD;
208
209
210
211
212 if (--word == -1 && i < len) {
213
214
215
216 xfs_trans_brelse(tp, bp);
217 error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
218 if (error) {
219 return error;
220 }
221 bufp = bp->b_addr;
222 word = XFS_BLOCKWMASK(mp);
223 b = &bufp[word];
224 } else {
225
226
227
228 b--;
229 }
230 }
231
232
233
234
235 if (len - i) {
236
237
238
239
240 firstbit = XFS_NBWORD - (len - i);
241 mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
242
243
244
245 if ((wdiff = (*b ^ want) & mask)) {
246
247
248
249 xfs_trans_brelse(tp, bp);
250 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
251 *rtblock = start - i + 1;
252 return 0;
253 } else
254 i = len;
255 }
256
257
258
259 xfs_trans_brelse(tp, bp);
260 *rtblock = start - i + 1;
261 return 0;
262}
263
264
265
266
267
268int
269xfs_rtfind_forw(
270 xfs_mount_t *mp,
271 xfs_trans_t *tp,
272 xfs_rtblock_t start,
273 xfs_rtblock_t limit,
274 xfs_rtblock_t *rtblock)
275{
276 xfs_rtword_t *b;
277 int bit;
278 xfs_rtblock_t block;
279 struct xfs_buf *bp;
280 xfs_rtword_t *bufp;
281 int error;
282 xfs_rtblock_t i;
283 xfs_rtblock_t lastbit;
284 xfs_rtblock_t len;
285 xfs_rtword_t mask;
286 xfs_rtword_t want;
287 xfs_rtword_t wdiff;
288 int word;
289
290
291
292
293 block = XFS_BITTOBLOCK(mp, start);
294 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
295 if (error) {
296 return error;
297 }
298 bufp = bp->b_addr;
299
300
301
302 word = XFS_BITTOWORD(mp, start);
303 b = &bufp[word];
304 bit = (int)(start & (XFS_NBWORD - 1));
305 len = limit - start + 1;
306
307
308
309
310 want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
311
312
313
314
315 if (bit) {
316
317
318
319
320 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
321 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
322
323
324
325
326 if ((wdiff = (*b ^ want) & mask)) {
327
328
329
330 xfs_trans_brelse(tp, bp);
331 i = XFS_RTLOBIT(wdiff) - bit;
332 *rtblock = start + i - 1;
333 return 0;
334 }
335 i = lastbit - bit;
336
337
338
339
340 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
341
342
343
344 xfs_trans_brelse(tp, bp);
345 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
346 if (error) {
347 return error;
348 }
349 b = bufp = bp->b_addr;
350 word = 0;
351 } else {
352
353
354
355 b++;
356 }
357 } else {
358
359
360
361 i = 0;
362 }
363
364
365
366
367 while (len - i >= XFS_NBWORD) {
368
369
370
371 if ((wdiff = *b ^ want)) {
372
373
374
375 xfs_trans_brelse(tp, bp);
376 i += XFS_RTLOBIT(wdiff);
377 *rtblock = start + i - 1;
378 return 0;
379 }
380 i += XFS_NBWORD;
381
382
383
384
385 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
386
387
388
389 xfs_trans_brelse(tp, bp);
390 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
391 if (error) {
392 return error;
393 }
394 b = bufp = bp->b_addr;
395 word = 0;
396 } else {
397
398
399
400 b++;
401 }
402 }
403
404
405
406
407 if ((lastbit = len - i)) {
408
409
410
411 mask = ((xfs_rtword_t)1 << lastbit) - 1;
412
413
414
415 if ((wdiff = (*b ^ want) & mask)) {
416
417
418
419 xfs_trans_brelse(tp, bp);
420 i += XFS_RTLOBIT(wdiff);
421 *rtblock = start + i - 1;
422 return 0;
423 } else
424 i = len;
425 }
426
427
428
429 xfs_trans_brelse(tp, bp);
430 *rtblock = start + i - 1;
431 return 0;
432}
433
434
435
436
437
438
439
440
441
442
443int
444xfs_rtmodify_summary_int(
445 xfs_mount_t *mp,
446 xfs_trans_t *tp,
447 int log,
448 xfs_rtblock_t bbno,
449 int delta,
450 struct xfs_buf **rbpp,
451 xfs_fsblock_t *rsb,
452 xfs_suminfo_t *sum)
453{
454 struct xfs_buf *bp;
455 int error;
456 xfs_fsblock_t sb;
457 int so;
458 xfs_suminfo_t *sp;
459
460
461
462
463 so = XFS_SUMOFFS(mp, log, bbno);
464
465
466
467 sb = XFS_SUMOFFSTOBLOCK(mp, so);
468
469
470
471 if (*rbpp && *rsb == sb)
472 bp = *rbpp;
473
474
475
476 else {
477
478
479
480 if (*rbpp)
481 xfs_trans_brelse(tp, *rbpp);
482 error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
483 if (error) {
484 return error;
485 }
486
487
488
489 *rbpp = bp;
490 *rsb = sb;
491 }
492
493
494
495 sp = XFS_SUMPTR(mp, bp, so);
496 if (delta) {
497 uint first = (uint)((char *)sp - (char *)bp->b_addr);
498
499 *sp += delta;
500 if (mp->m_rsum_cache) {
501 if (*sp == 0 && log == mp->m_rsum_cache[bbno])
502 mp->m_rsum_cache[bbno]++;
503 if (*sp != 0 && log < mp->m_rsum_cache[bbno])
504 mp->m_rsum_cache[bbno] = log;
505 }
506 xfs_trans_log_buf(tp, bp, first, first + sizeof(*sp) - 1);
507 }
508 if (sum)
509 *sum = *sp;
510 return 0;
511}
512
513int
514xfs_rtmodify_summary(
515 xfs_mount_t *mp,
516 xfs_trans_t *tp,
517 int log,
518 xfs_rtblock_t bbno,
519 int delta,
520 struct xfs_buf **rbpp,
521 xfs_fsblock_t *rsb)
522{
523 return xfs_rtmodify_summary_int(mp, tp, log, bbno,
524 delta, rbpp, rsb, NULL);
525}
526
527
528
529
530
531int
532xfs_rtmodify_range(
533 xfs_mount_t *mp,
534 xfs_trans_t *tp,
535 xfs_rtblock_t start,
536 xfs_extlen_t len,
537 int val)
538{
539 xfs_rtword_t *b;
540 int bit;
541 xfs_rtblock_t block;
542 struct xfs_buf *bp;
543 xfs_rtword_t *bufp;
544 int error;
545 xfs_rtword_t *first;
546 int i;
547 int lastbit;
548 xfs_rtword_t mask;
549 int word;
550
551
552
553
554 block = XFS_BITTOBLOCK(mp, start);
555
556
557
558 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
559 if (error) {
560 return error;
561 }
562 bufp = bp->b_addr;
563
564
565
566 word = XFS_BITTOWORD(mp, start);
567 first = b = &bufp[word];
568 bit = (int)(start & (XFS_NBWORD - 1));
569
570
571
572 val = -val;
573
574
575
576
577 if (bit) {
578
579
580
581 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
582 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
583
584
585
586 if (val)
587 *b |= mask;
588 else
589 *b &= ~mask;
590 i = lastbit - bit;
591
592
593
594
595 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
596
597
598
599
600 xfs_trans_log_buf(tp, bp,
601 (uint)((char *)first - (char *)bufp),
602 (uint)((char *)b - (char *)bufp));
603 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
604 if (error) {
605 return error;
606 }
607 first = b = bufp = bp->b_addr;
608 word = 0;
609 } else {
610
611
612
613 b++;
614 }
615 } else {
616
617
618
619 i = 0;
620 }
621
622
623
624
625 while (len - i >= XFS_NBWORD) {
626
627
628
629 *b = val;
630 i += XFS_NBWORD;
631
632
633
634
635 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
636
637
638
639
640 xfs_trans_log_buf(tp, bp,
641 (uint)((char *)first - (char *)bufp),
642 (uint)((char *)b - (char *)bufp));
643 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
644 if (error) {
645 return error;
646 }
647 first = b = bufp = bp->b_addr;
648 word = 0;
649 } else {
650
651
652
653 b++;
654 }
655 }
656
657
658
659
660 if ((lastbit = len - i)) {
661
662
663
664 mask = ((xfs_rtword_t)1 << lastbit) - 1;
665
666
667
668 if (val)
669 *b |= mask;
670 else
671 *b &= ~mask;
672 b++;
673 }
674
675
676
677 if (b > first)
678 xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
679 (uint)((char *)b - (char *)bufp - 1));
680 return 0;
681}
682
683
684
685
686
687int
688xfs_rtfree_range(
689 xfs_mount_t *mp,
690 xfs_trans_t *tp,
691 xfs_rtblock_t start,
692 xfs_extlen_t len,
693 struct xfs_buf **rbpp,
694 xfs_fsblock_t *rsb)
695{
696 xfs_rtblock_t end;
697 int error;
698 xfs_rtblock_t postblock;
699 xfs_rtblock_t preblock;
700
701 end = start + len - 1;
702
703
704
705 error = xfs_rtmodify_range(mp, tp, start, len, 1);
706 if (error) {
707 return error;
708 }
709
710
711
712
713
714 error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
715 if (error) {
716 return error;
717 }
718
719
720
721 error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
722 &postblock);
723 if (error)
724 return error;
725
726
727
728
729 if (preblock < start) {
730 error = xfs_rtmodify_summary(mp, tp,
731 XFS_RTBLOCKLOG(start - preblock),
732 XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
733 if (error) {
734 return error;
735 }
736 }
737
738
739
740
741 if (postblock > end) {
742 error = xfs_rtmodify_summary(mp, tp,
743 XFS_RTBLOCKLOG(postblock - end),
744 XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
745 if (error) {
746 return error;
747 }
748 }
749
750
751
752
753 error = xfs_rtmodify_summary(mp, tp,
754 XFS_RTBLOCKLOG(postblock + 1 - preblock),
755 XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
756 return error;
757}
758
759
760
761
762
763int
764xfs_rtcheck_range(
765 xfs_mount_t *mp,
766 xfs_trans_t *tp,
767 xfs_rtblock_t start,
768 xfs_extlen_t len,
769 int val,
770 xfs_rtblock_t *new,
771 int *stat)
772{
773 xfs_rtword_t *b;
774 int bit;
775 xfs_rtblock_t block;
776 struct xfs_buf *bp;
777 xfs_rtword_t *bufp;
778 int error;
779 xfs_rtblock_t i;
780 xfs_rtblock_t lastbit;
781 xfs_rtword_t mask;
782 xfs_rtword_t wdiff;
783 int word;
784
785
786
787
788 block = XFS_BITTOBLOCK(mp, start);
789
790
791
792 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
793 if (error) {
794 return error;
795 }
796 bufp = bp->b_addr;
797
798
799
800 word = XFS_BITTOWORD(mp, start);
801 b = &bufp[word];
802 bit = (int)(start & (XFS_NBWORD - 1));
803
804
805
806 val = -val;
807
808
809
810
811 if (bit) {
812
813
814
815 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
816
817
818
819 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
820
821
822
823 if ((wdiff = (*b ^ val) & mask)) {
824
825
826
827 xfs_trans_brelse(tp, bp);
828 i = XFS_RTLOBIT(wdiff) - bit;
829 *new = start + i;
830 *stat = 0;
831 return 0;
832 }
833 i = lastbit - bit;
834
835
836
837
838 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
839
840
841
842 xfs_trans_brelse(tp, bp);
843 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
844 if (error) {
845 return error;
846 }
847 b = bufp = bp->b_addr;
848 word = 0;
849 } else {
850
851
852
853 b++;
854 }
855 } else {
856
857
858
859 i = 0;
860 }
861
862
863
864
865 while (len - i >= XFS_NBWORD) {
866
867
868
869 if ((wdiff = *b ^ val)) {
870
871
872
873 xfs_trans_brelse(tp, bp);
874 i += XFS_RTLOBIT(wdiff);
875 *new = start + i;
876 *stat = 0;
877 return 0;
878 }
879 i += XFS_NBWORD;
880
881
882
883
884 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
885
886
887
888 xfs_trans_brelse(tp, bp);
889 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
890 if (error) {
891 return error;
892 }
893 b = bufp = bp->b_addr;
894 word = 0;
895 } else {
896
897
898
899 b++;
900 }
901 }
902
903
904
905
906 if ((lastbit = len - i)) {
907
908
909
910 mask = ((xfs_rtword_t)1 << lastbit) - 1;
911
912
913
914 if ((wdiff = (*b ^ val) & mask)) {
915
916
917
918 xfs_trans_brelse(tp, bp);
919 i += XFS_RTLOBIT(wdiff);
920 *new = start + i;
921 *stat = 0;
922 return 0;
923 } else
924 i = len;
925 }
926
927
928
929 xfs_trans_brelse(tp, bp);
930 *new = start + i;
931 *stat = 1;
932 return 0;
933}
934
935#ifdef DEBUG
936
937
938
939STATIC int
940xfs_rtcheck_alloc_range(
941 xfs_mount_t *mp,
942 xfs_trans_t *tp,
943 xfs_rtblock_t bno,
944 xfs_extlen_t len)
945{
946 xfs_rtblock_t new;
947 int stat;
948 int error;
949
950 error = xfs_rtcheck_range(mp, tp, bno, len, 0, &new, &stat);
951 if (error)
952 return error;
953 ASSERT(stat);
954 return 0;
955}
956#else
957#define xfs_rtcheck_alloc_range(m,t,b,l) (0)
958#endif
959
960
961
962
963int
964xfs_rtfree_extent(
965 xfs_trans_t *tp,
966 xfs_rtblock_t bno,
967 xfs_extlen_t len)
968{
969 int error;
970 xfs_mount_t *mp;
971 xfs_fsblock_t sb;
972 struct xfs_buf *sumbp = NULL;
973
974 mp = tp->t_mountp;
975
976 ASSERT(mp->m_rbmip->i_itemp != NULL);
977 ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
978
979 error = xfs_rtcheck_alloc_range(mp, tp, bno, len);
980 if (error)
981 return error;
982
983
984
985
986 error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
987 if (error) {
988 return error;
989 }
990
991
992
993 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
994
995
996
997
998 if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
999 mp->m_sb.sb_rextents) {
1000 if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
1001 mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
1002 *(uint64_t *)&VFS_I(mp->m_rbmip)->i_atime = 0;
1003 xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
1004 }
1005 return 0;
1006}
1007
1008
1009int
1010xfs_rtalloc_query_range(
1011 struct xfs_trans *tp,
1012 struct xfs_rtalloc_rec *low_rec,
1013 struct xfs_rtalloc_rec *high_rec,
1014 xfs_rtalloc_query_range_fn fn,
1015 void *priv)
1016{
1017 struct xfs_rtalloc_rec rec;
1018 struct xfs_mount *mp = tp->t_mountp;
1019 xfs_rtblock_t rtstart;
1020 xfs_rtblock_t rtend;
1021 int is_free;
1022 int error = 0;
1023
1024 if (low_rec->ar_startext > high_rec->ar_startext)
1025 return -EINVAL;
1026 if (low_rec->ar_startext >= mp->m_sb.sb_rextents ||
1027 low_rec->ar_startext == high_rec->ar_startext)
1028 return 0;
1029 high_rec->ar_startext = min(high_rec->ar_startext,
1030 mp->m_sb.sb_rextents - 1);
1031
1032
1033 rtstart = low_rec->ar_startext;
1034 while (rtstart <= high_rec->ar_startext) {
1035
1036 error = xfs_rtcheck_range(mp, tp, rtstart, 1, 1, &rtend,
1037 &is_free);
1038 if (error)
1039 break;
1040
1041
1042 error = xfs_rtfind_forw(mp, tp, rtstart,
1043 high_rec->ar_startext, &rtend);
1044 if (error)
1045 break;
1046
1047 if (is_free) {
1048 rec.ar_startext = rtstart;
1049 rec.ar_extcount = rtend - rtstart + 1;
1050
1051 error = fn(tp, &rec, priv);
1052 if (error)
1053 break;
1054 }
1055
1056 rtstart = rtend + 1;
1057 }
1058
1059 return error;
1060}
1061
1062
1063int
1064xfs_rtalloc_query_all(
1065 struct xfs_trans *tp,
1066 xfs_rtalloc_query_range_fn fn,
1067 void *priv)
1068{
1069 struct xfs_rtalloc_rec keys[2];
1070
1071 keys[0].ar_startext = 0;
1072 keys[1].ar_startext = tp->t_mountp->m_sb.sb_rextents - 1;
1073 keys[0].ar_extcount = keys[1].ar_extcount = 0;
1074
1075 return xfs_rtalloc_query_range(tp, &keys[0], &keys[1], fn, priv);
1076}
1077
1078
1079int
1080xfs_rtalloc_extent_is_free(
1081 struct xfs_mount *mp,
1082 struct xfs_trans *tp,
1083 xfs_rtblock_t start,
1084 xfs_extlen_t len,
1085 bool *is_free)
1086{
1087 xfs_rtblock_t end;
1088 int matches;
1089 int error;
1090
1091 error = xfs_rtcheck_range(mp, tp, start, len, 1, &end, &matches);
1092 if (error)
1093 return error;
1094
1095 *is_free = matches;
1096 return 0;
1097}
1098