ReactOS 0.4.15-dev-8093-g3285f69
indirect.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYRIGHT.TXT
3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP
4 * FILE: indirect.c
5 * PROGRAMMER: Matt Wu <mattwu@163.com>
6 * HOMEPAGE: http://www.ext2fsd.com
7 * UPDATE HISTORY:
8 */
9
10/* INCLUDES *****************************************************************/
11
12#include "ext2fs.h"
13
14/* GLOBALS *****************************************************************/
15
17
18/* DEFINITIONS *************************************************************/
19
20#ifdef ALLOC_PRAGMA
21#endif
22
23
26 IN PEXT2_IRP_CONTEXT IrpContext,
31 IN PULONG * Data,
32 IN PULONG Hint,
33 IN PULONG Block,
35)
36{
38 ULONG i;
40
41 if (Layer > 0 || IsMcbDirectory(Mcb)) {
42
43 /* allocate buffer for new block */
48 );
49 if (!pData) {
50 DEBUG(DL_ERR, ( "Ex2ExpandBlock: failed to allocate memory for Data.\n"));
52 goto errorout;
53 }
56 }
57
58 /* allocate block from disk */
60 IrpContext,
61 Vcb,
62 (Mcb->Inode.i_ino - 1) / BLOCKS_PER_GROUP,
63 *Hint,
64 Block,
65 Number
66 );
67
68 if (!NT_SUCCESS(Status)) {
69 goto errorout;
70 }
71
72 /* increase inode i_blocks */
73 Mcb->Inode.i_blocks += (*Number << (BLOCK_BITS - 9));
74
75 if (Layer == 0) {
76
77 if (IsMcbDirectory(Mcb)) {
78 /* for directory we need initialize it's entry structure */
81 pEntry->rec_len = (USHORT)(BLOCK_SIZE);
82 ASSERT(*Number == 1);
83 Ext2SaveBlock(IrpContext, Vcb, *Block, (PVOID)pData);
84 }
85
86 /* add new Extent into Mcb */
87 if (!Ext2AddBlockExtent(Vcb, Mcb, Base, (*Block), *Number)) {
88 DbgBreak();
90 Ext2ClearAllExtents(&Mcb->Extents);
91 }
92
93 } else {
94
95 /* zero the content of all meta blocks */
96 for (i = 0; i < *Number; i++) {
97 Ext2SaveBlock(IrpContext, Vcb, *Block + i, (PVOID)pData);
98 /* add block to meta extents */
99 if (!Ext2AddMcbMetaExts(Vcb, Mcb, *Block + i, 1)) {
100 DbgBreak();
101 Ext2Sleep(500);
102 Ext2AddMcbMetaExts(Vcb, Mcb, *Block + i, 1);
103 }
104 }
105 }
106
107errorout:
108
109 if (NT_SUCCESS(Status)) {
110 *Hint = *Block + *Number;
111 if (Data) {
112 *Data = pData;
113 ASSERT(*Number == 1);
114 } else {
115 if (pData) {
118 }
119 }
120 } else {
121 if (pData) {
124 }
125 if (*Block) {
126 Ext2FreeBlock(IrpContext, Vcb, *Block, *Number);
127 Mcb->Inode.i_blocks -= (*Number << (BLOCK_BITS - 9));
128 *Block = 0;
129 }
130 }
131
132 return Status;
133}
134
137 IN PEXT2_IRP_CONTEXT IrpContext,
140 IN ULONG Base,
141 IN ULONG Layer,
142 IN ULONG Start,
143 IN ULONG SizeArray,
144 IN PULONG BlockArray,
145 IN BOOLEAN bAlloc,
146 IN OUT PULONG Hint,
147 OUT PULONG Block,
149)
150{
152 PBCB Bcb = NULL;
153 PULONG pData = NULL;
154 ULONG Slot = 0, i = 0;
155 ULONG Unit = 1;
156
158
159 if (Layer == 0) {
160
161 *Number = 1;
162 if (BlockArray[0] == 0 && bAlloc) {
163
164 /* now allocate new block */
166 IrpContext,
167 Vcb,
168 Mcb,
169 Base,
170 Layer,
171 NULL,
172 Hint,
173 &BlockArray[0],
174 Number
175 );
176
177 if (!NT_SUCCESS(Status)) {
178 goto errorout;
179 }
180 } else {
181 /* check the block is valid or not */
182 if (BlockArray[0] >= TOTAL_BLOCKS) {
183 DbgBreak();
185 goto errorout;
186 }
187 }
188
189 *Block = BlockArray[0];
190 for (i=1; i < SizeArray; i++) {
191 if (BlockArray[i] == BlockArray[i-1] + 1) {
192 *Number = *Number + 1;
193 } else {
194 break;
195 }
196 }
197 *Hint = BlockArray[*Number - 1];
198
199 } else if (Layer <= 3) {
200
201 /* check the block is valid or not */
202 if (BlockArray[0] == 0 || BlockArray[0] >= TOTAL_BLOCKS) {
203 DbgBreak();
205 goto errorout;
206 }
207
208 /* add block to meta extents */
209 if (!Ext2AddMcbMetaExts(Vcb, Mcb, BlockArray[0], 1)) {
210 DbgBreak();
211 Ext2Sleep(500);
212 Ext2AddMcbMetaExts(Vcb, Mcb, BlockArray[0], 1);
213 }
214
215 /* map memory in cache for the index block */
216 Offset.QuadPart = ((LONGLONG)BlockArray[0]) << BLOCK_BITS;
217 if ( !CcPinRead( Vcb->Volume,
220 PIN_WAIT,
221 &Bcb,
222#ifdef __REACTOS__
223 (void **)&pData )) {
224#else
225 &pData )) {
226#endif
227
228 DEBUG(DL_ERR, ( "Ext2GetBlock: Failed to PinLock block: %xh ...\n",
229 BlockArray[0] ));
231 goto errorout;
232 }
233
234 if (Layer > 1) {
235 Unit = Vcb->max_blocks_per_layer[Layer - 1];
236 } else {
237 Unit = 1;
238 }
239
240 Slot = Start / Unit;
241 Start = Start % Unit;
242
243 if (pData[Slot] == 0) {
244
245 if (bAlloc) {
246
247 /* we need allocate new block and zero all data in case
248 it's an in-direct block. Index stores the new block no. */
249 ULONG Count = 1;
251 IrpContext,
252 Vcb,
253 Mcb,
254 Base,
255 Layer,
256 NULL,
257 Hint,
258 &pData[Slot],
259 &Count
260 );
261
262 if (!NT_SUCCESS(Status)) {
263 goto errorout;
264 }
265
266 /* refresh hint block */
267 *Hint = pData[Slot];
268
269 /* set dirty bit to notify system to flush */
271 SetFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
272 if (!Ext2AddVcbExtent(Vcb, Offset.QuadPart,
274 DbgBreak();
275 Ext2Sleep(100);
276 if (!Ext2AddVcbExtent(Vcb, Offset.QuadPart,
279 goto errorout;
280 }
281 }
282
283 /* save inode information here */
284 Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
285
286 } else {
287
288 *Number = 1;
289
290 if (Layer == 1) {
291 for (i = Slot + 1; i < BLOCK_SIZE/4; i++) {
292 if (pData[i] == 0) {
293 *Number = *Number + 1;
294 } else {
295 break;
296 }
297 }
298 } else if (Layer == 2) {
299 *Number = BLOCK_SIZE/4 - Start;
300 } else {
301 *Number = BLOCK_SIZE/4;
302 }
303
304 goto errorout;
305 }
306 }
307
308 /* transfer to next recursion call */
310 IrpContext,
311 Vcb,
312 Mcb,
313 Base,
314 Layer - 1,
315 Start,
316 BLOCK_SIZE/4 - Slot,
317 &pData[Slot],
318 bAlloc,
319 Hint,
320 Block,
321 Number
322 );
323
324 if (!NT_SUCCESS(Status)) {
325 goto errorout;
326 }
327 }
328
329errorout:
330
331 /* free the memory of pData */
332 if (Bcb) {
334 }
335
336 if (!NT_SUCCESS(Status)) {
337 *Block = 0;
338 }
339
340 return Status;
341}
342
343
346 IN PEXT2_IRP_CONTEXT IrpContext,
349 IN ULONG Base,
350 IN ULONG Layer,
351 IN ULONG Start,
352 IN ULONG SizeArray,
353 IN PULONG BlockArray,
354 IN PULONG Hint,
355 IN PULONG Extra
356)
357{
358 ULONG i = 0;
359 ULONG j;
360 ULONG Slot;
361 ULONG Block = 0;
363
364 PBCB Bcb = NULL;
365 PULONG pData = NULL;
366 ULONG Skip = 0;
367
369 ULONG Wanted;
370
372
373 if (Layer == 1) {
374
375 /*
376 * try to make all leaf block continuous to avoid fragments
377 */
378
379 Number = min(SizeArray, ((*Extra + (Start & (BLOCK_SIZE/4 - 1))) * 4 / BLOCK_SIZE));
380 Wanted = 0;
381 DEBUG(DL_BLK, ("Ext2ExpandBlock: SizeArray=%xh Extra=%xh Start=%xh %xh\n",
382 SizeArray, *Extra, Start, Number ));
383
384 for (i=0; i < Number; i++) {
385 if (BlockArray[i] == 0) {
386 Wanted += 1;
387 }
388 }
389
390 i = 0;
391 while (Wanted > 0) {
392
393 Number = Wanted;
395 IrpContext,
396 Vcb,
397 Mcb,
398 Base,
399 Layer,
400 NULL,
401 Hint,
402 &Block,
403 &Number
404 );
405 if (!NT_SUCCESS(Status)) {
406 goto errorout;
407 }
408
409 ASSERT(Number > 0);
410 Wanted -= Number;
411 while (Number) {
412 if (BlockArray[i] == 0) {
413 BlockArray[i] = Block++;
414 Number--;
415 }
416 i++;
417 }
418 }
419
420 } else if (Layer == 0) {
421
422 /*
423 * bulk allocation for inode data blocks
424 */
425
426 i = 0;
427
428 while (*Extra && i < SizeArray) {
429
430 Wanted = 0;
431 Number = 1;
432
433 for (j = i; j < SizeArray && j < i + *Extra; j++) {
434
435 if (BlockArray[j] >= TOTAL_BLOCKS) {
436 DbgBreak();
437 BlockArray[j] = 0;
438 }
439
440 if (BlockArray[j] == 0) {
441 Wanted += 1;
442 } else {
443 break;
444 }
445 }
446
447 if (Wanted == 0) {
448
449 /* add block extent into Mcb */
450 ASSERT(BlockArray[i] != 0);
451 if (!Ext2AddBlockExtent(Vcb, Mcb, Base + i, BlockArray[i], 1)) {
452 DbgBreak();
454 Ext2ClearAllExtents(&Mcb->Extents);
455 }
456
457 } else {
458
459 Number = Wanted;
461 IrpContext,
462 Vcb,
463 Mcb,
464 Base + i,
465 0,
466 NULL,
467 Hint,
468 &Block,
469 &Number
470 );
471 if (!NT_SUCCESS(Status)) {
472 goto errorout;
473 }
474
475 ASSERT(Number > 0);
476 for (j = 0; j < Number; j++) {
477 BlockArray[i + j] = Block++;
478 }
479 }
480
481 *Extra -= Number;
482 i += Number;
483 }
484
485 goto errorout;
486 }
487
488
489 /*
490 * only for meta blocks allocation
491 */
492
493 for (i = 0; *Extra && i < SizeArray; i++) {
494
495 if (Layer <= 3) {
496
497 if (BlockArray[i] >= TOTAL_BLOCKS) {
498 DbgBreak();
499 BlockArray[i] = 0;
500 }
501
502 if (BlockArray[i] == 0) {
503 Number = 1;
505 IrpContext,
506 Vcb,
507 Mcb,
508 Base,
509 Layer,
510 &pData,
511 Hint,
512 &BlockArray[i],
513 &Number
514 );
515 if (!NT_SUCCESS(Status)) {
516 goto errorout;
517 }
518
519 } else {
520
521 Offset.QuadPart = (((LONGLONG)BlockArray[i]) << BLOCK_BITS);
522 if (!CcPinRead(
523 Vcb->Volume,
524 &Offset,
526 PIN_WAIT,
527 &Bcb,
528#ifdef __REACTOS__
529 (void **)&pData )) {
530#else
531 &pData )) {
532#endif
533
534 DEBUG(DL_ERR, ( "Ext2ExpandInode: failed to PinLock offset :%I64xh...\n",
535 Offset.QuadPart));
537 DbgBreak();
538 goto errorout;
539 }
540
541 /* add block to meta extents */
542 if (!Ext2AddMcbMetaExts(Vcb, Mcb, BlockArray[i], 1)) {
543 DbgBreak();
544 Ext2Sleep(500);
545 Ext2AddMcbMetaExts(Vcb, Mcb, BlockArray[i], 1);
546 }
547 }
548
549 Skip = Vcb->max_blocks_per_layer[Layer] * i;
550
551 if (i == 0) {
552 if (Layer > 1) {
553 Slot = Start / Vcb->max_blocks_per_layer[Layer - 1];
554 Start = Start % Vcb->max_blocks_per_layer[Layer - 1];
555 Skip += Slot * Vcb->max_blocks_per_layer[Layer - 1];
556 } else {
557 Slot = Start;
558 Start = 0;
559 Skip += Slot;
560 }
561 } else {
562 Start = 0;
563 Slot = 0;
564 }
565
567 IrpContext,
568 Vcb,
569 Mcb,
570 Base + Skip,
571 Layer - 1,
572 Start,
573 BLOCK_SIZE/4 - Slot,
574 &pData[Slot],
575 Hint,
576 Extra
577 );
578
579 if (Bcb) {
582 BlockArray[i],
583 BlockArray[i], 1)) {
584 DbgBreak();
585 Ext2Sleep(500);
587 BlockArray[i],
588 BlockArray[i], 1)) {
589 }
590 }
591 } else {
592 Ext2SaveBlock(IrpContext, Vcb, BlockArray[i], (PVOID)pData);
593 }
594
595 if (pData) {
596 if (Bcb) {
598 Bcb = NULL;
599 } else {
602 }
603 pData = NULL;
604 }
605
606 if (!NT_SUCCESS(Status)) {
607 DbgBreak();
608 break;
609 }
610 }
611 }
612
613errorout:
614
615 return Status;
616}
617
619Ext2IsBlockEmpty(PULONG BlockArray, ULONG SizeArray)
620{
621 ULONG i = 0;
622 for (i=0; i < SizeArray; i++) {
623 if (BlockArray[i]) {
624 break;
625 }
626 }
627 return (i == SizeArray);
628}
629
630
633 IN PEXT2_IRP_CONTEXT IrpContext,
636 IN ULONG Base,
637 IN ULONG Start,
638 IN ULONG Layer,
639 IN ULONG SizeArray,
640 IN PULONG BlockArray,
641 IN PULONG Extra
642)
643{
645 ULONG i = 0;
646 ULONG Slot = 0;
647 ULONG Skip = 0;
648
650 PBCB Bcb = NULL;
651 PULONG pData = NULL;
652
653 ASSERT(Mcb != NULL);
654
655 for (i = 0; i < SizeArray; i++) {
656
657 if (Layer == 0) {
658
659 ULONG Number = 1;
660
661 while (Extra && SizeArray > i + 1 && Number < *Extra) {
662
663 if (BlockArray[SizeArray - i - 1] ==
664 BlockArray[SizeArray - i - 2] + 1) {
665
666 BlockArray[SizeArray - i - 1] = 0;
667 Number++;
668 SizeArray--;
669
670 } else {
671 break;
672 }
673 }
674
675 if (BlockArray[SizeArray - i - 1]) {
676
677 Status = Ext2FreeBlock(IrpContext, Vcb, BlockArray[SizeArray - i - 1], Number);
678 if (NT_SUCCESS(Status)) {
679 ASSERT(Mcb->Inode.i_blocks >= (Number << (BLOCK_BITS - 9)));
680 if (Mcb->Inode.i_blocks < (Number << (BLOCK_BITS - 9))) {
681 Mcb->Inode.i_blocks = 0;
682 DbgBreak();
683 } else {
684 Mcb->Inode.i_blocks -= (Number << (BLOCK_BITS - 9));
685 }
686 BlockArray[SizeArray - i - 1] = 0;
687 }
688 }
689
690 if (Extra) {
691
692 /* dec blocks count */
693 ASSERT(*Extra >= Number);
694 *Extra = *Extra - Number;
695
696 /* remove block mapping frm Mcb Extents */
697 if (!Ext2RemoveBlockExtent(Vcb, Mcb, Base + SizeArray - 1 - i, Number)) {
698 DbgBreak();
700 Ext2ClearAllExtents(&Mcb->Extents);
701 }
702 }
703
704 } else {
705
706 ASSERT(Layer <= 3);
707
708 if (BlockArray[SizeArray - i - 1] >= TOTAL_BLOCKS) {
709 DbgBreak();
710 BlockArray[SizeArray - i - 1] = 0;
711 }
712
713 if (i == 0) {
714 if (Layer > 1) {
715 Slot = Start / Vcb->max_blocks_per_layer[Layer - 1];
716 Start = Start % Vcb->max_blocks_per_layer[Layer - 1];
717 } else {
718 Slot = Start;
719 Start = (BLOCK_SIZE / 4) - 1;
720 }
721 } else {
722 Slot = Start = (BLOCK_SIZE / 4) - 1;
723 }
724
725 Skip = (SizeArray - i - 1) * Vcb->max_blocks_per_layer[Layer];
726
727 if (BlockArray[SizeArray - i - 1]) {
728
729 Offset = (LONGLONG) (BlockArray[SizeArray - i - 1]);
731
732 if (!CcPinRead( Vcb->Volume,
735 PIN_WAIT,
736 &Bcb,
737#ifdef __REACTOS__
738 (void **)&pData )) {
739#else
740 &pData )) {
741#endif
742
743 DEBUG(DL_ERR, ( "Ext2TruncateBlock: PinLock failed on block %xh ...\n",
744 BlockArray[SizeArray - i - 1]));
746 DbgBreak();
747 goto errorout;
748 }
749
751 IrpContext,
752 Vcb,
753 Mcb,
754 Base + Skip,
755 Start,
756 Layer - 1,
757 Slot + 1,
758 &pData[0],
759 Extra
760 );
761
762 if (!NT_SUCCESS(Status)) {
763 break;
764 }
765
768
769 if (*Extra || Ext2IsBlockEmpty(pData, BLOCK_SIZE/4)) {
770
772 IrpContext,
773 Vcb,
774 Mcb,
775 Base + Skip, /* base */
776 0, /* start */
777 0, /* layer */
778 1,
779 &BlockArray[SizeArray - i - 1],
780 NULL
781 );
782
783 if (!Ext2RemoveMcbMetaExts(Vcb, Mcb, BlockArray[SizeArray - i - 1], 1)) {
784 DbgBreak();
785 Ext2Sleep(500);
786 Ext2RemoveMcbMetaExts(Vcb, Mcb, BlockArray[SizeArray - i - 1], 1);
787 }
788 }
789
790 if (pData) {
792 Bcb = NULL;
793 pData = NULL;
794 }
795
796 } else {
797
798 if (Layer > 1) {
799 if (*Extra > Slot * Vcb->max_blocks_per_layer[Layer - 1] + Start + 1) {
800 *Extra -= (Slot * Vcb->max_blocks_per_layer[Layer - 1] + Start + 1);
801 } else {
802 *Extra = 0;
803 }
804 } else {
805 if (*Extra > Slot + 1) {
806 *Extra -= (Slot + 1);
807 } else {
808 *Extra = 0;
809 }
810 }
811
812 if (!Ext2RemoveBlockExtent(Vcb, Mcb, Base + Skip, (Start + 1))) {
813 DbgBreak();
815 Ext2ClearAllExtents(&Mcb->Extents);
816 }
817 }
818 }
819
820 if (Extra && *Extra == 0) {
821 break;
822 }
823 }
824
825errorout:
826
827 if (pData) {
829 }
830
831 return Status;
832}
833
836 IN PEXT2_IRP_CONTEXT IrpContext,
839 IN ULONG Index,
840 IN BOOLEAN bAlloc,
841 OUT PULONG pBlock,
843)
844{
845 ULONG Layer;
846 ULONG Slot;
847
848 ULONG Base = Index;
849
851
852 *pBlock = 0;
853 *Number = 0;
854
855 for (Layer = 0; Layer < EXT2_BLOCK_TYPES; Layer++) {
856
857 if (Index < Vcb->max_blocks_per_layer[Layer]) {
858
859 ULONG dwRet = 0, dwBlk = 0, dwHint = 0, dwArray = 0;
860
861 Slot = (Layer==0) ? (Index):(Layer + EXT2_NDIR_BLOCKS - 1);
862 dwBlk = Mcb->Inode.i_block[Slot];
863
864 if (dwBlk == 0) {
865
866 if (!bAlloc) {
867
868 *Number = 1;
869 goto errorout;
870
871 } else {
872
873 if (Slot) {
874 dwHint = Mcb->Inode.i_block[Slot - 1];
875 }
876
877 /* allocate and zero block if necessary */
878 *Number = 1;
880 IrpContext,
881 Vcb,
882 Mcb,
883 Base,
884 Layer,
885 NULL,
886 &dwHint,
887 &dwBlk,
888 Number
889 );
890
891 if (!NT_SUCCESS(Status)) {
892 goto errorout;
893 }
894
895 /* save the it into inode*/
896 Mcb->Inode.i_block[Slot] = dwBlk;
897
898 /* save the inode */
899 if (!Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode)) {
900 DbgBreak();
902 goto errorout;
903 }
904 }
905 }
906
907 if (Layer == 0)
908 dwArray = Vcb->max_blocks_per_layer[Layer] - Index;
909 else
910 dwArray = 1;
911
912 /* querying block number of the index-th file block */
914 IrpContext,
915 Vcb,
916 Mcb,
917 Base,
918 Layer,
919 Index,
920 dwArray,
921#ifdef __REACTOS__
922 (PULONG)&Mcb->Inode.i_block[Slot],
923#else
924 &Mcb->Inode.i_block[Slot],
925#endif
926 bAlloc,
927 &dwHint,
928 &dwRet,
929 Number
930 );
931
932 if (NT_SUCCESS(Status)) {
933 *pBlock = dwRet;
934 }
935
936 break;
937 }
938
939 Index -= Vcb->max_blocks_per_layer[Layer];
940 }
941
942errorout:
943
944 return Status;
945}
946
949 PEXT2_IRP_CONTEXT IrpContext,
952 ULONG Start,
953 ULONG End,
955)
956{
958
959 ULONG Layer = 0;
960 ULONG Extra = 0;
961 ULONG Hint = 0;
962 ULONG Slot = 0;
963 ULONG Base = 0;
964
965 Extra = End - Start;
966
967 /* exceeds the biggest file size (indirect) */
968 if (End > Vcb->max_data_blocks) {
970 }
971
972 for (Layer = 0; Layer < EXT2_BLOCK_TYPES && Extra; Layer++) {
973
974 if (Start >= Vcb->max_blocks_per_layer[Layer]) {
975
976 Base += Vcb->max_blocks_per_layer[Layer];
977 Start -= Vcb->max_blocks_per_layer[Layer];
978
979 } else {
980
981 /* get the slot in i_block array */
982 if (Layer == 0) {
983 Base = Slot = Start;
984 } else {
985 Slot = Layer + EXT2_NDIR_BLOCKS - 1;
986 }
987
988 /* set block hint to avoid fragments */
989 if (Hint == 0) {
990 if (Mcb->Inode.i_block[Slot] != 0) {
991 Hint = Mcb->Inode.i_block[Slot];
992 } else if (Slot > 1) {
993 Hint = Mcb->Inode.i_block[Slot-1];
994 }
995 }
996
997 /* now expand this slot */
999 IrpContext,
1000 Vcb,
1001 Mcb,
1002 Base,
1003 Layer,
1004 Start,
1005 (Layer == 0) ? (Vcb->max_blocks_per_layer[Layer] - Start) : 1,
1006#ifdef __REACTOS__
1007 (PULONG)&Mcb->Inode.i_block[Slot],
1008#else
1009 &Mcb->Inode.i_block[Slot],
1010#endif
1011 &Hint,
1012 &Extra
1013 );
1014 if (!NT_SUCCESS(Status)) {
1015 break;
1016 }
1017
1018 Start = 0;
1019 if (Layer == 0) {
1020 Base = 0;
1021 }
1022 Base += Vcb->max_blocks_per_layer[Layer];
1023 }
1024 }
1025
1026 Size->QuadPart = ((LONGLONG)(End - Extra)) << BLOCK_BITS;
1027
1028 /* save inode whatever it succeeds to expand or not */
1029 Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
1030
1031 return Status;
1032}
1033
1036 PEXT2_IRP_CONTEXT IrpContext,
1037 PEXT2_VCB Vcb,
1039 )
1040{
1041 LONGLONG Vba;
1042 LONGLONG Lba;
1045 int i;
1046
1047 /* try to load all indirect blocks if mcb zone is not initialized */
1048 if (!IsZoneInited(Mcb)) {
1049 Status = Ext2InitializeZone(IrpContext, Vcb, Mcb);
1050 if (!NT_SUCCESS(Status)) {
1051 DbgBreak();
1053 goto errorout;
1054 }
1055 }
1056
1058
1059 /* delete all data blocks here */
1060 if (FsRtlNumberOfRunsInLargeMcb(&Mcb->Extents) != 0) {
1061 for (i = 0; FsRtlGetNextLargeMcbEntry(&Mcb->Extents, i, &Vba, &Lba, &Length); i++) {
1062 /* ignore the non-existing runs */
1063 if (-1 == Lba || Vba == 0 || Length <= 0)
1064 continue;
1065 /* now do data block free */
1066 Ext2FreeBlock(IrpContext, Vcb, (ULONG)(Lba - 1), (ULONG)Length);
1067 }
1068 }
1069
1070 /* delete all meta blocks here */
1071 if (FsRtlNumberOfRunsInLargeMcb(&Mcb->MetaExts) != 0) {
1072 for (i = 0; FsRtlGetNextLargeMcbEntry(&Mcb->MetaExts, i, &Vba, &Lba, &Length); i++) {
1073 /* ignore the non-existing runs */
1074 if (-1 == Lba || Vba == 0 || Length <= 0)
1075 continue;
1076 /* now do meta block free */
1077 Ext2FreeBlock(IrpContext, Vcb, (ULONG)(Lba - 1), (ULONG)Length);
1078 }
1079 }
1080
1081 /* clear data and meta extents */
1082 Ext2ClearAllExtents(&Mcb->Extents);
1083 Ext2ClearAllExtents(&Mcb->MetaExts);
1084 ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
1085
1086 /* clear inode blocks & sizes */
1087 Mcb->Inode.i_blocks = 0;
1088 Mcb->Inode.i_size = 0;
1089 memset(&Mcb->Inode.i_block[0], 0, sizeof(__u32) * 15);
1090
1091 /* the caller will do inode save */
1092
1093errorout:
1094
1095 return Status;
1096}
1097
1100 PEXT2_IRP_CONTEXT IrpContext,
1101 PEXT2_VCB Vcb,
1102 PEXT2_MCB Mcb,
1104)
1105{
1107
1108 ULONG Layer = 0;
1109
1110 ULONG Extra = 0;
1111 ULONG Wanted = 0;
1112 ULONG End;
1113 ULONG Base;
1114
1115 ULONG SizeArray = 0;
1116 PULONG BlockArray = NULL;
1117
1118 /* translate file size to block */
1119 End = Base = Vcb->max_data_blocks;
1120 Wanted = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS);
1121
1122 /* do fast deletion here */
1123 if (Wanted == 0) {
1124 Status = Ext2TruncateIndirectFast(IrpContext, Vcb, Mcb);
1125 if (NT_SUCCESS(Status))
1126 goto errorout;
1127 }
1128
1129 /* calculate blocks to be freed */
1130 Extra = End - Wanted;
1131
1132 for (Layer = EXT2_BLOCK_TYPES; Layer > 0 && Extra; Layer--) {
1133
1134 if (Vcb->max_blocks_per_layer[Layer - 1] == 0) {
1135 continue;
1136 }
1137
1138 Base -= Vcb->max_blocks_per_layer[Layer - 1];
1139
1140 if (Layer - 1 == 0) {
1141#ifdef __REACTOS__
1142 BlockArray = (PULONG)&Mcb->Inode.i_block[0];
1143#else
1144 BlockArray = &Mcb->Inode.i_block[0];
1145#endif
1146 SizeArray = End;
1147 ASSERT(End == EXT2_NDIR_BLOCKS && Base == 0);
1148 } else {
1149#ifdef __REACTOS__
1150 BlockArray = (PULONG)&Mcb->Inode.i_block[EXT2_NDIR_BLOCKS - 1 + Layer - 1];
1151#else
1152 BlockArray = &Mcb->Inode.i_block[EXT2_NDIR_BLOCKS - 1 + Layer - 1];
1153#endif
1154 SizeArray = 1;
1155 }
1156
1158 IrpContext,
1159 Vcb,
1160 Mcb,
1161 Base,
1162 End - Base - 1,
1163 Layer - 1,
1164 SizeArray,
1165 BlockArray,
1166 &Extra
1167 );
1168 if (!NT_SUCCESS(Status)) {
1169 break;
1170 }
1171
1172 End = Base;
1173 }
1174
1175errorout:
1176
1177 if (!NT_SUCCESS(Status)) {
1178 Size->QuadPart += ((ULONGLONG)Extra << BLOCK_BITS);
1179 }
1180
1181 /* save inode */
1182 if (Mcb->Inode.i_size > (loff_t)(Size->QuadPart))
1183 Mcb->Inode.i_size = (loff_t)(Size->QuadPart);
1184 Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
1185
1186 return Status;
1187}
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DEBUG(args)
Definition: rdesktop.h:129
u32 __u32
Definition: btrfs.h:19
VOID NTAPI CcSetDirtyPinnedData(IN PVOID BcbVoid, IN OPTIONAL PLARGE_INTEGER Lsn)
Definition: cachesub.c:121
#define BLOCK_SIZE
Definition: dlist.c:220
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define BLOCK_BITS
Definition: stream.h:22
#define PS_BLOCK_DATA
Definition: common.h:31
#define EXT2_NDIR_BLOCKS
Definition: ext2_fs.h:177
unsigned __int64 loff_t
Definition: types.h:84
#define PagedPool
Definition: env_spec_w32.h:308
VOID Ext2FreePool(IN PVOID P, IN ULONG Tag)
Definition: debug.c:2697
#define ClearFlag(_F, _SF)
Definition: ext2fs.h:191
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
struct ext3_dir_entry_2 * PEXT2_DIR_ENTRY2
Definition: ext2fs.h:109
#define EXT2_DATA_MAGIC
Definition: ext2fs.h:296
#define EXT2_BLOCK_TYPES
Definition: ext2fs.h:77
BOOLEAN Ext2AddMcbMetaExts(IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN ULONG Block, IN ULONG Length)
Definition: memory.c:941
PVOID Ext2AllocatePool(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag)
Definition: debug.c:2684
NTSTATUS Ext2NewBlock(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN ULONG GroupHint, IN ULONG BlockHint, OUT PULONG Block, IN OUT PULONG Number)
Definition: generic.c:1008
NTSTATUS Ext2FreeBlock(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN ULONG Block, IN ULONG Number)
Definition: generic.c:1217
BOOLEAN Ext2SaveBlock(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN ULONG dwBlk, IN PVOID Buf)
Definition: generic.c:698
NTSTATUS Ext2InitializeZone(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb)
Definition: memory.c:1121
BOOLEAN Ext2SaveInode(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN struct inode *Inode)
Definition: generic.c:552
VOID Ext2Sleep(ULONG ms)
Definition: misc.c:297
#define TOTAL_BLOCKS
Definition: ext2fs.h:101
#define DEC_MEM_COUNT(_i, _p, _s)
Definition: ext2fs.h:608
BOOLEAN Ext2RemoveBlockExtent(IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN ULONG Start, IN ULONG Number)
Definition: memory.c:1097
#define BLOCKS_PER_GROUP
Definition: ext2fs.h:100
BOOLEAN Ext2RemoveMcbMetaExts(IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN ULONG Block, IN ULONG Length)
Definition: memory.c:985
#define ClearLongFlag(_F, _SF)
Definition: ext2fs.h:259
#define IsMcbDirectory(Mcb)
Definition: ext2fs.h:967
#define DbgBreak()
Definition: ext2fs.h:46
BOOLEAN Ext2AddBlockExtent(IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN ULONG Start, IN ULONG Block, IN ULONG Number)
Definition: memory.c:1027
#define MCB_ZONE_INITED
Definition: ext2fs.h:957
#define DL_ERR
Definition: ext2fs.h:1434
VOID Ext2ClearAllExtents(PLARGE_MCB Zone)
Definition: memory.c:637
#define IsZoneInited(Mcb)
Definition: ext2fs.h:963
#define INC_MEM_COUNT(_i, _p, _s)
Definition: ext2fs.h:607
#define DL_BLK
Definition: ext2fs.h:1441
BOOLEAN Ext2AddVcbExtent(IN PEXT2_VCB Vcb, IN LONGLONG Vbn, IN LONGLONG Length)
Definition: memory.c:648
IN PVCB IN VBO IN ULONG OUT PBCB * Bcb
Definition: fatprocs.h:414
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
Definition: fatprocs.h:348
PLIST_ENTRY pEntry
Definition: fxioqueue.cpp:4484
Unit
Definition: gdiplusenums.h:26
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
NTSTATUS Ext2ExpandIndirect(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb, PEXT2_MCB Mcb, ULONG Start, ULONG End, PLARGE_INTEGER Size)
Definition: indirect.c:948
NTSTATUS Ext2GetBlock(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN ULONG Base, IN ULONG Layer, IN ULONG Start, IN ULONG SizeArray, IN PULONG BlockArray, IN BOOLEAN bAlloc, IN OUT PULONG Hint, OUT PULONG Block, OUT PULONG Number)
Definition: indirect.c:136
NTSTATUS Ext2TruncateIndirectFast(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb, PEXT2_MCB Mcb)
Definition: indirect.c:1035
PEXT2_GLOBAL Ext2Global
Definition: init.c:16
NTSTATUS Ext2TruncateBlock(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN ULONG Base, IN ULONG Start, IN ULONG Layer, IN ULONG SizeArray, IN PULONG BlockArray, IN PULONG Extra)
Definition: indirect.c:632
NTSTATUS Ext2ExpandLast(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN ULONG Base, IN ULONG Layer, IN PULONG *Data, IN PULONG Hint, IN PULONG Block, IN OUT PULONG Number)
Definition: indirect.c:25
NTSTATUS Ext2ExpandBlock(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN ULONG Base, IN ULONG Layer, IN ULONG Start, IN ULONG SizeArray, IN PULONG BlockArray, IN PULONG Hint, IN PULONG Extra)
Definition: indirect.c:345
NTSTATUS Ext2TruncateIndirect(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb, PEXT2_MCB Mcb, PLARGE_INTEGER Size)
Definition: indirect.c:1099
NTSTATUS Ext2MapIndirect(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN ULONG Index, IN BOOLEAN bAlloc, OUT PULONG pBlock, OUT PULONG Number)
Definition: indirect.c:835
BOOLEAN Ext2IsBlockEmpty(PULONG BlockArray, ULONG SizeArray)
Definition: indirect.c:619
ULONG NTAPI FsRtlNumberOfRunsInLargeMcb(IN PLARGE_MCB Mcb)
Definition: largemcb.c:765
BOOLEAN NTAPI FsRtlGetNextLargeMcbEntry(IN PLARGE_MCB Mcb, IN ULONG RunIndex, OUT PLONGLONG Vbn, OUT PLONGLONG Lbn, OUT PLONGLONG SectorCount)
Definition: largemcb.c:392
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
#define min(a, b)
Definition: monoChain.cc:55
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2439
int Count
Definition: noreturn.cpp:7
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define PIN_WAIT
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:207
#define STATUS_CANT_WAIT
Definition: ntstatus.h:452
unsigned short USHORT
Definition: pedump.c:61
#define Vcb
Definition: cdprocs.h:1415
VOID NTAPI CcUnpinData(IN PVOID Bcb)
Definition: pinsup.c:955
BOOLEAN NTAPI CcPinRead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *Bcb, OUT PVOID *Buffer)
Definition: pinsup.c:802
#define memset(x, y, z)
Definition: compat.h:39
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: xml2sdb.h:111
Definition: ext3_fs.h:774
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1830
uint32_t * PULONG
Definition: typedefs.h:59
int64_t LONGLONG
Definition: typedefs.h:68
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define OUT
Definition: typedefs.h:40
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_DISK_CORRUPT_ERROR
Definition: udferr_usr.h:147
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
@ Start
Definition: partlist.h:33
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
#define FO_FILE_MODIFIED
Definition: iotypes.h:1788