1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#ifdef NTFS_RW
23
24#include <linux/pagemap.h>
25
26#include "lcnalloc.h"
27#include "debug.h"
28#include "bitmap.h"
29#include "inode.h"
30#include "volume.h"
31#include "attrib.h"
32#include "malloc.h"
33#include "aops.h"
34#include "ntfs.h"
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
51 const runlist_element *rl)
52{
53 struct inode *lcnbmp_vi = vol->lcnbmp_ino;
54 int ret = 0;
55
56 ntfs_debug("Entering.");
57 if (!rl)
58 return 0;
59 for (; rl->length; rl++) {
60 int err;
61
62 if (rl->lcn < 0)
63 continue;
64 err = ntfs_bitmap_clear_run(lcnbmp_vi, rl->lcn, rl->length);
65 if (unlikely(err && (!ret || ret == -ENOMEM) && ret != err))
66 ret = err;
67 }
68 ntfs_debug("Done.");
69 return ret;
70}
71
72
73
74
75
76
77
78
79
80
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
147 const s64 count, const LCN start_lcn,
148 const NTFS_CLUSTER_ALLOCATION_ZONES zone,
149 const bool is_extension)
150{
151 LCN zone_start, zone_end, bmp_pos, bmp_initial_pos, last_read_pos, lcn;
152 LCN prev_lcn = 0, prev_run_len = 0, mft_zone_size;
153 s64 clusters;
154 loff_t i_size;
155 struct inode *lcnbmp_vi;
156 runlist_element *rl = NULL;
157 struct address_space *mapping;
158 struct page *page = NULL;
159 u8 *buf, *byte;
160 int err = 0, rlpos, rlsize, buf_size;
161 u8 pass, done_zones, search_zone, need_writeback = 0, bit;
162
163 ntfs_debug("Entering for start_vcn 0x%llx, count 0x%llx, start_lcn "
164 "0x%llx, zone %s_ZONE.", (unsigned long long)start_vcn,
165 (unsigned long long)count,
166 (unsigned long long)start_lcn,
167 zone == MFT_ZONE ? "MFT" : "DATA");
168 BUG_ON(!vol);
169 lcnbmp_vi = vol->lcnbmp_ino;
170 BUG_ON(!lcnbmp_vi);
171 BUG_ON(start_vcn < 0);
172 BUG_ON(count < 0);
173 BUG_ON(start_lcn < -1);
174 BUG_ON(zone < FIRST_ZONE);
175 BUG_ON(zone > LAST_ZONE);
176
177
178 if (!count)
179 return NULL;
180
181 down_write(&vol->lcnbmp_lock);
182
183
184
185
186
187
188
189
190
191
192 done_zones = 0;
193 pass = 1;
194
195
196
197
198
199
200 zone_start = start_lcn;
201 if (zone_start < 0) {
202 if (zone == DATA_ZONE)
203 zone_start = vol->data1_zone_pos;
204 else
205 zone_start = vol->mft_zone_pos;
206 if (!zone_start) {
207
208
209
210
211 pass = 2;
212 }
213 } else if (zone == DATA_ZONE && zone_start >= vol->mft_zone_start &&
214 zone_start < vol->mft_zone_end) {
215 zone_start = vol->mft_zone_end;
216
217
218
219
220 pass = 2;
221 } else if (zone == MFT_ZONE && (zone_start < vol->mft_zone_start ||
222 zone_start >= vol->mft_zone_end)) {
223 zone_start = vol->mft_lcn;
224 if (!vol->mft_zone_end)
225 zone_start = 0;
226
227
228
229
230 pass = 2;
231 }
232 if (zone == MFT_ZONE) {
233 zone_end = vol->mft_zone_end;
234 search_zone = 1;
235 } else {
236
237 done_zones |= 1;
238 if (zone_start >= vol->mft_zone_end) {
239 zone_end = vol->nr_clusters;
240 search_zone = 2;
241 } else {
242 zone_end = vol->mft_zone_start;
243 search_zone = 4;
244 }
245 }
246
247
248
249
250 bmp_pos = bmp_initial_pos = zone_start;
251
252
253 clusters = count;
254 rlpos = rlsize = 0;
255 mapping = lcnbmp_vi->i_mapping;
256 i_size = i_size_read(lcnbmp_vi);
257 while (1) {
258 ntfs_debug("Start of outer while loop: done_zones 0x%x, "
259 "search_zone %i, pass %i, zone_start 0x%llx, "
260 "zone_end 0x%llx, bmp_initial_pos 0x%llx, "
261 "bmp_pos 0x%llx, rlpos %i, rlsize %i.",
262 done_zones, search_zone, pass,
263 (unsigned long long)zone_start,
264 (unsigned long long)zone_end,
265 (unsigned long long)bmp_initial_pos,
266 (unsigned long long)bmp_pos, rlpos, rlsize);
267
268 last_read_pos = bmp_pos >> 3;
269 ntfs_debug("last_read_pos 0x%llx.",
270 (unsigned long long)last_read_pos);
271 if (last_read_pos > i_size) {
272 ntfs_debug("End of attribute reached. "
273 "Skipping to zone_pass_done.");
274 goto zone_pass_done;
275 }
276 if (likely(page)) {
277 if (need_writeback) {
278 ntfs_debug("Marking page dirty.");
279 flush_dcache_page(page);
280 set_page_dirty(page);
281 need_writeback = 0;
282 }
283 ntfs_unmap_page(page);
284 }
285 page = ntfs_map_page(mapping, last_read_pos >>
286 PAGE_CACHE_SHIFT);
287 if (IS_ERR(page)) {
288 err = PTR_ERR(page);
289 ntfs_error(vol->sb, "Failed to map page.");
290 goto out;
291 }
292 buf_size = last_read_pos & ~PAGE_CACHE_MASK;
293 buf = page_address(page) + buf_size;
294 buf_size = PAGE_CACHE_SIZE - buf_size;
295 if (unlikely(last_read_pos + buf_size > i_size))
296 buf_size = i_size - last_read_pos;
297 buf_size <<= 3;
298 lcn = bmp_pos & 7;
299 bmp_pos &= ~(LCN)7;
300 ntfs_debug("Before inner while loop: buf_size %i, lcn 0x%llx, "
301 "bmp_pos 0x%llx, need_writeback %i.", buf_size,
302 (unsigned long long)lcn,
303 (unsigned long long)bmp_pos, need_writeback);
304 while (lcn < buf_size && lcn + bmp_pos < zone_end) {
305 byte = buf + (lcn >> 3);
306 ntfs_debug("In inner while loop: buf_size %i, "
307 "lcn 0x%llx, bmp_pos 0x%llx, "
308 "need_writeback %i, byte ofs 0x%x, "
309 "*byte 0x%x.", buf_size,
310 (unsigned long long)lcn,
311 (unsigned long long)bmp_pos,
312 need_writeback,
313 (unsigned int)(lcn >> 3),
314 (unsigned int)*byte);
315
316 if (*byte == 0xff) {
317 lcn = (lcn + 8) & ~(LCN)7;
318 ntfs_debug("Continuing while loop 1.");
319 continue;
320 }
321 bit = 1 << (lcn & 7);
322 ntfs_debug("bit 0x%x.", bit);
323
324 if (*byte & bit) {
325 lcn++;
326 ntfs_debug("Continuing while loop 2.");
327 continue;
328 }
329
330
331
332
333
334 if ((rlpos + 2) * sizeof(*rl) > rlsize) {
335 runlist_element *rl2;
336
337 ntfs_debug("Reallocating memory.");
338 if (!rl)
339 ntfs_debug("First free bit is at LCN "
340 "0x%llx.",
341 (unsigned long long)
342 (lcn + bmp_pos));
343 rl2 = ntfs_malloc_nofs(rlsize + (int)PAGE_SIZE);
344 if (unlikely(!rl2)) {
345 err = -ENOMEM;
346 ntfs_error(vol->sb, "Failed to "
347 "allocate memory.");
348 goto out;
349 }
350 memcpy(rl2, rl, rlsize);
351 ntfs_free(rl);
352 rl = rl2;
353 rlsize += PAGE_SIZE;
354 ntfs_debug("Reallocated memory, rlsize 0x%x.",
355 rlsize);
356 }
357
358 *byte |= bit;
359
360 need_writeback = 1;
361 ntfs_debug("*byte 0x%x, need_writeback is set.",
362 (unsigned int)*byte);
363
364
365
366
367 ntfs_debug("Adding run (lcn 0x%llx, len 0x%llx), "
368 "prev_lcn 0x%llx, lcn 0x%llx, "
369 "bmp_pos 0x%llx, prev_run_len 0x%llx, "
370 "rlpos %i.",
371 (unsigned long long)(lcn + bmp_pos),
372 1ULL, (unsigned long long)prev_lcn,
373 (unsigned long long)lcn,
374 (unsigned long long)bmp_pos,
375 (unsigned long long)prev_run_len,
376 rlpos);
377 if (prev_lcn == lcn + bmp_pos - prev_run_len && rlpos) {
378 ntfs_debug("Coalescing to run (lcn 0x%llx, "
379 "len 0x%llx).",
380 (unsigned long long)
381 rl[rlpos - 1].lcn,
382 (unsigned long long)
383 rl[rlpos - 1].length);
384 rl[rlpos - 1].length = ++prev_run_len;
385 ntfs_debug("Run now (lcn 0x%llx, len 0x%llx), "
386 "prev_run_len 0x%llx.",
387 (unsigned long long)
388 rl[rlpos - 1].lcn,
389 (unsigned long long)
390 rl[rlpos - 1].length,
391 (unsigned long long)
392 prev_run_len);
393 } else {
394 if (likely(rlpos)) {
395 ntfs_debug("Adding new run, (previous "
396 "run lcn 0x%llx, "
397 "len 0x%llx).",
398 (unsigned long long)
399 rl[rlpos - 1].lcn,
400 (unsigned long long)
401 rl[rlpos - 1].length);
402 rl[rlpos].vcn = rl[rlpos - 1].vcn +
403 prev_run_len;
404 } else {
405 ntfs_debug("Adding new run, is first "
406 "run.");
407 rl[rlpos].vcn = start_vcn;
408 }
409 rl[rlpos].lcn = prev_lcn = lcn + bmp_pos;
410 rl[rlpos].length = prev_run_len = 1;
411 rlpos++;
412 }
413
414 if (!--clusters) {
415 LCN tc;
416
417
418
419
420
421 tc = lcn + bmp_pos + 1;
422 ntfs_debug("Done. Updating current zone "
423 "position, tc 0x%llx, "
424 "search_zone %i.",
425 (unsigned long long)tc,
426 search_zone);
427 switch (search_zone) {
428 case 1:
429 ntfs_debug("Before checks, "
430 "vol->mft_zone_pos "
431 "0x%llx.",
432 (unsigned long long)
433 vol->mft_zone_pos);
434 if (tc >= vol->mft_zone_end) {
435 vol->mft_zone_pos =
436 vol->mft_lcn;
437 if (!vol->mft_zone_end)
438 vol->mft_zone_pos = 0;
439 } else if ((bmp_initial_pos >=
440 vol->mft_zone_pos ||
441 tc > vol->mft_zone_pos)
442 && tc >= vol->mft_lcn)
443 vol->mft_zone_pos = tc;
444 ntfs_debug("After checks, "
445 "vol->mft_zone_pos "
446 "0x%llx.",
447 (unsigned long long)
448 vol->mft_zone_pos);
449 break;
450 case 2:
451 ntfs_debug("Before checks, "
452 "vol->data1_zone_pos "
453 "0x%llx.",
454 (unsigned long long)
455 vol->data1_zone_pos);
456 if (tc >= vol->nr_clusters)
457 vol->data1_zone_pos =
458 vol->mft_zone_end;
459 else if ((bmp_initial_pos >=
460 vol->data1_zone_pos ||
461 tc > vol->data1_zone_pos)
462 && tc >= vol->mft_zone_end)
463 vol->data1_zone_pos = tc;
464 ntfs_debug("After checks, "
465 "vol->data1_zone_pos "
466 "0x%llx.",
467 (unsigned long long)
468 vol->data1_zone_pos);
469 break;
470 case 4:
471 ntfs_debug("Before checks, "
472 "vol->data2_zone_pos "
473 "0x%llx.",
474 (unsigned long long)
475 vol->data2_zone_pos);
476 if (tc >= vol->mft_zone_start)
477 vol->data2_zone_pos = 0;
478 else if (bmp_initial_pos >=
479 vol->data2_zone_pos ||
480 tc > vol->data2_zone_pos)
481 vol->data2_zone_pos = tc;
482 ntfs_debug("After checks, "
483 "vol->data2_zone_pos "
484 "0x%llx.",
485 (unsigned long long)
486 vol->data2_zone_pos);
487 break;
488 default:
489 BUG();
490 }
491 ntfs_debug("Finished. Going to out.");
492 goto out;
493 }
494 lcn++;
495 }
496 bmp_pos += buf_size;
497 ntfs_debug("After inner while loop: buf_size 0x%x, lcn "
498 "0x%llx, bmp_pos 0x%llx, need_writeback %i.",
499 buf_size, (unsigned long long)lcn,
500 (unsigned long long)bmp_pos, need_writeback);
501 if (bmp_pos < zone_end) {
502 ntfs_debug("Continuing outer while loop, "
503 "bmp_pos 0x%llx, zone_end 0x%llx.",
504 (unsigned long long)bmp_pos,
505 (unsigned long long)zone_end);
506 continue;
507 }
508zone_pass_done:
509 ntfs_debug("At zone_pass_done, pass %i.", pass);
510 if (pass == 1) {
511
512
513
514
515 pass = 2;
516 zone_end = zone_start;
517 switch (search_zone) {
518 case 1:
519 zone_start = vol->mft_zone_start;
520 break;
521 case 2:
522 zone_start = vol->mft_zone_end;
523 break;
524 case 4:
525 zone_start = 0;
526 break;
527 default:
528 BUG();
529 }
530
531 if (zone_end < zone_start)
532 zone_end = zone_start;
533 bmp_pos = zone_start;
534 ntfs_debug("Continuing outer while loop, pass 2, "
535 "zone_start 0x%llx, zone_end 0x%llx, "
536 "bmp_pos 0x%llx.",
537 (unsigned long long)zone_start,
538 (unsigned long long)zone_end,
539 (unsigned long long)bmp_pos);
540 continue;
541 }
542done_zones_check:
543 ntfs_debug("At done_zones_check, search_zone %i, done_zones "
544 "before 0x%x, done_zones after 0x%x.",
545 search_zone, done_zones,
546 done_zones | search_zone);
547 done_zones |= search_zone;
548 if (done_zones < 7) {
549 ntfs_debug("Switching zone.");
550
551 pass = 1;
552 switch (search_zone) {
553 case 1:
554 ntfs_debug("Switching from mft zone to data1 "
555 "zone.");
556
557 if (rlpos) {
558 LCN tc;
559
560 ntfs_debug("Before checks, "
561 "vol->mft_zone_pos "
562 "0x%llx.",
563 (unsigned long long)
564 vol->mft_zone_pos);
565 tc = rl[rlpos - 1].lcn +
566 rl[rlpos - 1].length;
567 if (tc >= vol->mft_zone_end) {
568 vol->mft_zone_pos =
569 vol->mft_lcn;
570 if (!vol->mft_zone_end)
571 vol->mft_zone_pos = 0;
572 } else if ((bmp_initial_pos >=
573 vol->mft_zone_pos ||
574 tc > vol->mft_zone_pos)
575 && tc >= vol->mft_lcn)
576 vol->mft_zone_pos = tc;
577 ntfs_debug("After checks, "
578 "vol->mft_zone_pos "
579 "0x%llx.",
580 (unsigned long long)
581 vol->mft_zone_pos);
582 }
583
584switch_to_data1_zone: search_zone = 2;
585 zone_start = bmp_initial_pos =
586 vol->data1_zone_pos;
587 zone_end = vol->nr_clusters;
588 if (zone_start == vol->mft_zone_end)
589 pass = 2;
590 if (zone_start >= zone_end) {
591 vol->data1_zone_pos = zone_start =
592 vol->mft_zone_end;
593 pass = 2;
594 }
595 break;
596 case 2:
597 ntfs_debug("Switching from data1 zone to "
598 "data2 zone.");
599
600 if (rlpos) {
601 LCN tc;
602
603 ntfs_debug("Before checks, "
604 "vol->data1_zone_pos "
605 "0x%llx.",
606 (unsigned long long)
607 vol->data1_zone_pos);
608 tc = rl[rlpos - 1].lcn +
609 rl[rlpos - 1].length;
610 if (tc >= vol->nr_clusters)
611 vol->data1_zone_pos =
612 vol->mft_zone_end;
613 else if ((bmp_initial_pos >=
614 vol->data1_zone_pos ||
615 tc > vol->data1_zone_pos)
616 && tc >= vol->mft_zone_end)
617 vol->data1_zone_pos = tc;
618 ntfs_debug("After checks, "
619 "vol->data1_zone_pos "
620 "0x%llx.",
621 (unsigned long long)
622 vol->data1_zone_pos);
623 }
624
625 search_zone = 4;
626 zone_start = bmp_initial_pos =
627 vol->data2_zone_pos;
628 zone_end = vol->mft_zone_start;
629 if (!zone_start)
630 pass = 2;
631 if (zone_start >= zone_end) {
632 vol->data2_zone_pos = zone_start =
633 bmp_initial_pos = 0;
634 pass = 2;
635 }
636 break;
637 case 4:
638 ntfs_debug("Switching from data2 zone to "
639 "data1 zone.");
640
641 if (rlpos) {
642 LCN tc;
643
644 ntfs_debug("Before checks, "
645 "vol->data2_zone_pos "
646 "0x%llx.",
647 (unsigned long long)
648 vol->data2_zone_pos);
649 tc = rl[rlpos - 1].lcn +
650 rl[rlpos - 1].length;
651 if (tc >= vol->mft_zone_start)
652 vol->data2_zone_pos = 0;
653 else if (bmp_initial_pos >=
654 vol->data2_zone_pos ||
655 tc > vol->data2_zone_pos)
656 vol->data2_zone_pos = tc;
657 ntfs_debug("After checks, "
658 "vol->data2_zone_pos "
659 "0x%llx.",
660 (unsigned long long)
661 vol->data2_zone_pos);
662 }
663
664 goto switch_to_data1_zone;
665 default:
666 BUG();
667 }
668 ntfs_debug("After zone switch, search_zone %i, "
669 "pass %i, bmp_initial_pos 0x%llx, "
670 "zone_start 0x%llx, zone_end 0x%llx.",
671 search_zone, pass,
672 (unsigned long long)bmp_initial_pos,
673 (unsigned long long)zone_start,
674 (unsigned long long)zone_end);
675 bmp_pos = zone_start;
676 if (zone_start == zone_end) {
677 ntfs_debug("Empty zone, going to "
678 "done_zones_check.");
679
680 goto done_zones_check;
681 }
682 ntfs_debug("Continuing outer while loop.");
683 continue;
684 }
685 ntfs_debug("All zones are finished.");
686
687
688
689
690 mft_zone_size = vol->mft_zone_end - vol->mft_zone_start;
691 ntfs_debug("vol->mft_zone_start 0x%llx, vol->mft_zone_end "
692 "0x%llx, mft_zone_size 0x%llx.",
693 (unsigned long long)vol->mft_zone_start,
694 (unsigned long long)vol->mft_zone_end,
695 (unsigned long long)mft_zone_size);
696 if (zone == MFT_ZONE || mft_zone_size <= 0) {
697 ntfs_debug("No free clusters left, going to out.");
698
699 err = -ENOSPC;
700 goto out;
701 }
702 ntfs_debug("Shrinking mft zone.");
703 zone_end = vol->mft_zone_end;
704 mft_zone_size >>= 1;
705 if (mft_zone_size > 0)
706 vol->mft_zone_end = vol->mft_zone_start + mft_zone_size;
707 else
708 vol->data2_zone_pos = vol->mft_zone_start =
709 vol->mft_zone_end = 0;
710 if (vol->mft_zone_pos >= vol->mft_zone_end) {
711 vol->mft_zone_pos = vol->mft_lcn;
712 if (!vol->mft_zone_end)
713 vol->mft_zone_pos = 0;
714 }
715 bmp_pos = zone_start = bmp_initial_pos =
716 vol->data1_zone_pos = vol->mft_zone_end;
717 search_zone = 2;
718 pass = 2;
719 done_zones &= ~2;
720 ntfs_debug("After shrinking mft zone, mft_zone_size 0x%llx, "
721 "vol->mft_zone_start 0x%llx, "
722 "vol->mft_zone_end 0x%llx, "
723 "vol->mft_zone_pos 0x%llx, search_zone 2, "
724 "pass 2, dones_zones 0x%x, zone_start 0x%llx, "
725 "zone_end 0x%llx, vol->data1_zone_pos 0x%llx, "
726 "continuing outer while loop.",
727 (unsigned long long)mft_zone_size,
728 (unsigned long long)vol->mft_zone_start,
729 (unsigned long long)vol->mft_zone_end,
730 (unsigned long long)vol->mft_zone_pos,
731 done_zones, (unsigned long long)zone_start,
732 (unsigned long long)zone_end,
733 (unsigned long long)vol->data1_zone_pos);
734 }
735 ntfs_debug("After outer while loop.");
736out:
737 ntfs_debug("At out.");
738
739 if (likely(rl)) {
740 rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length;
741 rl[rlpos].lcn = is_extension ? LCN_ENOENT : LCN_RL_NOT_MAPPED;
742 rl[rlpos].length = 0;
743 }
744 if (likely(page && !IS_ERR(page))) {
745 if (need_writeback) {
746 ntfs_debug("Marking page dirty.");
747 flush_dcache_page(page);
748 set_page_dirty(page);
749 need_writeback = 0;
750 }
751 ntfs_unmap_page(page);
752 }
753 if (likely(!err)) {
754 up_write(&vol->lcnbmp_lock);
755 ntfs_debug("Done.");
756 return rl;
757 }
758 ntfs_error(vol->sb, "Failed to allocate clusters, aborting "
759 "(error %i).", err);
760 if (rl) {
761 int err2;
762
763 if (err == -ENOSPC)
764 ntfs_debug("Not enough space to complete allocation, "
765 "err -ENOSPC, first free lcn 0x%llx, "
766 "could allocate up to 0x%llx "
767 "clusters.",
768 (unsigned long long)rl[0].lcn,
769 (unsigned long long)(count - clusters));
770
771 ntfs_debug("Attempting rollback...");
772 err2 = ntfs_cluster_free_from_rl_nolock(vol, rl);
773 if (err2) {
774 ntfs_error(vol->sb, "Failed to rollback (error %i). "
775 "Leaving inconsistent metadata! "
776 "Unmount and run chkdsk.", err2);
777 NVolSetErrors(vol);
778 }
779
780 ntfs_free(rl);
781 } else if (err == -ENOSPC)
782 ntfs_debug("No space left at all, err = -ENOSPC, first free "
783 "lcn = 0x%llx.",
784 (long long)vol->data1_zone_pos);
785 up_write(&vol->lcnbmp_lock);
786 return ERR_PTR(err);
787}
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count,
850 ntfs_attr_search_ctx *ctx, const bool is_rollback)
851{
852 s64 delta, to_free, total_freed, real_freed;
853 ntfs_volume *vol;
854 struct inode *lcnbmp_vi;
855 runlist_element *rl;
856 int err;
857
858 BUG_ON(!ni);
859 ntfs_debug("Entering for i_ino 0x%lx, start_vcn 0x%llx, count "
860 "0x%llx.%s", ni->mft_no, (unsigned long long)start_vcn,
861 (unsigned long long)count,
862 is_rollback ? " (rollback)" : "");
863 vol = ni->vol;
864 lcnbmp_vi = vol->lcnbmp_ino;
865 BUG_ON(!lcnbmp_vi);
866 BUG_ON(start_vcn < 0);
867 BUG_ON(count < -1);
868
869
870
871
872
873
874
875 if (likely(!is_rollback))
876 down_write(&vol->lcnbmp_lock);
877
878 total_freed = real_freed = 0;
879
880 rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, ctx);
881 if (IS_ERR(rl)) {
882 if (!is_rollback)
883 ntfs_error(vol->sb, "Failed to find first runlist "
884 "element (error %li), aborting.",
885 PTR_ERR(rl));
886 err = PTR_ERR(rl);
887 goto err_out;
888 }
889 if (unlikely(rl->lcn < LCN_HOLE)) {
890 if (!is_rollback)
891 ntfs_error(vol->sb, "First runlist element has "
892 "invalid lcn, aborting.");
893 err = -EIO;
894 goto err_out;
895 }
896
897 delta = start_vcn - rl->vcn;
898
899
900 to_free = rl->length - delta;
901 if (count >= 0 && to_free > count)
902 to_free = count;
903
904 if (likely(rl->lcn >= 0)) {
905
906 err = ntfs_bitmap_set_bits_in_run(lcnbmp_vi, rl->lcn + delta,
907 to_free, likely(!is_rollback) ? 0 : 1);
908 if (unlikely(err)) {
909 if (!is_rollback)
910 ntfs_error(vol->sb, "Failed to clear first run "
911 "(error %i), aborting.", err);
912 goto err_out;
913 }
914
915 real_freed = to_free;
916 };
917
918 ++rl;
919 if (count >= 0)
920 count -= to_free;
921
922
923 total_freed = to_free;
924
925
926
927
928 for (; rl->length && count != 0; ++rl) {
929 if (unlikely(rl->lcn < LCN_HOLE)) {
930 VCN vcn;
931
932
933 vcn = rl->vcn;
934 rl = ntfs_attr_find_vcn_nolock(ni, vcn, ctx);
935 if (IS_ERR(rl)) {
936 err = PTR_ERR(rl);
937 if (!is_rollback)
938 ntfs_error(vol->sb, "Failed to map "
939 "runlist fragment or "
940 "failed to find "
941 "subsequent runlist "
942 "element.");
943 goto err_out;
944 }
945 if (unlikely(rl->lcn < LCN_HOLE)) {
946 if (!is_rollback)
947 ntfs_error(vol->sb, "Runlist element "
948 "has invalid lcn "
949 "(0x%llx).",
950 (unsigned long long)
951 rl->lcn);
952 err = -EIO;
953 goto err_out;
954 }
955 }
956
957 to_free = rl->length;
958 if (count >= 0 && to_free > count)
959 to_free = count;
960
961 if (likely(rl->lcn >= 0)) {
962
963 err = ntfs_bitmap_set_bits_in_run(lcnbmp_vi, rl->lcn,
964 to_free, likely(!is_rollback) ? 0 : 1);
965 if (unlikely(err)) {
966 if (!is_rollback)
967 ntfs_error(vol->sb, "Failed to clear "
968 "subsequent run.");
969 goto err_out;
970 }
971
972 real_freed += to_free;
973 }
974
975 if (count >= 0)
976 count -= to_free;
977
978
979 total_freed += to_free;
980 }
981 if (likely(!is_rollback))
982 up_write(&vol->lcnbmp_lock);
983
984 BUG_ON(count > 0);
985
986
987 ntfs_debug("Done.");
988 return real_freed;
989err_out:
990 if (is_rollback)
991 return err;
992
993 if (!real_freed) {
994 up_write(&vol->lcnbmp_lock);
995 return err;
996 }
997
998
999
1000
1001
1002 delta = __ntfs_cluster_free(ni, start_vcn, total_freed, ctx, true);
1003 if (delta < 0) {
1004 ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving "
1005 "inconsistent metadata! Unmount and run "
1006 "chkdsk.", (int)delta);
1007 NVolSetErrors(vol);
1008 }
1009 up_write(&vol->lcnbmp_lock);
1010 ntfs_error(vol->sb, "Aborting (error %i).", err);
1011 return err;
1012}
1013
1014#endif
1015