This source file includes following definitions.
- ntfs_rl_mm
- ntfs_rl_mc
- ntfs_rl_realloc
- ntfs_rl_realloc_nofail
- ntfs_are_rl_mergeable
- __ntfs_rl_merge
- ntfs_rl_append
- ntfs_rl_insert
- ntfs_rl_replace
- ntfs_rl_split
- ntfs_runlists_merge
- ntfs_mapping_pairs_decompress
- ntfs_rl_vcn_to_lcn
- ntfs_rl_find_vcn_nolock
- ntfs_get_nr_significant_bytes
- ntfs_get_size_for_mapping_pairs
- ntfs_write_significant_bytes
- ntfs_mapping_pairs_build
- ntfs_rl_truncate_nolock
- ntfs_rl_punch_nolock
1
2
3
4
5
6
7
8
9 #include "debug.h"
10 #include "dir.h"
11 #include "endian.h"
12 #include "malloc.h"
13 #include "ntfs.h"
14
15
16
17
18
19
20 static inline void ntfs_rl_mm(runlist_element *base, int dst, int src,
21 int size)
22 {
23 if (likely((dst != src) && (size > 0)))
24 memmove(base + dst, base + src, size * sizeof(*base));
25 }
26
27
28
29
30
31
32
33 static inline void ntfs_rl_mc(runlist_element *dstbase, int dst,
34 runlist_element *srcbase, int src, int size)
35 {
36 if (likely(size > 0))
37 memcpy(dstbase + dst, srcbase + src, size * sizeof(*dstbase));
38 }
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 static inline runlist_element *ntfs_rl_realloc(runlist_element *rl,
61 int old_size, int new_size)
62 {
63 runlist_element *new_rl;
64
65 old_size = PAGE_ALIGN(old_size * sizeof(*rl));
66 new_size = PAGE_ALIGN(new_size * sizeof(*rl));
67 if (old_size == new_size)
68 return rl;
69
70 new_rl = ntfs_malloc_nofs(new_size);
71 if (unlikely(!new_rl))
72 return ERR_PTR(-ENOMEM);
73
74 if (likely(rl != NULL)) {
75 if (unlikely(old_size > new_size))
76 old_size = new_size;
77 memcpy(new_rl, rl, old_size);
78 ntfs_free(rl);
79 }
80 return new_rl;
81 }
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 static inline runlist_element *ntfs_rl_realloc_nofail(runlist_element *rl,
107 int old_size, int new_size)
108 {
109 runlist_element *new_rl;
110
111 old_size = PAGE_ALIGN(old_size * sizeof(*rl));
112 new_size = PAGE_ALIGN(new_size * sizeof(*rl));
113 if (old_size == new_size)
114 return rl;
115
116 new_rl = ntfs_malloc_nofs_nofail(new_size);
117 BUG_ON(!new_rl);
118
119 if (likely(rl != NULL)) {
120 if (unlikely(old_size > new_size))
121 old_size = new_size;
122 memcpy(new_rl, rl, old_size);
123 ntfs_free(rl);
124 }
125 return new_rl;
126 }
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141 static inline bool ntfs_are_rl_mergeable(runlist_element *dst,
142 runlist_element *src)
143 {
144 BUG_ON(!dst);
145 BUG_ON(!src);
146
147
148 if ((dst->lcn == LCN_RL_NOT_MAPPED) && (src->lcn == LCN_RL_NOT_MAPPED))
149 return true;
150
151 if ((dst->vcn + dst->length) != src->vcn)
152 return false;
153
154 if ((dst->lcn >= 0) && (src->lcn >= 0) &&
155 ((dst->lcn + dst->length) == src->lcn))
156 return true;
157
158 if ((dst->lcn == LCN_HOLE) && (src->lcn == LCN_HOLE))
159 return true;
160
161 return false;
162 }
163
164
165
166
167
168
169
170
171
172
173
174
175 static inline void __ntfs_rl_merge(runlist_element *dst, runlist_element *src)
176 {
177 dst->length += src->length;
178 }
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204 static inline runlist_element *ntfs_rl_append(runlist_element *dst,
205 int dsize, runlist_element *src, int ssize, int loc)
206 {
207 bool right = false;
208 int marker;
209
210 BUG_ON(!dst);
211 BUG_ON(!src);
212
213
214 if ((loc + 1) < dsize)
215 right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1);
216
217
218 dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - right);
219 if (IS_ERR(dst))
220 return dst;
221
222
223
224
225
226
227 if (right)
228 __ntfs_rl_merge(src + ssize - 1, dst + loc + 1);
229
230
231 marker = loc + ssize + 1;
232
233
234 ntfs_rl_mm(dst, marker, loc + 1 + right, dsize - (loc + 1 + right));
235 ntfs_rl_mc(dst, loc + 1, src, 0, ssize);
236
237
238 dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn;
239
240
241 if (dst[marker].lcn == LCN_ENOENT)
242 dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
243
244 return dst;
245 }
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271 static inline runlist_element *ntfs_rl_insert(runlist_element *dst,
272 int dsize, runlist_element *src, int ssize, int loc)
273 {
274 bool left = false;
275 bool disc = false;
276 int marker;
277
278 BUG_ON(!dst);
279 BUG_ON(!src);
280
281
282
283
284
285 if (loc == 0)
286 disc = (src[0].vcn > 0);
287 else {
288 s64 merged_length;
289
290 left = ntfs_are_rl_mergeable(dst + loc - 1, src);
291
292 merged_length = dst[loc - 1].length;
293 if (left)
294 merged_length += src->length;
295
296 disc = (src[0].vcn > dst[loc - 1].vcn + merged_length);
297 }
298
299
300
301
302 dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left + disc);
303 if (IS_ERR(dst))
304 return dst;
305
306
307
308
309 if (left)
310 __ntfs_rl_merge(dst + loc - 1, src);
311
312
313
314
315
316
317
318 marker = loc + ssize - left + disc;
319
320
321 ntfs_rl_mm(dst, marker, loc, dsize - loc);
322 ntfs_rl_mc(dst, loc + disc, src, left, ssize - left);
323
324
325 dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
326
327 if (dst[marker].lcn == LCN_HOLE || dst[marker].lcn == LCN_RL_NOT_MAPPED)
328 dst[marker].length = dst[marker + 1].vcn - dst[marker].vcn;
329
330
331 if (disc) {
332 if (loc > 0) {
333 dst[loc].vcn = dst[loc - 1].vcn + dst[loc - 1].length;
334 dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn;
335 } else {
336 dst[loc].vcn = 0;
337 dst[loc].length = dst[loc + 1].vcn;
338 }
339 dst[loc].lcn = LCN_RL_NOT_MAPPED;
340 }
341 return dst;
342 }
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367 static inline runlist_element *ntfs_rl_replace(runlist_element *dst,
368 int dsize, runlist_element *src, int ssize, int loc)
369 {
370 signed delta;
371 bool left = false;
372 bool right = false;
373 int tail;
374 int marker;
375
376 BUG_ON(!dst);
377 BUG_ON(!src);
378
379
380 if ((loc + 1) < dsize)
381 right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1);
382 if (loc > 0)
383 left = ntfs_are_rl_mergeable(dst + loc - 1, src);
384
385
386
387
388 delta = ssize - 1 - left - right;
389 if (delta > 0) {
390 dst = ntfs_rl_realloc(dst, dsize, dsize + delta);
391 if (IS_ERR(dst))
392 return dst;
393 }
394
395
396
397
398
399
400 if (right)
401 __ntfs_rl_merge(src + ssize - 1, dst + loc + 1);
402 if (left)
403 __ntfs_rl_merge(dst + loc - 1, src);
404
405
406
407
408
409
410
411
412 tail = loc + right + 1;
413
414
415
416
417
418
419
420 marker = loc + ssize - left;
421
422
423 ntfs_rl_mm(dst, marker, tail, dsize - tail);
424 ntfs_rl_mc(dst, loc, src, left, ssize - left);
425
426
427 if (dsize - tail > 0 && dst[marker].lcn == LCN_ENOENT)
428 dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
429 return dst;
430 }
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456 static inline runlist_element *ntfs_rl_split(runlist_element *dst, int dsize,
457 runlist_element *src, int ssize, int loc)
458 {
459 BUG_ON(!dst);
460 BUG_ON(!src);
461
462
463 dst = ntfs_rl_realloc(dst, dsize, dsize + ssize + 1);
464 if (IS_ERR(dst))
465 return dst;
466
467
468
469
470
471
472 ntfs_rl_mm(dst, loc + 1 + ssize, loc, dsize - loc);
473 ntfs_rl_mc(dst, loc + 1, src, 0, ssize);
474
475
476 dst[loc].length = dst[loc+1].vcn - dst[loc].vcn;
477 dst[loc+ssize+1].vcn = dst[loc+ssize].vcn + dst[loc+ssize].length;
478 dst[loc+ssize+1].length = dst[loc+ssize+2].vcn - dst[loc+ssize+1].vcn;
479
480 return dst;
481 }
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517 runlist_element *ntfs_runlists_merge(runlist_element *drl,
518 runlist_element *srl)
519 {
520 int di, si;
521 int sstart;
522 int dins;
523 int dend, send;
524 int dfinal, sfinal;
525
526 int marker = 0;
527 VCN marker_vcn = 0;
528
529 #ifdef DEBUG
530 ntfs_debug("dst:");
531 ntfs_debug_dump_runlist(drl);
532 ntfs_debug("src:");
533 ntfs_debug_dump_runlist(srl);
534 #endif
535
536
537 if (unlikely(!srl))
538 return drl;
539 if (IS_ERR(srl) || IS_ERR(drl))
540 return ERR_PTR(-EINVAL);
541
542
543 if (unlikely(!drl)) {
544 drl = srl;
545
546 if (unlikely(drl[0].vcn)) {
547
548 for (dend = 0; likely(drl[dend].length); dend++)
549 ;
550 dend++;
551 drl = ntfs_rl_realloc(drl, dend, dend + 1);
552 if (IS_ERR(drl))
553 return drl;
554
555 ntfs_rl_mm(drl, 1, 0, dend);
556 drl[0].vcn = 0;
557 drl[0].lcn = LCN_RL_NOT_MAPPED;
558 drl[0].length = drl[1].vcn;
559 }
560 goto finished;
561 }
562
563 si = di = 0;
564
565
566 while (srl[si].length && srl[si].lcn < LCN_HOLE)
567 si++;
568
569
570 BUG_ON(!srl[si].length);
571
572
573 sstart = si;
574
575
576
577
578
579
580 for (; drl[di].length; di++) {
581 if (drl[di].vcn + drl[di].length > srl[sstart].vcn)
582 break;
583 }
584 dins = di;
585
586
587 if ((drl[di].vcn == srl[si].vcn) && (drl[di].lcn >= 0) &&
588 (srl[si].lcn >= 0)) {
589 ntfs_error(NULL, "Run lists overlap. Cannot merge!");
590 return ERR_PTR(-ERANGE);
591 }
592
593
594 for (send = si; srl[send].length; send++)
595 ;
596 for (dend = di; drl[dend].length; dend++)
597 ;
598
599 if (srl[send].lcn == LCN_ENOENT)
600 marker_vcn = srl[marker = send].vcn;
601
602
603 for (sfinal = send; sfinal >= 0 && srl[sfinal].lcn < LCN_HOLE; sfinal--)
604 ;
605 for (dfinal = dend; dfinal >= 0 && drl[dfinal].lcn < LCN_HOLE; dfinal--)
606 ;
607
608 {
609 bool start;
610 bool finish;
611 int ds = dend + 1;
612 int ss = sfinal - sstart + 1;
613
614 start = ((drl[dins].lcn < LCN_RL_NOT_MAPPED) ||
615 (drl[dins].vcn == srl[sstart].vcn));
616 finish = ((drl[dins].lcn >= LCN_RL_NOT_MAPPED) &&
617 ((drl[dins].vcn + drl[dins].length) <=
618 (srl[send - 1].vcn + srl[send - 1].length)));
619
620
621 if (finish && !drl[dins].length)
622 ss++;
623 if (marker && (drl[dins].vcn + drl[dins].length > srl[send - 1].vcn))
624 finish = false;
625 #if 0
626 ntfs_debug("dfinal = %i, dend = %i", dfinal, dend);
627 ntfs_debug("sstart = %i, sfinal = %i, send = %i", sstart, sfinal, send);
628 ntfs_debug("start = %i, finish = %i", start, finish);
629 ntfs_debug("ds = %i, ss = %i, dins = %i", ds, ss, dins);
630 #endif
631 if (start) {
632 if (finish)
633 drl = ntfs_rl_replace(drl, ds, srl + sstart, ss, dins);
634 else
635 drl = ntfs_rl_insert(drl, ds, srl + sstart, ss, dins);
636 } else {
637 if (finish)
638 drl = ntfs_rl_append(drl, ds, srl + sstart, ss, dins);
639 else
640 drl = ntfs_rl_split(drl, ds, srl + sstart, ss, dins);
641 }
642 if (IS_ERR(drl)) {
643 ntfs_error(NULL, "Merge failed.");
644 return drl;
645 }
646 ntfs_free(srl);
647 if (marker) {
648 ntfs_debug("Triggering marker code.");
649 for (ds = dend; drl[ds].length; ds++)
650 ;
651
652 if (drl[ds].vcn <= marker_vcn) {
653 int slots = 0;
654
655 if (drl[ds].vcn == marker_vcn) {
656 ntfs_debug("Old marker = 0x%llx, replacing "
657 "with LCN_ENOENT.",
658 (unsigned long long)
659 drl[ds].lcn);
660 drl[ds].lcn = LCN_ENOENT;
661 goto finished;
662 }
663
664
665
666
667
668 if (drl[ds].lcn == LCN_ENOENT) {
669 ds--;
670 slots = 1;
671 }
672 if (drl[ds].lcn != LCN_RL_NOT_MAPPED) {
673
674 if (!slots) {
675 drl = ntfs_rl_realloc_nofail(drl, ds,
676 ds + 2);
677 slots = 2;
678 }
679 ds++;
680
681 if (slots != 1)
682 drl[ds].vcn = drl[ds - 1].vcn +
683 drl[ds - 1].length;
684 drl[ds].lcn = LCN_RL_NOT_MAPPED;
685
686 slots--;
687 }
688 drl[ds].length = marker_vcn - drl[ds].vcn;
689
690 ds++;
691 if (!slots)
692 drl = ntfs_rl_realloc_nofail(drl, ds, ds + 1);
693 drl[ds].vcn = marker_vcn;
694 drl[ds].lcn = LCN_ENOENT;
695 drl[ds].length = (s64)0;
696 }
697 }
698 }
699
700 finished:
701
702 ntfs_debug("Merged runlist:");
703 ntfs_debug_dump_runlist(drl);
704 return drl;
705 }
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735 runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol,
736 const ATTR_RECORD *attr, runlist_element *old_rl)
737 {
738 VCN vcn;
739 LCN lcn;
740 s64 deltaxcn;
741 runlist_element *rl;
742 u8 *buf;
743 u8 *attr_end;
744 int rlsize;
745 u16 rlpos;
746
747 u8 b;
748
749 #ifdef DEBUG
750
751 if (!attr || !attr->non_resident || sle64_to_cpu(
752 attr->data.non_resident.lowest_vcn) < (VCN)0) {
753 ntfs_error(vol->sb, "Invalid arguments.");
754 return ERR_PTR(-EINVAL);
755 }
756 #endif
757
758 vcn = sle64_to_cpu(attr->data.non_resident.lowest_vcn);
759 lcn = 0;
760
761 buf = (u8*)attr + le16_to_cpu(
762 attr->data.non_resident.mapping_pairs_offset);
763 attr_end = (u8*)attr + le32_to_cpu(attr->length);
764 if (unlikely(buf < (u8*)attr || buf > attr_end)) {
765 ntfs_error(vol->sb, "Corrupt attribute.");
766 return ERR_PTR(-EIO);
767 }
768
769 if (!vcn && !*buf)
770 return old_rl;
771
772 rlpos = 0;
773
774 rl = ntfs_malloc_nofs(rlsize = PAGE_SIZE);
775 if (unlikely(!rl))
776 return ERR_PTR(-ENOMEM);
777
778 if (vcn) {
779 rl->vcn = 0;
780 rl->lcn = LCN_RL_NOT_MAPPED;
781 rl->length = vcn;
782 rlpos++;
783 }
784 while (buf < attr_end && *buf) {
785
786
787
788
789
790 if (((rlpos + 3) * sizeof(*old_rl)) > rlsize) {
791 runlist_element *rl2;
792
793 rl2 = ntfs_malloc_nofs(rlsize + (int)PAGE_SIZE);
794 if (unlikely(!rl2)) {
795 ntfs_free(rl);
796 return ERR_PTR(-ENOMEM);
797 }
798 memcpy(rl2, rl, rlsize);
799 ntfs_free(rl);
800 rl = rl2;
801 rlsize += PAGE_SIZE;
802 }
803
804 rl[rlpos].vcn = vcn;
805
806
807
808
809
810
811
812 b = *buf & 0xf;
813 if (b) {
814 if (unlikely(buf + b > attr_end))
815 goto io_error;
816 for (deltaxcn = (s8)buf[b--]; b; b--)
817 deltaxcn = (deltaxcn << 8) + buf[b];
818 } else {
819 ntfs_error(vol->sb, "Missing length entry in mapping "
820 "pairs array.");
821 deltaxcn = (s64)-1;
822 }
823
824
825
826
827 if (unlikely(deltaxcn < 0)) {
828 ntfs_error(vol->sb, "Invalid length in mapping pairs "
829 "array.");
830 goto err_out;
831 }
832
833
834
835
836 rl[rlpos].length = deltaxcn;
837
838 vcn += deltaxcn;
839
840
841
842
843
844 if (!(*buf & 0xf0))
845 rl[rlpos].lcn = LCN_HOLE;
846 else {
847
848 u8 b2 = *buf & 0xf;
849 b = b2 + ((*buf >> 4) & 0xf);
850 if (buf + b > attr_end)
851 goto io_error;
852 for (deltaxcn = (s8)buf[b--]; b > b2; b--)
853 deltaxcn = (deltaxcn << 8) + buf[b];
854
855 lcn += deltaxcn;
856 #ifdef DEBUG
857
858
859
860
861
862
863
864 if (vol->major_ver < 3) {
865 if (unlikely(deltaxcn == (LCN)-1))
866 ntfs_error(vol->sb, "lcn delta == -1");
867 if (unlikely(lcn == (LCN)-1))
868 ntfs_error(vol->sb, "lcn == -1");
869 }
870 #endif
871
872 if (unlikely(lcn < (LCN)-1)) {
873 ntfs_error(vol->sb, "Invalid LCN < -1 in "
874 "mapping pairs array.");
875 goto err_out;
876 }
877
878 rl[rlpos].lcn = lcn;
879 }
880
881 rlpos++;
882
883 buf += (*buf & 0xf) + ((*buf >> 4) & 0xf) + 1;
884 }
885 if (unlikely(buf >= attr_end))
886 goto io_error;
887
888
889
890
891 deltaxcn = sle64_to_cpu(attr->data.non_resident.highest_vcn);
892 if (unlikely(deltaxcn && vcn - 1 != deltaxcn)) {
893 mpa_err:
894 ntfs_error(vol->sb, "Corrupt mapping pairs array in "
895 "non-resident attribute.");
896 goto err_out;
897 }
898
899 if (!attr->data.non_resident.lowest_vcn) {
900 VCN max_cluster;
901
902 max_cluster = ((sle64_to_cpu(
903 attr->data.non_resident.allocated_size) +
904 vol->cluster_size - 1) >>
905 vol->cluster_size_bits) - 1;
906
907
908
909
910 if (deltaxcn) {
911
912
913
914
915
916
917 if (deltaxcn < max_cluster) {
918 ntfs_debug("More extents to follow; deltaxcn "
919 "= 0x%llx, max_cluster = "
920 "0x%llx",
921 (unsigned long long)deltaxcn,
922 (unsigned long long)
923 max_cluster);
924 rl[rlpos].vcn = vcn;
925 vcn += rl[rlpos].length = max_cluster -
926 deltaxcn;
927 rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
928 rlpos++;
929 } else if (unlikely(deltaxcn > max_cluster)) {
930 ntfs_error(vol->sb, "Corrupt attribute. "
931 "deltaxcn = 0x%llx, "
932 "max_cluster = 0x%llx",
933 (unsigned long long)deltaxcn,
934 (unsigned long long)
935 max_cluster);
936 goto mpa_err;
937 }
938 }
939 rl[rlpos].lcn = LCN_ENOENT;
940 } else
941 rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
942
943
944 rl[rlpos].vcn = vcn;
945 rl[rlpos].length = (s64)0;
946
947 if (!old_rl) {
948 ntfs_debug("Mapping pairs array successfully decompressed:");
949 ntfs_debug_dump_runlist(rl);
950 return rl;
951 }
952
953 old_rl = ntfs_runlists_merge(old_rl, rl);
954 if (!IS_ERR(old_rl))
955 return old_rl;
956 ntfs_free(rl);
957 ntfs_error(vol->sb, "Failed to merge runlists.");
958 return old_rl;
959 io_error:
960 ntfs_error(vol->sb, "Corrupt attribute.");
961 err_out:
962 ntfs_free(rl);
963 return ERR_PTR(-EIO);
964 }
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990 LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn)
991 {
992 int i;
993
994 BUG_ON(vcn < 0);
995
996
997
998
999
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