0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "debug.h"
0010 #include "dir.h"
0011 #include "endian.h"
0012 #include "malloc.h"
0013 #include "ntfs.h"
0014
0015
0016
0017
0018
0019
0020 static inline void ntfs_rl_mm(runlist_element *base, int dst, int src,
0021 int size)
0022 {
0023 if (likely((dst != src) && (size > 0)))
0024 memmove(base + dst, base + src, size * sizeof(*base));
0025 }
0026
0027
0028
0029
0030
0031
0032
0033 static inline void ntfs_rl_mc(runlist_element *dstbase, int dst,
0034 runlist_element *srcbase, int src, int size)
0035 {
0036 if (likely(size > 0))
0037 memcpy(dstbase + dst, srcbase + src, size * sizeof(*dstbase));
0038 }
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060 static inline runlist_element *ntfs_rl_realloc(runlist_element *rl,
0061 int old_size, int new_size)
0062 {
0063 runlist_element *new_rl;
0064
0065 old_size = PAGE_ALIGN(old_size * sizeof(*rl));
0066 new_size = PAGE_ALIGN(new_size * sizeof(*rl));
0067 if (old_size == new_size)
0068 return rl;
0069
0070 new_rl = ntfs_malloc_nofs(new_size);
0071 if (unlikely(!new_rl))
0072 return ERR_PTR(-ENOMEM);
0073
0074 if (likely(rl != NULL)) {
0075 if (unlikely(old_size > new_size))
0076 old_size = new_size;
0077 memcpy(new_rl, rl, old_size);
0078 ntfs_free(rl);
0079 }
0080 return new_rl;
0081 }
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106 static inline runlist_element *ntfs_rl_realloc_nofail(runlist_element *rl,
0107 int old_size, int new_size)
0108 {
0109 runlist_element *new_rl;
0110
0111 old_size = PAGE_ALIGN(old_size * sizeof(*rl));
0112 new_size = PAGE_ALIGN(new_size * sizeof(*rl));
0113 if (old_size == new_size)
0114 return rl;
0115
0116 new_rl = ntfs_malloc_nofs_nofail(new_size);
0117 BUG_ON(!new_rl);
0118
0119 if (likely(rl != NULL)) {
0120 if (unlikely(old_size > new_size))
0121 old_size = new_size;
0122 memcpy(new_rl, rl, old_size);
0123 ntfs_free(rl);
0124 }
0125 return new_rl;
0126 }
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141 static inline bool ntfs_are_rl_mergeable(runlist_element *dst,
0142 runlist_element *src)
0143 {
0144 BUG_ON(!dst);
0145 BUG_ON(!src);
0146
0147
0148 if ((dst->lcn == LCN_RL_NOT_MAPPED) && (src->lcn == LCN_RL_NOT_MAPPED))
0149 return true;
0150
0151 if ((dst->vcn + dst->length) != src->vcn)
0152 return false;
0153
0154 if ((dst->lcn >= 0) && (src->lcn >= 0) &&
0155 ((dst->lcn + dst->length) == src->lcn))
0156 return true;
0157
0158 if ((dst->lcn == LCN_HOLE) && (src->lcn == LCN_HOLE))
0159 return true;
0160
0161 return false;
0162 }
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175 static inline void __ntfs_rl_merge(runlist_element *dst, runlist_element *src)
0176 {
0177 dst->length += src->length;
0178 }
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204 static inline runlist_element *ntfs_rl_append(runlist_element *dst,
0205 int dsize, runlist_element *src, int ssize, int loc)
0206 {
0207 bool right = false;
0208 int marker;
0209
0210 BUG_ON(!dst);
0211 BUG_ON(!src);
0212
0213
0214 if ((loc + 1) < dsize)
0215 right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1);
0216
0217
0218 dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - right);
0219 if (IS_ERR(dst))
0220 return dst;
0221
0222
0223
0224
0225
0226
0227 if (right)
0228 __ntfs_rl_merge(src + ssize - 1, dst + loc + 1);
0229
0230
0231 marker = loc + ssize + 1;
0232
0233
0234 ntfs_rl_mm(dst, marker, loc + 1 + right, dsize - (loc + 1 + right));
0235 ntfs_rl_mc(dst, loc + 1, src, 0, ssize);
0236
0237
0238 dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn;
0239
0240
0241 if (dst[marker].lcn == LCN_ENOENT)
0242 dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
0243
0244 return dst;
0245 }
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271 static inline runlist_element *ntfs_rl_insert(runlist_element *dst,
0272 int dsize, runlist_element *src, int ssize, int loc)
0273 {
0274 bool left = false;
0275 bool disc = false;
0276 int marker;
0277
0278 BUG_ON(!dst);
0279 BUG_ON(!src);
0280
0281
0282
0283
0284
0285 if (loc == 0)
0286 disc = (src[0].vcn > 0);
0287 else {
0288 s64 merged_length;
0289
0290 left = ntfs_are_rl_mergeable(dst + loc - 1, src);
0291
0292 merged_length = dst[loc - 1].length;
0293 if (left)
0294 merged_length += src->length;
0295
0296 disc = (src[0].vcn > dst[loc - 1].vcn + merged_length);
0297 }
0298
0299
0300
0301
0302 dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left + disc);
0303 if (IS_ERR(dst))
0304 return dst;
0305
0306
0307
0308
0309 if (left)
0310 __ntfs_rl_merge(dst + loc - 1, src);
0311
0312
0313
0314
0315
0316
0317
0318 marker = loc + ssize - left + disc;
0319
0320
0321 ntfs_rl_mm(dst, marker, loc, dsize - loc);
0322 ntfs_rl_mc(dst, loc + disc, src, left, ssize - left);
0323
0324
0325 dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
0326
0327 if (dst[marker].lcn == LCN_HOLE || dst[marker].lcn == LCN_RL_NOT_MAPPED)
0328 dst[marker].length = dst[marker + 1].vcn - dst[marker].vcn;
0329
0330
0331 if (disc) {
0332 if (loc > 0) {
0333 dst[loc].vcn = dst[loc - 1].vcn + dst[loc - 1].length;
0334 dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn;
0335 } else {
0336 dst[loc].vcn = 0;
0337 dst[loc].length = dst[loc + 1].vcn;
0338 }
0339 dst[loc].lcn = LCN_RL_NOT_MAPPED;
0340 }
0341 return dst;
0342 }
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367 static inline runlist_element *ntfs_rl_replace(runlist_element *dst,
0368 int dsize, runlist_element *src, int ssize, int loc)
0369 {
0370 signed delta;
0371 bool left = false;
0372 bool right = false;
0373 int tail;
0374 int marker;
0375
0376 BUG_ON(!dst);
0377 BUG_ON(!src);
0378
0379
0380 if ((loc + 1) < dsize)
0381 right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1);
0382 if (loc > 0)
0383 left = ntfs_are_rl_mergeable(dst + loc - 1, src);
0384
0385
0386
0387
0388 delta = ssize - 1 - left - right;
0389 if (delta > 0) {
0390 dst = ntfs_rl_realloc(dst, dsize, dsize + delta);
0391 if (IS_ERR(dst))
0392 return dst;
0393 }
0394
0395
0396
0397
0398
0399
0400 if (right)
0401 __ntfs_rl_merge(src + ssize - 1, dst + loc + 1);
0402 if (left)
0403 __ntfs_rl_merge(dst + loc - 1, src);
0404
0405
0406
0407
0408
0409
0410
0411
0412 tail = loc + right + 1;
0413
0414
0415
0416
0417
0418
0419
0420 marker = loc + ssize - left;
0421
0422
0423 ntfs_rl_mm(dst, marker, tail, dsize - tail);
0424 ntfs_rl_mc(dst, loc, src, left, ssize - left);
0425
0426
0427 if (dsize - tail > 0 && dst[marker].lcn == LCN_ENOENT)
0428 dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
0429 return dst;
0430 }
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456 static inline runlist_element *ntfs_rl_split(runlist_element *dst, int dsize,
0457 runlist_element *src, int ssize, int loc)
0458 {
0459 BUG_ON(!dst);
0460 BUG_ON(!src);
0461
0462
0463 dst = ntfs_rl_realloc(dst, dsize, dsize + ssize + 1);
0464 if (IS_ERR(dst))
0465 return dst;
0466
0467
0468
0469
0470
0471
0472 ntfs_rl_mm(dst, loc + 1 + ssize, loc, dsize - loc);
0473 ntfs_rl_mc(dst, loc + 1, src, 0, ssize);
0474
0475
0476 dst[loc].length = dst[loc+1].vcn - dst[loc].vcn;
0477 dst[loc+ssize+1].vcn = dst[loc+ssize].vcn + dst[loc+ssize].length;
0478 dst[loc+ssize+1].length = dst[loc+ssize+2].vcn - dst[loc+ssize+1].vcn;
0479
0480 return dst;
0481 }
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517 runlist_element *ntfs_runlists_merge(runlist_element *drl,
0518 runlist_element *srl)
0519 {
0520 int di, si;
0521 int sstart;
0522 int dins;
0523 int dend, send;
0524 int dfinal, sfinal;
0525
0526 int marker = 0;
0527 VCN marker_vcn = 0;
0528
0529 #ifdef DEBUG
0530 ntfs_debug("dst:");
0531 ntfs_debug_dump_runlist(drl);
0532 ntfs_debug("src:");
0533 ntfs_debug_dump_runlist(srl);
0534 #endif
0535
0536
0537 if (unlikely(!srl))
0538 return drl;
0539 if (IS_ERR(srl) || IS_ERR(drl))
0540 return ERR_PTR(-EINVAL);
0541
0542
0543 if (unlikely(!drl)) {
0544 drl = srl;
0545
0546 if (unlikely(drl[0].vcn)) {
0547
0548 for (dend = 0; likely(drl[dend].length); dend++)
0549 ;
0550 dend++;
0551 drl = ntfs_rl_realloc(drl, dend, dend + 1);
0552 if (IS_ERR(drl))
0553 return drl;
0554
0555 ntfs_rl_mm(drl, 1, 0, dend);
0556 drl[0].vcn = 0;
0557 drl[0].lcn = LCN_RL_NOT_MAPPED;
0558 drl[0].length = drl[1].vcn;
0559 }
0560 goto finished;
0561 }
0562
0563 si = di = 0;
0564
0565
0566 while (srl[si].length && srl[si].lcn < LCN_HOLE)
0567 si++;
0568
0569
0570 BUG_ON(!srl[si].length);
0571
0572
0573 sstart = si;
0574
0575
0576
0577
0578
0579
0580 for (; drl[di].length; di++) {
0581 if (drl[di].vcn + drl[di].length > srl[sstart].vcn)
0582 break;
0583 }
0584 dins = di;
0585
0586
0587 if ((drl[di].vcn == srl[si].vcn) && (drl[di].lcn >= 0) &&
0588 (srl[si].lcn >= 0)) {
0589 ntfs_error(NULL, "Run lists overlap. Cannot merge!");
0590 return ERR_PTR(-ERANGE);
0591 }
0592
0593
0594 for (send = si; srl[send].length; send++)
0595 ;
0596 for (dend = di; drl[dend].length; dend++)
0597 ;
0598
0599 if (srl[send].lcn == LCN_ENOENT)
0600 marker_vcn = srl[marker = send].vcn;
0601
0602
0603 for (sfinal = send; sfinal >= 0 && srl[sfinal].lcn < LCN_HOLE; sfinal--)
0604 ;
0605 for (dfinal = dend; dfinal >= 0 && drl[dfinal].lcn < LCN_HOLE; dfinal--)
0606 ;
0607
0608 {
0609 bool start;
0610 bool finish;
0611 int ds = dend + 1;
0612 int ss = sfinal - sstart + 1;
0613
0614 start = ((drl[dins].lcn < LCN_RL_NOT_MAPPED) ||
0615 (drl[dins].vcn == srl[sstart].vcn));
0616 finish = ((drl[dins].lcn >= LCN_RL_NOT_MAPPED) &&
0617 ((drl[dins].vcn + drl[dins].length) <=
0618 (srl[send - 1].vcn + srl[send - 1].length)));
0619
0620
0621 if (finish && !drl[dins].length)
0622 ss++;
0623 if (marker && (drl[dins].vcn + drl[dins].length > srl[send - 1].vcn))
0624 finish = false;
0625 #if 0
0626 ntfs_debug("dfinal = %i, dend = %i", dfinal, dend);
0627 ntfs_debug("sstart = %i, sfinal = %i, send = %i", sstart, sfinal, send);
0628 ntfs_debug("start = %i, finish = %i", start, finish);
0629 ntfs_debug("ds = %i, ss = %i, dins = %i", ds, ss, dins);
0630 #endif
0631 if (start) {
0632 if (finish)
0633 drl = ntfs_rl_replace(drl, ds, srl + sstart, ss, dins);
0634 else
0635 drl = ntfs_rl_insert(drl, ds, srl + sstart, ss, dins);
0636 } else {
0637 if (finish)
0638 drl = ntfs_rl_append(drl, ds, srl + sstart, ss, dins);
0639 else
0640 drl = ntfs_rl_split(drl, ds, srl + sstart, ss, dins);
0641 }
0642 if (IS_ERR(drl)) {
0643 ntfs_error(NULL, "Merge failed.");
0644 return drl;
0645 }
0646 ntfs_free(srl);
0647 if (marker) {
0648 ntfs_debug("Triggering marker code.");
0649 for (ds = dend; drl[ds].length; ds++)
0650 ;
0651
0652 if (drl[ds].vcn <= marker_vcn) {
0653 int slots = 0;
0654
0655 if (drl[ds].vcn == marker_vcn) {
0656 ntfs_debug("Old marker = 0x%llx, replacing "
0657 "with LCN_ENOENT.",
0658 (unsigned long long)
0659 drl[ds].lcn);
0660 drl[ds].lcn = LCN_ENOENT;
0661 goto finished;
0662 }
0663
0664
0665
0666
0667
0668 if (drl[ds].lcn == LCN_ENOENT) {
0669 ds--;
0670 slots = 1;
0671 }
0672 if (drl[ds].lcn != LCN_RL_NOT_MAPPED) {
0673
0674 if (!slots) {
0675 drl = ntfs_rl_realloc_nofail(drl, ds,
0676 ds + 2);
0677 slots = 2;
0678 }
0679 ds++;
0680
0681 if (slots != 1)
0682 drl[ds].vcn = drl[ds - 1].vcn +
0683 drl[ds - 1].length;
0684 drl[ds].lcn = LCN_RL_NOT_MAPPED;
0685
0686 slots--;
0687 }
0688 drl[ds].length = marker_vcn - drl[ds].vcn;
0689
0690 ds++;
0691 if (!slots)
0692 drl = ntfs_rl_realloc_nofail(drl, ds, ds + 1);
0693 drl[ds].vcn = marker_vcn;
0694 drl[ds].lcn = LCN_ENOENT;
0695 drl[ds].length = (s64)0;
0696 }
0697 }
0698 }
0699
0700 finished:
0701
0702 ntfs_debug("Merged runlist:");
0703 ntfs_debug_dump_runlist(drl);
0704 return drl;
0705 }
0706
0707
0708
0709
0710
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721
0722
0723
0724
0725
0726
0727
0728
0729
0730
0731
0732
0733
0734
0735 runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol,
0736 const ATTR_RECORD *attr, runlist_element *old_rl)
0737 {
0738 VCN vcn;
0739 LCN lcn;
0740 s64 deltaxcn;
0741 runlist_element *rl;
0742 u8 *buf;
0743 u8 *attr_end;
0744 int rlsize;
0745 u16 rlpos;
0746
0747 u8 b;
0748
0749 #ifdef DEBUG
0750
0751 if (!attr || !attr->non_resident || sle64_to_cpu(
0752 attr->data.non_resident.lowest_vcn) < (VCN)0) {
0753 ntfs_error(vol->sb, "Invalid arguments.");
0754 return ERR_PTR(-EINVAL);
0755 }
0756 #endif
0757
0758 vcn = sle64_to_cpu(attr->data.non_resident.lowest_vcn);
0759 lcn = 0;
0760
0761 buf = (u8*)attr + le16_to_cpu(
0762 attr->data.non_resident.mapping_pairs_offset);
0763 attr_end = (u8*)attr + le32_to_cpu(attr->length);
0764 if (unlikely(buf < (u8*)attr || buf > attr_end)) {
0765 ntfs_error(vol->sb, "Corrupt attribute.");
0766 return ERR_PTR(-EIO);
0767 }
0768
0769 if (!vcn && !*buf)
0770 return old_rl;
0771
0772 rlpos = 0;
0773
0774 rl = ntfs_malloc_nofs(rlsize = PAGE_SIZE);
0775 if (unlikely(!rl))
0776 return ERR_PTR(-ENOMEM);
0777
0778 if (vcn) {
0779 rl->vcn = 0;
0780 rl->lcn = LCN_RL_NOT_MAPPED;
0781 rl->length = vcn;
0782 rlpos++;
0783 }
0784 while (buf < attr_end && *buf) {
0785
0786
0787
0788
0789
0790 if (((rlpos + 3) * sizeof(*old_rl)) > rlsize) {
0791 runlist_element *rl2;
0792
0793 rl2 = ntfs_malloc_nofs(rlsize + (int)PAGE_SIZE);
0794 if (unlikely(!rl2)) {
0795 ntfs_free(rl);
0796 return ERR_PTR(-ENOMEM);
0797 }
0798 memcpy(rl2, rl, rlsize);
0799 ntfs_free(rl);
0800 rl = rl2;
0801 rlsize += PAGE_SIZE;
0802 }
0803
0804 rl[rlpos].vcn = vcn;
0805
0806
0807
0808
0809
0810
0811
0812 b = *buf & 0xf;
0813 if (b) {
0814 if (unlikely(buf + b > attr_end))
0815 goto io_error;
0816 for (deltaxcn = (s8)buf[b--]; b; b--)
0817 deltaxcn = (deltaxcn << 8) + buf[b];
0818 } else {
0819 ntfs_error(vol->sb, "Missing length entry in mapping "
0820 "pairs array.");
0821 deltaxcn = (s64)-1;
0822 }
0823
0824
0825
0826
0827 if (unlikely(deltaxcn < 0)) {
0828 ntfs_error(vol->sb, "Invalid length in mapping pairs "
0829 "array.");
0830 goto err_out;
0831 }
0832
0833
0834
0835
0836 rl[rlpos].length = deltaxcn;
0837
0838 vcn += deltaxcn;
0839
0840
0841
0842
0843
0844 if (!(*buf & 0xf0))
0845 rl[rlpos].lcn = LCN_HOLE;
0846 else {
0847
0848 u8 b2 = *buf & 0xf;
0849 b = b2 + ((*buf >> 4) & 0xf);
0850 if (buf + b > attr_end)
0851 goto io_error;
0852 for (deltaxcn = (s8)buf[b--]; b > b2; b--)
0853 deltaxcn = (deltaxcn << 8) + buf[b];
0854
0855 lcn += deltaxcn;
0856 #ifdef DEBUG
0857
0858
0859
0860
0861
0862
0863
0864 if (vol->major_ver < 3) {
0865 if (unlikely(deltaxcn == (LCN)-1))
0866 ntfs_error(vol->sb, "lcn delta == -1");
0867 if (unlikely(lcn == (LCN)-1))
0868 ntfs_error(vol->sb, "lcn == -1");
0869 }
0870 #endif
0871
0872 if (unlikely(lcn < (LCN)-1)) {
0873 ntfs_error(vol->sb, "Invalid LCN < -1 in "
0874 "mapping pairs array.");
0875 goto err_out;
0876 }
0877
0878 rl[rlpos].lcn = lcn;
0879 }
0880
0881 rlpos++;
0882
0883 buf += (*buf & 0xf) + ((*buf >> 4) & 0xf) + 1;
0884 }
0885 if (unlikely(buf >= attr_end))
0886 goto io_error;
0887
0888
0889
0890
0891 deltaxcn = sle64_to_cpu(attr->data.non_resident.highest_vcn);
0892 if (unlikely(deltaxcn && vcn - 1 != deltaxcn)) {
0893 mpa_err:
0894 ntfs_error(vol->sb, "Corrupt mapping pairs array in "
0895 "non-resident attribute.");
0896 goto err_out;
0897 }
0898
0899 if (!attr->data.non_resident.lowest_vcn) {
0900 VCN max_cluster;
0901
0902 max_cluster = ((sle64_to_cpu(
0903 attr->data.non_resident.allocated_size) +
0904 vol->cluster_size - 1) >>
0905 vol->cluster_size_bits) - 1;
0906
0907
0908
0909
0910 if (deltaxcn) {
0911
0912
0913
0914
0915
0916
0917 if (deltaxcn < max_cluster) {
0918 ntfs_debug("More extents to follow; deltaxcn "
0919 "= 0x%llx, max_cluster = "
0920 "0x%llx",
0921 (unsigned long long)deltaxcn,
0922 (unsigned long long)
0923 max_cluster);
0924 rl[rlpos].vcn = vcn;
0925 vcn += rl[rlpos].length = max_cluster -
0926 deltaxcn;
0927 rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
0928 rlpos++;
0929 } else if (unlikely(deltaxcn > max_cluster)) {
0930 ntfs_error(vol->sb, "Corrupt attribute. "
0931 "deltaxcn = 0x%llx, "
0932 "max_cluster = 0x%llx",
0933 (unsigned long long)deltaxcn,
0934 (unsigned long long)
0935 max_cluster);
0936 goto mpa_err;
0937 }
0938 }
0939 rl[rlpos].lcn = LCN_ENOENT;
0940 } else
0941 rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
0942
0943
0944 rl[rlpos].vcn = vcn;
0945 rl[rlpos].length = (s64)0;
0946
0947 if (!old_rl) {
0948 ntfs_debug("Mapping pairs array successfully decompressed:");
0949 ntfs_debug_dump_runlist(rl);
0950 return rl;
0951 }
0952
0953 old_rl = ntfs_runlists_merge(old_rl, rl);
0954 if (!IS_ERR(old_rl))
0955 return old_rl;
0956 ntfs_free(rl);
0957 ntfs_error(vol->sb, "Failed to merge runlists.");
0958 return old_rl;
0959 io_error:
0960 ntfs_error(vol->sb, "Corrupt attribute.");
0961 err_out:
0962 ntfs_free(rl);
0963 return ERR_PTR(-EIO);
0964 }
0965
0966
0967
0968
0969
0970
0971
0972
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988
0989
0990 LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn)
0991 {
0992 int i;
0993
0994 BUG_ON(vcn < 0);
0995
0996
0997
0998
0999
1000 if (unlikely(!rl))
1001 return LCN_RL_NOT_MAPPED;
1002
1003
1004 if (unlikely(vcn < rl[0].vcn))
1005 return LCN_ENOENT;
1006
1007 for (i = 0; likely(rl[i].length); i++) {
1008 if (unlikely(vcn < rl[i+1].vcn)) {
1009 if (likely(rl[i].lcn >= (LCN)0))
1010 return rl[i].lcn + (vcn - rl[i].vcn);
1011 return rl[i].lcn;
1012 }
1013 }
1014
1015
1016
1017
1018 if (likely(rl[i].lcn < (LCN)0))
1019 return rl[i].lcn;
1020
1021 return LCN_ENOENT;
1022 }
1023
1024 #ifdef NTFS_RW
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039 runlist_element *ntfs_rl_find_vcn_nolock(runlist_element *rl, const VCN vcn)
1040 {
1041 BUG_ON(vcn < 0);
1042 if (unlikely(!rl || vcn < rl[0].vcn))
1043 return NULL;
1044 while (likely(rl->length)) {
1045 if (unlikely(vcn < rl[1].vcn)) {
1046 if (likely(rl->lcn >= LCN_HOLE))
1047 return rl;
1048 return NULL;
1049 }
1050 rl++;
1051 }
1052 if (likely(rl->lcn == LCN_ENOENT))
1053 return rl;
1054 return NULL;
1055 }
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070 static inline int ntfs_get_nr_significant_bytes(const s64 n)
1071 {
1072 s64 l = n;
1073 int i;
1074 s8 j;
1075
1076 i = 0;
1077 do {
1078 l >>= 8;
1079 i++;
1080 } while (l != 0 && l != -1);
1081 j = (n >> 8 * (i - 1)) & 0xff;
1082
1083 if ((n < 0 && j >= 0) || (n > 0 && j < 0))
1084 i++;
1085 return i;
1086 }
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117 int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
1118 const runlist_element *rl, const VCN first_vcn,
1119 const VCN last_vcn)
1120 {
1121 LCN prev_lcn;
1122 int rls;
1123 bool the_end = false;
1124
1125 BUG_ON(first_vcn < 0);
1126 BUG_ON(last_vcn < -1);
1127 BUG_ON(last_vcn >= 0 && first_vcn > last_vcn);
1128 if (!rl) {
1129 BUG_ON(first_vcn);
1130 BUG_ON(last_vcn > 0);
1131 return 1;
1132 }
1133
1134 while (rl->length && first_vcn >= rl[1].vcn)
1135 rl++;
1136 if (unlikely((!rl->length && first_vcn > rl->vcn) ||
1137 first_vcn < rl->vcn))
1138 return -EINVAL;
1139 prev_lcn = 0;
1140
1141 rls = 1;
1142
1143 if (first_vcn > rl->vcn) {
1144 s64 delta, length = rl->length;
1145
1146
1147 if (unlikely(length < 0 || rl->lcn < LCN_HOLE))
1148 goto err_out;
1149
1150
1151
1152
1153 if (unlikely(last_vcn >= 0 && rl[1].vcn > last_vcn)) {
1154 s64 s1 = last_vcn + 1;
1155 if (unlikely(rl[1].vcn > s1))
1156 length = s1 - rl->vcn;
1157 the_end = true;
1158 }
1159 delta = first_vcn - rl->vcn;
1160
1161 rls += 1 + ntfs_get_nr_significant_bytes(length - delta);
1162
1163
1164
1165
1166
1167
1168
1169 if (likely(rl->lcn >= 0 || vol->major_ver < 3)) {
1170 prev_lcn = rl->lcn;
1171 if (likely(rl->lcn >= 0))
1172 prev_lcn += delta;
1173
1174 rls += ntfs_get_nr_significant_bytes(prev_lcn);
1175 }
1176
1177 rl++;
1178 }
1179
1180 for (; rl->length && !the_end; rl++) {
1181 s64 length = rl->length;
1182
1183 if (unlikely(length < 0 || rl->lcn < LCN_HOLE))
1184 goto err_out;
1185
1186
1187
1188
1189 if (unlikely(last_vcn >= 0 && rl[1].vcn > last_vcn)) {
1190 s64 s1 = last_vcn + 1;
1191 if (unlikely(rl[1].vcn > s1))
1192 length = s1 - rl->vcn;
1193 the_end = true;
1194 }
1195
1196 rls += 1 + ntfs_get_nr_significant_bytes(length);
1197
1198
1199
1200
1201
1202
1203
1204 if (likely(rl->lcn >= 0 || vol->major_ver < 3)) {
1205
1206 rls += ntfs_get_nr_significant_bytes(rl->lcn -
1207 prev_lcn);
1208 prev_lcn = rl->lcn;
1209 }
1210 }
1211 return rls;
1212 err_out:
1213 if (rl->lcn == LCN_RL_NOT_MAPPED)
1214 rls = -EINVAL;
1215 else
1216 rls = -EIO;
1217 return rls;
1218 }
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238 static inline int ntfs_write_significant_bytes(s8 *dst, const s8 *dst_max,
1239 const s64 n)
1240 {
1241 s64 l = n;
1242 int i;
1243 s8 j;
1244
1245 i = 0;
1246 do {
1247 if (unlikely(dst > dst_max))
1248 goto err_out;
1249 *dst++ = l & 0xffll;
1250 l >>= 8;
1251 i++;
1252 } while (l != 0 && l != -1);
1253 j = (n >> 8 * (i - 1)) & 0xff;
1254
1255 if (n < 0 && j >= 0) {
1256 if (unlikely(dst > dst_max))
1257 goto err_out;
1258 i++;
1259 *dst = (s8)-1;
1260 } else if (n > 0 && j < 0) {
1261 if (unlikely(dst > dst_max))
1262 goto err_out;
1263 i++;
1264 *dst = (s8)0;
1265 }
1266 return i;
1267 err_out:
1268 return -ENOSPC;
1269 }
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309 int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst,
1310 const int dst_len, const runlist_element *rl,
1311 const VCN first_vcn, const VCN last_vcn, VCN *const stop_vcn)
1312 {
1313 LCN prev_lcn;
1314 s8 *dst_max, *dst_next;
1315 int err = -ENOSPC;
1316 bool the_end = false;
1317 s8 len_len, lcn_len;
1318
1319 BUG_ON(first_vcn < 0);
1320 BUG_ON(last_vcn < -1);
1321 BUG_ON(last_vcn >= 0 && first_vcn > last_vcn);
1322 BUG_ON(dst_len < 1);
1323 if (!rl) {
1324 BUG_ON(first_vcn);
1325 BUG_ON(last_vcn > 0);
1326 if (stop_vcn)
1327 *stop_vcn = 0;
1328
1329 *dst = 0;
1330 return 0;
1331 }
1332
1333 while (rl->length && first_vcn >= rl[1].vcn)
1334 rl++;
1335 if (unlikely((!rl->length && first_vcn > rl->vcn) ||
1336 first_vcn < rl->vcn))
1337 return -EINVAL;
1338
1339
1340
1341
1342 dst_max = dst + dst_len - 1;
1343 prev_lcn = 0;
1344
1345 if (first_vcn > rl->vcn) {
1346 s64 delta, length = rl->length;
1347
1348
1349 if (unlikely(length < 0 || rl->lcn < LCN_HOLE))
1350 goto err_out;
1351
1352
1353
1354
1355 if (unlikely(last_vcn >= 0 && rl[1].vcn > last_vcn)) {
1356 s64 s1 = last_vcn + 1;
1357 if (unlikely(rl[1].vcn > s1))
1358 length = s1 - rl->vcn;
1359 the_end = true;
1360 }
1361 delta = first_vcn - rl->vcn;
1362
1363 len_len = ntfs_write_significant_bytes(dst + 1, dst_max,
1364 length - delta);
1365 if (unlikely(len_len < 0))
1366 goto size_err;
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376 if (likely(rl->lcn >= 0 || vol->major_ver < 3)) {
1377 prev_lcn = rl->lcn;
1378 if (likely(rl->lcn >= 0))
1379 prev_lcn += delta;
1380
1381 lcn_len = ntfs_write_significant_bytes(dst + 1 +
1382 len_len, dst_max, prev_lcn);
1383 if (unlikely(lcn_len < 0))
1384 goto size_err;
1385 } else
1386 lcn_len = 0;
1387 dst_next = dst + len_len + lcn_len + 1;
1388 if (unlikely(dst_next > dst_max))
1389 goto size_err;
1390
1391 *dst = lcn_len << 4 | len_len;
1392
1393 dst = dst_next;
1394
1395 rl++;
1396 }
1397
1398 for (; rl->length && !the_end; rl++) {
1399 s64 length = rl->length;
1400
1401 if (unlikely(length < 0 || rl->lcn < LCN_HOLE))
1402 goto err_out;
1403
1404
1405
1406
1407 if (unlikely(last_vcn >= 0 && rl[1].vcn > last_vcn)) {
1408 s64 s1 = last_vcn + 1;
1409 if (unlikely(rl[1].vcn > s1))
1410 length = s1 - rl->vcn;
1411 the_end = true;
1412 }
1413
1414 len_len = ntfs_write_significant_bytes(dst + 1, dst_max,
1415 length);
1416 if (unlikely(len_len < 0))
1417 goto size_err;
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427 if (likely(rl->lcn >= 0 || vol->major_ver < 3)) {
1428
1429 lcn_len = ntfs_write_significant_bytes(dst + 1 +
1430 len_len, dst_max, rl->lcn - prev_lcn);
1431 if (unlikely(lcn_len < 0))
1432 goto size_err;
1433 prev_lcn = rl->lcn;
1434 } else
1435 lcn_len = 0;
1436 dst_next = dst + len_len + lcn_len + 1;
1437 if (unlikely(dst_next > dst_max))
1438 goto size_err;
1439
1440 *dst = lcn_len << 4 | len_len;
1441
1442 dst = dst_next;
1443 }
1444
1445 err = 0;
1446 size_err:
1447
1448 if (stop_vcn)
1449 *stop_vcn = rl->vcn;
1450
1451 *dst = 0;
1452 return err;
1453 err_out:
1454 if (rl->lcn == LCN_RL_NOT_MAPPED)
1455 err = -EINVAL;
1456 else
1457 err = -EIO;
1458 return err;
1459 }
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485 int ntfs_rl_truncate_nolock(const ntfs_volume *vol, runlist *const runlist,
1486 const s64 new_length)
1487 {
1488 runlist_element *rl;
1489 int old_size;
1490
1491 ntfs_debug("Entering for new_length 0x%llx.", (long long)new_length);
1492 BUG_ON(!runlist);
1493 BUG_ON(new_length < 0);
1494 rl = runlist->rl;
1495 if (!new_length) {
1496 ntfs_debug("Freeing runlist.");
1497 runlist->rl = NULL;
1498 if (rl)
1499 ntfs_free(rl);
1500 return 0;
1501 }
1502 if (unlikely(!rl)) {
1503
1504
1505
1506
1507 rl = ntfs_malloc_nofs(PAGE_SIZE);
1508 if (unlikely(!rl)) {
1509 ntfs_error(vol->sb, "Not enough memory to allocate "
1510 "runlist element buffer.");
1511 return -ENOMEM;
1512 }
1513 runlist->rl = rl;
1514 rl[1].length = rl->vcn = 0;
1515 rl->lcn = LCN_HOLE;
1516 rl[1].vcn = rl->length = new_length;
1517 rl[1].lcn = LCN_ENOENT;
1518 return 0;
1519 }
1520 BUG_ON(new_length < rl->vcn);
1521
1522 while (likely(rl->length && new_length >= rl[1].vcn))
1523 rl++;
1524
1525
1526
1527
1528 if (rl->length) {
1529 runlist_element *trl;
1530 bool is_end;
1531
1532 ntfs_debug("Shrinking runlist.");
1533
1534 trl = rl + 1;
1535 while (likely(trl->length))
1536 trl++;
1537 old_size = trl - runlist->rl + 1;
1538
1539 rl->length = new_length - rl->vcn;
1540
1541
1542
1543
1544 is_end = false;
1545 if (rl->length) {
1546 rl++;
1547 if (!rl->length)
1548 is_end = true;
1549 rl->vcn = new_length;
1550 rl->length = 0;
1551 }
1552 rl->lcn = LCN_ENOENT;
1553
1554 if (!is_end) {
1555 int new_size = rl - runlist->rl + 1;
1556 rl = ntfs_rl_realloc(runlist->rl, old_size, new_size);
1557 if (IS_ERR(rl))
1558 ntfs_warning(vol->sb, "Failed to shrink "
1559 "runlist buffer. This just "
1560 "wastes a bit of memory "
1561 "temporarily so we ignore it "
1562 "and return success.");
1563 else
1564 runlist->rl = rl;
1565 }
1566 } else if (likely( new_length > rl->vcn)) {
1567 ntfs_debug("Expanding runlist.");
1568
1569
1570
1571
1572
1573 if ((rl > runlist->rl) && ((rl - 1)->lcn == LCN_HOLE))
1574 (rl - 1)->length = new_length - (rl - 1)->vcn;
1575 else {
1576
1577 old_size = rl - runlist->rl + 1;
1578
1579 rl = ntfs_rl_realloc(runlist->rl, old_size,
1580 old_size + 1);
1581 if (IS_ERR(rl)) {
1582 ntfs_error(vol->sb, "Failed to expand runlist "
1583 "buffer, aborting.");
1584 return PTR_ERR(rl);
1585 }
1586 runlist->rl = rl;
1587
1588
1589
1590
1591 rl += old_size - 1;
1592
1593 rl->lcn = LCN_HOLE;
1594 rl->length = new_length - rl->vcn;
1595
1596 rl++;
1597 rl->length = 0;
1598 }
1599 rl->vcn = new_length;
1600 rl->lcn = LCN_ENOENT;
1601 } else {
1602
1603 rl->lcn = LCN_ENOENT;
1604 }
1605 ntfs_debug("Done.");
1606 return 0;
1607 }
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630 int ntfs_rl_punch_nolock(const ntfs_volume *vol, runlist *const runlist,
1631 const VCN start, const s64 length)
1632 {
1633 const VCN end = start + length;
1634 s64 delta;
1635 runlist_element *rl, *rl_end, *rl_real_end, *trl;
1636 int old_size;
1637 bool lcn_fixup = false;
1638
1639 ntfs_debug("Entering for start 0x%llx, length 0x%llx.",
1640 (long long)start, (long long)length);
1641 BUG_ON(!runlist);
1642 BUG_ON(start < 0);
1643 BUG_ON(length < 0);
1644 BUG_ON(end < 0);
1645 rl = runlist->rl;
1646 if (unlikely(!rl)) {
1647 if (likely(!start && !length))
1648 return 0;
1649 return -ENOENT;
1650 }
1651
1652 while (likely(rl->length && start >= rl[1].vcn))
1653 rl++;
1654 rl_end = rl;
1655
1656 while (likely(rl_end->length && end >= rl_end[1].vcn)) {
1657
1658 if (unlikely(rl_end->lcn < LCN_HOLE))
1659 return -EINVAL;
1660 rl_end++;
1661 }
1662
1663 if (unlikely(rl_end->length && rl_end->lcn < LCN_HOLE))
1664 return -EINVAL;
1665
1666 if (!rl_end->length && end > rl_end->vcn)
1667 return -ENOENT;
1668 if (!length)
1669 return 0;
1670 if (!rl->length)
1671 return -ENOENT;
1672 rl_real_end = rl_end;
1673
1674 while (likely(rl_real_end->length))
1675 rl_real_end++;
1676 old_size = rl_real_end - runlist->rl + 1;
1677
1678 if (rl->lcn == LCN_HOLE) {
1679
1680
1681
1682
1683 if (end <= rl[1].vcn) {
1684 ntfs_debug("Done (requested hole is already sparse).");
1685 return 0;
1686 }
1687 extend_hole:
1688
1689 rl->length = end - rl->vcn;
1690
1691 if (rl_end->lcn == LCN_HOLE) {
1692 rl_end++;
1693 rl->length = rl_end->vcn - rl->vcn;
1694 }
1695
1696 rl++;
1697
1698 if (rl < rl_end)
1699 memmove(rl, rl_end, (rl_real_end - rl_end + 1) *
1700 sizeof(*rl));
1701
1702 if (end > rl->vcn) {
1703 delta = end - rl->vcn;
1704 rl->vcn = end;
1705 rl->length -= delta;
1706
1707 if (rl->lcn >= 0)
1708 rl->lcn += delta;
1709 }
1710 shrink_allocation:
1711
1712 if (rl < rl_end) {
1713 rl = ntfs_rl_realloc(runlist->rl, old_size,
1714 old_size - (rl_end - rl));
1715 if (IS_ERR(rl))
1716 ntfs_warning(vol->sb, "Failed to shrink "
1717 "runlist buffer. This just "
1718 "wastes a bit of memory "
1719 "temporarily so we ignore it "
1720 "and return success.");
1721 else
1722 runlist->rl = rl;
1723 }
1724 ntfs_debug("Done (extend hole).");
1725 return 0;
1726 }
1727
1728
1729
1730
1731 if (start == rl->vcn) {
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743 if (rl > runlist->rl && (rl - 1)->lcn == LCN_HOLE) {
1744 rl--;
1745 goto extend_hole;
1746 }
1747 if (end >= rl[1].vcn) {
1748 rl->lcn = LCN_HOLE;
1749 goto extend_hole;
1750 }
1751
1752
1753
1754
1755
1756
1757
1758 trl = ntfs_rl_realloc(runlist->rl, old_size, old_size + 1);
1759 if (IS_ERR(trl))
1760 goto enomem_out;
1761 old_size++;
1762 if (runlist->rl != trl) {
1763 rl = trl + (rl - runlist->rl);
1764 rl_end = trl + (rl_end - runlist->rl);
1765 rl_real_end = trl + (rl_real_end - runlist->rl);
1766 runlist->rl = trl;
1767 }
1768 split_end:
1769
1770 memmove(rl + 1, rl, (rl_real_end - rl + 1) * sizeof(*rl));
1771
1772 rl->lcn = LCN_HOLE;
1773 rl->length = length;
1774 rl++;
1775 rl->vcn += length;
1776
1777 if (rl->lcn >= 0 || lcn_fixup)
1778 rl->lcn += length;
1779 rl->length -= length;
1780 ntfs_debug("Done (split one).");
1781 return 0;
1782 }
1783
1784
1785
1786
1787
1788
1789
1790
1791 if (rl_end->lcn == LCN_HOLE) {
1792
1793 rl->length = start - rl->vcn;
1794 rl++;
1795
1796 if (rl < rl_end)
1797 memmove(rl, rl_end, (rl_real_end - rl_end + 1) *
1798 sizeof(*rl));
1799
1800 rl->vcn = start;
1801 rl->length = rl[1].vcn - start;
1802 goto shrink_allocation;
1803 }
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815 if (end >= rl[1].vcn) {
1816
1817
1818
1819
1820 if (rl[1].length && end >= rl[2].vcn) {
1821
1822 rl->length = start - rl->vcn;
1823 rl++;
1824 rl->vcn = start;
1825 rl->lcn = LCN_HOLE;
1826 goto extend_hole;
1827 }
1828 trl = ntfs_rl_realloc(runlist->rl, old_size, old_size + 1);
1829 if (IS_ERR(trl))
1830 goto enomem_out;
1831 old_size++;
1832 if (runlist->rl != trl) {
1833 rl = trl + (rl - runlist->rl);
1834 rl_end = trl + (rl_end - runlist->rl);
1835 rl_real_end = trl + (rl_real_end - runlist->rl);
1836 runlist->rl = trl;
1837 }
1838
1839 rl->length = start - rl->vcn;
1840 rl++;
1841
1842
1843
1844
1845
1846 delta = rl->vcn - start;
1847 rl->vcn = start;
1848 if (rl->lcn >= 0) {
1849 rl->lcn -= delta;
1850
1851 lcn_fixup = true;
1852 }
1853 rl->length += delta;
1854 goto split_end;
1855 }
1856
1857
1858
1859
1860
1861
1862
1863 trl = ntfs_rl_realloc(runlist->rl, old_size, old_size + 2);
1864 if (IS_ERR(trl))
1865 goto enomem_out;
1866 old_size += 2;
1867 if (runlist->rl != trl) {
1868 rl = trl + (rl - runlist->rl);
1869 rl_end = trl + (rl_end - runlist->rl);
1870 rl_real_end = trl + (rl_real_end - runlist->rl);
1871 runlist->rl = trl;
1872 }
1873
1874 memmove(rl + 2, rl, (rl_real_end - rl + 1) * sizeof(*rl));
1875
1876 rl->length = start - rl->vcn;
1877 rl++;
1878 rl->vcn = start;
1879 rl->lcn = LCN_HOLE;
1880 rl->length = length;
1881 rl++;
1882 delta = end - rl->vcn;
1883 rl->vcn = end;
1884 rl->lcn += delta;
1885 rl->length -= delta;
1886 ntfs_debug("Done (split both).");
1887 return 0;
1888 enomem_out:
1889 ntfs_error(vol->sb, "Not enough memory to extend runlist buffer.");
1890 return -ENOMEM;
1891 }
1892
1893 #endif