1 /*
2  * COPYRIGHT:        See COPYRIGHT.TXT
3  * PROJECT:          Ext2 File System Driver for WinNT/2K/XP
4  * FILE:             generic.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 #include "linux/ext4.h"
14 
15 /* GLOBALS ***************************************************************/
16 
17 extern PEXT2_GLOBAL Ext2Global;
18 
19 /* DEFINITIONS *************************************************************/
20 
21 
22 /* FUNCTIONS ***************************************************************/
23 
24 NTSTATUS
25 Ext2LoadSuper(IN PEXT2_VCB      Vcb,
26               IN BOOLEAN        bVerify,
27               OUT PEXT2_SUPER_BLOCK * Sb)
28 {
29     NTSTATUS          Status;
30     PEXT2_SUPER_BLOCK Ext2Sb = NULL;
31 
32     Ext2Sb = (PEXT2_SUPER_BLOCK)
33              Ext2AllocatePool(
34                  PagedPool,
35                  SUPER_BLOCK_SIZE,
36                  EXT2_SB_MAGIC
37              );
38     if (!Ext2Sb) {
39         Status = STATUS_INSUFFICIENT_RESOURCES;
40         goto errorout;
41     }
42 
43     Status = Ext2ReadDisk(
44                  Vcb,
45                  (ULONGLONG) SUPER_BLOCK_OFFSET,
46                  SUPER_BLOCK_SIZE,
47                  (PVOID) Ext2Sb,
48                  bVerify );
49 
50     if (!NT_SUCCESS(Status)) {
51         Ext2FreePool(Ext2Sb, EXT2_SB_MAGIC);
52         Ext2Sb = NULL;
53     }
54 
55 errorout:
56 
57     *Sb = Ext2Sb;
58     return Status;
59 }
60 
61 
62 BOOLEAN
63 Ext2SaveSuper(
64     IN PEXT2_IRP_CONTEXT    IrpContext,
65     IN PEXT2_VCB            Vcb
66 )
67 {
68     LONGLONG    offset;
69     BOOLEAN     rc;
70 
71     offset = (LONGLONG) SUPER_BLOCK_OFFSET;
72     rc = Ext2SaveBuffer( IrpContext,
73                          Vcb,
74                          offset,
75                          SUPER_BLOCK_SIZE,
76                          Vcb->SuperBlock
77                        );
78 
79     if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
80         Ext2StartFloppyFlushDpc(Vcb, NULL, NULL);
81     }
82 
83     return rc;
84 }
85 
86 
87 BOOLEAN
88 Ext2RefreshSuper (
89     IN PEXT2_IRP_CONTEXT    IrpContext,
90     IN PEXT2_VCB            Vcb
91 )
92 {
93     LONGLONG        offset;
94     IO_STATUS_BLOCK iosb;
95 
96     offset = (LONGLONG) SUPER_BLOCK_OFFSET;
97     if (!CcCopyRead(
98                 Vcb->Volume,
99                 (PLARGE_INTEGER)&offset,
100                 SUPER_BLOCK_SIZE,
101                 TRUE,
102                 (PVOID)Vcb->SuperBlock,
103                 &iosb )) {
104         return FALSE;
105     }
106 
107     if (!NT_SUCCESS(iosb.Status)) {
108         return FALSE;
109     }
110 
111     /* reload root inode */
112     if (Vcb->McbTree) {
113 
114         if (!Ext2LoadInode(Vcb, &Vcb->McbTree->Inode))
115             return FALSE;
116 
117         /* initializeroot node */
118         Vcb->McbTree->CreationTime = Ext2NtTime(Vcb->McbTree->Inode.i_ctime);
119         Vcb->McbTree->LastAccessTime = Ext2NtTime(Vcb->McbTree->Inode.i_atime);
120         Vcb->McbTree->LastWriteTime = Ext2NtTime(Vcb->McbTree->Inode.i_mtime);
121         Vcb->McbTree->ChangeTime = Ext2NtTime(Vcb->McbTree->Inode.i_mtime);
122     }
123 
124     return TRUE;
125 }
126 
127 VOID
128 Ext2DropGroupBH(IN PEXT2_VCB Vcb)
129 {
130     struct ext3_sb_info *sbi = &Vcb->sbi;
131     unsigned long i;
132 
133     if (NULL == Vcb->sbi.s_gd) {
134         return;
135     }
136 
137     for (i = 0; i < Vcb->sbi.s_gdb_count; i++) {
138         if (Vcb->sbi.s_gd[i].bh) {
139             fini_bh(&sbi->s_gd[i].bh);
140             Vcb->sbi.s_gd[i].bh = NULL;
141         }
142     }
143 }
144 
145 VOID
146 Ext2PutGroup(IN PEXT2_VCB Vcb)
147 {
148     struct ext3_sb_info *sbi = &Vcb->sbi;
149     unsigned long i;
150 
151 
152     if (NULL == Vcb->sbi.s_gd) {
153         return;
154     }
155 
156     Ext2DropGroupBH(Vcb);
157 
158     kfree(Vcb->sbi.s_gd);
159     Vcb->sbi.s_gd = NULL;
160 
161     ClearFlag(Vcb->Flags, VCB_GD_LOADED);
162 }
163 
164 
165 BOOLEAN
166 Ext2LoadGroupBH(IN PEXT2_VCB Vcb)
167 {
168     struct super_block  *sb = &Vcb->sb;
169     struct ext3_sb_info *sbi = &Vcb->sbi;
170     unsigned long i;
171     BOOLEAN rc = FALSE;
172 
173     _SEH2_TRY {
174 
175         ExAcquireResourceExclusiveLite(&Vcb->sbi.s_gd_lock, TRUE);
176         ASSERT (NULL != sbi->s_gd);
177 
178         for (i = 0; i < sbi->s_gdb_count; i++) {
179             ASSERT (sbi->s_gd[i].block);
180             if (sbi->s_gd[i].bh)
181                 continue;
182             sbi->s_gd[i].bh = sb_getblk(sb, sbi->s_gd[i].block);
183             if (!sbi->s_gd[i].bh) {
184                 DEBUG(DL_ERR, ("Ext2LoadGroupBH: can't read group descriptor %d\n", i));
185                 DbgBreak();
186                 _SEH2_LEAVE;
187             }
188             sbi->s_gd[i].gd = (struct ext4_group_desc *)sbi->s_gd[i].bh->b_data;
189         }
190 
191         rc = TRUE;
192 
193     } _SEH2_FINALLY {
194 
195         ExReleaseResourceLite(&Vcb->sbi.s_gd_lock);
196     } _SEH2_END;
197 
198     return rc;
199 }
200 
201 
202 BOOLEAN
203 Ext2LoadGroup(IN PEXT2_VCB Vcb)
204 {
205     struct super_block  *sb = &Vcb->sb;
206     struct ext3_sb_info *sbi = &Vcb->sbi;
207     ext3_fsblk_t sb_block = 1;
208     unsigned long i;
209     BOOLEAN rc = FALSE;
210 
211     _SEH2_TRY {
212 
213         ExAcquireResourceExclusiveLite(&Vcb->sbi.s_gd_lock, TRUE);
214 
215         if (NULL == sbi->s_gd) {
216             sbi->s_gd = kzalloc(sbi->s_gdb_count * sizeof(struct ext3_gd),
217                                         GFP_KERNEL);
218         }
219         if (sbi->s_gd == NULL) {
220             DEBUG(DL_ERR, ("Ext2LoadGroup: not enough memory.\n"));
221             _SEH2_LEAVE;
222         }
223 
224         if (BLOCK_SIZE != EXT3_MIN_BLOCK_SIZE) {
225             sb_block = EXT4_MIN_BLOCK_SIZE / BLOCK_SIZE;
226         }
227 
228         for (i = 0; i < sbi->s_gdb_count; i++) {
229             sbi->s_gd[i].block =  descriptor_loc(sb, sb_block, i);
230             if (!sbi->s_gd[i].block) {
231                 DEBUG(DL_ERR, ("Ext2LoadGroup: can't locate group descriptor %d\n", i));
232                 _SEH2_LEAVE;
233             }
234         }
235 
236         if (!Ext2LoadGroupBH(Vcb)) {
237             DEBUG(DL_ERR, ("Ext2LoadGroup: Failed to load group descriptions !\n"));
238             _SEH2_LEAVE;
239         }
240 
241         if (!ext4_check_descriptors(sb)) {
242             DbgBreak();
243             DEBUG(DL_ERR, ("Ext2LoadGroup: group descriptors corrupted !\n"));
244             _SEH2_LEAVE;
245         }
246 
247         SetFlag(Vcb->Flags, VCB_GD_LOADED);
248         rc = TRUE;
249 
250     } _SEH2_FINALLY {
251 
252         if (!rc)
253             Ext2PutGroup(Vcb);
254 
255         ExReleaseResourceLite(&Vcb->sbi.s_gd_lock);
256     } _SEH2_END;
257 
258     return rc;
259 }
260 
261 VOID
262 Ext2DropBH(IN PEXT2_VCB Vcb)
263 {
264     struct ext3_sb_info *sbi = &Vcb->sbi;
265 
266     /* do nothing if Vcb is not initialized yet */
267     if (!IsFlagOn(Vcb->Flags, VCB_INITIALIZED))
268         return;
269 
270     _SEH2_TRY {
271 
272         /* acquire bd lock to avoid bh creation */
273         ExAcquireResourceExclusiveLite(&Vcb->bd.bd_bh_lock, TRUE);
274 
275         SetFlag(Vcb->Flags, VCB_BEING_DROPPED);
276         Ext2DropGroupBH(Vcb);
277 
278         while (!IsListEmpty(&Vcb->bd.bd_bh_free)) {
279             struct buffer_head *bh;
280             PLIST_ENTRY         l;
281             l = RemoveHeadList(&Vcb->bd.bd_bh_free);
282             bh = CONTAINING_RECORD(l, struct buffer_head, b_link);
283             InitializeListHead(&bh->b_link);
284             if (0 == atomic_read(&bh->b_count)) {
285                 buffer_head_remove(&Vcb->bd, bh);
286                 free_buffer_head(bh);
287             }
288         }
289 
290     } _SEH2_FINALLY {
291         ExReleaseResourceLite(&Vcb->bd.bd_bh_lock);
292     } _SEH2_END;
293 
294     ClearFlag(Vcb->Flags, VCB_BEING_DROPPED);
295 }
296 
297 
298 VOID
299 Ext2FlushRange(IN PEXT2_VCB Vcb, LARGE_INTEGER s, LARGE_INTEGER e)
300 {
301     ULONG len;
302 
303     if (e.QuadPart <= s.QuadPart)
304         return;
305 
306     /* loop per 2G */
307     while (s.QuadPart < e.QuadPart) {
308         if (e.QuadPart > s.QuadPart + 1024 * 1024 * 1024) {
309             len = 1024 * 1024 * 1024;
310         } else {
311             len = (ULONG) (e.QuadPart - s.QuadPart);
312         }
313         CcFlushCache(&Vcb->SectionObject, &s, len, NULL);
314         s.QuadPart += len;
315     }
316 }
317 
318 NTSTATUS
319 Ext2FlushVcb(IN PEXT2_VCB Vcb)
320 {
321     LARGE_INTEGER        s = {0}, o;
322     struct ext3_sb_info *sbi = &Vcb->sbi;
323     struct rb_node      *node;
324     struct buffer_head  *bh;
325 
326     if (!IsFlagOn(Vcb->Flags, VCB_GD_LOADED)) {
327         CcFlushCache(&Vcb->SectionObject, NULL, 0, NULL);
328         goto errorout;
329     }
330 
331     ASSERT(ExIsResourceAcquiredExclusiveLite(&Vcb->MainResource));
332 
333     _SEH2_TRY {
334 
335         /* acqurie gd block */
336         ExAcquireResourceExclusiveLite(&Vcb->sbi.s_gd_lock, TRUE);
337 
338         /* acquire bd lock to avoid bh creation */
339         ExAcquireResourceExclusiveLite(&Vcb->bd.bd_bh_lock, TRUE);
340 
341         /* drop unused bh */
342         Ext2DropBH(Vcb);
343 
344         /* flush volume with all outstanding bh skipped */
345 
346         node = rb_first(&Vcb->bd.bd_bh_root);
347         while (node) {
348 
349             bh = container_of(node, struct buffer_head, b_rb_node);
350             node = rb_next(node);
351 
352             o.QuadPart = bh->b_blocknr << BLOCK_BITS;
353             ASSERT(o.QuadPart >= s.QuadPart);
354 
355             if (o.QuadPart == s.QuadPart) {
356                 s.QuadPart = s.QuadPart + bh->b_size;
357                 continue;
358             }
359 
360             if (o.QuadPart > s.QuadPart) {
361                 Ext2FlushRange(Vcb, s, o);
362                 s.QuadPart = (bh->b_blocknr << BLOCK_BITS) + bh->b_size;
363                 continue;
364             }
365         }
366 
367         o = Vcb->PartitionInformation.PartitionLength;
368         Ext2FlushRange(Vcb, s, o);
369 
370     } _SEH2_FINALLY {
371 
372         ExReleaseResourceLite(&Vcb->bd.bd_bh_lock);
373         ExReleaseResourceLite(&Vcb->sbi.s_gd_lock);
374     } _SEH2_END;
375 
376 errorout:
377     return STATUS_SUCCESS;
378 }
379 
380 
381 BOOLEAN
382 Ext2SaveGroup(
383     IN PEXT2_IRP_CONTEXT    IrpContext,
384     IN PEXT2_VCB            Vcb,
385     IN ULONG                Group
386 )
387 {
388     struct ext4_group_desc *gd;
389     struct buffer_head     *gb = NULL;
390     unsigned long i;
391 
392     gd = ext4_get_group_desc(&Vcb->sb, Group, &gb);
393     if (!gd)
394         return 0;
395 
396     gd->bg_checksum = ext4_group_desc_csum(&Vcb->sbi, Group, gd);
397     mark_buffer_dirty(gb);
398     fini_bh(&gb);
399 
400     return TRUE;
401 }
402 
403 
404 BOOLEAN
405 Ext2RefreshGroup(
406     IN PEXT2_IRP_CONTEXT    IrpContext,
407     IN PEXT2_VCB            Vcb
408 )
409 {
410     return TRUE;
411 }
412 
413 BOOLEAN
414 Ext2GetInodeLba (
415     IN PEXT2_VCB    Vcb,
416     IN  ULONG       inode,
417     OUT PLONGLONG   offset
418 )
419 {
420     PEXT2_GROUP_DESC gd;
421     struct buffer_head *bh = NULL;
422     ext4_fsblk_t loc;
423     int group;
424 
425     if (inode < 1 || inode > INODES_COUNT)  {
426         DEBUG(DL_ERR, ( "Ext2GetInodeLba: Inode value %xh is invalid.\n",inode));
427         *offset = 0;
428         return FALSE;
429     }
430 
431     group = (inode - 1) / INODES_PER_GROUP ;
432     gd = ext4_get_group_desc(&Vcb->sb, group, &bh);
433     if (!bh) {
434         *offset = 0;
435         DbgBreak();
436         return FALSE;
437     }
438     loc = (LONGLONG)ext4_inode_table(&Vcb->sb, gd);
439     loc = loc << BLOCK_BITS;
440     loc = loc + ((inode - 1) % INODES_PER_GROUP) * Vcb->InodeSize;
441 
442     *offset = loc;
443     __brelse(bh);
444 
445     return TRUE;
446 }
447 
448 void Ext2DecodeInode(struct inode *dst, struct ext3_inode *src)
449 {
450     dst->i_mode = src->i_mode;
451     dst->i_flags = src->i_flags;
452     dst->i_uid = src->i_uid;
453     dst->i_gid = src->i_gid;
454     dst->i_nlink = src->i_links_count;
455     dst->i_generation = src->i_generation;
456     dst->i_size = src->i_size;
457     if (S_ISREG(src->i_mode)) {
458         dst->i_size |= (loff_t)src->i_size_high << 32;
459     }
460     dst->i_file_acl = src->i_file_acl_lo;
461     dst->i_file_acl |= (ext4_fsblk_t)src->osd2.linux2.l_i_file_acl_high << 32;
462     dst->i_atime = src->i_atime;
463     dst->i_ctime = src->i_ctime;
464     dst->i_mtime = src->i_mtime;
465     dst->i_dtime = src->i_dtime;
466     dst->i_blocks = ext3_inode_blocks(src, dst);
467     memcpy(&dst->i_block[0], &src->i_block[0], sizeof(__u32) * 15);
468     if (EXT3_HAS_RO_COMPAT_FEATURE(dst->i_sb,
469                                    EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE))
470         dst->i_extra_isize = src->i_extra_isize;
471     else
472         dst->i_extra_isize = 0;
473 }
474 
475 void Ext2EncodeInode(struct ext3_inode *dst,  struct inode *src)
476 {
477     dst->i_mode = src->i_mode;
478     dst->i_flags = src->i_flags;
479     dst->i_uid = src->i_uid;
480     dst->i_gid = src->i_gid;
481     dst->i_links_count = src->i_nlink;
482     dst->i_generation = src->i_generation;
483     dst->i_size = (__u32)src->i_size;
484     if (S_ISREG(src->i_mode)) {
485         dst->i_size_high = (__u32)(src->i_size >> 32);
486     }
487     dst->i_file_acl_lo = (__u32)src->i_file_acl;
488     dst->osd2.linux2.l_i_file_acl_high |= (__u16)(src->i_file_acl >> 32);
489     dst->i_atime = src->i_atime;
490     dst->i_ctime = src->i_ctime;
491     dst->i_mtime = src->i_mtime;
492     dst->i_dtime = src->i_dtime;
493     dst->i_extra_isize = src->i_extra_isize;
494     ASSERT(src->i_sb);
495     ext3_inode_blocks_set(dst, src);
496     memcpy(&dst->i_block[0], &src->i_block[0], sizeof(__u32) * 15);
497     if (EXT3_HAS_RO_COMPAT_FEATURE(src->i_sb,
498                                    EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE))
499         dst->i_extra_isize = src->i_extra_isize;
500 }
501 
502 
503 BOOLEAN
504 Ext2LoadInode (IN PEXT2_VCB Vcb,
505                IN struct inode *Inode)
506 {
507     struct ext3_inode   ext3i = {0};
508     LONGLONG            offset;
509 
510     if (!Ext2GetInodeLba(Vcb, Inode->i_ino, &offset))  {
511         DEBUG(DL_ERR, ("Ext2LoadInode: failed inode %u.\n", Inode->i_ino));
512         return FALSE;
513     }
514 
515     if (!Ext2LoadBuffer(NULL, Vcb, offset, sizeof(ext3i), &ext3i)) {
516         return FALSE;
517     }
518 
519     Ext2DecodeInode(Inode, &ext3i);
520 
521     return TRUE;
522 }
523 
524 
525 BOOLEAN
526 Ext2ClearInode (
527     IN PEXT2_IRP_CONTEXT IrpContext,
528     IN PEXT2_VCB Vcb,
529     IN ULONG Inode)
530 {
531     LONGLONG            Offset = 0;
532     BOOLEAN             rc;
533 
534     rc = Ext2GetInodeLba(Vcb, Inode, &Offset);
535     if (!rc)  {
536         DEBUG(DL_ERR, ( "Ext2SaveInode: failed inode %u.\n", Inode));
537         goto errorout;
538     }
539 
540     rc = Ext2ZeroBuffer(IrpContext, Vcb, Offset, Vcb->InodeSize);
541 
542 errorout:
543 
544     return rc;
545 }
546 
547 BOOLEAN
548 Ext2SaveInode ( IN PEXT2_IRP_CONTEXT IrpContext,
549                 IN PEXT2_VCB Vcb,
550                 IN struct inode *Inode)
551 {
552     struct ext3_inode   ext3i = {0};
553 
554     LONGLONG            Offset = 0;
555     ULONG               InodeSize = sizeof(ext3i);
556     BOOLEAN             rc = 0;
557 
558     DEBUG(DL_INF, ( "Ext2SaveInode: Saving Inode %xh: Mode=%xh Size=%xh\n",
559                     Inode->i_ino, Inode->i_mode, Inode->i_size));
560     rc = Ext2GetInodeLba(Vcb,  Inode->i_ino, &Offset);
561     if (!rc)  {
562         DEBUG(DL_ERR, ( "Ext2SaveInode: failed inode %u.\n", Inode->i_ino));
563         goto errorout;
564     }
565 
566     rc = Ext2LoadBuffer(NULL, Vcb, Offset, InodeSize, &ext3i);
567     if (!rc) {
568         DEBUG(DL_ERR, ( "Ext2SaveInode: failed reading inode %u.\n", Inode->i_ino));
569         goto errorout;;
570     }
571 
572     Ext2EncodeInode(&ext3i, Inode);
573     if (InodeSize > Vcb->InodeSize)
574         InodeSize = Vcb->InodeSize;
575     rc = Ext2SaveBuffer(IrpContext, Vcb, Offset, InodeSize, &ext3i);
576 
577     if (rc && IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
578         Ext2StartFloppyFlushDpc(Vcb, NULL, NULL);
579     }
580 
581 errorout:
582     return rc;
583 }
584 
585 BOOLEAN
586 Ext2LoadInodeXattr(IN PEXT2_VCB Vcb,
587 	IN struct inode *Inode,
588 	IN PEXT2_INODE InodeXattr)
589 {
590 	IO_STATUS_BLOCK     IoStatus;
591 	LONGLONG            Offset;
592 
593 	if (!Ext2GetInodeLba(Vcb, Inode->i_ino, &Offset)) {
594 		DEBUG(DL_ERR, ("Ext2LoadRawInode: error get inode(%xh)'s addr.\n", Inode->i_ino));
595 		return FALSE;
596 	}
597 
598 	if (!CcCopyRead(
599 		Vcb->Volume,
600 		(PLARGE_INTEGER)&Offset,
601 		Vcb->InodeSize,
602 		PIN_WAIT,
603 		(PVOID)InodeXattr,
604 		&IoStatus)) {
605 		return FALSE;
606 	}
607 
608 	if (!NT_SUCCESS(IoStatus.Status)) {
609 		return FALSE;
610 	}
611 
612 	Ext2EncodeInode(InodeXattr, Inode);
613 	return TRUE;
614 }
615 
616 BOOLEAN
617 Ext2SaveInodeXattr(IN PEXT2_IRP_CONTEXT IrpContext,
618 	IN PEXT2_VCB Vcb,
619 	IN struct inode *Inode,
620 	IN PEXT2_INODE InodeXattr)
621 {
622 	IO_STATUS_BLOCK     IoStatus;
623 	LONGLONG            Offset = 0;
624 	ULONG               InodeSize = Vcb->InodeSize;
625 	BOOLEAN             rc = 0;
626 
627 	/* There is no way to put EA information in such a small inode */
628 	if (InodeSize == EXT2_GOOD_OLD_INODE_SIZE)
629 		return FALSE;
630 
631 	DEBUG(DL_INF, ("Ext2SaveInodeXattr: Saving Inode %xh: Mode=%xh Size=%xh\n",
632 		Inode->i_ino, Inode->i_mode, Inode->i_size));
633 	rc = Ext2GetInodeLba(Vcb, Inode->i_ino, &Offset);
634 	if (!rc) {
635 		DEBUG(DL_ERR, ("Ext2SaveInodeXattr: error get inode(%xh)'s addr.\n", Inode->i_ino));
636 		goto errorout;
637 	}
638 
639 	rc = Ext2SaveBuffer(IrpContext,
640 									Vcb,
641 									Offset + EXT2_GOOD_OLD_INODE_SIZE + Inode->i_extra_isize,
642 									InodeSize - EXT2_GOOD_OLD_INODE_SIZE - Inode->i_extra_isize,
643 									(char *)InodeXattr + EXT2_GOOD_OLD_INODE_SIZE + Inode->i_extra_isize);
644 
645 	if (rc && IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
646 		Ext2StartFloppyFlushDpc(Vcb, NULL, NULL);
647 	}
648 
649 errorout:
650 	return rc;
651 }
652 
653 
654 BOOLEAN
655 Ext2LoadBlock (IN PEXT2_VCB Vcb,
656                IN ULONG     Index,
657                IN PVOID     Buffer )
658 {
659     struct buffer_head *bh = NULL;
660     BOOLEAN             rc = 0;
661 
662     _SEH2_TRY {
663 
664         bh = sb_getblk(&Vcb->sb, (sector_t)Index);
665 
666         if (!bh) {
667             DEBUG(DL_ERR, ("Ext2Loadblock: can't load block %u\n", Index));
668             DbgBreak();
669             _SEH2_LEAVE;
670         }
671 
672         if (!buffer_uptodate(bh)) {
673             int err = bh_submit_read(bh);
674 	        if (err < 0) {
675 	            DEBUG(DL_ERR, ("Ext2LoadBlock: reading failed %d\n", err));
676 		        _SEH2_LEAVE;
677 	        }
678         }
679 
680         RtlCopyMemory(Buffer, bh->b_data, BLOCK_SIZE);
681         rc = TRUE;
682 
683     } _SEH2_FINALLY {
684 
685         if (bh)
686             fini_bh(&bh);
687     } _SEH2_END;
688 
689     return rc;
690 }
691 
692 
693 BOOLEAN
694 Ext2SaveBlock ( IN PEXT2_IRP_CONTEXT    IrpContext,
695                 IN PEXT2_VCB            Vcb,
696                 IN ULONG                Index,
697                 IN PVOID                Buf )
698 {
699     struct buffer_head *bh = NULL;
700     BOOLEAN             rc = 0;
701 
702     _SEH2_TRY {
703 
704         bh = sb_getblk_zero(&Vcb->sb, (sector_t)Index);
705 
706         if (!bh) {
707             DEBUG(DL_ERR, ("Ext2Saveblock: can't load block %u\n", Index));
708             DbgBreak();
709             _SEH2_LEAVE;
710         }
711 
712         if (!buffer_uptodate(bh)) {
713         }
714 
715         RtlCopyMemory(bh->b_data, Buf, BLOCK_SIZE);
716         mark_buffer_dirty(bh);
717         rc = TRUE;
718 
719     } _SEH2_FINALLY {
720 
721         if (bh)
722             fini_bh(&bh);
723     } _SEH2_END;
724 
725     return rc;
726 }
727 
728 BOOLEAN
729 Ext2LoadBuffer( IN PEXT2_IRP_CONTEXT    IrpContext,
730                 IN PEXT2_VCB            Vcb,
731                 IN LONGLONG             offset,
732                 IN ULONG                size,
733                 IN PVOID                buf )
734 {
735     struct buffer_head *bh = NULL;
736     BOOLEAN             rc;
737 
738     _SEH2_TRY {
739 
740         while (size) {
741 
742             sector_t    block;
743             ULONG       len = 0, delta = 0;
744 
745             block = (sector_t) (offset >> BLOCK_BITS);
746             delta = (ULONG)offset & (BLOCK_SIZE - 1);
747             len = BLOCK_SIZE - delta;
748             if (size < len)
749                 len = size;
750 
751             bh = sb_getblk(&Vcb->sb, block);
752             if (!bh) {
753                 DEBUG(DL_ERR, ("Ext2SaveBuffer: can't load block %I64u\n", block));
754                 DbgBreak();
755                 _SEH2_LEAVE;
756             }
757 
758             if (!buffer_uptodate(bh)) {
759 	            int err = bh_submit_read(bh);
760 	            if (err < 0) {
761 		            DEBUG(DL_ERR, ("Ext2SaveBuffer: bh_submit_read failed: %d\n", err));
762 		            _SEH2_LEAVE;
763 	            }
764             }
765 
766             _SEH2_TRY {
767                 RtlCopyMemory(buf, bh->b_data + delta, len);
768             } _SEH2_FINALLY {
769                 fini_bh(&bh);
770             } _SEH2_END;
771 
772             buf = (PUCHAR)buf + len;
773             offset = offset + len;
774             size = size - len;
775         }
776 
777         rc = TRUE;
778 
779     } _SEH2_FINALLY {
780 
781         if (bh)
782             fini_bh(&bh);
783 
784     } _SEH2_END;
785 
786     return rc;
787 }
788 
789 
790 BOOLEAN
791 Ext2ZeroBuffer( IN PEXT2_IRP_CONTEXT    IrpContext,
792                 IN PEXT2_VCB            Vcb,
793                 IN LONGLONG             offset,
794                 IN ULONG                size
795     )
796 {
797     struct buffer_head *bh = NULL;
798     BOOLEAN             rc = 0;
799 
800     _SEH2_TRY {
801 
802         while (size) {
803 
804             sector_t    block;
805             ULONG       len = 0, delta = 0;
806 
807             block = (sector_t) (offset >> BLOCK_BITS);
808             delta = (ULONG)offset & (BLOCK_SIZE - 1);
809             len = BLOCK_SIZE - delta;
810             if (size < len)
811                 len = size;
812 
813             if (delta == 0 && len >= BLOCK_SIZE) {
814                 bh = sb_getblk_zero(&Vcb->sb, block);
815             } else {
816                 bh = sb_getblk(&Vcb->sb, block);
817             }
818 
819             if (!bh) {
820                 DEBUG(DL_ERR, ("Ext2SaveBuffer: can't load block %I64u\n", block));
821                 DbgBreak();
822                 _SEH2_LEAVE;
823             }
824 
825             if (!buffer_uptodate(bh)) {
826 	            int err = bh_submit_read(bh);
827 	            if (err < 0) {
828 		            DEBUG(DL_ERR, ("Ext2SaveBuffer: bh_submit_read failed: %d\n", err));
829 		            _SEH2_LEAVE;
830 	            }
831             }
832 
833             _SEH2_TRY {
834                 if (delta == 0 && len >= BLOCK_SIZE) {
835                     /* bh (cache) was already cleaned as zero */
836                 } else {
837                     RtlZeroMemory(bh->b_data + delta, len);
838                 }
839                 mark_buffer_dirty(bh);
840             } _SEH2_FINALLY {
841                 fini_bh(&bh);
842             } _SEH2_END;
843 
844             offset = offset + len;
845             size = size - len;
846         }
847 
848         rc = TRUE;
849 
850     } _SEH2_FINALLY {
851 
852         if (bh)
853             fini_bh(&bh);
854 
855     } _SEH2_END;
856 
857     return rc;
858 }
859 
860 
861 #define SIZE_256K 0x40000
862 
863 BOOLEAN
864 Ext2SaveBuffer( IN PEXT2_IRP_CONTEXT    IrpContext,
865                 IN PEXT2_VCB            Vcb,
866                 IN LONGLONG             Offset,
867                 IN ULONG                Size,
868                 IN PVOID                Buf )
869 {
870     BOOLEAN     rc;
871 
872     while (Size) {
873 
874         PBCB        Bcb;
875         PVOID       Buffer;
876         ULONG       Length;
877 
878         Length = (ULONG)Offset & (SIZE_256K - 1);
879         Length = SIZE_256K - Length;
880         if (Size < Length)
881             Length = Size;
882 
883         if ( !CcPreparePinWrite(
884                     Vcb->Volume,
885                     (PLARGE_INTEGER) (&Offset),
886                     Length,
887                     FALSE,
888                     PIN_WAIT | PIN_EXCLUSIVE,
889                     &Bcb,
890                     &Buffer )) {
891 
892             DEBUG(DL_ERR, ( "Ext2SaveBuffer: failed to PinLock offset %I64xh ...\n", Offset));
893             return FALSE;
894         }
895 
896         _SEH2_TRY {
897 
898             RtlCopyMemory(Buffer, Buf, Length);
899             CcSetDirtyPinnedData(Bcb, NULL );
900             SetFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
901 
902             rc = Ext2AddVcbExtent(Vcb, Offset, (LONGLONG)Length);
903             if (!rc) {
904                 DbgBreak();
905                 Ext2Sleep(100);
906                 rc = Ext2AddVcbExtent(Vcb, Offset, (LONGLONG)Length);
907             }
908 
909         } _SEH2_FINALLY {
910             CcUnpinData(Bcb);
911         } _SEH2_END;
912 
913         Buf = (PUCHAR)Buf + Length;
914         Offset = Offset + Length;
915         Size = Size - Length;
916     }
917 
918     return rc;
919 }
920 
921 
922 VOID
923 Ext2UpdateVcbStat(
924     IN PEXT2_IRP_CONTEXT    IrpContext,
925     IN PEXT2_VCB            Vcb
926 )
927 {
928     Vcb->SuperBlock->s_free_inodes_count = ext4_count_free_inodes(&Vcb->sb);
929     ext3_free_blocks_count_set(SUPER_BLOCK, ext4_count_free_blocks(&Vcb->sb));
930     Ext2SaveSuper(IrpContext, Vcb);
931 }
932 
933 NTSTATUS
934 Ext2NewBlock(
935     IN PEXT2_IRP_CONTEXT    IrpContext,
936     IN PEXT2_VCB            Vcb,
937     IN ULONG                GroupHint,
938     IN ULONG                BlockHint,
939     OUT PULONG              Block,
940     IN OUT PULONG           Number
941 )
942 {
943     struct super_block      *sb = &Vcb->sb;
944     PEXT2_GROUP_DESC        gd;
945     struct buffer_head     *gb = NULL;
946     struct buffer_head     *bh = NULL;
947     ext4_fsblk_t            bitmap_blk;
948 
949     RTL_BITMAP              BlockBitmap;
950 
951     ULONG                   Group = 0;
952     ULONG                   Index = 0xFFFFFFFF;
953     ULONG                   dwHint = 0;
954     ULONG                   Count = 0;
955     ULONG                   Length = 0;
956 
957     NTSTATUS                Status = STATUS_DISK_FULL;
958 
959     *Block = 0;
960 
961     ExAcquireResourceExclusiveLite(&Vcb->MetaBlock, TRUE);
962 
963     /* validate the hint group and hint block */
964     if (GroupHint >= Vcb->sbi.s_groups_count) {
965         DbgBreak();
966         GroupHint = Vcb->sbi.s_groups_count - 1;
967     }
968 
969     if (BlockHint != 0) {
970         GroupHint = (BlockHint - EXT2_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP;
971         dwHint = (BlockHint - EXT2_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP;
972     }
973 
974     Group = GroupHint;
975 
976 Again:
977 
978     if (bh)
979         fini_bh(&bh);
980 
981     if (gb)
982         fini_bh(&gb);
983 
984     gd = ext4_get_group_desc(sb, Group, &gb);
985     if (!gd) {
986         DbgBreak();
987         Status = STATUS_INSUFFICIENT_RESOURCES;
988         goto errorout;
989     }
990 
991     bitmap_blk = ext4_block_bitmap(sb, gd);
992 
993     if (gd->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
994         bh = sb_getblk_zero(sb, bitmap_blk);
995         if (!bh) {
996             DbgBreak();
997             Status = STATUS_INSUFFICIENT_RESOURCES;
998             goto errorout;
999         }
1000         gd->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, gd);
1001         ext4_init_block_bitmap(sb, bh, Group, gd);
1002         set_buffer_uptodate(bh);
1003         gd->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
1004         Ext2SaveGroup(IrpContext, Vcb, Group);
1005     } else {
1006         bh = sb_getblk(sb, bitmap_blk);
1007         if (!bh) {
1008             DbgBreak();
1009             Status = STATUS_INSUFFICIENT_RESOURCES;
1010             goto errorout;
1011         }
1012     }
1013 
1014     if (!buffer_uptodate(bh)) {
1015 	    int err = bh_submit_read(bh);
1016 	    if (err < 0) {
1017 		    DbgPrint("bh_submit_read error! err: %d\n", err);
1018 		    Status = Ext2WinntError(err);
1019 		    goto errorout;
1020 	    }
1021     }
1022 
1023     if (ext4_free_blks_count(sb, gd)) {
1024 
1025         if (Group == Vcb->sbi.s_groups_count - 1) {
1026 
1027             Length = (ULONG)(TOTAL_BLOCKS % BLOCKS_PER_GROUP);
1028 
1029             /* s_blocks_count is integer multiple of s_blocks_per_group */
1030             if (Length == 0) {
1031                 Length = BLOCKS_PER_GROUP;
1032             }
1033         } else {
1034             Length = BLOCKS_PER_GROUP;
1035         }
1036 
1037         /* initialize bitmap buffer */
1038         RtlInitializeBitMap(&BlockBitmap, (PULONG)bh->b_data, Length);
1039 
1040         /* try to find a clear bit range */
1041         Index = RtlFindClearBits(&BlockBitmap, *Number, dwHint);
1042 
1043         /* We could not get new block in the prefered group */
1044         if (Index == 0xFFFFFFFF) {
1045 
1046             /* search clear bits from the hint block */
1047             Count = RtlFindNextForwardRunClear(&BlockBitmap, dwHint, &Index);
1048             if (dwHint != 0 && Count == 0) {
1049                 /* search clear bits from the very beginning */
1050                 Count = RtlFindNextForwardRunClear(&BlockBitmap, 0, &Index);
1051             }
1052 
1053             if (Count == 0) {
1054 
1055                 RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
1056 
1057                 /* no blocks found: set bg_free_blocks_count to 0 */
1058                 ext4_free_blks_set(sb, gd, 0);
1059                 Ext2SaveGroup(IrpContext, Vcb, Group);
1060 
1061                 /* will try next group */
1062                 goto Again;
1063 
1064             } else {
1065 
1066                 /* we got free blocks */
1067                 if (Count <= *Number) {
1068                     *Number = Count;
1069                 }
1070             }
1071         }
1072 
1073     } else {
1074 
1075         /* try next group */
1076         dwHint = 0;
1077         Group = (Group + 1) % Vcb->sbi.s_groups_count;
1078         if (Group != GroupHint) {
1079             goto Again;
1080         }
1081 
1082         Index = 0xFFFFFFFF;
1083     }
1084 
1085     if (Index < Length) {
1086 
1087         /* mark block bits as allocated */
1088         RtlSetBits(&BlockBitmap, Index, *Number);
1089 
1090         /* set block bitmap dirty in cache */
1091         mark_buffer_dirty(bh);
1092 
1093         /* update group description */
1094         ext4_free_blks_set(sb, gd, RtlNumberOfClearBits(&BlockBitmap));
1095         Ext2SaveGroup(IrpContext, Vcb, Group);
1096 
1097         /* update Vcb free blocks */
1098         Ext2UpdateVcbStat(IrpContext, Vcb);
1099 
1100         /* validate the new allocated block number */
1101         *Block = Index + EXT2_FIRST_DATA_BLOCK + Group * BLOCKS_PER_GROUP;
1102         if (*Block >= TOTAL_BLOCKS || *Block + *Number > TOTAL_BLOCKS) {
1103             DbgBreak();
1104             dwHint = 0;
1105             goto Again;
1106         }
1107 
1108         if (ext4_block_bitmap(sb, gd) == *Block ||
1109             ext4_inode_bitmap(sb, gd) == *Block ||
1110             ext4_inode_table(sb,  gd)  == *Block ) {
1111             DbgBreak();
1112             dwHint = 0;
1113             goto Again;
1114         }
1115 
1116         /* Always remove dirty MCB to prevent Volume's lazy writing.
1117            Metadata blocks will be re-added during modifications.*/
1118         if (Ext2RemoveBlockExtent(Vcb, NULL, *Block, *Number)) {
1119         } else {
1120             DbgBreak();
1121             Ext2RemoveBlockExtent(Vcb, NULL, *Block, *Number);
1122         }
1123 
1124         DEBUG(DL_INF, ("Ext2NewBlock:  Block %xh - %x allocated.\n",
1125                        *Block, *Block + *Number));
1126         Status = STATUS_SUCCESS;
1127     }
1128 
1129 errorout:
1130 
1131     ExReleaseResourceLite(&Vcb->MetaBlock);
1132 
1133     if (bh)
1134         fini_bh(&bh);
1135 
1136     if (gb)
1137         fini_bh(&gb);
1138 
1139     return Status;
1140 }
1141 
1142 NTSTATUS
1143 Ext2FreeBlock(
1144     IN PEXT2_IRP_CONTEXT    IrpContext,
1145     IN PEXT2_VCB            Vcb,
1146     IN ULONG                Block,
1147     IN ULONG                Number
1148 )
1149 {
1150     struct super_block     *sb = &Vcb->sb;
1151     PEXT2_GROUP_DESC        gd;
1152     struct buffer_head     *gb = NULL;
1153     ext4_fsblk_t            bitmap_blk;
1154 
1155     RTL_BITMAP      BlockBitmap;
1156     LARGE_INTEGER   Offset;
1157 
1158     PBCB            BitmapBcb;
1159     PVOID           BitmapCache;
1160 
1161     ULONG           Group;
1162     ULONG           Index;
1163     ULONG           Length;
1164     ULONG           Count;
1165 
1166     NTSTATUS        Status = STATUS_UNSUCCESSFUL;
1167 
1168     ExAcquireResourceExclusiveLite(&Vcb->MetaBlock, TRUE);
1169 
1170     DEBUG(DL_INF, ("Ext2FreeBlock: Block %xh - %x to be freed.\n",
1171                    Block, Block + Number));
1172 
1173     Group = (Block - EXT2_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP;
1174     Index = (Block - EXT2_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP;
1175 
1176 Again:
1177 
1178     if (gb)
1179         fini_bh(&gb);
1180 
1181     if ( Block < EXT2_FIRST_DATA_BLOCK ||
1182          Block >= TOTAL_BLOCKS ||
1183          Group >= Vcb->sbi.s_groups_count) {
1184 
1185         DbgBreak();
1186         Status = STATUS_SUCCESS;
1187 
1188     } else  {
1189 
1190         gd = ext4_get_group_desc(sb, Group, &gb);
1191         if (!gd) {
1192             DbgBreak();
1193             Status = STATUS_INSUFFICIENT_RESOURCES;
1194             goto errorout;
1195         }
1196         bitmap_blk = ext4_block_bitmap(sb, gd);
1197 
1198         /* check the block is valid or not */
1199         if (bitmap_blk >= TOTAL_BLOCKS) {
1200             DbgBreak();
1201             Status = STATUS_DISK_CORRUPT_ERROR;
1202             goto errorout;
1203         }
1204 
1205         /* get bitmap block offset and length */
1206         Offset.QuadPart = bitmap_blk;
1207         Offset.QuadPart = Offset.QuadPart << BLOCK_BITS;
1208 
1209         if (Group == Vcb->sbi.s_groups_count - 1) {
1210 
1211             Length = (ULONG)(TOTAL_BLOCKS % BLOCKS_PER_GROUP);
1212 
1213             /* s_blocks_count is integer multiple of s_blocks_per_group */
1214             if (Length == 0) {
1215                 Length = BLOCKS_PER_GROUP;
1216             }
1217 
1218         } else {
1219             Length = BLOCKS_PER_GROUP;
1220         }
1221 
1222         /* read and initialize bitmap */
1223         if (!CcPinRead( Vcb->Volume,
1224                         &Offset,
1225                         Vcb->BlockSize,
1226                         PIN_WAIT,
1227                         &BitmapBcb,
1228                         &BitmapCache ) ) {
1229 
1230             DEBUG(DL_ERR, ("Ext2FreeBlock: failed to PinLock bitmap block %xh.\n",
1231                            bitmap_blk));
1232             Status = STATUS_CANT_WAIT;
1233             DbgBreak();
1234             goto errorout;
1235         }
1236 
1237         /* clear usused bits */
1238         RtlInitializeBitMap(&BlockBitmap, BitmapCache, Length);
1239         Count = min(Length - Index, Number);
1240         RtlClearBits(&BlockBitmap, Index, Count);
1241 
1242         /* update group description table */
1243         ext4_free_blks_set(sb, gd, RtlNumberOfClearBits(&BlockBitmap));
1244 
1245         /* indict the cache range is dirty */
1246         CcSetDirtyPinnedData(BitmapBcb, NULL );
1247         Ext2AddVcbExtent(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
1248         CcUnpinData(BitmapBcb);
1249         BitmapBcb = NULL;
1250         BitmapCache = NULL;
1251         Ext2SaveGroup(IrpContext, Vcb, Group);
1252 
1253         /* remove dirty MCB to prevent Volume's lazy writing. */
1254         if (Ext2RemoveBlockExtent(Vcb, NULL, Block, Count)) {
1255         } else {
1256             DbgBreak();
1257             Ext2RemoveBlockExtent(Vcb, NULL, Block, Count);
1258         }
1259 
1260         /* save super block (used/unused blocks statics) */
1261         Ext2UpdateVcbStat(IrpContext, Vcb);
1262 
1263         /* try next group to clear all remaining */
1264         Number -= Count;
1265         if (Number) {
1266             Group += 1;
1267             if (Group < Vcb->sbi.s_groups_count) {
1268                 Index = 0;
1269                 Block += Count;
1270                 goto Again;
1271             } else {
1272                 DEBUG(DL_ERR, ("Ext2FreeBlock: block number beyonds max group.\n"));
1273                 goto errorout;
1274             }
1275         }
1276     }
1277 
1278     Status = STATUS_SUCCESS;
1279 
1280 errorout:
1281 
1282     if (gb)
1283         fini_bh(&gb);
1284 
1285     ExReleaseResourceLite(&Vcb->MetaBlock);
1286 
1287     return Status;
1288 }
1289 
1290 
1291 NTSTATUS
1292 Ext2NewInode(
1293     IN PEXT2_IRP_CONTEXT    IrpContext,
1294     IN PEXT2_VCB            Vcb,
1295     IN ULONG                GroupHint,
1296     IN ULONG                Type,
1297     OUT PULONG              Inode
1298 )
1299 {
1300     struct super_block     *sb = &Vcb->sb;
1301     PEXT2_GROUP_DESC        gd;
1302     struct buffer_head     *gb = NULL;
1303     struct buffer_head     *bh = NULL;
1304     ext4_fsblk_t            bitmap_blk;
1305 
1306     RTL_BITMAP      InodeBitmap;
1307 
1308     ULONG           Group, i, j;
1309     ULONG           Average, Length;
1310 
1311     ULONG           dwInode;
1312 
1313     NTSTATUS        Status = STATUS_DISK_FULL;
1314 
1315     *Inode = dwInode = 0XFFFFFFFF;
1316 
1317     ExAcquireResourceExclusiveLite(&Vcb->MetaInode, TRUE);
1318 
1319     if (GroupHint >= Vcb->sbi.s_groups_count)
1320         GroupHint = GroupHint % Vcb->sbi.s_groups_count;
1321 
1322 repeat:
1323 
1324     if (bh)
1325         fini_bh(&bh);
1326 
1327     if (gb)
1328         fini_bh(&gb);
1329 
1330     Group = i = 0;
1331     gd = NULL;
1332 
1333     if (Type == EXT2_FT_DIR) {
1334 
1335         Average = Vcb->SuperBlock->s_free_inodes_count / Vcb->sbi.s_groups_count;
1336 
1337         for (j = 0; j < Vcb->sbi.s_groups_count; j++) {
1338 
1339             i = (j + GroupHint) % (Vcb->sbi.s_groups_count);
1340             gd = ext4_get_group_desc(sb, i, &gb);
1341             if (!gd) {
1342                     DbgBreak();
1343                 Status = STATUS_INSUFFICIENT_RESOURCES;
1344                 goto errorout;
1345             }
1346 
1347             if ((gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) ||
1348                 (ext4_used_dirs_count(sb, gd) << 8 <
1349                  ext4_free_inodes_count(sb, gd)) ) {
1350                 Group = i + 1;
1351                 break;
1352             }
1353             fini_bh(&gb);
1354         }
1355 
1356         if (!Group) {
1357 
1358             PEXT2_GROUP_DESC  desc = NULL;
1359 
1360             gd = NULL;
1361 
1362             /* get the group with the biggest vacancy */
1363             for (j = 0; j < Vcb->sbi.s_groups_count; j++) {
1364 
1365                 struct buffer_head *gt = NULL;
1366                 desc = ext4_get_group_desc(sb, j, &gt);
1367                 if (!desc) {
1368                     DbgBreak();
1369                     Status = STATUS_INSUFFICIENT_RESOURCES;
1370                     goto errorout;
1371                 }
1372 
1373                 /* return the group if it's not initialized yet */
1374                 if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
1375                     Group = j + 1;
1376                     gd = desc;
1377 
1378                     if (gb)
1379                         fini_bh(&gb);
1380                     gb = gt;
1381                     gt = NULL;
1382                     break;
1383                 }
1384 
1385                 if (!gd) {
1386                     if (ext4_free_inodes_count(sb, desc) > 0) {
1387                         Group = j + 1;
1388                         gd = desc;
1389                         if (gb)
1390                             fini_bh(&gb);
1391                         gb = gt;
1392                         gt = NULL;
1393                     }
1394                 } else {
1395                     if (ext4_free_inodes_count(sb, desc) >
1396                         ext4_free_inodes_count(sb, gd)) {
1397                         Group = j + 1;
1398                         gd = desc;
1399                         if (gb)
1400                             fini_bh(&gb);
1401                         gb = gt;
1402                         gt = NULL;
1403                         break;
1404                     }
1405                 }
1406                 if (gt)
1407                     fini_bh(&gt);
1408             }
1409         }
1410 
1411     } else {
1412 
1413         /*
1414          * Try to place the inode in its parent directory (GroupHint)
1415          */
1416 
1417         gd = ext4_get_group_desc(sb, GroupHint, &gb);
1418         if (!gb) {
1419             DbgBreak();
1420             Status = STATUS_INSUFFICIENT_RESOURCES;
1421             goto errorout;
1422         }
1423 
1424         if (gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT) ||
1425             ext4_free_inodes_count(sb, gd)) {
1426 
1427             Group = GroupHint + 1;
1428 
1429         } else {
1430 
1431             /* this group is 100% cocucpied */
1432             fini_bh(&gb);
1433 
1434             i = GroupHint;
1435 
1436             /*
1437              * Use a quadratic hash to find a group with a free inode
1438              */
1439 
1440             for (j = 1; j < Vcb->sbi.s_groups_count; j <<= 1) {
1441 
1442 
1443                 i = (i + j) % Vcb->sbi.s_groups_count;
1444                 gd = ext4_get_group_desc(sb, i, &gb);
1445                 if (!gd) {
1446                     DbgBreak();
1447                     Status = STATUS_INSUFFICIENT_RESOURCES;
1448                     goto errorout;
1449                 }
1450 
1451                 if (gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT) ||
1452                     ext4_free_inodes_count(sb, gd)) {
1453                     Group = i + 1;
1454                     break;
1455                 }
1456 
1457                 fini_bh(&gb);
1458             }
1459         }
1460 
1461         if (!Group) {
1462             /*
1463              * That failed: try linear search for a free inode
1464              */
1465             i = GroupHint;
1466             for (j = 2; j < Vcb->sbi.s_groups_count; j++) {
1467 
1468                 i = (i + 1) % Vcb->sbi.s_groups_count;
1469                 gd = ext4_get_group_desc(sb, i, &gb);
1470                 if (!gd) {
1471                     DbgBreak();
1472                     Status = STATUS_INSUFFICIENT_RESOURCES;
1473                     goto errorout;
1474                 }
1475 
1476                 if (gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT) ||
1477                     ext4_free_inodes_count(sb, gd)) {
1478                     Group = i + 1;
1479                     break;
1480                 }
1481 
1482                 fini_bh(&gb);
1483             }
1484         }
1485     }
1486 
1487     if (gd == NULL || Group == 0) {
1488         goto errorout;
1489     }
1490 
1491     /* finally we got the group, but is it valid ? */
1492     if (Group > Vcb->sbi.s_groups_count) {
1493         DbgBreak();
1494         goto errorout;
1495     }
1496 
1497     /* valid group number starts from 1, not 0 */
1498     Group -= 1;
1499 
1500     ASSERT(gd);
1501     bitmap_blk = ext4_inode_bitmap(sb, gd);
1502     /* check the block is valid or not */
1503     if (bitmap_blk == 0 || bitmap_blk >= TOTAL_BLOCKS) {
1504         DbgBreak();
1505         Status = STATUS_DISK_CORRUPT_ERROR;
1506         goto errorout;
1507     }
1508 
1509     if (gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
1510         bh = sb_getblk_zero(sb, bitmap_blk);
1511         if (!bh) {
1512             DbgBreak();
1513             Status = STATUS_INSUFFICIENT_RESOURCES;
1514             goto errorout;
1515         }
1516         gd->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, gd);
1517         ext4_init_inode_bitmap(sb, bh, Group, gd);
1518         set_buffer_uptodate(bh);
1519         gd->bg_flags &= cpu_to_le16(~EXT4_BG_INODE_UNINIT);
1520         Ext2SaveGroup(IrpContext, Vcb, Group);
1521     } else {
1522         bh = sb_getblk(sb, bitmap_blk);
1523         if (!bh) {
1524             DbgBreak();
1525             Status = STATUS_INSUFFICIENT_RESOURCES;
1526             goto errorout;
1527         }
1528     }
1529 
1530     if (!buffer_uptodate(bh)) {
1531 	    int err = bh_submit_read(bh);
1532 	    if (err < 0) {
1533 		    DbgPrint("bh_submit_read error! err: %d\n", err);
1534 		    Status = Ext2WinntError(err);
1535 		    goto errorout;
1536 	    }
1537     }
1538 
1539     if (Vcb->sbi.s_groups_count == 1) {
1540         Length = INODES_COUNT;
1541     } else {
1542         if (Group + 1 == Vcb->sbi.s_groups_count) {
1543             Length = INODES_COUNT % INODES_PER_GROUP;
1544             if (!Length) {
1545                 /* INODES_COUNT is integer multiple of INODES_PER_GROUP */
1546                 Length = INODES_PER_GROUP;
1547             }
1548         } else  {
1549             Length = INODES_PER_GROUP;
1550         }
1551     }
1552 
1553     RtlInitializeBitMap(&InodeBitmap, (PULONG)bh->b_data, Length);
1554     dwInode = RtlFindClearBits(&InodeBitmap, 1, 0);
1555 
1556     if (dwInode == 0xFFFFFFFF || dwInode >= Length) {
1557 
1558         RtlZeroMemory(&InodeBitmap, sizeof(RTL_BITMAP));
1559         if (ext4_free_inodes_count(sb, gd) > 0) {
1560             ext4_free_inodes_set(sb, gd, 0);
1561             Ext2SaveGroup(IrpContext, Vcb, Group);
1562         }
1563         goto repeat;
1564 
1565     } else {
1566 
1567         __u32 count = 0;
1568 
1569         /* update unused inodes count */
1570         count = ext4_free_inodes_count(sb, gd) - 1;
1571         ext4_free_inodes_set(sb, gd, count);
1572 
1573         RtlSetBits(&InodeBitmap, dwInode, 1);
1574 
1575         /* set block bitmap dirty in cache */
1576         mark_buffer_dirty(bh);
1577 
1578         /* If we didn't allocate from within the initialized part of the inode
1579          * table then we need to initialize up to this inode. */
1580         if (EXT3_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
1581 
1582             __u32 free;
1583 
1584             if (gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
1585                 gd->bg_flags &= cpu_to_le16(~EXT4_BG_INODE_UNINIT);
1586                 /* When marking the block group with
1587                  * ~EXT4_BG_INODE_UNINIT we don't want to depend
1588                  * on the value of bg_itable_unused even though
1589                  * mke2fs could have initialized the same for us.
1590                  * Instead we calculated the value below
1591                  */
1592 
1593                 free = 0;
1594             } else {
1595                 free = EXT3_INODES_PER_GROUP(sb) - ext4_itable_unused_count(sb, gd);
1596             }
1597 
1598             /*
1599              * Check the relative inode number against the last used
1600              * relative inode number in this group. if it is greater
1601              * we need to  update the bg_itable_unused count
1602              *
1603              */
1604             if (dwInode + 1 > free) {
1605                 ext4_itable_unused_set(sb, gd,
1606                                        (EXT3_INODES_PER_GROUP(sb) - 1 - dwInode));
1607             }
1608 
1609             /* We may have to initialize the block bitmap if it isn't already */
1610             if (gd->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
1611 
1612                 struct buffer_head *block_bitmap_bh = NULL;
1613 
1614                 /* recheck and clear flag under lock if we still need to */
1615                 block_bitmap_bh = sb_getblk_zero(sb, ext4_block_bitmap(sb, gd));
1616                 if (block_bitmap_bh) {
1617                     gd->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, gd);
1618                     free = ext4_init_block_bitmap(sb, block_bitmap_bh, Group, gd);
1619                     set_buffer_uptodate(block_bitmap_bh);
1620                     brelse(block_bitmap_bh);
1621                     gd->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
1622                     ext4_free_blks_set(sb, gd, free);
1623                     Ext2SaveGroup(IrpContext, Vcb, Group);
1624                 }
1625             }
1626         }
1627 
1628         *Inode = dwInode + 1 + Group * INODES_PER_GROUP;
1629 
1630         /* update group_desc / super_block */
1631         if (Type == EXT2_FT_DIR) {
1632             ext4_used_dirs_set(sb, gd, ext4_used_dirs_count(sb, gd) + 1);
1633         }
1634         Ext2SaveGroup(IrpContext, Vcb, Group);
1635         Ext2UpdateVcbStat(IrpContext, Vcb);
1636         Status = STATUS_SUCCESS;
1637     }
1638 
1639 errorout:
1640 
1641     ExReleaseResourceLite(&Vcb->MetaInode);
1642 
1643     if (bh)
1644         fini_bh(&bh);
1645 
1646     if (gb)
1647         fini_bh(&gb);
1648 
1649 
1650     return Status;
1651 }
1652 
1653 NTSTATUS
1654 Ext2UpdateGroupDirStat(
1655     IN PEXT2_IRP_CONTEXT    IrpContext,
1656     IN PEXT2_VCB            Vcb,
1657     IN ULONG                group
1658     )
1659 {
1660     struct super_block     *sb = &Vcb->sb;
1661     PEXT2_GROUP_DESC        gd;
1662     struct buffer_head     *gb = NULL;
1663     NTSTATUS                status;
1664 
1665     ExAcquireResourceExclusiveLite(&Vcb->MetaInode, TRUE);
1666 
1667     /* get group desc */
1668     gd = ext4_get_group_desc(sb, group, &gb);
1669     if (!gd) {
1670         status = STATUS_INSUFFICIENT_RESOURCES;
1671         goto errorout;
1672     }
1673 
1674     /* update group_desc and super_block */
1675     ext4_used_dirs_set(sb, gd, ext4_used_dirs_count(sb, gd) - 1);
1676     Ext2SaveGroup(IrpContext, Vcb, group);
1677     Ext2UpdateVcbStat(IrpContext, Vcb);
1678     status = STATUS_SUCCESS;
1679 
1680 errorout:
1681 
1682     ExReleaseResourceLite(&Vcb->MetaInode);
1683 
1684     if (gb)
1685         fini_bh(&gb);
1686 
1687     return status;
1688 }
1689 
1690 
1691 NTSTATUS
1692 Ext2FreeInode(
1693     IN PEXT2_IRP_CONTEXT    IrpContext,
1694     IN PEXT2_VCB            Vcb,
1695     IN ULONG                Inode,
1696     IN ULONG                Type
1697 )
1698 {
1699     struct super_block     *sb = &Vcb->sb;
1700     PEXT2_GROUP_DESC        gd;
1701     struct buffer_head     *gb = NULL;
1702     struct buffer_head     *bh = NULL;
1703     ext4_fsblk_t            bitmap_blk;
1704 
1705     RTL_BITMAP      InodeBitmap;
1706     ULONG           Group;
1707     ULONG           Length;
1708     LARGE_INTEGER   Offset;
1709 
1710     ULONG           dwIno;
1711     BOOLEAN         bModified = FALSE;
1712 
1713     NTSTATUS        Status = STATUS_UNSUCCESSFUL;
1714 
1715     ExAcquireResourceExclusiveLite(&Vcb->MetaInode, TRUE);
1716 
1717     Group = (Inode - 1) / INODES_PER_GROUP;
1718     dwIno = (Inode - 1) % INODES_PER_GROUP;
1719 
1720     DEBUG(DL_INF, ( "Ext2FreeInode: Inode: %xh (Group/Off = %xh/%xh)\n",
1721                     Inode, Group, dwIno));
1722 
1723     if (Group >= Vcb->sbi.s_groups_count)  {
1724         DbgBreak();
1725         goto errorout;
1726     }
1727 
1728     gd = ext4_get_group_desc(sb, Group, &gb);
1729     if (!gd) {
1730         DbgBreak();
1731         Status = STATUS_INSUFFICIENT_RESOURCES;
1732         goto errorout;
1733     }
1734 
1735     bitmap_blk = ext4_inode_bitmap(sb, gd);
1736     bh = sb_getblk(sb, bitmap_blk);
1737     if (!bh) {
1738         DbgBreak();
1739         Status = STATUS_INSUFFICIENT_RESOURCES;
1740         goto errorout;
1741     }
1742     if (!buffer_uptodate(bh)) {
1743         int err = bh_submit_read(bh);
1744         if (err < 0) {
1745             DbgPrint("bh_submit_read error! err: %d\n", err);
1746             Status = Ext2WinntError(err);
1747             goto errorout;
1748         }
1749     }
1750 
1751     if (Group == Vcb->sbi.s_groups_count - 1) {
1752 
1753         Length = INODES_COUNT % INODES_PER_GROUP;
1754         if (!Length) {
1755             /* s_inodes_count is integer multiple of s_inodes_per_group */
1756             Length = INODES_PER_GROUP;
1757         }
1758     } else {
1759         Length = INODES_PER_GROUP;
1760     }
1761 
1762     RtlInitializeBitMap(&InodeBitmap, (PULONG)bh->b_data, Length);
1763 
1764     if (RtlCheckBit(&InodeBitmap, dwIno) == 0) {
1765         DbgBreak();
1766         Status = STATUS_SUCCESS;
1767     } else {
1768         RtlClearBits(&InodeBitmap, dwIno, 1);
1769         bModified = TRUE;
1770     }
1771 
1772     if (bModified) {
1773         /* update group free inodes */
1774         ext4_free_inodes_set(sb, gd,
1775                              RtlNumberOfClearBits(&InodeBitmap));
1776 
1777         /* set inode block dirty and add to vcb dirty range */
1778         mark_buffer_dirty(bh);
1779 
1780         /* update group_desc and super_block */
1781         if (Type == EXT2_FT_DIR) {
1782             ext4_used_dirs_set(sb, gd,
1783                                ext4_used_dirs_count(sb, gd) - 1);
1784         }
1785         Ext2SaveGroup(IrpContext, Vcb, Group);
1786         Ext2UpdateVcbStat(IrpContext, Vcb);
1787         Status = STATUS_SUCCESS;
1788     }
1789 
1790 errorout:
1791 
1792     ExReleaseResourceLite(&Vcb->MetaInode);
1793 
1794     if (bh)
1795         fini_bh(&bh);
1796 
1797     if (gb)
1798         fini_bh(&gb);
1799 
1800     return Status;
1801 }
1802 
1803 
1804 NTSTATUS
1805 Ext2AddEntry (
1806     IN PEXT2_IRP_CONTEXT   IrpContext,
1807     IN PEXT2_VCB           Vcb,
1808     IN PEXT2_FCB           Dcb,
1809     IN struct inode       *Inode,
1810     IN PUNICODE_STRING     FileName,
1811     struct dentry        **Dentry
1812 )
1813 {
1814     struct dentry          *de = NULL;
1815 
1816     NTSTATUS                status = STATUS_UNSUCCESSFUL;
1817     OEM_STRING              oem;
1818     int                     rc;
1819 
1820     BOOLEAN                 MainResourceAcquired = FALSE;
1821 
1822     if (!IsDirectory(Dcb)) {
1823         DbgBreak();
1824         return STATUS_NOT_A_DIRECTORY;
1825     }
1826 
1827     ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);
1828     MainResourceAcquired = TRUE;
1829 
1830     _SEH2_TRY {
1831 
1832         Ext2ReferXcb(&Dcb->ReferenceCount);
1833         de = Ext2BuildEntry(Vcb, Dcb->Mcb, FileName);
1834         if (!de) {
1835             status = STATUS_INSUFFICIENT_RESOURCES;
1836             _SEH2_LEAVE;
1837         }
1838         de->d_inode = Inode;
1839 
1840         rc = ext3_add_entry(IrpContext, de, Inode);
1841         status = Ext2WinntError(rc);
1842         if (NT_SUCCESS(status)) {
1843 
1844             /* increase dir inode's nlink for .. */
1845             if (S_ISDIR(Inode->i_mode)) {
1846                 ext3_inc_count(Dcb->Inode);
1847                 ext3_mark_inode_dirty(IrpContext, Dcb->Inode);
1848             }
1849 
1850             /* increase inode nlink reference */
1851             ext3_inc_count(Inode);
1852             ext3_mark_inode_dirty(IrpContext, Inode);
1853 
1854             if (Dentry) {
1855                 *Dentry = de;
1856                 de = NULL;
1857             }
1858         }
1859 
1860     } _SEH2_FINALLY {
1861 
1862         Ext2DerefXcb(&Dcb->ReferenceCount);
1863 
1864         if (MainResourceAcquired)    {
1865             ExReleaseResourceLite(&Dcb->MainResource);
1866         }
1867 
1868         if (de)
1869             Ext2FreeEntry(de);
1870     } _SEH2_END;
1871 
1872     return status;
1873 }
1874 
1875 
1876 NTSTATUS
1877 Ext2SetFileType (
1878     IN PEXT2_IRP_CONTEXT    IrpContext,
1879     IN PEXT2_VCB            Vcb,
1880     IN PEXT2_FCB            Dcb,
1881     IN PEXT2_MCB            Mcb,
1882     IN umode_t              mode
1883     )
1884 {
1885     struct inode *dir = Dcb->Inode;
1886     struct buffer_head *bh = NULL;
1887     struct ext3_dir_entry_2 *de;
1888     struct inode *inode;
1889     NTSTATUS Status = STATUS_UNSUCCESSFUL;
1890     BOOLEAN  MainResourceAcquired = FALSE;
1891 
1892     if (!EXT3_HAS_INCOMPAT_FEATURE(dir->i_sb, EXT3_FEATURE_INCOMPAT_FILETYPE)) {
1893         return STATUS_SUCCESS;
1894     }
1895 
1896     if (!IsDirectory(Dcb)) {
1897         return STATUS_NOT_A_DIRECTORY;
1898     }
1899 
1900     ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);
1901     MainResourceAcquired = TRUE;
1902 
1903     _SEH2_TRY {
1904 
1905         Ext2ReferXcb(&Dcb->ReferenceCount);
1906 
1907         bh = ext3_find_entry(IrpContext, Mcb->de, &de);
1908         if (!bh)
1909             _SEH2_LEAVE;
1910 
1911         inode = &Mcb->Inode;
1912         if (le32_to_cpu(de->inode) != inode->i_ino)
1913             _SEH2_LEAVE;
1914 
1915         ext3_set_de_type(inode->i_sb, de, mode);
1916         mark_buffer_dirty(bh);
1917 
1918         if (S_ISDIR(inode->i_mode) == S_ISDIR(mode)) {
1919         } else if (S_ISDIR(inode->i_mode)) {
1920             ext3_dec_count(dir);
1921         } else if (S_ISDIR(mode)) {
1922             ext3_inc_count(dir);
1923         }
1924         dir->i_ctime = dir->i_mtime = ext3_current_time(dir);
1925         ext3_mark_inode_dirty(IrpContext, dir);
1926 
1927         inode->i_mode = mode;
1928         ext3_mark_inode_dirty(IrpContext, inode);
1929 
1930         Status = STATUS_SUCCESS;
1931 
1932     } _SEH2_FINALLY {
1933 
1934         Ext2DerefXcb(&Dcb->ReferenceCount);
1935 
1936         if (MainResourceAcquired)
1937             ExReleaseResourceLite(&Dcb->MainResource);
1938 
1939         if (bh)
1940             brelse(bh);
1941     } _SEH2_END;
1942 
1943     return Status;
1944 }
1945 
1946 NTSTATUS
1947 Ext2RemoveEntry (
1948     IN PEXT2_IRP_CONTEXT    IrpContext,
1949     IN PEXT2_VCB            Vcb,
1950     IN PEXT2_FCB            Dcb,
1951     IN PEXT2_MCB            Mcb
1952 )
1953 {
1954     struct inode *dir = Dcb->Inode;
1955     struct buffer_head *bh = NULL;
1956     struct ext3_dir_entry_2 *de;
1957     struct inode *inode;
1958     int rc = -ENOENT;
1959     NTSTATUS Status = STATUS_UNSUCCESSFUL;
1960     BOOLEAN  MainResourceAcquired = FALSE;
1961 
1962     if (!IsDirectory(Dcb)) {
1963         return STATUS_NOT_A_DIRECTORY;
1964     }
1965 
1966     ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);
1967     MainResourceAcquired = TRUE;
1968 
1969     _SEH2_TRY {
1970 
1971         Ext2ReferXcb(&Dcb->ReferenceCount);
1972 
1973         bh = ext3_find_entry(IrpContext, Mcb->de, &de);
1974         if (!bh)
1975             _SEH2_LEAVE;
1976 
1977         inode = &Mcb->Inode;
1978         if (le32_to_cpu(de->inode) != inode->i_ino)
1979             _SEH2_LEAVE;
1980 
1981         if (!inode->i_nlink) {
1982             ext3_warning (inode->i_sb, "ext3_unlink",
1983                           "Deleting nonexistent file (%lu), %d",
1984                           inode->i_ino, inode->i_nlink);
1985             inode->i_nlink = 1;
1986         }
1987         rc = ext3_delete_entry(IrpContext, dir, de, bh);
1988         if (rc) {
1989             Status = Ext2WinntError(rc);
1990             _SEH2_LEAVE;
1991         }
1992         /*
1993         	    if (!inode->i_nlink)
1994         		    ext3_orphan_add(handle, inode);
1995         */
1996         inode->i_ctime = dir->i_ctime = dir->i_mtime = ext3_current_time(dir);
1997         ext3_dec_count(inode);
1998         ext3_mark_inode_dirty(IrpContext, inode);
1999 
2000         /* decrease dir inode's nlink for .. */
2001         if (S_ISDIR(inode->i_mode)) {
2002             ext3_update_dx_flag(dir);
2003             ext3_dec_count(dir);
2004             ext3_mark_inode_dirty(IrpContext, dir);
2005         }
2006 
2007         Status = STATUS_SUCCESS;
2008 
2009     } _SEH2_FINALLY {
2010 
2011         Ext2DerefXcb(&Dcb->ReferenceCount);
2012 
2013         if (MainResourceAcquired)
2014             ExReleaseResourceLite(&Dcb->MainResource);
2015 
2016         if (bh)
2017             brelse(bh);
2018     } _SEH2_END;
2019 
2020     return Status;
2021 }
2022 
2023 NTSTATUS
2024 Ext2SetParentEntry (
2025     IN PEXT2_IRP_CONTEXT   IrpContext,
2026     IN PEXT2_VCB           Vcb,
2027     IN PEXT2_FCB           Dcb,
2028     IN ULONG               OldParent,
2029     IN ULONG               NewParent )
2030 {
2031     NTSTATUS                Status = STATUS_UNSUCCESSFUL;
2032 
2033     PEXT2_DIR_ENTRY2        pSelf   = NULL;
2034     PEXT2_DIR_ENTRY2        pParent = NULL;
2035 
2036     ULONG                   dwBytes = 0;
2037 
2038     BOOLEAN                 MainResourceAcquired = FALSE;
2039 
2040     ULONG                   Offset = 0;
2041 
2042     if (!IsDirectory(Dcb)) {
2043         return STATUS_NOT_A_DIRECTORY;
2044     }
2045 
2046     if (OldParent == NewParent) {
2047         return STATUS_SUCCESS;
2048     }
2049 
2050     MainResourceAcquired =
2051         ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);
2052 
2053     _SEH2_TRY {
2054 
2055         Ext2ReferXcb(&Dcb->ReferenceCount);
2056 
2057         pSelf = (PEXT2_DIR_ENTRY2)
2058                 Ext2AllocatePool(
2059                     PagedPool,
2060                     EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2),
2061                     EXT2_DENTRY_MAGIC
2062                 );
2063         if (!pSelf) {
2064             DEBUG(DL_ERR, ( "Ex2SetParentEntry: failed to allocate pSelf.\n"));
2065             Status = STATUS_INSUFFICIENT_RESOURCES;
2066             _SEH2_LEAVE;
2067         }
2068 
2069         dwBytes = 0;
2070 
2071         //
2072         // Reading the DCB contents
2073         //
2074 
2075         Status = Ext2ReadInode(
2076                      IrpContext,
2077                      Vcb,
2078                      Dcb->Mcb,
2079                      (ULONGLONG)Offset,
2080                      (PVOID)pSelf,
2081                      EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2),
2082                      FALSE,
2083                      &dwBytes );
2084 
2085         if (!NT_SUCCESS(Status)) {
2086             DEBUG(DL_ERR, ( "Ext2SetParentEntry: failed to read directory.\n"));
2087             _SEH2_LEAVE;
2088         }
2089 
2090         ASSERT(dwBytes == EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2));
2091 
2092         pParent = (PEXT2_DIR_ENTRY2)((PUCHAR)pSelf + pSelf->rec_len);
2093 
2094         if (pSelf->name_len == 1 && pSelf->name[0] == '.' &&
2095                 pParent->name_len == 2 && pParent->name[0] == '.' &&
2096                 pParent->name[1] == '.') {
2097 
2098             if (pParent->inode != OldParent) {
2099                 DbgBreak();
2100             }
2101             pParent->inode = NewParent;
2102 
2103             Status = Ext2WriteInode(
2104                          IrpContext,
2105                          Vcb,
2106                          Dcb->Mcb,
2107                          (ULONGLONG)Offset,
2108                          pSelf,
2109                          dwBytes,
2110                          FALSE,
2111                          &dwBytes );
2112         } else {
2113             DbgBreak();
2114         }
2115 
2116     } _SEH2_FINALLY {
2117 
2118 
2119         if (Ext2DerefXcb(&Dcb->ReferenceCount) == 0) {
2120             DEBUG(DL_ERR, ( "Ext2SetParentEntry: Dcb reference goes to ZERO.\n"));
2121         }
2122 
2123         if (MainResourceAcquired)    {
2124             ExReleaseResourceLite(&Dcb->MainResource);
2125         }
2126 
2127         if (pSelf) {
2128             Ext2FreePool(pSelf, EXT2_DENTRY_MAGIC);
2129         }
2130     } _SEH2_END;
2131 
2132     return Status;
2133 }
2134 
2135 int ext3_check_dir_entry (const char * function, struct inode * dir,
2136                           struct ext3_dir_entry_2 * de,
2137                           struct buffer_head * bh,
2138                           unsigned long offset)
2139 {
2140     const char * error_msg = NULL;
2141     const int rlen = ext3_rec_len_from_disk(de->rec_len);
2142 
2143     if (rlen < EXT3_DIR_REC_LEN(1))
2144         error_msg = "rec_len is smaller than minimal";
2145     else if (rlen % 4 != 0)
2146         error_msg = "rec_len % 4 != 0";
2147     else if (rlen < EXT3_DIR_REC_LEN(de->name_len))
2148         error_msg = "rec_len is too small for name_len";
2149     else if ((char *) de + rlen > bh->b_data + dir->i_sb->s_blocksize)
2150         error_msg = "directory entry across blocks";
2151     else if (le32_to_cpu(de->inode) >
2152              le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count))
2153         error_msg = "inode out of bounds";
2154 
2155     if (error_msg != NULL) {
2156         DEBUG(DL_ERR, ("%s: bad entry in directory %u: %s - "
2157                        "offset=%u, inode=%u, rec_len=%d, name_len=%d\n",
2158                        function, dir->i_ino, error_msg, offset,
2159                        (unsigned long) le32_to_cpu(de->inode),
2160                        rlen, de->name_len));
2161     }
2162     return error_msg == NULL ? 1 : 0;
2163 }
2164 
2165 
2166 /*
2167  * p is at least 6 bytes before the end of page
2168  */
2169 struct ext3_dir_entry_2 *
2170             ext3_next_entry(struct ext3_dir_entry_2 *p)
2171 {
2172     return (struct ext3_dir_entry_2 *)((char *)p +
2173                                        ext3_rec_len_from_disk(p->rec_len));
2174 }
2175 
2176 #define MAX_LFS_FILESIZE 	0x7fffffffffffffff
2177 
2178 /*
2179  * Maximal extent format file size.
2180  * Resulting logical blkno at s_maxbytes must fit in our on-disk
2181  * extent format containers, within a sector_t, and within i_blocks
2182  * in the vfs.  ext4 inode has 48 bits of i_block in fsblock units,
2183  * so that won't be a limiting factor.
2184  *
2185  * Note, this does *not* consider any metadata overhead for vfs i_blocks.
2186  */
2187 static loff_t ext4_max_size(int blkbits, int has_huge_files)
2188 {
2189     loff_t res;
2190     loff_t upper_limit = MAX_LFS_FILESIZE;
2191 
2192     /* small i_blocks in vfs inode? */
2193     if (!has_huge_files || sizeof(blkcnt_t) < sizeof(u64)) {
2194         /*
2195          * CONFIG_LBD is not enabled implies the inode
2196          * i_block represent total blocks in 512 bytes
2197          * 32 == size of vfs inode i_blocks * 8
2198          */
2199         upper_limit = (1LL << 32) - 1;
2200 
2201         /* total blocks in file system block size */
2202         upper_limit >>= (blkbits - 9);
2203         upper_limit <<= blkbits;
2204     }
2205 
2206     /* 32-bit extent-start container, ee_block */
2207     res = 1LL << 32;
2208     res <<= blkbits;
2209     res -= 1;
2210 
2211     /* Sanity check against vm- & vfs- imposed limits */
2212     if (res > upper_limit)
2213         res = upper_limit;
2214 
2215     return res;
2216 }
2217 
2218 /*
2219  * Maximal extent format file size.
2220  * Resulting logical blkno at s_maxbytes must fit in our on-disk
2221  * extent format containers, within a sector_t, and within i_blocks
2222  * in the vfs.  ext4 inode has 48 bits of i_block in fsblock units,
2223  * so that won't be a limiting factor.
2224  *
2225  * Note, this does *not* consider any metadata overhead for vfs i_blocks.
2226  */
2227 loff_t ext3_max_size(int blkbits, int has_huge_files)
2228 {
2229     loff_t res;
2230     loff_t upper_limit = MAX_LFS_FILESIZE;
2231 
2232     /* small i_blocks in vfs inode? */
2233     if (!has_huge_files) {
2234         /*
2235          * CONFIG_LBD is not enabled implies the inode
2236          * i_block represent total blocks in 512 bytes
2237          * 32 == size of vfs inode i_blocks * 8
2238          */
2239         upper_limit = ((loff_t)1 << 32) - 1;
2240 
2241         /* total blocks in file system block size */
2242         upper_limit >>= (blkbits - 9);
2243         upper_limit <<= blkbits;
2244     }
2245 
2246     /* 32-bit extent-start container, ee_block */
2247     res = (loff_t)1 << 32;
2248     res <<= blkbits;
2249     res -= 1;
2250 
2251     /* Sanity check against vm- & vfs- imposed limits */
2252     if (res > upper_limit)
2253         res = upper_limit;
2254 
2255     return res;
2256 }
2257 
2258 /*
2259  * Maximal bitmap file size.  There is a direct, and {,double-,triple-}indirect
2260  * block limit, and also a limit of (2^48 - 1) 512-byte sectors in i_blocks.
2261  * We need to be 1 filesystem block less than the 2^48 sector limit.
2262  */
2263 loff_t ext3_max_bitmap_size(int bits, int has_huge_files)
2264 {
2265     loff_t res = EXT3_NDIR_BLOCKS;
2266     int meta_blocks;
2267     loff_t upper_limit;
2268     /* This is calculated to be the largest file size for a
2269      * dense, bitmapped file such that the total number of
2270      * sectors in the file, including data and all indirect blocks,
2271      * does not exceed 2^48 -1
2272      * __u32 i_blocks_lo and _u16 i_blocks_high representing the
2273      * total number of  512 bytes blocks of the file
2274      */
2275 
2276     if (!has_huge_files) {
2277         /*
2278          * !has_huge_files or CONFIG_LBD is not enabled
2279          * implies the inode i_block represent total blocks in
2280          * 512 bytes 32 == size of vfs inode i_blocks * 8
2281          */
2282         upper_limit = ((loff_t)1 << 32) - 1;
2283 
2284         /* total blocks in file system block size */
2285         upper_limit >>= (bits - 9);
2286 
2287     } else {
2288         /*
2289          * We use 48 bit ext4_inode i_blocks
2290          * With EXT4_HUGE_FILE_FL set the i_blocks
2291          * represent total number of blocks in
2292          * file system block size
2293          */
2294         upper_limit = ((loff_t)1 << 48) - 1;
2295 
2296     }
2297 
2298     /* indirect blocks */
2299     meta_blocks = 1;
2300     /* double indirect blocks */
2301     meta_blocks += 1 + ((loff_t)1 << (bits-2));
2302     /* tripple indirect blocks */
2303     meta_blocks += 1 + ((loff_t)1 << (bits-2)) + ((loff_t)1 << (2*(bits-2)));
2304 
2305     upper_limit -= meta_blocks;
2306     upper_limit <<= bits;
2307 
2308     res += (loff_t)1 << (bits-2);
2309     res += (loff_t)1 << (2*(bits-2));
2310     res += (loff_t)1 << (3*(bits-2));
2311     res <<= bits;
2312     if (res > upper_limit)
2313         res = upper_limit;
2314 
2315     if (res > MAX_LFS_FILESIZE)
2316         res = MAX_LFS_FILESIZE;
2317 
2318     return res;
2319 }
2320 
2321 blkcnt_t ext3_inode_blocks(struct ext3_inode *raw_inode,
2322                            struct inode *inode)
2323 {
2324     blkcnt_t i_blocks ;
2325     struct super_block *sb = inode->i_sb;
2326     PEXT2_VCB Vcb = (PEXT2_VCB)sb->s_priv;
2327 
2328     if (EXT3_HAS_RO_COMPAT_FEATURE(sb,
2329                                    EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
2330         /* we are using combined 48 bit field */
2331         i_blocks = ((u64)le16_to_cpu(raw_inode->i_blocks_high)) << 32 |
2332                    le32_to_cpu(raw_inode->i_blocks);
2333         if (inode->i_flags & EXT4_HUGE_FILE_FL) {
2334             /* i_blocks represent file system block size */
2335             return i_blocks  << (BLOCK_BITS - 9);
2336         } else {
2337             return i_blocks;
2338         }
2339     } else {
2340         return le32_to_cpu(raw_inode->i_blocks);
2341     }
2342 }
2343 
2344 int ext3_inode_blocks_set(struct ext3_inode *raw_inode,
2345                           struct inode * inode)
2346 {
2347     u64 i_blocks = inode->i_blocks;
2348     struct super_block *sb = inode->i_sb;
2349     PEXT2_VCB Vcb = (PEXT2_VCB)sb->s_priv;
2350 
2351     if (i_blocks < 0x100000000) {
2352         /*
2353          * i_blocks can be represnted in a 32 bit variable
2354          * as multiple of 512 bytes
2355          */
2356         raw_inode->i_blocks = cpu_to_le32(i_blocks);
2357         raw_inode->i_blocks_high = 0;
2358         inode->i_flags &= ~EXT4_HUGE_FILE_FL;
2359         return 0;
2360     }
2361 
2362     if (!EXT3_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
2363         EXT3_SET_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
2364         Ext2SaveSuper(NULL, Vcb);
2365     }
2366 
2367     if (i_blocks <= 0xffffffffffff) {
2368         /*
2369          * i_blocks can be represented in a 48 bit variable
2370          * as multiple of 512 bytes
2371          */
2372         raw_inode->i_blocks = (__u32)cpu_to_le32(i_blocks);
2373         raw_inode->i_blocks_high = (__u16)cpu_to_le16(i_blocks >> 32);
2374         inode->i_flags &= ~EXT4_HUGE_FILE_FL;
2375     } else {
2376         inode->i_flags |= EXT4_HUGE_FILE_FL;
2377         /* i_block is stored in file system block size */
2378         i_blocks = i_blocks >> (BLOCK_BITS - 9);
2379         raw_inode->i_blocks  = (__u32)cpu_to_le32(i_blocks);
2380         raw_inode->i_blocks_high = (__u16)cpu_to_le16(i_blocks >> 32);
2381     }
2382     return 0;
2383 }
2384 
2385 ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
2386                                struct ext4_group_desc *bg)
2387 {
2388     return le32_to_cpu(bg->bg_block_bitmap) |
2389            (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
2390             (ext4_fsblk_t)le32_to_cpu(bg->bg_block_bitmap_hi) << 32 : 0);
2391 }
2392 
2393 ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,
2394                                struct ext4_group_desc *bg)
2395 {
2396     return le32_to_cpu(bg->bg_inode_bitmap) |
2397            (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
2398             (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_bitmap_hi) << 32 : 0);
2399 }
2400 
2401 ext4_fsblk_t ext4_inode_table(struct super_block *sb,
2402                               struct ext4_group_desc *bg)
2403 {
2404     return le32_to_cpu(bg->bg_inode_table) |
2405            (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
2406             (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0);
2407 }
2408 
2409 __u32 ext4_free_blks_count(struct super_block *sb,
2410                            struct ext4_group_desc *bg)
2411 {
2412     return le16_to_cpu(bg->bg_free_blocks_count) |
2413            (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
2414             (__u32)le16_to_cpu(bg->bg_free_blocks_count_hi) << 16 : 0);
2415 }
2416 
2417 __u32 ext4_free_inodes_count(struct super_block *sb,
2418                              struct ext4_group_desc *bg)
2419 {
2420     return le16_to_cpu(bg->bg_free_inodes_count) |
2421            (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
2422             (__u32)le16_to_cpu(bg->bg_free_inodes_count_hi) << 16 : 0);
2423 }
2424 
2425 __u32 ext4_used_dirs_count(struct super_block *sb,
2426                            struct ext4_group_desc *bg)
2427 {
2428     return le16_to_cpu(bg->bg_used_dirs_count) |
2429            (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
2430             (__u32)le16_to_cpu(bg->bg_used_dirs_count_hi) << 16 : 0);
2431 }
2432 
2433 __u32 ext4_itable_unused_count(struct super_block *sb,
2434                                struct ext4_group_desc *bg)
2435 {
2436     return le16_to_cpu(bg->bg_itable_unused) |
2437            (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
2438             (__u32)le16_to_cpu(bg->bg_itable_unused_hi) << 16 : 0);
2439 }
2440 
2441 void ext4_block_bitmap_set(struct super_block *sb,
2442                            struct ext4_group_desc *bg, ext4_fsblk_t blk)
2443 {
2444     bg->bg_block_bitmap = cpu_to_le32((u32)blk);
2445     if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
2446         bg->bg_block_bitmap_hi = cpu_to_le32(blk >> 32);
2447 }
2448 
2449 void ext4_inode_bitmap_set(struct super_block *sb,
2450                            struct ext4_group_desc *bg, ext4_fsblk_t blk)
2451 {
2452     bg->bg_inode_bitmap  = cpu_to_le32((u32)blk);
2453     if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
2454         bg->bg_inode_bitmap_hi = cpu_to_le32(blk >> 32);
2455 }
2456 
2457 void ext4_inode_table_set(struct super_block *sb,
2458                           struct ext4_group_desc *bg, ext4_fsblk_t blk)
2459 {
2460     bg->bg_inode_table = cpu_to_le32((u32)blk);
2461     if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
2462         bg->bg_inode_table_hi = cpu_to_le32(blk >> 32);
2463 }
2464 
2465 void ext4_free_blks_set(struct super_block *sb,
2466                         struct ext4_group_desc *bg, __u32 count)
2467 {
2468     bg->bg_free_blocks_count = cpu_to_le16((__u16)count);
2469     if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
2470         bg->bg_free_blocks_count_hi = cpu_to_le16(count >> 16);
2471 }
2472 
2473 void ext4_free_inodes_set(struct super_block *sb,
2474                           struct ext4_group_desc *bg, __u32 count)
2475 {
2476     bg->bg_free_inodes_count = cpu_to_le16((__u16)count);
2477     if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
2478         bg->bg_free_inodes_count_hi = cpu_to_le16(count >> 16);
2479 }
2480 
2481 void ext4_used_dirs_set(struct super_block *sb,
2482                         struct ext4_group_desc *bg, __u32 count)
2483 {
2484     bg->bg_used_dirs_count = cpu_to_le16((__u16)count);
2485     if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
2486         bg->bg_used_dirs_count_hi = cpu_to_le16(count >> 16);
2487 }
2488 
2489 void ext4_itable_unused_set(struct super_block *sb,
2490                             struct ext4_group_desc *bg, __u32 count)
2491 {
2492     bg->bg_itable_unused = cpu_to_le16((__u16)count);
2493     if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
2494         bg->bg_itable_unused_hi = cpu_to_le16(count >> 16);
2495 }
2496 
2497 /** CRC table for the CRC-16. The poly is 0x8005 (x16 + x15 + x2 + 1) */
2498 __u16 const crc16_table[256] = {
2499     0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
2500     0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
2501     0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
2502     0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
2503     0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
2504     0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
2505     0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
2506     0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
2507     0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
2508     0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
2509     0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
2510     0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
2511     0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
2512     0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
2513     0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
2514     0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
2515     0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
2516     0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
2517     0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
2518     0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
2519     0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
2520     0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
2521     0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
2522     0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
2523     0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
2524     0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
2525     0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
2526     0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
2527     0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
2528     0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
2529     0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
2530     0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
2531 };
2532 
2533 static inline __u16 crc16_byte(__u16 crc, const __u8 data)
2534 {
2535     return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff];
2536 }
2537 
2538 __u16 crc16(__u16 crc, __u8 const *buffer, size_t len)
2539 {
2540     while (len--)
2541         crc = crc16_byte(crc, *buffer++);
2542     return crc;
2543 }
2544 
2545 __le16 ext4_group_desc_csum(struct ext3_sb_info *sbi, __u32 block_group,
2546                             struct ext4_group_desc *gdp)
2547 {
2548 	int offset;
2549 	__u16 crc = 0;
2550 	__le32 le_group = cpu_to_le32(block_group);
2551 
2552 	/* old crc16 code */
2553 	if (!(sbi->s_es->s_feature_ro_compat &
2554 	      cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM)))
2555 		return 0;
2556 
2557 	offset = offsetof(struct ext4_group_desc, bg_checksum);
2558 
2559 	crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid));
2560 	crc = crc16(crc, (__u8 *)&le_group, sizeof(le_group));
2561 	crc = crc16(crc, (__u8 *)gdp, offset);
2562 	offset += sizeof(gdp->bg_checksum); /* skip checksum */
2563 	/* for checksum of struct ext4_group_desc do the rest...*/
2564 	if ((sbi->s_es->s_feature_incompat &
2565 	     cpu_to_le32(EXT4_FEATURE_INCOMPAT_64BIT)) &&
2566 	    offset < le16_to_cpu(sbi->s_es->s_desc_size))
2567 		crc = crc16(crc, (__u8 *)gdp + offset,
2568 			    le16_to_cpu(sbi->s_es->s_desc_size) -
2569 				offset);
2570 
2571 	return cpu_to_le16(crc);
2572 }
2573 
2574 int ext4_group_desc_csum_verify(struct ext3_sb_info *sbi, __u32 block_group,
2575                                 struct ext4_group_desc *gdp)
2576 {
2577     if ((sbi->s_es->s_feature_ro_compat & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) &&
2578         (gdp->bg_checksum != ext4_group_desc_csum(sbi, block_group, gdp)))
2579         return 0;
2580 
2581     return 1;
2582 }
2583 
2584 
2585 static inline int test_root(ext3_group_t a, ext3_group_t b)
2586 {
2587     ext3_group_t num = b;
2588 
2589     while (a > num)
2590         num *= b;
2591     return num == a;
2592 }
2593 
2594 static int ext3_group_sparse(ext3_group_t group)
2595 {
2596     if (group <= 1)
2597         return 1;
2598     if (!(group & 1))
2599         return 0;
2600     return (test_root(group, 7) || test_root(group, 5) ||
2601             test_root(group, 3));
2602 }
2603 
2604 /**
2605  *	ext4_bg_has_super - number of blocks used by the superblock in group
2606  *	@sb: superblock for filesystem
2607  *	@group: group number to check
2608  *
2609  *	Return the number of blocks used by the superblock (primary or backup)
2610  *	in this group.  Currently this will be only 0 or 1.
2611  */
2612 int ext3_bg_has_super(struct super_block *sb, ext3_group_t group)
2613 {
2614     if (EXT3_HAS_RO_COMPAT_FEATURE(sb,
2615                                    EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER) &&
2616             !ext3_group_sparse(group))
2617         return 0;
2618     return 1;
2619 }
2620 
2621 static unsigned long ext4_bg_num_gdb_meta(struct super_block *sb,
2622         ext4_group_t group)
2623 {
2624     unsigned long metagroup = group / EXT4_DESC_PER_BLOCK(sb);
2625     ext4_group_t first = metagroup * EXT4_DESC_PER_BLOCK(sb);
2626     ext4_group_t last = first + EXT4_DESC_PER_BLOCK(sb) - 1;
2627 
2628     if (group == first || group == first + 1 || group == last)
2629         return 1;
2630     return 0;
2631 }
2632 
2633 static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb,
2634         ext4_group_t group)
2635 {
2636     return ext3_bg_has_super(sb, group) ? EXT3_SB(sb)->s_gdb_count : 0;
2637 }
2638 
2639 /**
2640  *	ext4_bg_num_gdb - number of blocks used by the group table in group
2641  *	@sb: superblock for filesystem
2642  *	@group: group number to check
2643  *
2644  *	Return the number of blocks used by the group descriptor table
2645  *	(primary or backup) in this group.  In the future there may be a
2646  *	different number of descriptor blocks in each group.
2647  */
2648 unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group)
2649 {
2650     unsigned long first_meta_bg =
2651         le32_to_cpu(EXT3_SB(sb)->s_es->s_first_meta_bg);
2652     unsigned long metagroup = group / EXT4_DESC_PER_BLOCK(sb);
2653 
2654     if (!EXT3_HAS_INCOMPAT_FEATURE(sb,EXT4_FEATURE_INCOMPAT_META_BG) ||
2655             metagroup < first_meta_bg)
2656         return ext4_bg_num_gdb_nometa(sb, group);
2657 
2658     return ext4_bg_num_gdb_meta(sb,group);
2659 
2660 }
2661 
2662 ext3_fsblk_t descriptor_loc(struct super_block *sb,
2663                             ext3_fsblk_t logical_sb_block, unsigned int nr)
2664 {
2665     struct ext3_sb_info *sbi = EXT3_SB(sb);
2666     ext3_group_t bg, first_meta_bg;
2667     int has_super = 0;
2668 
2669     first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg);
2670 
2671     if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) ||
2672             nr < first_meta_bg)
2673         return logical_sb_block + nr + 1;
2674     bg = sbi->s_desc_per_block * nr;
2675     if (ext3_bg_has_super(sb, bg))
2676         has_super = 1;
2677     return (has_super + ext3_group_first_block_no(sb, bg));
2678 }
2679 
2680 #define ext4_set_bit(n, p) set_bit((int)(n), (unsigned long *)(p))
2681 
2682 /*
2683  * The free inodes are managed by bitmaps.  A file system contains several
2684  * blocks groups.  Each group contains 1 bitmap block for blocks, 1 bitmap
2685  * block for inodes, N blocks for the inode table and data blocks.
2686  *
2687  * The file system contains group descriptors which are located after the
2688  * super block.  Each descriptor contains the number of the bitmap block and
2689  * the free blocks count in the block.
2690  */
2691 
2692 /*
2693  * To avoid calling the atomic setbit hundreds or thousands of times, we only
2694  * need to use it within a single byte (to ensure we get endianness right).
2695  * We can use memset for the rest of the bitmap as there are no other users.
2696  */
2697 void mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
2698 {
2699     int i;
2700 
2701     if (start_bit >= end_bit)
2702         return;
2703 
2704     DEBUG(DL_INF, ("mark end bits +%d through +%d used\n", start_bit, end_bit));
2705     for (i = start_bit; (unsigned)i < ((start_bit + 7) & ~7UL); i++)
2706         ext4_set_bit(i, bitmap);
2707     if (i < end_bit)
2708         memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3);
2709 }
2710 
2711 /* Initializes an uninitialized inode bitmap */
2712 unsigned ext4_init_inode_bitmap(struct super_block *sb, struct buffer_head *bh,
2713                                 ext4_group_t block_group,
2714                                 struct ext4_group_desc *gdp)
2715 {
2716     struct ext3_sb_info *sbi = EXT3_SB(sb);
2717 
2718     mark_buffer_dirty(bh);
2719 
2720     /* If checksum is bad mark all blocks and inodes use to prevent
2721      * allocation, essentially implementing a per-group read-only flag. */
2722     if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
2723         ext4_error(sb, __FUNCTION__, "Checksum bad for group %u",
2724                    block_group);
2725         ext4_free_blks_set(sb, gdp, 0);
2726         ext4_free_inodes_set(sb, gdp, 0);
2727         ext4_itable_unused_set(sb, gdp, 0);
2728         memset(bh->b_data, 0xff, sb->s_blocksize);
2729         return 0;
2730     }
2731 
2732     memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8);
2733     mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8,
2734                     bh->b_data);
2735     ext4_itable_unused_set(sb, gdp, EXT4_INODES_PER_GROUP(sb));
2736 
2737     return EXT4_INODES_PER_GROUP(sb);
2738 }
2739 
2740 /*
2741  * Calculate the block group number and offset, given a block number
2742  */
2743 void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
2744                                   ext4_group_t *blockgrpp, ext4_grpblk_t *offsetp)
2745 {
2746     struct ext3_super_block *es = EXT3_SB(sb)->s_es;
2747     ext4_grpblk_t offset;
2748 
2749     blocknr = blocknr - le32_to_cpu(es->s_first_data_block);
2750     offset = do_div(blocknr, EXT4_BLOCKS_PER_GROUP(sb));
2751     if (offsetp)
2752         *offsetp = offset;
2753     if (blockgrpp)
2754         *blockgrpp = (ext4_grpblk_t)blocknr;
2755 
2756 }
2757 
2758 static int ext4_block_in_group(struct super_block *sb, ext4_fsblk_t block,
2759                                ext4_group_t block_group)
2760 {
2761     ext4_group_t actual_group;
2762     ext4_get_group_no_and_offset(sb, block, &actual_group, NULL);
2763     if (actual_group == block_group)
2764         return 1;
2765     return 0;
2766 }
2767 
2768 static int ext4_group_used_meta_blocks(struct super_block *sb,
2769                                        ext4_group_t block_group)
2770 {
2771     ext4_fsblk_t tmp;
2772     struct ext3_sb_info *sbi = EXT3_SB(sb);
2773     /* block bitmap, inode bitmap, and inode table blocks */
2774     int used_blocks = sbi->s_itb_per_group + 2;
2775 
2776     if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
2777         struct ext4_group_desc *gdp;
2778         struct buffer_head *bh = NULL;
2779 
2780         gdp = ext4_get_group_desc(sb, block_group, &bh);
2781         if (!ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp),
2782                                  block_group))
2783             used_blocks--;
2784 
2785         if (!ext4_block_in_group(sb, ext4_inode_bitmap(sb, gdp),
2786                                  block_group))
2787             used_blocks--;
2788 
2789         tmp = ext4_inode_table(sb, gdp);
2790         for (; tmp < ext4_inode_table(sb, gdp) +
2791                 sbi->s_itb_per_group; tmp++) {
2792             if (!ext4_block_in_group(sb, tmp, block_group))
2793                 used_blocks -= 1;
2794         }
2795         if (bh)
2796             fini_bh(&bh);
2797     }
2798     return used_blocks;
2799 }
2800 
2801 /* Initializes an uninitialized block bitmap if given, and returns the
2802  * number of blocks free in the group. */
2803 unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
2804                                 ext4_group_t block_group, struct ext4_group_desc *gdp)
2805 {
2806     int bit, bit_max;
2807     unsigned free_blocks, group_blocks;
2808     struct ext3_sb_info *sbi = EXT3_SB(sb);
2809 
2810     if (bh) {
2811         mark_buffer_dirty(bh);
2812         /* If checksum is bad mark all blocks used to prevent allocation
2813          * essentially implementing a per-group read-only flag. */
2814         if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
2815             ext4_error(sb, __FUNCTION__,
2816                        "Checksum bad for group %u", block_group);
2817             ext4_free_blks_set(sb, gdp, 0);
2818             ext4_free_inodes_set(sb, gdp, 0);
2819             ext4_itable_unused_set(sb, gdp, 0);
2820             memset(bh->b_data, 0xff, sb->s_blocksize);
2821             return 0;
2822         }
2823         memset(bh->b_data, 0, sb->s_blocksize);
2824     }
2825 
2826     /* Check for superblock and gdt backups in this group */
2827     bit_max = ext3_bg_has_super(sb, block_group);
2828 
2829     if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) ||
2830             block_group < le32_to_cpu(sbi->s_es->s_first_meta_bg) *
2831             sbi->s_desc_per_block) {
2832         if (bit_max) {
2833             bit_max += ext4_bg_num_gdb(sb, block_group);
2834             bit_max +=
2835                 le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks);
2836         }
2837     } else { /* For META_BG_BLOCK_GROUPS */
2838         bit_max += ext4_bg_num_gdb(sb, block_group);
2839     }
2840 
2841     if (block_group == sbi->s_groups_count - 1) {
2842         /*
2843          * Even though mke2fs always initialize first and last group
2844          * if some other tool enabled the EXT4_BG_BLOCK_UNINIT we need
2845          * to make sure we calculate the right free blocks
2846          */
2847         group_blocks = (unsigned int)(ext3_blocks_count(sbi->s_es) -
2848                                       le32_to_cpu(sbi->s_es->s_first_data_block) -
2849                                       (EXT4_BLOCKS_PER_GROUP(sb) * (sbi->s_groups_count - 1)));
2850     } else {
2851         group_blocks = EXT4_BLOCKS_PER_GROUP(sb);
2852     }
2853 
2854     free_blocks = group_blocks - bit_max;
2855 
2856     if (bh) {
2857         ext4_fsblk_t start, tmp;
2858         int flex_bg = 0;
2859 
2860         for (bit = 0; bit < bit_max; bit++)
2861             ext4_set_bit(bit, bh->b_data);
2862 
2863         start = ext3_group_first_block_no(sb, block_group);
2864 
2865         if (EXT3_HAS_INCOMPAT_FEATURE(sb,
2866                                       EXT4_FEATURE_INCOMPAT_FLEX_BG))
2867             flex_bg = 1;
2868 
2869         /* Set bits for block and inode bitmaps, and inode table */
2870         tmp = ext4_block_bitmap(sb, gdp);
2871         if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
2872             ext4_set_bit(tmp - start, bh->b_data);
2873 
2874         tmp = ext4_inode_bitmap(sb, gdp);
2875         if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
2876             ext4_set_bit(tmp - start, bh->b_data);
2877 
2878         tmp = ext4_inode_table(sb, gdp);
2879         for (; tmp < ext4_inode_table(sb, gdp) +
2880                 sbi->s_itb_per_group; tmp++) {
2881             if (!flex_bg ||
2882                     ext4_block_in_group(sb, tmp, block_group))
2883                 ext4_set_bit(tmp - start, bh->b_data);
2884         }
2885         /*
2886          * Also if the number of blocks within the group is
2887          * less than the blocksize * 8 ( which is the size
2888          * of bitmap ), set rest of the block bitmap to 1
2889          */
2890         mark_bitmap_end(group_blocks, sb->s_blocksize * 8, bh->b_data);
2891     }
2892     return free_blocks - ext4_group_used_meta_blocks(sb, block_group);
2893 }
2894 
2895 /**
2896  * ext4_get_group_desc() -- load group descriptor from disk
2897  * @sb:			super block
2898  * @block_group:	given block group
2899  * @bh:			pointer to the buffer head to store the block
2900  *			group descriptor
2901  */
2902 struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
2903                     ext4_group_t block_group, struct buffer_head **bh)
2904 {
2905     struct ext4_group_desc *desc = NULL;
2906     struct ext3_sb_info *sbi = EXT3_SB(sb);
2907     PEXT2_VCB vcb = sb->s_priv;
2908     ext4_group_t group;
2909     ext4_group_t offset;
2910 
2911     if (bh)
2912         *bh = NULL;
2913 
2914     if (block_group >= sbi->s_groups_count) {
2915         ext4_error(sb, "ext4_get_group_desc",
2916                    "block_group >= groups_count - "
2917                    "block_group = %u, groups_count = %u",
2918                    block_group, sbi->s_groups_count);
2919 
2920         return NULL;
2921     }
2922 
2923     _SEH2_TRY {
2924 
2925         group = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb);
2926         offset = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1);
2927 
2928         if (!sbi->s_gd) {
2929             if (!Ext2LoadGroup(vcb)) {
2930                 _SEH2_LEAVE;
2931             }
2932         } else if ( !sbi->s_gd[group].block ||
2933                     !sbi->s_gd[group].bh) {
2934             if (!Ext2LoadGroupBH(vcb)) {
2935                 _SEH2_LEAVE;
2936             }
2937         }
2938 
2939         desc = (struct ext4_group_desc *)((PCHAR)sbi->s_gd[group].gd +
2940                                           offset * EXT4_DESC_SIZE(sb));
2941         if (bh) {
2942             atomic_inc(&sbi->s_gd[group].bh->b_count);
2943             *bh = sbi->s_gd[group].bh;
2944         }
2945     } _SEH2_FINALLY {
2946         /* do cleanup */
2947     } _SEH2_END;
2948 
2949     return desc;
2950 }
2951 
2952 
2953 /**
2954  * ext4_count_free_blocks() -- count filesystem free blocks
2955  * @sb:		superblock
2956  *
2957  * Adds up the number of free blocks from each block group.
2958  */
2959 ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
2960 {
2961     ext4_fsblk_t desc_count;
2962     struct ext4_group_desc *gdp;
2963     struct buffer_head *bh = NULL;
2964     ext4_group_t i;
2965     ext4_group_t ngroups = EXT3_SB(sb)->s_groups_count;
2966 
2967     desc_count = 0;
2968     smp_rmb();
2969     for (i = 0; i < ngroups; i++) {
2970         gdp = ext4_get_group_desc(sb, i, &bh);
2971         if (!bh)
2972             continue;
2973         desc_count += ext4_free_blks_count(sb, gdp);
2974         fini_bh(&bh);
2975     }
2976 
2977     return desc_count;
2978 }
2979 
2980 unsigned long ext4_count_free_inodes(struct super_block *sb)
2981 {
2982     unsigned long desc_count;
2983     struct ext4_group_desc *gdp;
2984     struct buffer_head *bh = NULL;
2985     ext4_group_t i;
2986 
2987     desc_count = 0;
2988     for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) {
2989         gdp = ext4_get_group_desc(sb, i, &bh);
2990         if (!bh)
2991             continue;
2992         desc_count += ext4_free_inodes_count(sb, gdp);
2993         fini_bh(&bh);
2994     }
2995     return desc_count;
2996 }
2997 
2998 /* Called at mount-time, super-block is locked */
2999 unsigned long ext4_count_dirs(struct super_block * sb)
3000 {
3001     struct ext4_group_desc *gdp;
3002     struct buffer_head *bh = NULL;
3003     unsigned long count = 0;
3004     ext4_group_t i;
3005 
3006     for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) {
3007         gdp = ext4_get_group_desc(sb, i, &bh);
3008         if (!bh)
3009             continue;
3010         count += ext4_used_dirs_count(sb, gdp);
3011         fini_bh(&bh);
3012     }
3013     return count;
3014 }
3015 
3016 /* Called at mount-time, super-block is locked */
3017 int ext4_check_descriptors(struct super_block *sb)
3018 {
3019     PEXT2_VCB            Vcb = sb->s_priv;
3020     struct ext3_sb_info *sbi = EXT3_SB(sb);
3021     ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
3022     ext4_fsblk_t last_block;
3023     ext4_fsblk_t block_bitmap;
3024     ext4_fsblk_t inode_bitmap;
3025     ext4_fsblk_t inode_table;
3026     int flexbg_flag = 0;
3027     ext4_group_t i;
3028 
3029     if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
3030         flexbg_flag = 1;
3031 
3032     DEBUG(DL_INF, ("Checking group descriptors"));
3033 
3034     for (i = 0; i < sbi->s_groups_count; i++) {
3035 
3036         struct buffer_head *bh = NULL;
3037         struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, &bh);
3038 
3039         if (!bh)
3040             continue;
3041 
3042         if (i == sbi->s_groups_count - 1 || flexbg_flag)
3043             last_block = ext3_blocks_count(sbi->s_es) - 1;
3044         else
3045             last_block = first_block +
3046                          (EXT3_BLOCKS_PER_GROUP(sb) - 1);
3047 
3048         block_bitmap = ext4_block_bitmap(sb, gdp);
3049         if (block_bitmap < first_block || block_bitmap > last_block) {
3050             printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
3051                    "Block bitmap for group %u not in group "
3052                    "(block %llu)!\n", i, block_bitmap);
3053             __brelse(bh);
3054             return 0;
3055         }
3056         inode_bitmap = ext4_inode_bitmap(sb, gdp);
3057         if (inode_bitmap < first_block || inode_bitmap > last_block) {
3058             printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
3059                    "Inode bitmap for group %u not in group "
3060                    "(block %llu)!\n", i, inode_bitmap);
3061             __brelse(bh);
3062             return 0;
3063         }
3064         inode_table = ext4_inode_table(sb, gdp);
3065         if (inode_table < first_block ||
3066                 inode_table + sbi->s_itb_per_group - 1 > last_block) {
3067             printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
3068                    "Inode table for group %u not in group "
3069                    "(block %llu)!\n", i, inode_table);
3070             __brelse(bh);
3071             return 0;
3072         }
3073 
3074         if (!ext4_group_desc_csum_verify(sbi, i, gdp)) {
3075             printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
3076                    "Checksum for group %u failed (%u!=%u)\n",
3077                    i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
3078                                                        gdp)),
3079                    le16_to_cpu(gdp->bg_checksum));
3080             if (!IsVcbReadOnly(Vcb)) {
3081                 __brelse(bh);
3082                 return 0;
3083             }
3084         }
3085 
3086         if (!flexbg_flag)
3087             first_block += EXT4_BLOCKS_PER_GROUP(sb);
3088 
3089         __brelse(bh);
3090     }
3091 
3092     ext3_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb));
3093     sbi->s_es->s_free_inodes_count = cpu_to_le32(ext4_count_free_inodes(sb));
3094     return 1;
3095 }
3096