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