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