ReactOS  0.4.13-dev-464-g6b95727
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,
29  IN ULONG Base,
30  IN ULONG Layer,
31  IN PULONG * Data,
32  IN PULONG Hint,
33  IN PULONG Block,
35 )
36 {
37  PULONG pData = NULL;
38  ULONG i;
40 
41  if (Layer > 0 || IsMcbDirectory(Mcb)) {
42 
43  /* allocate buffer for new block */
45  PagedPool,
46  BLOCK_SIZE,
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 */
79  PEXT2_DIR_ENTRY2 pEntry;
80  pEntry = (PEXT2_DIR_ENTRY2) pData;
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();
89  ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
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 
107 errorout:
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 
135 NTSTATUS
137  IN PEXT2_IRP_CONTEXT IrpContext,
138  IN PEXT2_VCB Vcb,
139  IN PEXT2_MCB Mcb,
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,
218  (PLARGE_INTEGER) (&Offset),
219  BLOCK_SIZE,
220  PIN_WAIT,
221  &Bcb,
222  (void **)&pData )) {
223 
224  DEBUG(DL_ERR, ( "Ext2GetBlock: Failed to PinLock block: %xh ...\n",
225  BlockArray[0] ));
227  goto errorout;
228  }
229 
230  if (Layer > 1) {
231  Unit = Vcb->max_blocks_per_layer[Layer - 1];
232  } else {
233  Unit = 1;
234  }
235 
236  Slot = Start / Unit;
237  Start = Start % Unit;
238 
239  if (pData[Slot] == 0) {
240 
241  if (bAlloc) {
242 
243  /* we need allocate new block and zero all data in case
244  it's an in-direct block. Index stores the new block no. */
245  ULONG Count = 1;
247  IrpContext,
248  Vcb,
249  Mcb,
250  Base,
251  Layer,
252  NULL,
253  Hint,
254  &pData[Slot],
255  &Count
256  );
257 
258  if (!NT_SUCCESS(Status)) {
259  goto errorout;
260  }
261 
262  /* refresh hint block */
263  *Hint = pData[Slot];
264 
265  /* set dirty bit to notify system to flush */
267  SetFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
268  if (!Ext2AddVcbExtent(Vcb, Offset.QuadPart,
269  (LONGLONG)BLOCK_SIZE)) {
270  DbgBreak();
271  Ext2Sleep(100);
272  if (!Ext2AddVcbExtent(Vcb, Offset.QuadPart,
273  (LONGLONG)BLOCK_SIZE)) {
275  goto errorout;
276  }
277  }
278 
279  /* save inode information here */
280  Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
281 
282  } else {
283 
284  *Number = 1;
285 
286  if (Layer == 1) {
287  for (i = Slot + 1; i < BLOCK_SIZE/4; i++) {
288  if (pData[i] == 0) {
289  *Number = *Number + 1;
290  } else {
291  break;
292  }
293  }
294  } else if (Layer == 2) {
295  *Number = BLOCK_SIZE/4 - Start;
296  } else {
297  *Number = BLOCK_SIZE/4;
298  }
299 
300  goto errorout;
301  }
302  }
303 
304  /* transfer to next recursion call */
306  IrpContext,
307  Vcb,
308  Mcb,
309  Base,
310  Layer - 1,
311  Start,
312  BLOCK_SIZE/4 - Slot,
313  &pData[Slot],
314  bAlloc,
315  Hint,
316  Block,
317  Number
318  );
319 
320  if (!NT_SUCCESS(Status)) {
321  goto errorout;
322  }
323  }
324 
325 errorout:
326 
327  /* free the memory of pData */
328  if (Bcb) {
329  CcUnpinData(Bcb);
330  }
331 
332  if (!NT_SUCCESS(Status)) {
333  *Block = 0;
334  }
335 
336  return Status;
337 }
338 
339 
340 NTSTATUS
342  IN PEXT2_IRP_CONTEXT IrpContext,
343  IN PEXT2_VCB Vcb,
344  IN PEXT2_MCB Mcb,
345  IN ULONG Base,
346  IN ULONG Layer,
347  IN ULONG Start,
348  IN ULONG SizeArray,
349  IN PULONG BlockArray,
350  IN PULONG Hint,
351  IN PULONG Extra
352 )
353 {
354  ULONG i = 0;
355  ULONG j;
356  ULONG Slot;
357  ULONG Block = 0;
359 
360  PBCB Bcb = NULL;
361  PULONG pData = NULL;
362  ULONG Skip = 0;
363 
364  ULONG Number;
365  ULONG Wanted;
366 
368 
369  if (Layer == 1) {
370 
371  /*
372  * try to make all leaf block continuous to avoid fragments
373  */
374 
375  Number = min(SizeArray, ((*Extra + (Start & (BLOCK_SIZE/4 - 1))) * 4 / BLOCK_SIZE));
376  Wanted = 0;
377  DEBUG(DL_BLK, ("Ext2ExpandBlock: SizeArray=%xh Extra=%xh Start=%xh %xh\n",
378  SizeArray, *Extra, Start, Number ));
379 
380  for (i=0; i < Number; i++) {
381  if (BlockArray[i] == 0) {
382  Wanted += 1;
383  }
384  }
385 
386  i = 0;
387  while (Wanted > 0) {
388 
389  Number = Wanted;
391  IrpContext,
392  Vcb,
393  Mcb,
394  Base,
395  Layer,
396  NULL,
397  Hint,
398  &Block,
399  &Number
400  );
401  if (!NT_SUCCESS(Status)) {
402  goto errorout;
403  }
404 
405  ASSERT(Number > 0);
406  Wanted -= Number;
407  while (Number) {
408  if (BlockArray[i] == 0) {
409  BlockArray[i] = Block++;
410  Number--;
411  }
412  i++;
413  }
414  }
415 
416  } else if (Layer == 0) {
417 
418  /*
419  * bulk allocation for inode data blocks
420  */
421 
422  i = 0;
423 
424  while (*Extra && i < SizeArray) {
425 
426  Wanted = 0;
427  Number = 1;
428 
429  for (j = i; j < SizeArray && j < i + *Extra; j++) {
430 
431  if (BlockArray[j] >= TOTAL_BLOCKS) {
432  DbgBreak();
433  BlockArray[j] = 0;
434  }
435 
436  if (BlockArray[j] == 0) {
437  Wanted += 1;
438  } else {
439  break;
440  }
441  }
442 
443  if (Wanted == 0) {
444 
445  /* add block extent into Mcb */
446  ASSERT(BlockArray[i] != 0);
447  if (!Ext2AddBlockExtent(Vcb, Mcb, Base + i, BlockArray[i], 1)) {
448  DbgBreak();
449  ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
450  Ext2ClearAllExtents(&Mcb->Extents);
451  }
452 
453  } else {
454 
455  Number = Wanted;
457  IrpContext,
458  Vcb,
459  Mcb,
460  Base + i,
461  0,
462  NULL,
463  Hint,
464  &Block,
465  &Number
466  );
467  if (!NT_SUCCESS(Status)) {
468  goto errorout;
469  }
470 
471  ASSERT(Number > 0);
472  for (j = 0; j < Number; j++) {
473  BlockArray[i + j] = Block++;
474  }
475  }
476 
477  *Extra -= Number;
478  i += Number;
479  }
480 
481  goto errorout;
482  }
483 
484 
485  /*
486  * only for meta blocks allocation
487  */
488 
489  for (i = 0; *Extra && i < SizeArray; i++) {
490 
491  if (Layer <= 3) {
492 
493  if (BlockArray[i] >= TOTAL_BLOCKS) {
494  DbgBreak();
495  BlockArray[i] = 0;
496  }
497 
498  if (BlockArray[i] == 0) {
499  Number = 1;
501  IrpContext,
502  Vcb,
503  Mcb,
504  Base,
505  Layer,
506  &pData,
507  Hint,
508  &BlockArray[i],
509  &Number
510  );
511  if (!NT_SUCCESS(Status)) {
512  goto errorout;
513  }
514 
515  } else {
516 
517  Offset.QuadPart = (((LONGLONG)BlockArray[i]) << BLOCK_BITS);
518  if (!CcPinRead(
519  Vcb->Volume,
520  &Offset,
521  BLOCK_SIZE,
522  PIN_WAIT,
523  &Bcb,
524  (void **)&pData )) {
525 
526  DEBUG(DL_ERR, ( "Ext2ExpandInode: failed to PinLock offset :%I64xh...\n",
527  Offset.QuadPart));
529  DbgBreak();
530  goto errorout;
531  }
532 
533  /* add block to meta extents */
534  if (!Ext2AddMcbMetaExts(Vcb, Mcb, BlockArray[i], 1)) {
535  DbgBreak();
536  Ext2Sleep(500);
537  Ext2AddMcbMetaExts(Vcb, Mcb, BlockArray[i], 1);
538  }
539  }
540 
541  Skip = Vcb->max_blocks_per_layer[Layer] * i;
542 
543  if (i == 0) {
544  if (Layer > 1) {
545  Slot = Start / Vcb->max_blocks_per_layer[Layer - 1];
546  Start = Start % Vcb->max_blocks_per_layer[Layer - 1];
547  Skip += Slot * Vcb->max_blocks_per_layer[Layer - 1];
548  } else {
549  Slot = Start;
550  Start = 0;
551  Skip += Slot;
552  }
553  } else {
554  Start = 0;
555  Slot = 0;
556  }
557 
559  IrpContext,
560  Vcb,
561  Mcb,
562  Base + Skip,
563  Layer - 1,
564  Start,
565  BLOCK_SIZE/4 - Slot,
566  &pData[Slot],
567  Hint,
568  Extra
569  );
570 
571  if (Bcb) {
574  BlockArray[i],
575  BlockArray[i], 1)) {
576  DbgBreak();
577  Ext2Sleep(500);
579  BlockArray[i],
580  BlockArray[i], 1)) {
581  }
582  }
583  } else {
584  Ext2SaveBlock(IrpContext, Vcb, BlockArray[i], (PVOID)pData);
585  }
586 
587  if (pData) {
588  if (Bcb) {
589  CcUnpinData(Bcb);
590  Bcb = NULL;
591  } else {
594  }
595  pData = NULL;
596  }
597 
598  if (!NT_SUCCESS(Status)) {
599  DbgBreak();
600  break;
601  }
602  }
603  }
604 
605 errorout:
606 
607  return Status;
608 }
609 
610 BOOLEAN
611 Ext2IsBlockEmpty(PULONG BlockArray, ULONG SizeArray)
612 {
613  ULONG i = 0;
614  for (i=0; i < SizeArray; i++) {
615  if (BlockArray[i]) {
616  break;
617  }
618  }
619  return (i == SizeArray);
620 }
621 
622 
623 NTSTATUS
625  IN PEXT2_IRP_CONTEXT IrpContext,
626  IN PEXT2_VCB Vcb,
627  IN PEXT2_MCB Mcb,
628  IN ULONG Base,
629  IN ULONG Start,
630  IN ULONG Layer,
631  IN ULONG SizeArray,
632  IN PULONG BlockArray,
633  IN PULONG Extra
634 )
635 {
637  ULONG i = 0;
638  ULONG Slot = 0;
639  ULONG Skip = 0;
640 
642  PBCB Bcb = NULL;
643  PULONG pData = NULL;
644 
645  ASSERT(Mcb != NULL);
646 
647  for (i = 0; i < SizeArray; i++) {
648 
649  if (Layer == 0) {
650 
651  ULONG Number = 1;
652 
653  while (Extra && SizeArray > i + 1 && Number < *Extra) {
654 
655  if (BlockArray[SizeArray - i - 1] ==
656  BlockArray[SizeArray - i - 2] + 1) {
657 
658  BlockArray[SizeArray - i - 1] = 0;
659  Number++;
660  SizeArray--;
661 
662  } else {
663  break;
664  }
665  }
666 
667  if (BlockArray[SizeArray - i - 1]) {
668 
669  Status = Ext2FreeBlock(IrpContext, Vcb, BlockArray[SizeArray - i - 1], Number);
670  if (NT_SUCCESS(Status)) {
671  ASSERT(Mcb->Inode.i_blocks >= (Number << (BLOCK_BITS - 9)));
672  if (Mcb->Inode.i_blocks < (Number << (BLOCK_BITS - 9))) {
673  Mcb->Inode.i_blocks = 0;
674  DbgBreak();
675  } else {
676  Mcb->Inode.i_blocks -= (Number << (BLOCK_BITS - 9));
677  }
678  BlockArray[SizeArray - i - 1] = 0;
679  }
680  }
681 
682  if (Extra) {
683 
684  /* dec blocks count */
685  ASSERT(*Extra >= Number);
686  *Extra = *Extra - Number;
687 
688  /* remove block mapping frm Mcb Extents */
689  if (!Ext2RemoveBlockExtent(Vcb, Mcb, Base + SizeArray - 1 - i, Number)) {
690  DbgBreak();
691  ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
692  Ext2ClearAllExtents(&Mcb->Extents);
693  }
694  }
695 
696  } else {
697 
698  ASSERT(Layer <= 3);
699 
700  if (BlockArray[SizeArray - i - 1] >= TOTAL_BLOCKS) {
701  DbgBreak();
702  BlockArray[SizeArray - i - 1] = 0;
703  }
704 
705  if (i == 0) {
706  if (Layer > 1) {
707  Slot = Start / Vcb->max_blocks_per_layer[Layer - 1];
708  Start = Start % Vcb->max_blocks_per_layer[Layer - 1];
709  } else {
710  Slot = Start;
711  Start = (BLOCK_SIZE / 4) - 1;
712  }
713  } else {
714  Slot = Start = (BLOCK_SIZE / 4) - 1;
715  }
716 
717  Skip = (SizeArray - i - 1) * Vcb->max_blocks_per_layer[Layer];
718 
719  if (BlockArray[SizeArray - i - 1]) {
720 
721  Offset = (LONGLONG) (BlockArray[SizeArray - i - 1]);
722  Offset = Offset << BLOCK_BITS;
723 
724  if (!CcPinRead( Vcb->Volume,
725  (PLARGE_INTEGER) (&Offset),
726  BLOCK_SIZE,
727  PIN_WAIT,
728  &Bcb,
729  (void **)&pData )) {
730 
731  DEBUG(DL_ERR, ( "Ext2TruncateBlock: PinLock failed on block %xh ...\n",
732  BlockArray[SizeArray - i - 1]));
734  DbgBreak();
735  goto errorout;
736  }
737 
739  IrpContext,
740  Vcb,
741  Mcb,
742  Base + Skip,
743  Start,
744  Layer - 1,
745  Slot + 1,
746  &pData[0],
747  Extra
748  );
749 
750  if (!NT_SUCCESS(Status)) {
751  break;
752  }
753 
756 
757  if (*Extra || Ext2IsBlockEmpty(pData, BLOCK_SIZE/4)) {
758 
760  IrpContext,
761  Vcb,
762  Mcb,
763  Base + Skip, /* base */
764  0, /* start */
765  0, /* layer */
766  1,
767  &BlockArray[SizeArray - i - 1],
768  NULL
769  );
770 
771  if (!Ext2RemoveMcbMetaExts(Vcb, Mcb, BlockArray[SizeArray - i - 1], 1)) {
772  DbgBreak();
773  Ext2Sleep(500);
774  Ext2RemoveMcbMetaExts(Vcb, Mcb, BlockArray[SizeArray - i - 1], 1);
775  }
776  }
777 
778  if (pData) {
779  CcUnpinData(Bcb);
780  Bcb = NULL;
781  pData = NULL;
782  }
783 
784  } else {
785 
786  if (Layer > 1) {
787  if (*Extra > Slot * Vcb->max_blocks_per_layer[Layer - 1] + Start + 1) {
788  *Extra -= (Slot * Vcb->max_blocks_per_layer[Layer - 1] + Start + 1);
789  } else {
790  *Extra = 0;
791  }
792  } else {
793  if (*Extra > Slot + 1) {
794  *Extra -= (Slot + 1);
795  } else {
796  *Extra = 0;
797  }
798  }
799 
800  if (!Ext2RemoveBlockExtent(Vcb, Mcb, Base + Skip, (Start + 1))) {
801  DbgBreak();
802  ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
803  Ext2ClearAllExtents(&Mcb->Extents);
804  }
805  }
806  }
807 
808  if (Extra && *Extra == 0) {
809  break;
810  }
811  }
812 
813 errorout:
814 
815  if (pData) {
816  CcUnpinData(Bcb);
817  }
818 
819  return Status;
820 }
821 
822 NTSTATUS
824  IN PEXT2_IRP_CONTEXT IrpContext,
825  IN PEXT2_VCB Vcb,
826  IN PEXT2_MCB Mcb,
827  IN ULONG Index,
828  IN BOOLEAN bAlloc,
829  OUT PULONG pBlock,
831 )
832 {
833  ULONG Layer;
834  ULONG Slot;
835 
836  ULONG Base = Index;
837 
839 
840  *pBlock = 0;
841  *Number = 0;
842 
843  for (Layer = 0; Layer < EXT2_BLOCK_TYPES; Layer++) {
844 
845  if (Index < Vcb->max_blocks_per_layer[Layer]) {
846 
847  ULONG dwRet = 0, dwBlk = 0, dwHint = 0, dwArray = 0;
848 
849  Slot = (Layer==0) ? (Index):(Layer + EXT2_NDIR_BLOCKS - 1);
850  dwBlk = Mcb->Inode.i_block[Slot];
851 
852  if (dwBlk == 0) {
853 
854  if (!bAlloc) {
855 
856  *Number = 1;
857  goto errorout;
858 
859  } else {
860 
861  if (Slot) {
862  dwHint = Mcb->Inode.i_block[Slot - 1];
863  }
864 
865  /* allocate and zero block if necessary */
866  *Number = 1;
868  IrpContext,
869  Vcb,
870  Mcb,
871  Base,
872  Layer,
873  NULL,
874  &dwHint,
875  &dwBlk,
876  Number
877  );
878 
879  if (!NT_SUCCESS(Status)) {
880  goto errorout;
881  }
882 
883  /* save the it into inode*/
884  Mcb->Inode.i_block[Slot] = dwBlk;
885 
886  /* save the inode */
887  if (!Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode)) {
888  DbgBreak();
890  goto errorout;
891  }
892  }
893  }
894 
895  if (Layer == 0)
896  dwArray = Vcb->max_blocks_per_layer[Layer] - Index;
897  else
898  dwArray = 1;
899 
900  /* querying block number of the index-th file block */
902  IrpContext,
903  Vcb,
904  Mcb,
905  Base,
906  Layer,
907  Index,
908  dwArray,
909  (PULONG)&Mcb->Inode.i_block[Slot],
910  bAlloc,
911  &dwHint,
912  &dwRet,
913  Number
914  );
915 
916  if (NT_SUCCESS(Status)) {
917  *pBlock = dwRet;
918  }
919 
920  break;
921  }
922 
923  Index -= Vcb->max_blocks_per_layer[Layer];
924  }
925 
926 errorout:
927 
928  return Status;
929 }
930 
931 NTSTATUS
933  PEXT2_IRP_CONTEXT IrpContext,
934  PEXT2_VCB Vcb,
935  PEXT2_MCB Mcb,
936  ULONG Start,
937  ULONG End,
939 )
940 {
942 
943  ULONG Layer = 0;
944  ULONG Extra = 0;
945  ULONG Hint = 0;
946  ULONG Slot = 0;
947  ULONG Base = 0;
948 
949  Extra = End - Start;
950 
951  /* exceeds the biggest file size (indirect) */
952  if (End > Vcb->max_data_blocks) {
954  }
955 
956  for (Layer = 0; Layer < EXT2_BLOCK_TYPES && Extra; Layer++) {
957 
958  if (Start >= Vcb->max_blocks_per_layer[Layer]) {
959 
960  Base += Vcb->max_blocks_per_layer[Layer];
961  Start -= Vcb->max_blocks_per_layer[Layer];
962 
963  } else {
964 
965  /* get the slot in i_block array */
966  if (Layer == 0) {
967  Base = Slot = Start;
968  } else {
969  Slot = Layer + EXT2_NDIR_BLOCKS - 1;
970  }
971 
972  /* set block hint to avoid fragments */
973  if (Hint == 0) {
974  if (Mcb->Inode.i_block[Slot] != 0) {
975  Hint = Mcb->Inode.i_block[Slot];
976  } else if (Slot > 1) {
977  Hint = Mcb->Inode.i_block[Slot-1];
978  }
979  }
980 
981  /* now expand this slot */
983  IrpContext,
984  Vcb,
985  Mcb,
986  Base,
987  Layer,
988  Start,
989  (Layer == 0) ? (Vcb->max_blocks_per_layer[Layer] - Start) : 1,
990  (PULONG)&Mcb->Inode.i_block[Slot],
991  &Hint,
992  &Extra
993  );
994  if (!NT_SUCCESS(Status)) {
995  break;
996  }
997 
998  Start = 0;
999  if (Layer == 0) {
1000  Base = 0;
1001  }
1002  Base += Vcb->max_blocks_per_layer[Layer];
1003  }
1004  }
1005 
1006  Size->QuadPart = ((LONGLONG)(End - Extra)) << BLOCK_BITS;
1007 
1008  /* save inode whatever it succeeds to expand or not */
1009  Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
1010 
1011  return Status;
1012 }
1013 
1014 NTSTATUS
1016  PEXT2_IRP_CONTEXT IrpContext,
1017  PEXT2_VCB Vcb,
1018  PEXT2_MCB Mcb
1019  )
1020 {
1021  LONGLONG Vba;
1022  LONGLONG Lba;
1023  LONGLONG Length;
1025  int i;
1026 
1027  /* try to load all indirect blocks if mcb zone is not initialized */
1028  if (!IsZoneInited(Mcb)) {
1029  Status = Ext2InitializeZone(IrpContext, Vcb, Mcb);
1030  if (!NT_SUCCESS(Status)) {
1031  DbgBreak();
1033  goto errorout;
1034  }
1035  }
1036 
1037  ASSERT (IsZoneInited(Mcb));
1038 
1039  /* delete all data blocks here */
1040  if (FsRtlNumberOfRunsInLargeMcb(&Mcb->Extents) != 0) {
1041  for (i = 0; FsRtlGetNextLargeMcbEntry(&Mcb->Extents, i, &Vba, &Lba, &Length); i++) {
1042  /* ignore the non-existing runs */
1043  if (-1 == Lba || Vba == 0 || Length <= 0)
1044  continue;
1045  /* now do data block free */
1046  Ext2FreeBlock(IrpContext, Vcb, (ULONG)(Lba - 1), (ULONG)Length);
1047  }
1048  }
1049 
1050  /* delete all meta blocks here */
1051  if (FsRtlNumberOfRunsInLargeMcb(&Mcb->MetaExts) != 0) {
1052  for (i = 0; FsRtlGetNextLargeMcbEntry(&Mcb->MetaExts, i, &Vba, &Lba, &Length); i++) {
1053  /* ignore the non-existing runs */
1054  if (-1 == Lba || Vba == 0 || Length <= 0)
1055  continue;
1056  /* now do meta block free */
1057  Ext2FreeBlock(IrpContext, Vcb, (ULONG)(Lba - 1), (ULONG)Length);
1058  }
1059  }
1060 
1061  /* clear data and meta extents */
1062  Ext2ClearAllExtents(&Mcb->Extents);
1063  Ext2ClearAllExtents(&Mcb->MetaExts);
1064  ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
1065 
1066  /* clear inode blocks & sizes */
1067  Mcb->Inode.i_blocks = 0;
1068  Mcb->Inode.i_size = 0;
1069  memset(&Mcb->Inode.i_block[0], 0, sizeof(__u32) * 15);
1070 
1071  /* the caller will do inode save */
1072 
1073 errorout:
1074 
1075  return Status;
1076 }
1077 
1078 NTSTATUS
1080  PEXT2_IRP_CONTEXT IrpContext,
1081  PEXT2_VCB Vcb,
1082  PEXT2_MCB Mcb,
1084 )
1085 {
1087 
1088  ULONG Layer = 0;
1089 
1090  ULONG Extra = 0;
1091  ULONG Wanted = 0;
1092  ULONG End;
1093  ULONG Base;
1094 
1095  ULONG SizeArray = 0;
1096  PULONG BlockArray = NULL;
1097 
1098  /* translate file size to block */
1099  End = Base = Vcb->max_data_blocks;
1100  Wanted = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS);
1101 
1102  /* do fast deletion here */
1103  if (Wanted == 0) {
1104  Status = Ext2TruncateIndirectFast(IrpContext, Vcb, Mcb);
1105  if (NT_SUCCESS(Status))
1106  goto errorout;
1107  }
1108 
1109  /* calculate blocks to be freed */
1110  Extra = End - Wanted;
1111 
1112  for (Layer = EXT2_BLOCK_TYPES; Layer > 0 && Extra; Layer--) {
1113 
1114  if (Vcb->max_blocks_per_layer[Layer - 1] == 0) {
1115  continue;
1116  }
1117 
1118  Base -= Vcb->max_blocks_per_layer[Layer - 1];
1119 
1120  if (Layer - 1 == 0) {
1121  BlockArray = (PULONG)&Mcb->Inode.i_block[0];
1122  SizeArray = End;
1123  ASSERT(End == EXT2_NDIR_BLOCKS && Base == 0);
1124  } else {
1125  BlockArray = (PULONG)&Mcb->Inode.i_block[EXT2_NDIR_BLOCKS - 1 + Layer - 1];
1126  SizeArray = 1;
1127  }
1128 
1130  IrpContext,
1131  Vcb,
1132  Mcb,
1133  Base,
1134  End - Base - 1,
1135  Layer - 1,
1136  SizeArray,
1137  BlockArray,
1138  &Extra
1139  );
1140  if (!NT_SUCCESS(Status)) {
1141  break;
1142  }
1143 
1144  End = Base;
1145  }
1146 
1147 errorout:
1148 
1149  if (!NT_SUCCESS(Status)) {
1150  Size->QuadPart += ((ULONGLONG)Extra << BLOCK_BITS);
1151  }
1152 
1153  /* save inode */
1154  if (Mcb->Inode.i_size > (loff_t)(Size->QuadPart))
1155  Mcb->Inode.i_size = (loff_t)(Size->QuadPart);
1156  Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
1157 
1158  return Status;
1159 }
#define IN
Definition: typedefs.h:38
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:941
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define IsMcbDirectory(Mcb)
Definition: ext2fs.h:958
IN PVCB IN VBO IN ULONG OUT PBCB * Bcb
Definition: fatprocs.h:402
Unit
Definition: gdiplusenums.h:25
#define DEC_MEM_COUNT(_i, _p, _s)
Definition: ext2fs.h:599
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define EXT2_BLOCK_TYPES
Definition: ext2fs.h:77
Definition: ext3_fs.h:774
VOID NTAPI CcSetDirtyPinnedData(IN PVOID BcbVoid, IN OPTIONAL PLARGE_INTEGER Lsn)
Definition: cachesub.c:121
VOID Ext2ClearAllExtents(PLARGE_MCB Zone)
Definition: memory.c:637
LONG NTSTATUS
Definition: precomp.h:26
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2327
VOID NTAPI CcUnpinData(IN PVOID Bcb)
Definition: pinsup.c:955
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
#define PIN_WAIT
NTSTATUS Ext2TruncateIndirect(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb, PEXT2_MCB Mcb, PLARGE_INTEGER Size)
Definition: indirect.c:1079
BOOLEAN Ext2SaveBlock(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN ULONG dwBlk, IN PVOID Buf)
Definition: generic.c:694
ULONG NTAPI FsRtlNumberOfRunsInLargeMcb(IN PLARGE_MCB Mcb)
Definition: largemcb.c:769
BOOLEAN Ext2RemoveMcbMetaExts(IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN ULONG Block, IN ULONG Length)
Definition: memory.c:985
BOOLEAN NTAPI FsRtlGetNextLargeMcbEntry(IN PLARGE_MCB Mcb, IN ULONG RunIndex, OUT PLONGLONG Vbn, OUT PLONGLONG Lbn, OUT PLONGLONG SectorCount)
Definition: largemcb.c:391
#define FO_FILE_MODIFIED
Definition: iotypes.h:1744
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
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define TOTAL_BLOCKS
Definition: ext2fs.h:101
unsigned char BOOLEAN
#define BLOCK_BITS
Definition: stream.h:22
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS Ext2FreeBlock(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN ULONG Block, IN ULONG Number)
Definition: generic.c:1150
#define INC_MEM_COUNT(_i, _p, _s)
Definition: ext2fs.h:598
#define ClearLongFlag(_F, _SF)
Definition: ext2fs.h:254
BOOLEAN Ext2RemoveBlockExtent(IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN ULONG Start, IN ULONG Number)
Definition: memory.c:1097
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
VOID Ext2Sleep(ULONG ms)
Definition: misc.c:297
int64_t LONGLONG
Definition: typedefs.h:66
NTSTATUS Ext2InitializeZone(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb)
Definition: memory.c:1121
#define BLOCK_SIZE
Definition: dlist.c:220
#define EXT2_NDIR_BLOCKS
Definition: ext2_fs.h:177
#define EXT2_DATA_MAGIC
Definition: ext2fs.h:291
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t ULONGLONG
Definition: typedefs.h:65
#define Vcb
Definition: cdprocs.h:1425
struct ext3_dir_entry_2 * PEXT2_DIR_ENTRY2
Definition: ext2fs.h:109
BOOLEAN Ext2AddVcbExtent(IN PEXT2_VCB Vcb, IN LONGLONG Vbn, IN LONGLONG Length)
Definition: memory.c:648
static const UCHAR Index[8]
Definition: usbohci.c:18
unsigned int __u32
Definition: compat.h:90
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
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
Definition: partlist.h:33
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
unsigned __int64 loff_t
Definition: types.h:80
#define DL_BLK
Definition: ext2fs.h:1404
PEXT2_GLOBAL Ext2Global
Definition: init.c:16
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:204
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
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:823
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
Status
Definition: gdiplustypes.h:24
#define DL_ERR
Definition: ext2fs.h:1397
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define MCB_ZONE_INITED
Definition: ext2fs.h:948
unsigned short USHORT
Definition: pedump.c:61
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
Definition: fatprocs.h:334
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
NTSTATUS Ext2TruncateIndirectFast(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb, PEXT2_MCB Mcb)
Definition: indirect.c:1015
#define OUT
Definition: typedefs.h:39
#define STATUS_DISK_CORRUPT_ERROR
Definition: udferr_usr.h:147
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:624
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define DbgBreak()
Definition: ext2fs.h:46
VOID Ext2FreePool(IN PVOID P, IN ULONG Tag)
Definition: debug.c:2697
__le16 rec_len
Definition: ext3_fs.h:776
BOOLEAN Ext2AddMcbMetaExts(IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN ULONG Block, IN ULONG Length)
Definition: memory.c:941
#define DEBUG(args)
Definition: rdesktop.h:129
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
Definition: xml2sdb.h:110
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1827
return STATUS_SUCCESS
Definition: btrfs.c:2777
PVOID Ext2AllocatePool(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag)
Definition: debug.c:2684
#define memset(x, y, z)
Definition: compat.h:39
NTSTATUS Ext2ExpandIndirect(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb, PEXT2_MCB Mcb, ULONG Start, ULONG End, PLARGE_INTEGER Size)
Definition: indirect.c:932
BOOLEAN Ext2SaveInode(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN struct inode *Inode)
Definition: generic.c:548
BOOLEAN Ext2AddBlockExtent(IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN ULONG Start, IN ULONG Block, IN ULONG Number)
Definition: memory.c:1027
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:341
BOOLEAN Ext2IsBlockEmpty(PULONG BlockArray, ULONG SizeArray)
Definition: indirect.c:611
#define IsZoneInited(Mcb)
Definition: ext2fs.h:954
#define BLOCKS_PER_GROUP
Definition: ext2fs.h:100
#define PS_BLOCK_DATA
Definition: common.h:31
#define STATUS_CANT_WAIT
Definition: ntstatus.h:438