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 BOOLEAN 862 Ext2SaveBuffer( IN PEXT2_IRP_CONTEXT IrpContext, 863 IN PEXT2_VCB Vcb, 864 IN LONGLONG offset, 865 IN ULONG size, 866 IN PVOID buf ) 867 { 868 struct buffer_head *bh = NULL; 869 BOOLEAN rc = 0; 870 871 _SEH2_TRY { 872 873 while (size) { 874 875 sector_t block; 876 ULONG len = 0, delta = 0; 877 878 block = (sector_t) (offset >> BLOCK_BITS); 879 delta = (ULONG)offset & (BLOCK_SIZE - 1); 880 len = BLOCK_SIZE - delta; 881 if (size < len) 882 len = size; 883 884 if (delta == 0 && len >= BLOCK_SIZE) { 885 bh = sb_getblk_zero(&Vcb->sb, block); 886 } else { 887 bh = sb_getblk(&Vcb->sb, block); 888 } 889 890 if (!bh) { 891 DEBUG(DL_ERR, ("Ext2SaveBuffer: can't load block %I64u\n", block)); 892 DbgBreak(); 893 _SEH2_LEAVE; 894 } 895 896 if (!buffer_uptodate(bh)) { 897 int err = bh_submit_read(bh); 898 if (err < 0) { 899 DEBUG(DL_ERR, ("Ext2SaveBuffer: bh_submit_read failed: %d\n", err)); 900 _SEH2_LEAVE; 901 } 902 } 903 904 _SEH2_TRY { 905 RtlCopyMemory(bh->b_data + delta, buf, len); 906 mark_buffer_dirty(bh); 907 } _SEH2_FINALLY { 908 fini_bh(&bh); 909 } _SEH2_END; 910 911 buf = (PUCHAR)buf + len; 912 offset = offset + len; 913 size = size - len; 914 } 915 916 rc = TRUE; 917 918 } _SEH2_FINALLY { 919 920 if (bh) 921 fini_bh(&bh); 922 923 } _SEH2_END; 924 925 return rc; 926 } 927 928 929 VOID 930 Ext2UpdateVcbStat( 931 IN PEXT2_IRP_CONTEXT IrpContext, 932 IN PEXT2_VCB Vcb 933 ) 934 { 935 Vcb->SuperBlock->s_free_inodes_count = ext4_count_free_inodes(&Vcb->sb); 936 ext3_free_blocks_count_set(SUPER_BLOCK, ext4_count_free_blocks(&Vcb->sb)); 937 Ext2SaveSuper(IrpContext, Vcb); 938 } 939 940 NTSTATUS 941 Ext2NewBlock( 942 IN PEXT2_IRP_CONTEXT IrpContext, 943 IN PEXT2_VCB Vcb, 944 IN ULONG GroupHint, 945 IN ULONG BlockHint, 946 OUT PULONG Block, 947 IN OUT PULONG Number 948 ) 949 { 950 struct super_block *sb = &Vcb->sb; 951 PEXT2_GROUP_DESC gd; 952 struct buffer_head *gb = NULL; 953 struct buffer_head *bh = NULL; 954 ext4_fsblk_t bitmap_blk; 955 956 RTL_BITMAP BlockBitmap; 957 958 ULONG Group = 0; 959 ULONG Index = 0xFFFFFFFF; 960 ULONG dwHint = 0; 961 ULONG Count = 0; 962 ULONG Length = 0; 963 964 NTSTATUS Status = STATUS_DISK_FULL; 965 966 *Block = 0; 967 968 ExAcquireResourceExclusiveLite(&Vcb->MetaBlock, TRUE); 969 970 /* validate the hint group and hint block */ 971 if (GroupHint >= Vcb->sbi.s_groups_count) { 972 DbgBreak(); 973 GroupHint = Vcb->sbi.s_groups_count - 1; 974 } 975 976 if (BlockHint != 0) { 977 GroupHint = (BlockHint - EXT2_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP; 978 dwHint = (BlockHint - EXT2_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP; 979 } 980 981 Group = GroupHint; 982 983 Again: 984 985 if (bh) 986 fini_bh(&bh); 987 988 if (gb) 989 fini_bh(&gb); 990 991 gd = ext4_get_group_desc(sb, Group, &gb); 992 if (!gd) { 993 DbgBreak(); 994 Status = STATUS_INSUFFICIENT_RESOURCES; 995 goto errorout; 996 } 997 998 bitmap_blk = ext4_block_bitmap(sb, gd); 999 1000 if (gd->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { 1001 bh = sb_getblk_zero(sb, bitmap_blk); 1002 if (!bh) { 1003 DbgBreak(); 1004 Status = STATUS_INSUFFICIENT_RESOURCES; 1005 goto errorout; 1006 } 1007 gd->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, gd); 1008 ext4_init_block_bitmap(sb, bh, Group, gd); 1009 set_buffer_uptodate(bh); 1010 gd->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); 1011 Ext2SaveGroup(IrpContext, Vcb, Group); 1012 } else { 1013 bh = sb_getblk(sb, bitmap_blk); 1014 if (!bh) { 1015 DbgBreak(); 1016 Status = STATUS_INSUFFICIENT_RESOURCES; 1017 goto errorout; 1018 } 1019 } 1020 1021 if (!buffer_uptodate(bh)) { 1022 int err = bh_submit_read(bh); 1023 if (err < 0) { 1024 DbgPrint("bh_submit_read error! err: %d\n", err); 1025 Status = Ext2WinntError(err); 1026 goto errorout; 1027 } 1028 } 1029 1030 if (ext4_free_blks_count(sb, gd)) { 1031 1032 if (Group == Vcb->sbi.s_groups_count - 1) { 1033 1034 Length = (ULONG)(TOTAL_BLOCKS % BLOCKS_PER_GROUP); 1035 1036 /* s_blocks_count is integer multiple of s_blocks_per_group */ 1037 if (Length == 0) { 1038 Length = BLOCKS_PER_GROUP; 1039 } 1040 } else { 1041 Length = BLOCKS_PER_GROUP; 1042 } 1043 1044 /* initialize bitmap buffer */ 1045 RtlInitializeBitMap(&BlockBitmap, (PULONG)bh->b_data, Length); 1046 1047 /* try to find a clear bit range */ 1048 Index = RtlFindClearBits(&BlockBitmap, *Number, dwHint); 1049 1050 /* We could not get new block in the prefered group */ 1051 if (Index == 0xFFFFFFFF) { 1052 1053 /* search clear bits from the hint block */ 1054 Count = RtlFindNextForwardRunClear(&BlockBitmap, dwHint, &Index); 1055 if (dwHint != 0 && Count == 0) { 1056 /* search clear bits from the very beginning */ 1057 Count = RtlFindNextForwardRunClear(&BlockBitmap, 0, &Index); 1058 } 1059 1060 if (Count == 0) { 1061 1062 RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP)); 1063 1064 /* no blocks found: set bg_free_blocks_count to 0 */ 1065 ext4_free_blks_set(sb, gd, 0); 1066 Ext2SaveGroup(IrpContext, Vcb, Group); 1067 1068 /* will try next group */ 1069 goto Again; 1070 1071 } else { 1072 1073 /* we got free blocks */ 1074 if (Count <= *Number) { 1075 *Number = Count; 1076 } 1077 } 1078 } 1079 1080 } else { 1081 1082 /* try next group */ 1083 dwHint = 0; 1084 Group = (Group + 1) % Vcb->sbi.s_groups_count; 1085 if (Group != GroupHint) { 1086 goto Again; 1087 } 1088 1089 Index = 0xFFFFFFFF; 1090 } 1091 1092 if (Index < Length) { 1093 1094 /* mark block bits as allocated */ 1095 RtlSetBits(&BlockBitmap, Index, *Number); 1096 1097 /* set block bitmap dirty in cache */ 1098 mark_buffer_dirty(bh); 1099 1100 /* update group description */ 1101 ext4_free_blks_set(sb, gd, RtlNumberOfClearBits(&BlockBitmap)); 1102 Ext2SaveGroup(IrpContext, Vcb, Group); 1103 1104 /* update Vcb free blocks */ 1105 Ext2UpdateVcbStat(IrpContext, Vcb); 1106 1107 /* validate the new allocated block number */ 1108 *Block = Index + EXT2_FIRST_DATA_BLOCK + Group * BLOCKS_PER_GROUP; 1109 if (*Block >= TOTAL_BLOCKS || *Block + *Number > TOTAL_BLOCKS) { 1110 DbgBreak(); 1111 dwHint = 0; 1112 goto Again; 1113 } 1114 1115 if (ext4_block_bitmap(sb, gd) == *Block || 1116 ext4_inode_bitmap(sb, gd) == *Block || 1117 ext4_inode_table(sb, gd) == *Block ) { 1118 DbgBreak(); 1119 dwHint = 0; 1120 goto Again; 1121 } 1122 1123 /* Always remove dirty MCB to prevent Volume's lazy writing. 1124 Metadata blocks will be re-added during modifications.*/ 1125 if (Ext2RemoveBlockExtent(Vcb, NULL, *Block, *Number)) { 1126 } else { 1127 DbgBreak(); 1128 Ext2RemoveBlockExtent(Vcb, NULL, *Block, *Number); 1129 } 1130 1131 DEBUG(DL_INF, ("Ext2NewBlock: Block %xh - %x allocated.\n", 1132 *Block, *Block + *Number)); 1133 Status = STATUS_SUCCESS; 1134 } 1135 1136 errorout: 1137 1138 ExReleaseResourceLite(&Vcb->MetaBlock); 1139 1140 if (bh) 1141 fini_bh(&bh); 1142 1143 if (gb) 1144 fini_bh(&gb); 1145 1146 return Status; 1147 } 1148 1149 NTSTATUS 1150 Ext2FreeBlock( 1151 IN PEXT2_IRP_CONTEXT IrpContext, 1152 IN PEXT2_VCB Vcb, 1153 IN ULONG Block, 1154 IN ULONG Number 1155 ) 1156 { 1157 struct super_block *sb = &Vcb->sb; 1158 PEXT2_GROUP_DESC gd; 1159 struct buffer_head *gb = NULL; 1160 ext4_fsblk_t bitmap_blk; 1161 1162 RTL_BITMAP BlockBitmap; 1163 LARGE_INTEGER Offset; 1164 1165 PBCB BitmapBcb; 1166 PVOID BitmapCache; 1167 1168 ULONG Group; 1169 ULONG Index; 1170 ULONG Length; 1171 ULONG Count; 1172 1173 NTSTATUS Status = STATUS_UNSUCCESSFUL; 1174 1175 ExAcquireResourceExclusiveLite(&Vcb->MetaBlock, TRUE); 1176 1177 DEBUG(DL_INF, ("Ext2FreeBlock: Block %xh - %x to be freed.\n", 1178 Block, Block + Number)); 1179 1180 Group = (Block - EXT2_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP; 1181 Index = (Block - EXT2_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP; 1182 1183 Again: 1184 1185 if (gb) 1186 fini_bh(&gb); 1187 1188 if ( Block < EXT2_FIRST_DATA_BLOCK || 1189 Block >= TOTAL_BLOCKS || 1190 Group >= Vcb->sbi.s_groups_count) { 1191 1192 DbgBreak(); 1193 Status = STATUS_SUCCESS; 1194 1195 } else { 1196 1197 gd = ext4_get_group_desc(sb, Group, &gb); 1198 if (!gd) { 1199 DbgBreak(); 1200 Status = STATUS_INSUFFICIENT_RESOURCES; 1201 goto errorout; 1202 } 1203 bitmap_blk = ext4_block_bitmap(sb, gd); 1204 1205 /* check the block is valid or not */ 1206 if (bitmap_blk >= TOTAL_BLOCKS) { 1207 DbgBreak(); 1208 Status = STATUS_DISK_CORRUPT_ERROR; 1209 goto errorout; 1210 } 1211 1212 /* get bitmap block offset and length */ 1213 Offset.QuadPart = bitmap_blk; 1214 Offset.QuadPart = Offset.QuadPart << BLOCK_BITS; 1215 1216 if (Group == Vcb->sbi.s_groups_count - 1) { 1217 1218 Length = (ULONG)(TOTAL_BLOCKS % BLOCKS_PER_GROUP); 1219 1220 /* s_blocks_count is integer multiple of s_blocks_per_group */ 1221 if (Length == 0) { 1222 Length = BLOCKS_PER_GROUP; 1223 } 1224 1225 } else { 1226 Length = BLOCKS_PER_GROUP; 1227 } 1228 1229 /* read and initialize bitmap */ 1230 if (!CcPinRead( Vcb->Volume, 1231 &Offset, 1232 Vcb->BlockSize, 1233 PIN_WAIT, 1234 &BitmapBcb, 1235 &BitmapCache ) ) { 1236 1237 DEBUG(DL_ERR, ("Ext2FreeBlock: failed to PinLock bitmap block %xh.\n", 1238 bitmap_blk)); 1239 Status = STATUS_CANT_WAIT; 1240 DbgBreak(); 1241 goto errorout; 1242 } 1243 1244 /* clear usused bits */ 1245 RtlInitializeBitMap(&BlockBitmap, BitmapCache, Length); 1246 Count = min(Length - Index, Number); 1247 RtlClearBits(&BlockBitmap, Index, Count); 1248 1249 /* update group description table */ 1250 ext4_free_blks_set(sb, gd, RtlNumberOfClearBits(&BlockBitmap)); 1251 1252 /* indict the cache range is dirty */ 1253 CcSetDirtyPinnedData(BitmapBcb, NULL ); 1254 Ext2AddVcbExtent(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize); 1255 CcUnpinData(BitmapBcb); 1256 BitmapBcb = NULL; 1257 BitmapCache = NULL; 1258 Ext2SaveGroup(IrpContext, Vcb, Group); 1259 1260 /* remove dirty MCB to prevent Volume's lazy writing. */ 1261 if (Ext2RemoveBlockExtent(Vcb, NULL, Block, Count)) { 1262 } else { 1263 DbgBreak(); 1264 Ext2RemoveBlockExtent(Vcb, NULL, Block, Count); 1265 } 1266 1267 /* save super block (used/unused blocks statics) */ 1268 Ext2UpdateVcbStat(IrpContext, Vcb); 1269 1270 /* try next group to clear all remaining */ 1271 Number -= Count; 1272 if (Number) { 1273 Group += 1; 1274 if (Group < Vcb->sbi.s_groups_count) { 1275 Index = 0; 1276 Block += Count; 1277 goto Again; 1278 } else { 1279 DEBUG(DL_ERR, ("Ext2FreeBlock: block number beyonds max group.\n")); 1280 goto errorout; 1281 } 1282 } 1283 } 1284 1285 Status = STATUS_SUCCESS; 1286 1287 errorout: 1288 1289 if (gb) 1290 fini_bh(&gb); 1291 1292 ExReleaseResourceLite(&Vcb->MetaBlock); 1293 1294 return Status; 1295 } 1296 1297 1298 NTSTATUS 1299 Ext2NewInode( 1300 IN PEXT2_IRP_CONTEXT IrpContext, 1301 IN PEXT2_VCB Vcb, 1302 IN ULONG GroupHint, 1303 IN ULONG Type, 1304 OUT PULONG Inode 1305 ) 1306 { 1307 struct super_block *sb = &Vcb->sb; 1308 PEXT2_GROUP_DESC gd; 1309 struct buffer_head *gb = NULL; 1310 struct buffer_head *bh = NULL; 1311 ext4_fsblk_t bitmap_blk; 1312 1313 RTL_BITMAP InodeBitmap; 1314 1315 ULONG Group, i, j; 1316 ULONG Average, Length; 1317 1318 ULONG dwInode; 1319 1320 NTSTATUS Status = STATUS_DISK_FULL; 1321 1322 *Inode = dwInode = 0XFFFFFFFF; 1323 1324 ExAcquireResourceExclusiveLite(&Vcb->MetaInode, TRUE); 1325 1326 if (GroupHint >= Vcb->sbi.s_groups_count) 1327 GroupHint = GroupHint % Vcb->sbi.s_groups_count; 1328 1329 repeat: 1330 1331 if (bh) 1332 fini_bh(&bh); 1333 1334 if (gb) 1335 fini_bh(&gb); 1336 1337 Group = i = 0; 1338 gd = NULL; 1339 1340 if (Type == EXT2_FT_DIR) { 1341 1342 Average = Vcb->SuperBlock->s_free_inodes_count / Vcb->sbi.s_groups_count; 1343 1344 for (j = 0; j < Vcb->sbi.s_groups_count; j++) { 1345 1346 i = (j + GroupHint) % (Vcb->sbi.s_groups_count); 1347 gd = ext4_get_group_desc(sb, i, &gb); 1348 if (!gd) { 1349 DbgBreak(); 1350 Status = STATUS_INSUFFICIENT_RESOURCES; 1351 goto errorout; 1352 } 1353 1354 if ((gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) || 1355 (ext4_used_dirs_count(sb, gd) << 8 < 1356 ext4_free_inodes_count(sb, gd)) ) { 1357 Group = i + 1; 1358 break; 1359 } 1360 fini_bh(&gb); 1361 } 1362 1363 if (!Group) { 1364 1365 PEXT2_GROUP_DESC desc = NULL; 1366 1367 gd = NULL; 1368 1369 /* get the group with the biggest vacancy */ 1370 for (j = 0; j < Vcb->sbi.s_groups_count; j++) { 1371 1372 struct buffer_head *gt = NULL; 1373 desc = ext4_get_group_desc(sb, j, >); 1374 if (!desc) { 1375 DbgBreak(); 1376 Status = STATUS_INSUFFICIENT_RESOURCES; 1377 goto errorout; 1378 } 1379 1380 /* return the group if it's not initialized yet */ 1381 if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { 1382 Group = j + 1; 1383 gd = desc; 1384 1385 if (gb) 1386 fini_bh(&gb); 1387 gb = gt; 1388 gt = NULL; 1389 break; 1390 } 1391 1392 if (!gd) { 1393 if (ext4_free_inodes_count(sb, desc) > 0) { 1394 Group = j + 1; 1395 gd = desc; 1396 if (gb) 1397 fini_bh(&gb); 1398 gb = gt; 1399 gt = NULL; 1400 } 1401 } else { 1402 if (ext4_free_inodes_count(sb, desc) > 1403 ext4_free_inodes_count(sb, gd)) { 1404 Group = j + 1; 1405 gd = desc; 1406 if (gb) 1407 fini_bh(&gb); 1408 gb = gt; 1409 gt = NULL; 1410 break; 1411 } 1412 } 1413 if (gt) 1414 fini_bh(>); 1415 } 1416 } 1417 1418 } else { 1419 1420 /* 1421 * Try to place the inode in its parent directory (GroupHint) 1422 */ 1423 1424 gd = ext4_get_group_desc(sb, GroupHint, &gb); 1425 if (!gb) { 1426 DbgBreak(); 1427 Status = STATUS_INSUFFICIENT_RESOURCES; 1428 goto errorout; 1429 } 1430 1431 if (gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT) || 1432 ext4_free_inodes_count(sb, gd)) { 1433 1434 Group = GroupHint + 1; 1435 1436 } else { 1437 1438 /* this group is 100% cocucpied */ 1439 fini_bh(&gb); 1440 1441 i = GroupHint; 1442 1443 /* 1444 * Use a quadratic hash to find a group with a free inode 1445 */ 1446 1447 for (j = 1; j < Vcb->sbi.s_groups_count; j <<= 1) { 1448 1449 1450 i = (i + j) % Vcb->sbi.s_groups_count; 1451 gd = ext4_get_group_desc(sb, i, &gb); 1452 if (!gd) { 1453 DbgBreak(); 1454 Status = STATUS_INSUFFICIENT_RESOURCES; 1455 goto errorout; 1456 } 1457 1458 if (gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT) || 1459 ext4_free_inodes_count(sb, gd)) { 1460 Group = i + 1; 1461 break; 1462 } 1463 1464 fini_bh(&gb); 1465 } 1466 } 1467 1468 if (!Group) { 1469 /* 1470 * That failed: try linear search for a free inode 1471 */ 1472 i = GroupHint; 1473 for (j = 2; j < Vcb->sbi.s_groups_count; j++) { 1474 1475 i = (i + 1) % Vcb->sbi.s_groups_count; 1476 gd = ext4_get_group_desc(sb, i, &gb); 1477 if (!gd) { 1478 DbgBreak(); 1479 Status = STATUS_INSUFFICIENT_RESOURCES; 1480 goto errorout; 1481 } 1482 1483 if (gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT) || 1484 ext4_free_inodes_count(sb, gd)) { 1485 Group = i + 1; 1486 break; 1487 } 1488 1489 fini_bh(&gb); 1490 } 1491 } 1492 } 1493 1494 if (gd == NULL || Group == 0) { 1495 goto errorout; 1496 } 1497 1498 /* finally we got the group, but is it valid ? */ 1499 if (Group > Vcb->sbi.s_groups_count) { 1500 DbgBreak(); 1501 goto errorout; 1502 } 1503 1504 /* valid group number starts from 1, not 0 */ 1505 Group -= 1; 1506 1507 ASSERT(gd); 1508 bitmap_blk = ext4_inode_bitmap(sb, gd); 1509 /* check the block is valid or not */ 1510 if (bitmap_blk == 0 || bitmap_blk >= TOTAL_BLOCKS) { 1511 DbgBreak(); 1512 Status = STATUS_DISK_CORRUPT_ERROR; 1513 goto errorout; 1514 } 1515 1516 if (gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { 1517 bh = sb_getblk_zero(sb, bitmap_blk); 1518 if (!bh) { 1519 DbgBreak(); 1520 Status = STATUS_INSUFFICIENT_RESOURCES; 1521 goto errorout; 1522 } 1523 gd->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, gd); 1524 ext4_init_inode_bitmap(sb, bh, Group, gd); 1525 set_buffer_uptodate(bh); 1526 gd->bg_flags &= cpu_to_le16(~EXT4_BG_INODE_UNINIT); 1527 Ext2SaveGroup(IrpContext, Vcb, Group); 1528 } else { 1529 bh = sb_getblk(sb, bitmap_blk); 1530 if (!bh) { 1531 DbgBreak(); 1532 Status = STATUS_INSUFFICIENT_RESOURCES; 1533 goto errorout; 1534 } 1535 } 1536 1537 if (!buffer_uptodate(bh)) { 1538 int err = bh_submit_read(bh); 1539 if (err < 0) { 1540 DbgPrint("bh_submit_read error! err: %d\n", err); 1541 Status = Ext2WinntError(err); 1542 goto errorout; 1543 } 1544 } 1545 1546 if (Vcb->sbi.s_groups_count == 1) { 1547 Length = INODES_COUNT; 1548 } else { 1549 if (Group + 1 == Vcb->sbi.s_groups_count) { 1550 Length = INODES_COUNT % INODES_PER_GROUP; 1551 if (!Length) { 1552 /* INODES_COUNT is integer multiple of INODES_PER_GROUP */ 1553 Length = INODES_PER_GROUP; 1554 } 1555 } else { 1556 Length = INODES_PER_GROUP; 1557 } 1558 } 1559 1560 RtlInitializeBitMap(&InodeBitmap, (PULONG)bh->b_data, Length); 1561 dwInode = RtlFindClearBits(&InodeBitmap, 1, 0); 1562 1563 if (dwInode == 0xFFFFFFFF || dwInode >= Length) { 1564 1565 RtlZeroMemory(&InodeBitmap, sizeof(RTL_BITMAP)); 1566 if (ext4_free_inodes_count(sb, gd) > 0) { 1567 ext4_free_inodes_set(sb, gd, 0); 1568 Ext2SaveGroup(IrpContext, Vcb, Group); 1569 } 1570 goto repeat; 1571 1572 } else { 1573 1574 __u32 count = 0; 1575 1576 /* update unused inodes count */ 1577 count = ext4_free_inodes_count(sb, gd) - 1; 1578 ext4_free_inodes_set(sb, gd, count); 1579 1580 RtlSetBits(&InodeBitmap, dwInode, 1); 1581 1582 /* set block bitmap dirty in cache */ 1583 mark_buffer_dirty(bh); 1584 1585 /* If we didn't allocate from within the initialized part of the inode 1586 * table then we need to initialize up to this inode. */ 1587 if (EXT3_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { 1588 1589 __u32 free; 1590 1591 if (gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { 1592 gd->bg_flags &= cpu_to_le16(~EXT4_BG_INODE_UNINIT); 1593 /* When marking the block group with 1594 * ~EXT4_BG_INODE_UNINIT we don't want to depend 1595 * on the value of bg_itable_unused even though 1596 * mke2fs could have initialized the same for us. 1597 * Instead we calculated the value below 1598 */ 1599 1600 free = 0; 1601 } else { 1602 free = EXT3_INODES_PER_GROUP(sb) - ext4_itable_unused_count(sb, gd); 1603 } 1604 1605 /* 1606 * Check the relative inode number against the last used 1607 * relative inode number in this group. if it is greater 1608 * we need to update the bg_itable_unused count 1609 * 1610 */ 1611 if (dwInode + 1 > free) { 1612 ext4_itable_unused_set(sb, gd, 1613 (EXT3_INODES_PER_GROUP(sb) - 1 - dwInode)); 1614 } 1615 1616 /* We may have to initialize the block bitmap if it isn't already */ 1617 if (gd->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { 1618 1619 struct buffer_head *block_bitmap_bh = NULL; 1620 1621 /* recheck and clear flag under lock if we still need to */ 1622 block_bitmap_bh = sb_getblk_zero(sb, ext4_block_bitmap(sb, gd)); 1623 if (block_bitmap_bh) { 1624 gd->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, gd); 1625 free = ext4_init_block_bitmap(sb, block_bitmap_bh, Group, gd); 1626 set_buffer_uptodate(block_bitmap_bh); 1627 brelse(block_bitmap_bh); 1628 gd->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); 1629 ext4_free_blks_set(sb, gd, free); 1630 Ext2SaveGroup(IrpContext, Vcb, Group); 1631 } 1632 } 1633 } 1634 1635 *Inode = dwInode + 1 + Group * INODES_PER_GROUP; 1636 1637 /* update group_desc / super_block */ 1638 if (Type == EXT2_FT_DIR) { 1639 ext4_used_dirs_set(sb, gd, ext4_used_dirs_count(sb, gd) + 1); 1640 } 1641 Ext2SaveGroup(IrpContext, Vcb, Group); 1642 Ext2UpdateVcbStat(IrpContext, Vcb); 1643 Status = STATUS_SUCCESS; 1644 } 1645 1646 errorout: 1647 1648 ExReleaseResourceLite(&Vcb->MetaInode); 1649 1650 if (bh) 1651 fini_bh(&bh); 1652 1653 if (gb) 1654 fini_bh(&gb); 1655 1656 1657 return Status; 1658 } 1659 1660 NTSTATUS 1661 Ext2UpdateGroupDirStat( 1662 IN PEXT2_IRP_CONTEXT IrpContext, 1663 IN PEXT2_VCB Vcb, 1664 IN ULONG group 1665 ) 1666 { 1667 struct super_block *sb = &Vcb->sb; 1668 PEXT2_GROUP_DESC gd; 1669 struct buffer_head *gb = NULL; 1670 NTSTATUS status; 1671 1672 ExAcquireResourceExclusiveLite(&Vcb->MetaInode, TRUE); 1673 1674 /* get group desc */ 1675 gd = ext4_get_group_desc(sb, group, &gb); 1676 if (!gd) { 1677 status = STATUS_INSUFFICIENT_RESOURCES; 1678 goto errorout; 1679 } 1680 1681 /* update group_desc and super_block */ 1682 ext4_used_dirs_set(sb, gd, ext4_used_dirs_count(sb, gd) - 1); 1683 Ext2SaveGroup(IrpContext, Vcb, group); 1684 Ext2UpdateVcbStat(IrpContext, Vcb); 1685 status = STATUS_SUCCESS; 1686 1687 errorout: 1688 1689 ExReleaseResourceLite(&Vcb->MetaInode); 1690 1691 if (gb) 1692 fini_bh(&gb); 1693 1694 return status; 1695 } 1696 1697 1698 NTSTATUS 1699 Ext2FreeInode( 1700 IN PEXT2_IRP_CONTEXT IrpContext, 1701 IN PEXT2_VCB Vcb, 1702 IN ULONG Inode, 1703 IN ULONG Type 1704 ) 1705 { 1706 struct super_block *sb = &Vcb->sb; 1707 PEXT2_GROUP_DESC gd; 1708 struct buffer_head *gb = NULL; 1709 struct buffer_head *bh = NULL; 1710 ext4_fsblk_t bitmap_blk; 1711 1712 RTL_BITMAP InodeBitmap; 1713 ULONG Group; 1714 ULONG Length; 1715 LARGE_INTEGER Offset; 1716 1717 ULONG dwIno; 1718 BOOLEAN bModified = FALSE; 1719 1720 NTSTATUS Status = STATUS_UNSUCCESSFUL; 1721 1722 ExAcquireResourceExclusiveLite(&Vcb->MetaInode, TRUE); 1723 1724 Group = (Inode - 1) / INODES_PER_GROUP; 1725 dwIno = (Inode - 1) % INODES_PER_GROUP; 1726 1727 DEBUG(DL_INF, ( "Ext2FreeInode: Inode: %xh (Group/Off = %xh/%xh)\n", 1728 Inode, Group, dwIno)); 1729 1730 if (Group >= Vcb->sbi.s_groups_count) { 1731 DbgBreak(); 1732 goto errorout; 1733 } 1734 1735 gd = ext4_get_group_desc(sb, Group, &gb); 1736 if (!gd) { 1737 DbgBreak(); 1738 Status = STATUS_INSUFFICIENT_RESOURCES; 1739 goto errorout; 1740 } 1741 1742 bitmap_blk = ext4_inode_bitmap(sb, gd); 1743 bh = sb_getblk(sb, bitmap_blk); 1744 if (!bh) { 1745 DbgBreak(); 1746 Status = STATUS_INSUFFICIENT_RESOURCES; 1747 goto errorout; 1748 } 1749 if (!buffer_uptodate(bh)) { 1750 int err = bh_submit_read(bh); 1751 if (err < 0) { 1752 DbgPrint("bh_submit_read error! err: %d\n", err); 1753 Status = Ext2WinntError(err); 1754 goto errorout; 1755 } 1756 } 1757 1758 if (Group == Vcb->sbi.s_groups_count - 1) { 1759 1760 Length = INODES_COUNT % INODES_PER_GROUP; 1761 if (!Length) { 1762 /* s_inodes_count is integer multiple of s_inodes_per_group */ 1763 Length = INODES_PER_GROUP; 1764 } 1765 } else { 1766 Length = INODES_PER_GROUP; 1767 } 1768 1769 RtlInitializeBitMap(&InodeBitmap, (PULONG)bh->b_data, Length); 1770 1771 if (RtlCheckBit(&InodeBitmap, dwIno) == 0) { 1772 DbgBreak(); 1773 Status = STATUS_SUCCESS; 1774 } else { 1775 RtlClearBits(&InodeBitmap, dwIno, 1); 1776 bModified = TRUE; 1777 } 1778 1779 if (bModified) { 1780 /* update group free inodes */ 1781 ext4_free_inodes_set(sb, gd, 1782 RtlNumberOfClearBits(&InodeBitmap)); 1783 1784 /* set inode block dirty and add to vcb dirty range */ 1785 mark_buffer_dirty(bh); 1786 1787 /* update group_desc and super_block */ 1788 if (Type == EXT2_FT_DIR) { 1789 ext4_used_dirs_set(sb, gd, 1790 ext4_used_dirs_count(sb, gd) - 1); 1791 } 1792 Ext2SaveGroup(IrpContext, Vcb, Group); 1793 Ext2UpdateVcbStat(IrpContext, Vcb); 1794 Status = STATUS_SUCCESS; 1795 } 1796 1797 errorout: 1798 1799 ExReleaseResourceLite(&Vcb->MetaInode); 1800 1801 if (bh) 1802 fini_bh(&bh); 1803 1804 if (gb) 1805 fini_bh(&gb); 1806 1807 return Status; 1808 } 1809 1810 1811 NTSTATUS 1812 Ext2AddEntry ( 1813 IN PEXT2_IRP_CONTEXT IrpContext, 1814 IN PEXT2_VCB Vcb, 1815 IN PEXT2_FCB Dcb, 1816 IN struct inode *Inode, 1817 IN PUNICODE_STRING FileName, 1818 struct dentry **Dentry 1819 ) 1820 { 1821 struct dentry *de = NULL; 1822 1823 NTSTATUS status = STATUS_UNSUCCESSFUL; 1824 OEM_STRING oem; 1825 int rc; 1826 1827 BOOLEAN MainResourceAcquired = FALSE; 1828 1829 if (!IsDirectory(Dcb)) { 1830 DbgBreak(); 1831 return STATUS_NOT_A_DIRECTORY; 1832 } 1833 1834 ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE); 1835 MainResourceAcquired = TRUE; 1836 1837 _SEH2_TRY { 1838 1839 Ext2ReferXcb(&Dcb->ReferenceCount); 1840 de = Ext2BuildEntry(Vcb, Dcb->Mcb, FileName); 1841 if (!de) { 1842 status = STATUS_INSUFFICIENT_RESOURCES; 1843 _SEH2_LEAVE; 1844 } 1845 de->d_inode = Inode; 1846 1847 rc = ext3_add_entry(IrpContext, de, Inode); 1848 status = Ext2WinntError(rc); 1849 if (NT_SUCCESS(status)) { 1850 1851 /* increase dir inode's nlink for .. */ 1852 if (S_ISDIR(Inode->i_mode)) { 1853 ext3_inc_count(Dcb->Inode); 1854 ext3_mark_inode_dirty(IrpContext, Dcb->Inode); 1855 } 1856 1857 /* increase inode nlink reference */ 1858 ext3_inc_count(Inode); 1859 ext3_mark_inode_dirty(IrpContext, Inode); 1860 1861 if (Dentry) { 1862 *Dentry = de; 1863 de = NULL; 1864 } 1865 } 1866 1867 } _SEH2_FINALLY { 1868 1869 Ext2DerefXcb(&Dcb->ReferenceCount); 1870 1871 if (MainResourceAcquired) { 1872 ExReleaseResourceLite(&Dcb->MainResource); 1873 } 1874 1875 if (de) 1876 Ext2FreeEntry(de); 1877 } _SEH2_END; 1878 1879 return status; 1880 } 1881 1882 1883 NTSTATUS 1884 Ext2SetFileType ( 1885 IN PEXT2_IRP_CONTEXT IrpContext, 1886 IN PEXT2_VCB Vcb, 1887 IN PEXT2_FCB Dcb, 1888 IN PEXT2_MCB Mcb, 1889 IN umode_t mode 1890 ) 1891 { 1892 struct inode *dir = Dcb->Inode; 1893 struct buffer_head *bh = NULL; 1894 struct ext3_dir_entry_2 *de; 1895 struct inode *inode; 1896 NTSTATUS Status = STATUS_UNSUCCESSFUL; 1897 BOOLEAN MainResourceAcquired = FALSE; 1898 1899 if (!EXT3_HAS_INCOMPAT_FEATURE(dir->i_sb, EXT3_FEATURE_INCOMPAT_FILETYPE)) { 1900 return STATUS_SUCCESS; 1901 } 1902 1903 if (!IsDirectory(Dcb)) { 1904 return STATUS_NOT_A_DIRECTORY; 1905 } 1906 1907 ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE); 1908 MainResourceAcquired = TRUE; 1909 1910 _SEH2_TRY { 1911 1912 Ext2ReferXcb(&Dcb->ReferenceCount); 1913 1914 bh = ext3_find_entry(IrpContext, Mcb->de, &de); 1915 if (!bh) 1916 _SEH2_LEAVE; 1917 1918 inode = &Mcb->Inode; 1919 if (le32_to_cpu(de->inode) != inode->i_ino) 1920 _SEH2_LEAVE; 1921 1922 ext3_set_de_type(inode->i_sb, de, mode); 1923 mark_buffer_dirty(bh); 1924 1925 if (S_ISDIR(inode->i_mode) == S_ISDIR(mode)) { 1926 } else if (S_ISDIR(inode->i_mode)) { 1927 ext3_dec_count(dir); 1928 } else if (S_ISDIR(mode)) { 1929 ext3_inc_count(dir); 1930 } 1931 dir->i_ctime = dir->i_mtime = ext3_current_time(dir); 1932 ext3_mark_inode_dirty(IrpContext, dir); 1933 1934 inode->i_mode = mode; 1935 ext3_mark_inode_dirty(IrpContext, inode); 1936 1937 Status = STATUS_SUCCESS; 1938 1939 } _SEH2_FINALLY { 1940 1941 Ext2DerefXcb(&Dcb->ReferenceCount); 1942 1943 if (MainResourceAcquired) 1944 ExReleaseResourceLite(&Dcb->MainResource); 1945 1946 if (bh) 1947 brelse(bh); 1948 } _SEH2_END; 1949 1950 return Status; 1951 } 1952 1953 NTSTATUS 1954 Ext2RemoveEntry ( 1955 IN PEXT2_IRP_CONTEXT IrpContext, 1956 IN PEXT2_VCB Vcb, 1957 IN PEXT2_FCB Dcb, 1958 IN PEXT2_MCB Mcb 1959 ) 1960 { 1961 struct inode *dir = Dcb->Inode; 1962 struct buffer_head *bh = NULL; 1963 struct ext3_dir_entry_2 *de; 1964 struct inode *inode; 1965 int rc = -ENOENT; 1966 NTSTATUS Status = STATUS_UNSUCCESSFUL; 1967 BOOLEAN MainResourceAcquired = FALSE; 1968 1969 if (!IsDirectory(Dcb)) { 1970 return STATUS_NOT_A_DIRECTORY; 1971 } 1972 1973 ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE); 1974 MainResourceAcquired = TRUE; 1975 1976 _SEH2_TRY { 1977 1978 Ext2ReferXcb(&Dcb->ReferenceCount); 1979 1980 bh = ext3_find_entry(IrpContext, Mcb->de, &de); 1981 if (!bh) 1982 _SEH2_LEAVE; 1983 1984 inode = &Mcb->Inode; 1985 if (le32_to_cpu(de->inode) != inode->i_ino) 1986 _SEH2_LEAVE; 1987 1988 if (!inode->i_nlink) { 1989 ext3_warning (inode->i_sb, "ext3_unlink", 1990 "Deleting nonexistent file (%lu), %d", 1991 inode->i_ino, inode->i_nlink); 1992 inode->i_nlink = 1; 1993 } 1994 rc = ext3_delete_entry(IrpContext, dir, de, bh); 1995 if (rc) { 1996 Status = Ext2WinntError(rc); 1997 _SEH2_LEAVE; 1998 } 1999 /* 2000 if (!inode->i_nlink) 2001 ext3_orphan_add(handle, inode); 2002 */ 2003 inode->i_ctime = dir->i_ctime = dir->i_mtime = ext3_current_time(dir); 2004 ext3_dec_count(inode); 2005 ext3_mark_inode_dirty(IrpContext, inode); 2006 2007 /* decrease dir inode's nlink for .. */ 2008 if (S_ISDIR(inode->i_mode)) { 2009 ext3_update_dx_flag(dir); 2010 ext3_dec_count(dir); 2011 ext3_mark_inode_dirty(IrpContext, dir); 2012 } 2013 2014 Status = STATUS_SUCCESS; 2015 2016 } _SEH2_FINALLY { 2017 2018 Ext2DerefXcb(&Dcb->ReferenceCount); 2019 2020 if (MainResourceAcquired) 2021 ExReleaseResourceLite(&Dcb->MainResource); 2022 2023 if (bh) 2024 brelse(bh); 2025 } _SEH2_END; 2026 2027 return Status; 2028 } 2029 2030 NTSTATUS 2031 Ext2SetParentEntry ( 2032 IN PEXT2_IRP_CONTEXT IrpContext, 2033 IN PEXT2_VCB Vcb, 2034 IN PEXT2_FCB Dcb, 2035 IN ULONG OldParent, 2036 IN ULONG NewParent ) 2037 { 2038 NTSTATUS Status = STATUS_UNSUCCESSFUL; 2039 2040 PEXT2_DIR_ENTRY2 pSelf = NULL; 2041 PEXT2_DIR_ENTRY2 pParent = NULL; 2042 2043 ULONG dwBytes = 0; 2044 2045 BOOLEAN MainResourceAcquired = FALSE; 2046 2047 ULONG Offset = 0; 2048 2049 if (!IsDirectory(Dcb)) { 2050 return STATUS_NOT_A_DIRECTORY; 2051 } 2052 2053 if (OldParent == NewParent) { 2054 return STATUS_SUCCESS; 2055 } 2056 2057 MainResourceAcquired = 2058 ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE); 2059 2060 _SEH2_TRY { 2061 2062 Ext2ReferXcb(&Dcb->ReferenceCount); 2063 2064 pSelf = (PEXT2_DIR_ENTRY2) 2065 Ext2AllocatePool( 2066 PagedPool, 2067 EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2), 2068 EXT2_DENTRY_MAGIC 2069 ); 2070 if (!pSelf) { 2071 DEBUG(DL_ERR, ( "Ex2SetParentEntry: failed to allocate pSelf.\n")); 2072 Status = STATUS_INSUFFICIENT_RESOURCES; 2073 _SEH2_LEAVE; 2074 } 2075 2076 dwBytes = 0; 2077 2078 // 2079 // Reading the DCB contents 2080 // 2081 2082 Status = Ext2ReadInode( 2083 IrpContext, 2084 Vcb, 2085 Dcb->Mcb, 2086 (ULONGLONG)Offset, 2087 (PVOID)pSelf, 2088 EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2), 2089 FALSE, 2090 &dwBytes ); 2091 2092 if (!NT_SUCCESS(Status)) { 2093 DEBUG(DL_ERR, ( "Ext2SetParentEntry: failed to read directory.\n")); 2094 _SEH2_LEAVE; 2095 } 2096 2097 ASSERT(dwBytes == EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2)); 2098 2099 pParent = (PEXT2_DIR_ENTRY2)((PUCHAR)pSelf + pSelf->rec_len); 2100 2101 if (pSelf->name_len == 1 && pSelf->name[0] == '.' && 2102 pParent->name_len == 2 && pParent->name[0] == '.' && 2103 pParent->name[1] == '.') { 2104 2105 if (pParent->inode != OldParent) { 2106 DbgBreak(); 2107 } 2108 pParent->inode = NewParent; 2109 2110 Status = Ext2WriteInode( 2111 IrpContext, 2112 Vcb, 2113 Dcb->Mcb, 2114 (ULONGLONG)Offset, 2115 pSelf, 2116 dwBytes, 2117 FALSE, 2118 &dwBytes ); 2119 } else { 2120 DbgBreak(); 2121 } 2122 2123 } _SEH2_FINALLY { 2124 2125 2126 if (Ext2DerefXcb(&Dcb->ReferenceCount) == 0) { 2127 DEBUG(DL_ERR, ( "Ext2SetParentEntry: Dcb reference goes to ZERO.\n")); 2128 } 2129 2130 if (MainResourceAcquired) { 2131 ExReleaseResourceLite(&Dcb->MainResource); 2132 } 2133 2134 if (pSelf) { 2135 Ext2FreePool(pSelf, EXT2_DENTRY_MAGIC); 2136 } 2137 } _SEH2_END; 2138 2139 return Status; 2140 } 2141 2142 int ext3_check_dir_entry (const char * function, struct inode * dir, 2143 struct ext3_dir_entry_2 * de, 2144 struct buffer_head * bh, 2145 unsigned long offset) 2146 { 2147 const char * error_msg = NULL; 2148 const int rlen = ext3_rec_len_from_disk(de->rec_len); 2149 2150 if (rlen < EXT3_DIR_REC_LEN(1)) 2151 error_msg = "rec_len is smaller than minimal"; 2152 else if (rlen % 4 != 0) 2153 error_msg = "rec_len % 4 != 0"; 2154 else if (rlen < EXT3_DIR_REC_LEN(de->name_len)) 2155 error_msg = "rec_len is too small for name_len"; 2156 else if ((char *) de + rlen > bh->b_data + dir->i_sb->s_blocksize) 2157 error_msg = "directory entry across blocks"; 2158 else if (le32_to_cpu(de->inode) > 2159 le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count)) 2160 error_msg = "inode out of bounds"; 2161 2162 if (error_msg != NULL) { 2163 DEBUG(DL_ERR, ("%s: bad entry in directory %u: %s - " 2164 "offset=%u, inode=%u, rec_len=%d, name_len=%d\n", 2165 function, dir->i_ino, error_msg, offset, 2166 (unsigned long) le32_to_cpu(de->inode), 2167 rlen, de->name_len)); 2168 } 2169 return error_msg == NULL ? 1 : 0; 2170 } 2171 2172 2173 /* 2174 * p is at least 6 bytes before the end of page 2175 */ 2176 struct ext3_dir_entry_2 * 2177 ext3_next_entry(struct ext3_dir_entry_2 *p) 2178 { 2179 return (struct ext3_dir_entry_2 *)((char *)p + 2180 ext3_rec_len_from_disk(p->rec_len)); 2181 } 2182 2183 #define MAX_LFS_FILESIZE 0x7fffffffffffffff 2184 2185 /* 2186 * Maximal extent format file size. 2187 * Resulting logical blkno at s_maxbytes must fit in our on-disk 2188 * extent format containers, within a sector_t, and within i_blocks 2189 * in the vfs. ext4 inode has 48 bits of i_block in fsblock units, 2190 * so that won't be a limiting factor. 2191 * 2192 * Note, this does *not* consider any metadata overhead for vfs i_blocks. 2193 */ 2194 static loff_t ext4_max_size(int blkbits, int has_huge_files) 2195 { 2196 loff_t res; 2197 loff_t upper_limit = MAX_LFS_FILESIZE; 2198 2199 /* small i_blocks in vfs inode? */ 2200 if (!has_huge_files || sizeof(blkcnt_t) < sizeof(u64)) { 2201 /* 2202 * CONFIG_LBD is not enabled implies the inode 2203 * i_block represent total blocks in 512 bytes 2204 * 32 == size of vfs inode i_blocks * 8 2205 */ 2206 upper_limit = (1LL << 32) - 1; 2207 2208 /* total blocks in file system block size */ 2209 upper_limit >>= (blkbits - 9); 2210 upper_limit <<= blkbits; 2211 } 2212 2213 /* 32-bit extent-start container, ee_block */ 2214 res = 1LL << 32; 2215 res <<= blkbits; 2216 res -= 1; 2217 2218 /* Sanity check against vm- & vfs- imposed limits */ 2219 if (res > upper_limit) 2220 res = upper_limit; 2221 2222 return res; 2223 } 2224 2225 /* 2226 * Maximal extent format file size. 2227 * Resulting logical blkno at s_maxbytes must fit in our on-disk 2228 * extent format containers, within a sector_t, and within i_blocks 2229 * in the vfs. ext4 inode has 48 bits of i_block in fsblock units, 2230 * so that won't be a limiting factor. 2231 * 2232 * Note, this does *not* consider any metadata overhead for vfs i_blocks. 2233 */ 2234 loff_t ext3_max_size(int blkbits, int has_huge_files) 2235 { 2236 loff_t res; 2237 loff_t upper_limit = MAX_LFS_FILESIZE; 2238 2239 /* small i_blocks in vfs inode? */ 2240 if (!has_huge_files) { 2241 /* 2242 * CONFIG_LBD is not enabled implies the inode 2243 * i_block represent total blocks in 512 bytes 2244 * 32 == size of vfs inode i_blocks * 8 2245 */ 2246 upper_limit = ((loff_t)1 << 32) - 1; 2247 2248 /* total blocks in file system block size */ 2249 upper_limit >>= (blkbits - 9); 2250 upper_limit <<= blkbits; 2251 } 2252 2253 /* 32-bit extent-start container, ee_block */ 2254 res = (loff_t)1 << 32; 2255 res <<= blkbits; 2256 res -= 1; 2257 2258 /* Sanity check against vm- & vfs- imposed limits */ 2259 if (res > upper_limit) 2260 res = upper_limit; 2261 2262 return res; 2263 } 2264 2265 /* 2266 * Maximal bitmap file size. There is a direct, and {,double-,triple-}indirect 2267 * block limit, and also a limit of (2^48 - 1) 512-byte sectors in i_blocks. 2268 * We need to be 1 filesystem block less than the 2^48 sector limit. 2269 */ 2270 loff_t ext3_max_bitmap_size(int bits, int has_huge_files) 2271 { 2272 loff_t res = EXT3_NDIR_BLOCKS; 2273 int meta_blocks; 2274 loff_t upper_limit; 2275 /* This is calculated to be the largest file size for a 2276 * dense, bitmapped file such that the total number of 2277 * sectors in the file, including data and all indirect blocks, 2278 * does not exceed 2^48 -1 2279 * __u32 i_blocks_lo and _u16 i_blocks_high representing the 2280 * total number of 512 bytes blocks of the file 2281 */ 2282 2283 if (!has_huge_files) { 2284 /* 2285 * !has_huge_files or CONFIG_LBD is not enabled 2286 * implies the inode i_block represent total blocks in 2287 * 512 bytes 32 == size of vfs inode i_blocks * 8 2288 */ 2289 upper_limit = ((loff_t)1 << 32) - 1; 2290 2291 /* total blocks in file system block size */ 2292 upper_limit >>= (bits - 9); 2293 2294 } else { 2295 /* 2296 * We use 48 bit ext4_inode i_blocks 2297 * With EXT4_HUGE_FILE_FL set the i_blocks 2298 * represent total number of blocks in 2299 * file system block size 2300 */ 2301 upper_limit = ((loff_t)1 << 48) - 1; 2302 2303 } 2304 2305 /* indirect blocks */ 2306 meta_blocks = 1; 2307 /* double indirect blocks */ 2308 meta_blocks += 1 + ((loff_t)1 << (bits-2)); 2309 /* tripple indirect blocks */ 2310 meta_blocks += 1 + ((loff_t)1 << (bits-2)) + ((loff_t)1 << (2*(bits-2))); 2311 2312 upper_limit -= meta_blocks; 2313 upper_limit <<= bits; 2314 2315 res += (loff_t)1 << (bits-2); 2316 res += (loff_t)1 << (2*(bits-2)); 2317 res += (loff_t)1 << (3*(bits-2)); 2318 res <<= bits; 2319 if (res > upper_limit) 2320 res = upper_limit; 2321 2322 if (res > MAX_LFS_FILESIZE) 2323 res = MAX_LFS_FILESIZE; 2324 2325 return res; 2326 } 2327 2328 blkcnt_t ext3_inode_blocks(struct ext3_inode *raw_inode, 2329 struct inode *inode) 2330 { 2331 blkcnt_t i_blocks ; 2332 struct super_block *sb = inode->i_sb; 2333 PEXT2_VCB Vcb = (PEXT2_VCB)sb->s_priv; 2334 2335 if (EXT3_HAS_RO_COMPAT_FEATURE(sb, 2336 EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) { 2337 /* we are using combined 48 bit field */ 2338 i_blocks = ((u64)le16_to_cpu(raw_inode->i_blocks_high)) << 32 | 2339 le32_to_cpu(raw_inode->i_blocks); 2340 if (inode->i_flags & EXT4_HUGE_FILE_FL) { 2341 /* i_blocks represent file system block size */ 2342 return i_blocks << (BLOCK_BITS - 9); 2343 } else { 2344 return i_blocks; 2345 } 2346 } else { 2347 return le32_to_cpu(raw_inode->i_blocks); 2348 } 2349 } 2350 2351 int ext3_inode_blocks_set(struct ext3_inode *raw_inode, 2352 struct inode * inode) 2353 { 2354 u64 i_blocks = inode->i_blocks; 2355 struct super_block *sb = inode->i_sb; 2356 PEXT2_VCB Vcb = (PEXT2_VCB)sb->s_priv; 2357 2358 if (i_blocks < 0x100000000) { 2359 /* 2360 * i_blocks can be represnted in a 32 bit variable 2361 * as multiple of 512 bytes 2362 */ 2363 raw_inode->i_blocks = cpu_to_le32(i_blocks); 2364 raw_inode->i_blocks_high = 0; 2365 inode->i_flags &= ~EXT4_HUGE_FILE_FL; 2366 return 0; 2367 } 2368 2369 if (!EXT3_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) { 2370 EXT3_SET_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE); 2371 Ext2SaveSuper(NULL, Vcb); 2372 } 2373 2374 if (i_blocks <= 0xffffffffffff) { 2375 /* 2376 * i_blocks can be represented in a 48 bit variable 2377 * as multiple of 512 bytes 2378 */ 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 inode->i_flags &= ~EXT4_HUGE_FILE_FL; 2382 } else { 2383 inode->i_flags |= EXT4_HUGE_FILE_FL; 2384 /* i_block is stored in file system block size */ 2385 i_blocks = i_blocks >> (BLOCK_BITS - 9); 2386 raw_inode->i_blocks = (__u32)cpu_to_le32(i_blocks); 2387 raw_inode->i_blocks_high = (__u16)cpu_to_le16(i_blocks >> 32); 2388 } 2389 return 0; 2390 } 2391 2392 ext4_fsblk_t ext4_block_bitmap(struct super_block *sb, 2393 struct ext4_group_desc *bg) 2394 { 2395 return le32_to_cpu(bg->bg_block_bitmap) | 2396 (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ? 2397 (ext4_fsblk_t)le32_to_cpu(bg->bg_block_bitmap_hi) << 32 : 0); 2398 } 2399 2400 ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb, 2401 struct ext4_group_desc *bg) 2402 { 2403 return le32_to_cpu(bg->bg_inode_bitmap) | 2404 (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ? 2405 (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_bitmap_hi) << 32 : 0); 2406 } 2407 2408 ext4_fsblk_t ext4_inode_table(struct super_block *sb, 2409 struct ext4_group_desc *bg) 2410 { 2411 return le32_to_cpu(bg->bg_inode_table) | 2412 (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ? 2413 (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0); 2414 } 2415 2416 __u32 ext4_free_blks_count(struct super_block *sb, 2417 struct ext4_group_desc *bg) 2418 { 2419 return le16_to_cpu(bg->bg_free_blocks_count) | 2420 (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ? 2421 (__u32)le16_to_cpu(bg->bg_free_blocks_count_hi) << 16 : 0); 2422 } 2423 2424 __u32 ext4_free_inodes_count(struct super_block *sb, 2425 struct ext4_group_desc *bg) 2426 { 2427 return le16_to_cpu(bg->bg_free_inodes_count) | 2428 (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ? 2429 (__u32)le16_to_cpu(bg->bg_free_inodes_count_hi) << 16 : 0); 2430 } 2431 2432 __u32 ext4_used_dirs_count(struct super_block *sb, 2433 struct ext4_group_desc *bg) 2434 { 2435 return le16_to_cpu(bg->bg_used_dirs_count) | 2436 (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ? 2437 (__u32)le16_to_cpu(bg->bg_used_dirs_count_hi) << 16 : 0); 2438 } 2439 2440 __u32 ext4_itable_unused_count(struct super_block *sb, 2441 struct ext4_group_desc *bg) 2442 { 2443 return le16_to_cpu(bg->bg_itable_unused) | 2444 (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ? 2445 (__u32)le16_to_cpu(bg->bg_itable_unused_hi) << 16 : 0); 2446 } 2447 2448 void ext4_block_bitmap_set(struct super_block *sb, 2449 struct ext4_group_desc *bg, ext4_fsblk_t blk) 2450 { 2451 bg->bg_block_bitmap = cpu_to_le32((u32)blk); 2452 if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT) 2453 bg->bg_block_bitmap_hi = cpu_to_le32(blk >> 32); 2454 } 2455 2456 void ext4_inode_bitmap_set(struct super_block *sb, 2457 struct ext4_group_desc *bg, ext4_fsblk_t blk) 2458 { 2459 bg->bg_inode_bitmap = cpu_to_le32((u32)blk); 2460 if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT) 2461 bg->bg_inode_bitmap_hi = cpu_to_le32(blk >> 32); 2462 } 2463 2464 void ext4_inode_table_set(struct super_block *sb, 2465 struct ext4_group_desc *bg, ext4_fsblk_t blk) 2466 { 2467 bg->bg_inode_table = cpu_to_le32((u32)blk); 2468 if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT) 2469 bg->bg_inode_table_hi = cpu_to_le32(blk >> 32); 2470 } 2471 2472 void ext4_free_blks_set(struct super_block *sb, 2473 struct ext4_group_desc *bg, __u32 count) 2474 { 2475 bg->bg_free_blocks_count = cpu_to_le16((__u16)count); 2476 if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT) 2477 bg->bg_free_blocks_count_hi = cpu_to_le16(count >> 16); 2478 } 2479 2480 void ext4_free_inodes_set(struct super_block *sb, 2481 struct ext4_group_desc *bg, __u32 count) 2482 { 2483 bg->bg_free_inodes_count = cpu_to_le16((__u16)count); 2484 if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT) 2485 bg->bg_free_inodes_count_hi = cpu_to_le16(count >> 16); 2486 } 2487 2488 void ext4_used_dirs_set(struct super_block *sb, 2489 struct ext4_group_desc *bg, __u32 count) 2490 { 2491 bg->bg_used_dirs_count = cpu_to_le16((__u16)count); 2492 if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT) 2493 bg->bg_used_dirs_count_hi = cpu_to_le16(count >> 16); 2494 } 2495 2496 void ext4_itable_unused_set(struct super_block *sb, 2497 struct ext4_group_desc *bg, __u32 count) 2498 { 2499 bg->bg_itable_unused = cpu_to_le16((__u16)count); 2500 if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT) 2501 bg->bg_itable_unused_hi = cpu_to_le16(count >> 16); 2502 } 2503 2504 /** CRC table for the CRC-16. The poly is 0x8005 (x16 + x15 + x2 + 1) */ 2505 __u16 const crc16_table[256] = { 2506 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 2507 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, 2508 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 2509 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 2510 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 2511 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 2512 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 2513 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 2514 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 2515 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 2516 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 2517 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 2518 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 2519 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 2520 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 2521 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 2522 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 2523 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, 2524 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 2525 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 2526 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 2527 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 2528 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, 2529 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 2530 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 2531 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 2532 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 2533 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, 2534 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 2535 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, 2536 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 2537 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 2538 }; 2539 2540 static inline __u16 crc16_byte(__u16 crc, const __u8 data) 2541 { 2542 return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff]; 2543 } 2544 2545 __u16 crc16(__u16 crc, __u8 const *buffer, size_t len) 2546 { 2547 while (len--) 2548 crc = crc16_byte(crc, *buffer++); 2549 return crc; 2550 } 2551 2552 __le16 ext4_group_desc_csum(struct ext3_sb_info *sbi, __u32 block_group, 2553 struct ext4_group_desc *gdp) 2554 { 2555 int offset; 2556 __u16 crc = 0; 2557 __le32 le_group = cpu_to_le32(block_group); 2558 2559 /* old crc16 code */ 2560 if (!(sbi->s_es->s_feature_ro_compat & 2561 cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM))) 2562 return 0; 2563 2564 offset = offsetof(struct ext4_group_desc, bg_checksum); 2565 2566 crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid)); 2567 crc = crc16(crc, (__u8 *)&le_group, sizeof(le_group)); 2568 crc = crc16(crc, (__u8 *)gdp, offset); 2569 offset += sizeof(gdp->bg_checksum); /* skip checksum */ 2570 /* for checksum of struct ext4_group_desc do the rest...*/ 2571 if ((sbi->s_es->s_feature_incompat & 2572 cpu_to_le32(EXT4_FEATURE_INCOMPAT_64BIT)) && 2573 offset < le16_to_cpu(sbi->s_es->s_desc_size)) 2574 crc = crc16(crc, (__u8 *)gdp + offset, 2575 le16_to_cpu(sbi->s_es->s_desc_size) - 2576 offset); 2577 2578 return cpu_to_le16(crc); 2579 } 2580 2581 int ext4_group_desc_csum_verify(struct ext3_sb_info *sbi, __u32 block_group, 2582 struct ext4_group_desc *gdp) 2583 { 2584 if ((sbi->s_es->s_feature_ro_compat & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) && 2585 (gdp->bg_checksum != ext4_group_desc_csum(sbi, block_group, gdp))) 2586 return 0; 2587 2588 return 1; 2589 } 2590 2591 2592 static inline int test_root(ext3_group_t a, ext3_group_t b) 2593 { 2594 ext3_group_t num = b; 2595 2596 while (a > num) 2597 num *= b; 2598 return num == a; 2599 } 2600 2601 static int ext3_group_sparse(ext3_group_t group) 2602 { 2603 if (group <= 1) 2604 return 1; 2605 if (!(group & 1)) 2606 return 0; 2607 return (test_root(group, 7) || test_root(group, 5) || 2608 test_root(group, 3)); 2609 } 2610 2611 /** 2612 * ext4_bg_has_super - number of blocks used by the superblock in group 2613 * @sb: superblock for filesystem 2614 * @group: group number to check 2615 * 2616 * Return the number of blocks used by the superblock (primary or backup) 2617 * in this group. Currently this will be only 0 or 1. 2618 */ 2619 int ext3_bg_has_super(struct super_block *sb, ext3_group_t group) 2620 { 2621 if (EXT3_HAS_RO_COMPAT_FEATURE(sb, 2622 EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER) && 2623 !ext3_group_sparse(group)) 2624 return 0; 2625 return 1; 2626 } 2627 2628 static unsigned long ext4_bg_num_gdb_meta(struct super_block *sb, 2629 ext4_group_t group) 2630 { 2631 unsigned long metagroup = group / EXT4_DESC_PER_BLOCK(sb); 2632 ext4_group_t first = metagroup * EXT4_DESC_PER_BLOCK(sb); 2633 ext4_group_t last = first + EXT4_DESC_PER_BLOCK(sb) - 1; 2634 2635 if (group == first || group == first + 1 || group == last) 2636 return 1; 2637 return 0; 2638 } 2639 2640 static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb, 2641 ext4_group_t group) 2642 { 2643 return ext3_bg_has_super(sb, group) ? EXT3_SB(sb)->s_gdb_count : 0; 2644 } 2645 2646 /** 2647 * ext4_bg_num_gdb - number of blocks used by the group table in group 2648 * @sb: superblock for filesystem 2649 * @group: group number to check 2650 * 2651 * Return the number of blocks used by the group descriptor table 2652 * (primary or backup) in this group. In the future there may be a 2653 * different number of descriptor blocks in each group. 2654 */ 2655 unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group) 2656 { 2657 unsigned long first_meta_bg = 2658 le32_to_cpu(EXT3_SB(sb)->s_es->s_first_meta_bg); 2659 unsigned long metagroup = group / EXT4_DESC_PER_BLOCK(sb); 2660 2661 if (!EXT3_HAS_INCOMPAT_FEATURE(sb,EXT4_FEATURE_INCOMPAT_META_BG) || 2662 metagroup < first_meta_bg) 2663 return ext4_bg_num_gdb_nometa(sb, group); 2664 2665 return ext4_bg_num_gdb_meta(sb,group); 2666 2667 } 2668 2669 ext3_fsblk_t descriptor_loc(struct super_block *sb, 2670 ext3_fsblk_t logical_sb_block, unsigned int nr) 2671 { 2672 struct ext3_sb_info *sbi = EXT3_SB(sb); 2673 ext3_group_t bg, first_meta_bg; 2674 int has_super = 0; 2675 2676 first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg); 2677 2678 if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) || 2679 nr < first_meta_bg) 2680 return logical_sb_block + nr + 1; 2681 bg = sbi->s_desc_per_block * nr; 2682 if (ext3_bg_has_super(sb, bg)) 2683 has_super = 1; 2684 return (has_super + ext3_group_first_block_no(sb, bg)); 2685 } 2686 2687 #define ext4_set_bit(n, p) set_bit((int)(n), (unsigned long *)(p)) 2688 2689 /* 2690 * The free inodes are managed by bitmaps. A file system contains several 2691 * blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap 2692 * block for inodes, N blocks for the inode table and data blocks. 2693 * 2694 * The file system contains group descriptors which are located after the 2695 * super block. Each descriptor contains the number of the bitmap block and 2696 * the free blocks count in the block. 2697 */ 2698 2699 /* 2700 * To avoid calling the atomic setbit hundreds or thousands of times, we only 2701 * need to use it within a single byte (to ensure we get endianness right). 2702 * We can use memset for the rest of the bitmap as there are no other users. 2703 */ 2704 void mark_bitmap_end(int start_bit, int end_bit, char *bitmap) 2705 { 2706 int i; 2707 2708 if (start_bit >= end_bit) 2709 return; 2710 2711 DEBUG(DL_INF, ("mark end bits +%d through +%d used\n", start_bit, end_bit)); 2712 for (i = start_bit; (unsigned)i < ((start_bit + 7) & ~7UL); i++) 2713 ext4_set_bit(i, bitmap); 2714 if (i < end_bit) 2715 memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3); 2716 } 2717 2718 /* Initializes an uninitialized inode bitmap */ 2719 unsigned ext4_init_inode_bitmap(struct super_block *sb, struct buffer_head *bh, 2720 ext4_group_t block_group, 2721 struct ext4_group_desc *gdp) 2722 { 2723 struct ext3_sb_info *sbi = EXT3_SB(sb); 2724 2725 mark_buffer_dirty(bh); 2726 2727 /* If checksum is bad mark all blocks and inodes use to prevent 2728 * allocation, essentially implementing a per-group read-only flag. */ 2729 if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) { 2730 ext4_error(sb, __FUNCTION__, "Checksum bad for group %u", 2731 block_group); 2732 ext4_free_blks_set(sb, gdp, 0); 2733 ext4_free_inodes_set(sb, gdp, 0); 2734 ext4_itable_unused_set(sb, gdp, 0); 2735 memset(bh->b_data, 0xff, sb->s_blocksize); 2736 return 0; 2737 } 2738 2739 memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8); 2740 mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8, 2741 bh->b_data); 2742 ext4_itable_unused_set(sb, gdp, EXT4_INODES_PER_GROUP(sb)); 2743 2744 return EXT4_INODES_PER_GROUP(sb); 2745 } 2746 2747 /* 2748 * Calculate the block group number and offset, given a block number 2749 */ 2750 void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr, 2751 ext4_group_t *blockgrpp, ext4_grpblk_t *offsetp) 2752 { 2753 struct ext3_super_block *es = EXT3_SB(sb)->s_es; 2754 ext4_grpblk_t offset; 2755 2756 blocknr = blocknr - le32_to_cpu(es->s_first_data_block); 2757 offset = do_div(blocknr, EXT4_BLOCKS_PER_GROUP(sb)); 2758 if (offsetp) 2759 *offsetp = offset; 2760 if (blockgrpp) 2761 *blockgrpp = (ext4_grpblk_t)blocknr; 2762 2763 } 2764 2765 static int ext4_block_in_group(struct super_block *sb, ext4_fsblk_t block, 2766 ext4_group_t block_group) 2767 { 2768 ext4_group_t actual_group; 2769 ext4_get_group_no_and_offset(sb, block, &actual_group, NULL); 2770 if (actual_group == block_group) 2771 return 1; 2772 return 0; 2773 } 2774 2775 static int ext4_group_used_meta_blocks(struct super_block *sb, 2776 ext4_group_t block_group) 2777 { 2778 ext4_fsblk_t tmp; 2779 struct ext3_sb_info *sbi = EXT3_SB(sb); 2780 /* block bitmap, inode bitmap, and inode table blocks */ 2781 int used_blocks = sbi->s_itb_per_group + 2; 2782 2783 if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) { 2784 struct ext4_group_desc *gdp; 2785 struct buffer_head *bh = NULL; 2786 2787 gdp = ext4_get_group_desc(sb, block_group, &bh); 2788 if (!ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp), 2789 block_group)) 2790 used_blocks--; 2791 2792 if (!ext4_block_in_group(sb, ext4_inode_bitmap(sb, gdp), 2793 block_group)) 2794 used_blocks--; 2795 2796 tmp = ext4_inode_table(sb, gdp); 2797 for (; tmp < ext4_inode_table(sb, gdp) + 2798 sbi->s_itb_per_group; tmp++) { 2799 if (!ext4_block_in_group(sb, tmp, block_group)) 2800 used_blocks -= 1; 2801 } 2802 if (bh) 2803 fini_bh(&bh); 2804 } 2805 return used_blocks; 2806 } 2807 2808 /* Initializes an uninitialized block bitmap if given, and returns the 2809 * number of blocks free in the group. */ 2810 unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, 2811 ext4_group_t block_group, struct ext4_group_desc *gdp) 2812 { 2813 int bit, bit_max; 2814 unsigned free_blocks, group_blocks; 2815 struct ext3_sb_info *sbi = EXT3_SB(sb); 2816 2817 if (bh) { 2818 mark_buffer_dirty(bh); 2819 /* If checksum is bad mark all blocks used to prevent allocation 2820 * essentially implementing a per-group read-only flag. */ 2821 if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) { 2822 ext4_error(sb, __FUNCTION__, 2823 "Checksum bad for group %u", block_group); 2824 ext4_free_blks_set(sb, gdp, 0); 2825 ext4_free_inodes_set(sb, gdp, 0); 2826 ext4_itable_unused_set(sb, gdp, 0); 2827 memset(bh->b_data, 0xff, sb->s_blocksize); 2828 return 0; 2829 } 2830 memset(bh->b_data, 0, sb->s_blocksize); 2831 } 2832 2833 /* Check for superblock and gdt backups in this group */ 2834 bit_max = ext3_bg_has_super(sb, block_group); 2835 2836 if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) || 2837 block_group < le32_to_cpu(sbi->s_es->s_first_meta_bg) * 2838 sbi->s_desc_per_block) { 2839 if (bit_max) { 2840 bit_max += ext4_bg_num_gdb(sb, block_group); 2841 bit_max += 2842 le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks); 2843 } 2844 } else { /* For META_BG_BLOCK_GROUPS */ 2845 bit_max += ext4_bg_num_gdb(sb, block_group); 2846 } 2847 2848 if (block_group == sbi->s_groups_count - 1) { 2849 /* 2850 * Even though mke2fs always initialize first and last group 2851 * if some other tool enabled the EXT4_BG_BLOCK_UNINIT we need 2852 * to make sure we calculate the right free blocks 2853 */ 2854 group_blocks = (unsigned int)(ext3_blocks_count(sbi->s_es) - 2855 le32_to_cpu(sbi->s_es->s_first_data_block) - 2856 (EXT4_BLOCKS_PER_GROUP(sb) * (sbi->s_groups_count - 1))); 2857 } else { 2858 group_blocks = EXT4_BLOCKS_PER_GROUP(sb); 2859 } 2860 2861 free_blocks = group_blocks - bit_max; 2862 2863 if (bh) { 2864 ext4_fsblk_t start, tmp; 2865 int flex_bg = 0; 2866 2867 for (bit = 0; bit < bit_max; bit++) 2868 ext4_set_bit(bit, bh->b_data); 2869 2870 start = ext3_group_first_block_no(sb, block_group); 2871 2872 if (EXT3_HAS_INCOMPAT_FEATURE(sb, 2873 EXT4_FEATURE_INCOMPAT_FLEX_BG)) 2874 flex_bg = 1; 2875 2876 /* Set bits for block and inode bitmaps, and inode table */ 2877 tmp = ext4_block_bitmap(sb, gdp); 2878 if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) 2879 ext4_set_bit(tmp - start, bh->b_data); 2880 2881 tmp = ext4_inode_bitmap(sb, gdp); 2882 if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) 2883 ext4_set_bit(tmp - start, bh->b_data); 2884 2885 tmp = ext4_inode_table(sb, gdp); 2886 for (; tmp < ext4_inode_table(sb, gdp) + 2887 sbi->s_itb_per_group; tmp++) { 2888 if (!flex_bg || 2889 ext4_block_in_group(sb, tmp, block_group)) 2890 ext4_set_bit(tmp - start, bh->b_data); 2891 } 2892 /* 2893 * Also if the number of blocks within the group is 2894 * less than the blocksize * 8 ( which is the size 2895 * of bitmap ), set rest of the block bitmap to 1 2896 */ 2897 mark_bitmap_end(group_blocks, sb->s_blocksize * 8, bh->b_data); 2898 } 2899 return free_blocks - ext4_group_used_meta_blocks(sb, block_group); 2900 } 2901 2902 /** 2903 * ext4_get_group_desc() -- load group descriptor from disk 2904 * @sb: super block 2905 * @block_group: given block group 2906 * @bh: pointer to the buffer head to store the block 2907 * group descriptor 2908 */ 2909 struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb, 2910 ext4_group_t block_group, struct buffer_head **bh) 2911 { 2912 struct ext4_group_desc *desc = NULL; 2913 struct ext3_sb_info *sbi = EXT3_SB(sb); 2914 PEXT2_VCB vcb = sb->s_priv; 2915 ext4_group_t group; 2916 ext4_group_t offset; 2917 2918 if (bh) 2919 *bh = NULL; 2920 2921 if (block_group >= sbi->s_groups_count) { 2922 ext4_error(sb, "ext4_get_group_desc", 2923 "block_group >= groups_count - " 2924 "block_group = %u, groups_count = %u", 2925 block_group, sbi->s_groups_count); 2926 2927 return NULL; 2928 } 2929 2930 _SEH2_TRY { 2931 2932 group = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb); 2933 offset = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1); 2934 2935 if (!sbi->s_gd) { 2936 if (!Ext2LoadGroup(vcb)) { 2937 _SEH2_LEAVE; 2938 } 2939 } else if ( !sbi->s_gd[group].block || 2940 !sbi->s_gd[group].bh) { 2941 if (!Ext2LoadGroupBH(vcb)) { 2942 _SEH2_LEAVE; 2943 } 2944 } 2945 2946 desc = (struct ext4_group_desc *)((PCHAR)sbi->s_gd[group].gd + 2947 offset * EXT4_DESC_SIZE(sb)); 2948 if (bh) { 2949 atomic_inc(&sbi->s_gd[group].bh->b_count); 2950 *bh = sbi->s_gd[group].bh; 2951 } 2952 } _SEH2_FINALLY { 2953 /* do cleanup */ 2954 } _SEH2_END; 2955 2956 return desc; 2957 } 2958 2959 2960 /** 2961 * ext4_count_free_blocks() -- count filesystem free blocks 2962 * @sb: superblock 2963 * 2964 * Adds up the number of free blocks from each block group. 2965 */ 2966 ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb) 2967 { 2968 ext4_fsblk_t desc_count; 2969 struct ext4_group_desc *gdp; 2970 struct buffer_head *bh = NULL; 2971 ext4_group_t i; 2972 ext4_group_t ngroups = EXT3_SB(sb)->s_groups_count; 2973 2974 desc_count = 0; 2975 smp_rmb(); 2976 for (i = 0; i < ngroups; i++) { 2977 gdp = ext4_get_group_desc(sb, i, &bh); 2978 if (!bh) 2979 continue; 2980 desc_count += ext4_free_blks_count(sb, gdp); 2981 fini_bh(&bh); 2982 } 2983 2984 return desc_count; 2985 } 2986 2987 unsigned long ext4_count_free_inodes(struct super_block *sb) 2988 { 2989 unsigned long desc_count; 2990 struct ext4_group_desc *gdp; 2991 struct buffer_head *bh = NULL; 2992 ext4_group_t i; 2993 2994 desc_count = 0; 2995 for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) { 2996 gdp = ext4_get_group_desc(sb, i, &bh); 2997 if (!bh) 2998 continue; 2999 desc_count += ext4_free_inodes_count(sb, gdp); 3000 fini_bh(&bh); 3001 } 3002 return desc_count; 3003 } 3004 3005 /* Called at mount-time, super-block is locked */ 3006 unsigned long ext4_count_dirs(struct super_block * sb) 3007 { 3008 struct ext4_group_desc *gdp; 3009 struct buffer_head *bh = NULL; 3010 unsigned long count = 0; 3011 ext4_group_t i; 3012 3013 for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) { 3014 gdp = ext4_get_group_desc(sb, i, &bh); 3015 if (!bh) 3016 continue; 3017 count += ext4_used_dirs_count(sb, gdp); 3018 fini_bh(&bh); 3019 } 3020 return count; 3021 } 3022 3023 /* Called at mount-time, super-block is locked */ 3024 int ext4_check_descriptors(struct super_block *sb) 3025 { 3026 PEXT2_VCB Vcb = sb->s_priv; 3027 struct ext3_sb_info *sbi = EXT3_SB(sb); 3028 ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block); 3029 ext4_fsblk_t last_block; 3030 ext4_fsblk_t block_bitmap; 3031 ext4_fsblk_t inode_bitmap; 3032 ext4_fsblk_t inode_table; 3033 int flexbg_flag = 0; 3034 ext4_group_t i; 3035 3036 if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) 3037 flexbg_flag = 1; 3038 3039 DEBUG(DL_INF, ("Checking group descriptors")); 3040 3041 for (i = 0; i < sbi->s_groups_count; i++) { 3042 3043 struct buffer_head *bh = NULL; 3044 struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, &bh); 3045 3046 if (!bh) 3047 continue; 3048 3049 if (i == sbi->s_groups_count - 1 || flexbg_flag) 3050 last_block = ext3_blocks_count(sbi->s_es) - 1; 3051 else 3052 last_block = first_block + 3053 (EXT3_BLOCKS_PER_GROUP(sb) - 1); 3054 3055 block_bitmap = ext4_block_bitmap(sb, gdp); 3056 if (block_bitmap < first_block || block_bitmap > last_block) { 3057 printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: " 3058 "Block bitmap for group %u not in group " 3059 "(block %llu)!\n", i, block_bitmap); 3060 __brelse(bh); 3061 return 0; 3062 } 3063 inode_bitmap = ext4_inode_bitmap(sb, gdp); 3064 if (inode_bitmap < first_block || inode_bitmap > last_block) { 3065 printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: " 3066 "Inode bitmap for group %u not in group " 3067 "(block %llu)!\n", i, inode_bitmap); 3068 __brelse(bh); 3069 return 0; 3070 } 3071 inode_table = ext4_inode_table(sb, gdp); 3072 if (inode_table < first_block || 3073 inode_table + sbi->s_itb_per_group - 1 > last_block) { 3074 printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: " 3075 "Inode table for group %u not in group " 3076 "(block %llu)!\n", i, inode_table); 3077 __brelse(bh); 3078 return 0; 3079 } 3080 3081 if (!ext4_group_desc_csum_verify(sbi, i, gdp)) { 3082 printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: " 3083 "Checksum for group %u failed (%u!=%u)\n", 3084 i, le16_to_cpu(ext4_group_desc_csum(sbi, i, 3085 gdp)), 3086 le16_to_cpu(gdp->bg_checksum)); 3087 if (!IsVcbReadOnly(Vcb)) { 3088 __brelse(bh); 3089 return 0; 3090 } 3091 } 3092 3093 if (!flexbg_flag) 3094 first_block += EXT4_BLOCKS_PER_GROUP(sb); 3095 3096 __brelse(bh); 3097 } 3098 3099 ext3_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb)); 3100 sbi->s_es->s_free_inodes_count = cpu_to_le32(ext4_count_free_inodes(sb)); 3101 return 1; 3102 } 3103