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