0001
0002
0003
0004
0005
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_log_format.h"
0011 #include "xfs_trans_resv.h"
0012 #include "xfs_bit.h"
0013 #include "xfs_mount.h"
0014 #include "xfs_inode.h"
0015 #include "xfs_bmap.h"
0016 #include "xfs_trans.h"
0017 #include "xfs_rtalloc.h"
0018 #include "xfs_error.h"
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 static void
0030 xfs_rtbuf_verify_read(
0031 struct xfs_buf *bp)
0032 {
0033 return;
0034 }
0035
0036 static void
0037 xfs_rtbuf_verify_write(
0038 struct xfs_buf *bp)
0039 {
0040 return;
0041 }
0042
0043 const struct xfs_buf_ops xfs_rtbuf_ops = {
0044 .name = "rtbuf",
0045 .verify_read = xfs_rtbuf_verify_read,
0046 .verify_write = xfs_rtbuf_verify_write,
0047 };
0048
0049
0050
0051
0052
0053 int
0054 xfs_rtbuf_get(
0055 xfs_mount_t *mp,
0056 xfs_trans_t *tp,
0057 xfs_rtblock_t block,
0058 int issum,
0059 struct xfs_buf **bpp)
0060 {
0061 struct xfs_buf *bp;
0062 xfs_inode_t *ip;
0063 xfs_bmbt_irec_t map;
0064 int nmap = 1;
0065 int error;
0066
0067 ip = issum ? mp->m_rsumip : mp->m_rbmip;
0068
0069 error = xfs_bmapi_read(ip, block, 1, &map, &nmap, 0);
0070 if (error)
0071 return error;
0072
0073 if (XFS_IS_CORRUPT(mp, nmap == 0 || !xfs_bmap_is_written_extent(&map)))
0074 return -EFSCORRUPTED;
0075
0076 ASSERT(map.br_startblock != NULLFSBLOCK);
0077 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
0078 XFS_FSB_TO_DADDR(mp, map.br_startblock),
0079 mp->m_bsize, 0, &bp, &xfs_rtbuf_ops);
0080 if (error)
0081 return error;
0082
0083 xfs_trans_buf_set_type(tp, bp, issum ? XFS_BLFT_RTSUMMARY_BUF
0084 : XFS_BLFT_RTBITMAP_BUF);
0085 *bpp = bp;
0086 return 0;
0087 }
0088
0089
0090
0091
0092
0093 int
0094 xfs_rtfind_back(
0095 xfs_mount_t *mp,
0096 xfs_trans_t *tp,
0097 xfs_rtblock_t start,
0098 xfs_rtblock_t limit,
0099 xfs_rtblock_t *rtblock)
0100 {
0101 xfs_rtword_t *b;
0102 int bit;
0103 xfs_rtblock_t block;
0104 struct xfs_buf *bp;
0105 xfs_rtword_t *bufp;
0106 int error;
0107 xfs_rtblock_t firstbit;
0108 xfs_rtblock_t i;
0109 xfs_rtblock_t len;
0110 xfs_rtword_t mask;
0111 xfs_rtword_t want;
0112 xfs_rtword_t wdiff;
0113 int word;
0114
0115
0116
0117
0118 block = XFS_BITTOBLOCK(mp, start);
0119 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
0120 if (error) {
0121 return error;
0122 }
0123 bufp = bp->b_addr;
0124
0125
0126
0127 word = XFS_BITTOWORD(mp, start);
0128 b = &bufp[word];
0129 bit = (int)(start & (XFS_NBWORD - 1));
0130 len = start - limit + 1;
0131
0132
0133
0134
0135 want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
0136
0137
0138
0139
0140 if (bit < XFS_NBWORD - 1) {
0141
0142
0143
0144
0145 firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
0146 mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
0147 firstbit;
0148
0149
0150
0151
0152 if ((wdiff = (*b ^ want) & mask)) {
0153
0154
0155
0156 xfs_trans_brelse(tp, bp);
0157 i = bit - XFS_RTHIBIT(wdiff);
0158 *rtblock = start - i + 1;
0159 return 0;
0160 }
0161 i = bit - firstbit + 1;
0162
0163
0164
0165
0166 if (--word == -1 && i < len) {
0167
0168
0169
0170 xfs_trans_brelse(tp, bp);
0171 error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
0172 if (error) {
0173 return error;
0174 }
0175 bufp = bp->b_addr;
0176 word = XFS_BLOCKWMASK(mp);
0177 b = &bufp[word];
0178 } else {
0179
0180
0181
0182 b--;
0183 }
0184 } else {
0185
0186
0187
0188 i = 0;
0189 }
0190
0191
0192
0193
0194 while (len - i >= XFS_NBWORD) {
0195
0196
0197
0198 if ((wdiff = *b ^ want)) {
0199
0200
0201
0202 xfs_trans_brelse(tp, bp);
0203 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
0204 *rtblock = start - i + 1;
0205 return 0;
0206 }
0207 i += XFS_NBWORD;
0208
0209
0210
0211
0212 if (--word == -1 && i < len) {
0213
0214
0215
0216 xfs_trans_brelse(tp, bp);
0217 error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
0218 if (error) {
0219 return error;
0220 }
0221 bufp = bp->b_addr;
0222 word = XFS_BLOCKWMASK(mp);
0223 b = &bufp[word];
0224 } else {
0225
0226
0227
0228 b--;
0229 }
0230 }
0231
0232
0233
0234
0235 if (len - i) {
0236
0237
0238
0239
0240 firstbit = XFS_NBWORD - (len - i);
0241 mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
0242
0243
0244
0245 if ((wdiff = (*b ^ want) & mask)) {
0246
0247
0248
0249 xfs_trans_brelse(tp, bp);
0250 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
0251 *rtblock = start - i + 1;
0252 return 0;
0253 } else
0254 i = len;
0255 }
0256
0257
0258
0259 xfs_trans_brelse(tp, bp);
0260 *rtblock = start - i + 1;
0261 return 0;
0262 }
0263
0264
0265
0266
0267
0268 int
0269 xfs_rtfind_forw(
0270 xfs_mount_t *mp,
0271 xfs_trans_t *tp,
0272 xfs_rtblock_t start,
0273 xfs_rtblock_t limit,
0274 xfs_rtblock_t *rtblock)
0275 {
0276 xfs_rtword_t *b;
0277 int bit;
0278 xfs_rtblock_t block;
0279 struct xfs_buf *bp;
0280 xfs_rtword_t *bufp;
0281 int error;
0282 xfs_rtblock_t i;
0283 xfs_rtblock_t lastbit;
0284 xfs_rtblock_t len;
0285 xfs_rtword_t mask;
0286 xfs_rtword_t want;
0287 xfs_rtword_t wdiff;
0288 int word;
0289
0290
0291
0292
0293 block = XFS_BITTOBLOCK(mp, start);
0294 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
0295 if (error) {
0296 return error;
0297 }
0298 bufp = bp->b_addr;
0299
0300
0301
0302 word = XFS_BITTOWORD(mp, start);
0303 b = &bufp[word];
0304 bit = (int)(start & (XFS_NBWORD - 1));
0305 len = limit - start + 1;
0306
0307
0308
0309
0310 want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
0311
0312
0313
0314
0315 if (bit) {
0316
0317
0318
0319
0320 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
0321 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
0322
0323
0324
0325
0326 if ((wdiff = (*b ^ want) & mask)) {
0327
0328
0329
0330 xfs_trans_brelse(tp, bp);
0331 i = XFS_RTLOBIT(wdiff) - bit;
0332 *rtblock = start + i - 1;
0333 return 0;
0334 }
0335 i = lastbit - bit;
0336
0337
0338
0339
0340 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
0341
0342
0343
0344 xfs_trans_brelse(tp, bp);
0345 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
0346 if (error) {
0347 return error;
0348 }
0349 b = bufp = bp->b_addr;
0350 word = 0;
0351 } else {
0352
0353
0354
0355 b++;
0356 }
0357 } else {
0358
0359
0360
0361 i = 0;
0362 }
0363
0364
0365
0366
0367 while (len - i >= XFS_NBWORD) {
0368
0369
0370
0371 if ((wdiff = *b ^ want)) {
0372
0373
0374
0375 xfs_trans_brelse(tp, bp);
0376 i += XFS_RTLOBIT(wdiff);
0377 *rtblock = start + i - 1;
0378 return 0;
0379 }
0380 i += XFS_NBWORD;
0381
0382
0383
0384
0385 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
0386
0387
0388
0389 xfs_trans_brelse(tp, bp);
0390 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
0391 if (error) {
0392 return error;
0393 }
0394 b = bufp = bp->b_addr;
0395 word = 0;
0396 } else {
0397
0398
0399
0400 b++;
0401 }
0402 }
0403
0404
0405
0406
0407 if ((lastbit = len - i)) {
0408
0409
0410
0411 mask = ((xfs_rtword_t)1 << lastbit) - 1;
0412
0413
0414
0415 if ((wdiff = (*b ^ want) & mask)) {
0416
0417
0418
0419 xfs_trans_brelse(tp, bp);
0420 i += XFS_RTLOBIT(wdiff);
0421 *rtblock = start + i - 1;
0422 return 0;
0423 } else
0424 i = len;
0425 }
0426
0427
0428
0429 xfs_trans_brelse(tp, bp);
0430 *rtblock = start + i - 1;
0431 return 0;
0432 }
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443 int
0444 xfs_rtmodify_summary_int(
0445 xfs_mount_t *mp,
0446 xfs_trans_t *tp,
0447 int log,
0448 xfs_rtblock_t bbno,
0449 int delta,
0450 struct xfs_buf **rbpp,
0451 xfs_fsblock_t *rsb,
0452 xfs_suminfo_t *sum)
0453 {
0454 struct xfs_buf *bp;
0455 int error;
0456 xfs_fsblock_t sb;
0457 int so;
0458 xfs_suminfo_t *sp;
0459
0460
0461
0462
0463 so = XFS_SUMOFFS(mp, log, bbno);
0464
0465
0466
0467 sb = XFS_SUMOFFSTOBLOCK(mp, so);
0468
0469
0470
0471 if (*rbpp && *rsb == sb)
0472 bp = *rbpp;
0473
0474
0475
0476 else {
0477
0478
0479
0480 if (*rbpp)
0481 xfs_trans_brelse(tp, *rbpp);
0482 error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
0483 if (error) {
0484 return error;
0485 }
0486
0487
0488
0489 *rbpp = bp;
0490 *rsb = sb;
0491 }
0492
0493
0494
0495 sp = XFS_SUMPTR(mp, bp, so);
0496 if (delta) {
0497 uint first = (uint)((char *)sp - (char *)bp->b_addr);
0498
0499 *sp += delta;
0500 if (mp->m_rsum_cache) {
0501 if (*sp == 0 && log == mp->m_rsum_cache[bbno])
0502 mp->m_rsum_cache[bbno]++;
0503 if (*sp != 0 && log < mp->m_rsum_cache[bbno])
0504 mp->m_rsum_cache[bbno] = log;
0505 }
0506 xfs_trans_log_buf(tp, bp, first, first + sizeof(*sp) - 1);
0507 }
0508 if (sum)
0509 *sum = *sp;
0510 return 0;
0511 }
0512
0513 int
0514 xfs_rtmodify_summary(
0515 xfs_mount_t *mp,
0516 xfs_trans_t *tp,
0517 int log,
0518 xfs_rtblock_t bbno,
0519 int delta,
0520 struct xfs_buf **rbpp,
0521 xfs_fsblock_t *rsb)
0522 {
0523 return xfs_rtmodify_summary_int(mp, tp, log, bbno,
0524 delta, rbpp, rsb, NULL);
0525 }
0526
0527
0528
0529
0530
0531 int
0532 xfs_rtmodify_range(
0533 xfs_mount_t *mp,
0534 xfs_trans_t *tp,
0535 xfs_rtblock_t start,
0536 xfs_extlen_t len,
0537 int val)
0538 {
0539 xfs_rtword_t *b;
0540 int bit;
0541 xfs_rtblock_t block;
0542 struct xfs_buf *bp;
0543 xfs_rtword_t *bufp;
0544 int error;
0545 xfs_rtword_t *first;
0546 int i;
0547 int lastbit;
0548 xfs_rtword_t mask;
0549 int word;
0550
0551
0552
0553
0554 block = XFS_BITTOBLOCK(mp, start);
0555
0556
0557
0558 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
0559 if (error) {
0560 return error;
0561 }
0562 bufp = bp->b_addr;
0563
0564
0565
0566 word = XFS_BITTOWORD(mp, start);
0567 first = b = &bufp[word];
0568 bit = (int)(start & (XFS_NBWORD - 1));
0569
0570
0571
0572 val = -val;
0573
0574
0575
0576
0577 if (bit) {
0578
0579
0580
0581 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
0582 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
0583
0584
0585
0586 if (val)
0587 *b |= mask;
0588 else
0589 *b &= ~mask;
0590 i = lastbit - bit;
0591
0592
0593
0594
0595 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
0596
0597
0598
0599
0600 xfs_trans_log_buf(tp, bp,
0601 (uint)((char *)first - (char *)bufp),
0602 (uint)((char *)b - (char *)bufp));
0603 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
0604 if (error) {
0605 return error;
0606 }
0607 first = b = bufp = bp->b_addr;
0608 word = 0;
0609 } else {
0610
0611
0612
0613 b++;
0614 }
0615 } else {
0616
0617
0618
0619 i = 0;
0620 }
0621
0622
0623
0624
0625 while (len - i >= XFS_NBWORD) {
0626
0627
0628
0629 *b = val;
0630 i += XFS_NBWORD;
0631
0632
0633
0634
0635 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
0636
0637
0638
0639
0640 xfs_trans_log_buf(tp, bp,
0641 (uint)((char *)first - (char *)bufp),
0642 (uint)((char *)b - (char *)bufp));
0643 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
0644 if (error) {
0645 return error;
0646 }
0647 first = b = bufp = bp->b_addr;
0648 word = 0;
0649 } else {
0650
0651
0652
0653 b++;
0654 }
0655 }
0656
0657
0658
0659
0660 if ((lastbit = len - i)) {
0661
0662
0663
0664 mask = ((xfs_rtword_t)1 << lastbit) - 1;
0665
0666
0667
0668 if (val)
0669 *b |= mask;
0670 else
0671 *b &= ~mask;
0672 b++;
0673 }
0674
0675
0676
0677 if (b > first)
0678 xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
0679 (uint)((char *)b - (char *)bufp - 1));
0680 return 0;
0681 }
0682
0683
0684
0685
0686
0687 int
0688 xfs_rtfree_range(
0689 xfs_mount_t *mp,
0690 xfs_trans_t *tp,
0691 xfs_rtblock_t start,
0692 xfs_extlen_t len,
0693 struct xfs_buf **rbpp,
0694 xfs_fsblock_t *rsb)
0695 {
0696 xfs_rtblock_t end;
0697 int error;
0698 xfs_rtblock_t postblock;
0699 xfs_rtblock_t preblock;
0700
0701 end = start + len - 1;
0702
0703
0704
0705 error = xfs_rtmodify_range(mp, tp, start, len, 1);
0706 if (error) {
0707 return error;
0708 }
0709
0710
0711
0712
0713
0714 error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
0715 if (error) {
0716 return error;
0717 }
0718
0719
0720
0721 error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
0722 &postblock);
0723 if (error)
0724 return error;
0725
0726
0727
0728
0729 if (preblock < start) {
0730 error = xfs_rtmodify_summary(mp, tp,
0731 XFS_RTBLOCKLOG(start - preblock),
0732 XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
0733 if (error) {
0734 return error;
0735 }
0736 }
0737
0738
0739
0740
0741 if (postblock > end) {
0742 error = xfs_rtmodify_summary(mp, tp,
0743 XFS_RTBLOCKLOG(postblock - end),
0744 XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
0745 if (error) {
0746 return error;
0747 }
0748 }
0749
0750
0751
0752
0753 error = xfs_rtmodify_summary(mp, tp,
0754 XFS_RTBLOCKLOG(postblock + 1 - preblock),
0755 XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
0756 return error;
0757 }
0758
0759
0760
0761
0762
0763 int
0764 xfs_rtcheck_range(
0765 xfs_mount_t *mp,
0766 xfs_trans_t *tp,
0767 xfs_rtblock_t start,
0768 xfs_extlen_t len,
0769 int val,
0770 xfs_rtblock_t *new,
0771 int *stat)
0772 {
0773 xfs_rtword_t *b;
0774 int bit;
0775 xfs_rtblock_t block;
0776 struct xfs_buf *bp;
0777 xfs_rtword_t *bufp;
0778 int error;
0779 xfs_rtblock_t i;
0780 xfs_rtblock_t lastbit;
0781 xfs_rtword_t mask;
0782 xfs_rtword_t wdiff;
0783 int word;
0784
0785
0786
0787
0788 block = XFS_BITTOBLOCK(mp, start);
0789
0790
0791
0792 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
0793 if (error) {
0794 return error;
0795 }
0796 bufp = bp->b_addr;
0797
0798
0799
0800 word = XFS_BITTOWORD(mp, start);
0801 b = &bufp[word];
0802 bit = (int)(start & (XFS_NBWORD - 1));
0803
0804
0805
0806 val = -val;
0807
0808
0809
0810
0811 if (bit) {
0812
0813
0814
0815 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
0816
0817
0818
0819 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
0820
0821
0822
0823 if ((wdiff = (*b ^ val) & mask)) {
0824
0825
0826
0827 xfs_trans_brelse(tp, bp);
0828 i = XFS_RTLOBIT(wdiff) - bit;
0829 *new = start + i;
0830 *stat = 0;
0831 return 0;
0832 }
0833 i = lastbit - bit;
0834
0835
0836
0837
0838 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
0839
0840
0841
0842 xfs_trans_brelse(tp, bp);
0843 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
0844 if (error) {
0845 return error;
0846 }
0847 b = bufp = bp->b_addr;
0848 word = 0;
0849 } else {
0850
0851
0852
0853 b++;
0854 }
0855 } else {
0856
0857
0858
0859 i = 0;
0860 }
0861
0862
0863
0864
0865 while (len - i >= XFS_NBWORD) {
0866
0867
0868
0869 if ((wdiff = *b ^ val)) {
0870
0871
0872
0873 xfs_trans_brelse(tp, bp);
0874 i += XFS_RTLOBIT(wdiff);
0875 *new = start + i;
0876 *stat = 0;
0877 return 0;
0878 }
0879 i += XFS_NBWORD;
0880
0881
0882
0883
0884 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
0885
0886
0887
0888 xfs_trans_brelse(tp, bp);
0889 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
0890 if (error) {
0891 return error;
0892 }
0893 b = bufp = bp->b_addr;
0894 word = 0;
0895 } else {
0896
0897
0898
0899 b++;
0900 }
0901 }
0902
0903
0904
0905
0906 if ((lastbit = len - i)) {
0907
0908
0909
0910 mask = ((xfs_rtword_t)1 << lastbit) - 1;
0911
0912
0913
0914 if ((wdiff = (*b ^ val) & mask)) {
0915
0916
0917
0918 xfs_trans_brelse(tp, bp);
0919 i += XFS_RTLOBIT(wdiff);
0920 *new = start + i;
0921 *stat = 0;
0922 return 0;
0923 } else
0924 i = len;
0925 }
0926
0927
0928
0929 xfs_trans_brelse(tp, bp);
0930 *new = start + i;
0931 *stat = 1;
0932 return 0;
0933 }
0934
0935 #ifdef DEBUG
0936
0937
0938
0939 STATIC int
0940 xfs_rtcheck_alloc_range(
0941 xfs_mount_t *mp,
0942 xfs_trans_t *tp,
0943 xfs_rtblock_t bno,
0944 xfs_extlen_t len)
0945 {
0946 xfs_rtblock_t new;
0947 int stat;
0948 int error;
0949
0950 error = xfs_rtcheck_range(mp, tp, bno, len, 0, &new, &stat);
0951 if (error)
0952 return error;
0953 ASSERT(stat);
0954 return 0;
0955 }
0956 #else
0957 #define xfs_rtcheck_alloc_range(m,t,b,l) (0)
0958 #endif
0959
0960
0961
0962
0963 int
0964 xfs_rtfree_extent(
0965 xfs_trans_t *tp,
0966 xfs_rtblock_t bno,
0967 xfs_extlen_t len)
0968 {
0969 int error;
0970 xfs_mount_t *mp;
0971 xfs_fsblock_t sb;
0972 struct xfs_buf *sumbp = NULL;
0973
0974 mp = tp->t_mountp;
0975
0976 ASSERT(mp->m_rbmip->i_itemp != NULL);
0977 ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
0978
0979 error = xfs_rtcheck_alloc_range(mp, tp, bno, len);
0980 if (error)
0981 return error;
0982
0983
0984
0985
0986 error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
0987 if (error) {
0988 return error;
0989 }
0990
0991
0992
0993 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
0994
0995
0996
0997
0998 if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
0999 mp->m_sb.sb_rextents) {
1000 if (!(mp->m_rbmip->i_diflags & XFS_DIFLAG_NEWRTBM))
1001 mp->m_rbmip->i_diflags |= 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
1009 int
1010 xfs_rtalloc_query_range(
1011 struct xfs_mount *mp,
1012 struct xfs_trans *tp,
1013 const struct xfs_rtalloc_rec *low_rec,
1014 const struct xfs_rtalloc_rec *high_rec,
1015 xfs_rtalloc_query_range_fn fn,
1016 void *priv)
1017 {
1018 struct xfs_rtalloc_rec rec;
1019 xfs_rtblock_t rtstart;
1020 xfs_rtblock_t rtend;
1021 xfs_rtblock_t high_key;
1022 int is_free;
1023 int error = 0;
1024
1025 if (low_rec->ar_startext > high_rec->ar_startext)
1026 return -EINVAL;
1027 if (low_rec->ar_startext >= mp->m_sb.sb_rextents ||
1028 low_rec->ar_startext == high_rec->ar_startext)
1029 return 0;
1030
1031 high_key = min(high_rec->ar_startext, mp->m_sb.sb_rextents - 1);
1032
1033
1034 rtstart = low_rec->ar_startext;
1035 while (rtstart <= high_key) {
1036
1037 error = xfs_rtcheck_range(mp, tp, rtstart, 1, 1, &rtend,
1038 &is_free);
1039 if (error)
1040 break;
1041
1042
1043 error = xfs_rtfind_forw(mp, tp, rtstart, high_key, &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(mp, tp, &rec, priv);
1052 if (error)
1053 break;
1054 }
1055
1056 rtstart = rtend + 1;
1057 }
1058
1059 return error;
1060 }
1061
1062
1063 int
1064 xfs_rtalloc_query_all(
1065 struct xfs_mount *mp,
1066 struct xfs_trans *tp,
1067 xfs_rtalloc_query_range_fn fn,
1068 void *priv)
1069 {
1070 struct xfs_rtalloc_rec keys[2];
1071
1072 keys[0].ar_startext = 0;
1073 keys[1].ar_startext = mp->m_sb.sb_rextents - 1;
1074 keys[0].ar_extcount = keys[1].ar_extcount = 0;
1075
1076 return xfs_rtalloc_query_range(mp, tp, &keys[0], &keys[1], fn, priv);
1077 }
1078
1079
1080 int
1081 xfs_rtalloc_extent_is_free(
1082 struct xfs_mount *mp,
1083 struct xfs_trans *tp,
1084 xfs_rtblock_t start,
1085 xfs_extlen_t len,
1086 bool *is_free)
1087 {
1088 xfs_rtblock_t end;
1089 int matches;
1090 int error;
1091
1092 error = xfs_rtcheck_range(mp, tp, start, len, 1, &end, &matches);
1093 if (error)
1094 return error;
1095
1096 *is_free = matches;
1097 return 0;
1098 }