[haiku-commits] r40129 - haiku/trunk/src/add-ons/kernel/file_systems/ext2

  • From: korli@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 5 Jan 2011 22:56:12 +0100 (CET)

Author: korli
Date: 2011-01-05 22:56:12 +0100 (Wed, 05 Jan 2011)
New Revision: 40129
Changeset: http://dev.haiku-os.org/changeset/40129

Added:
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/CRCTable.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/CRCTable.h
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/crc_table.cpp
Modified:
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/ExtentStream.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/ExtentStream.h
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/HTree.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/Inode.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/Inode.h
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/InodeAllocator.h
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/Jamfile
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/Volume.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/Volume.h
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/ext2.h
Log:
* added flex group, dirnlink and gdtchecksum features for ext4.
* I reused crc_table.cpp from the UDF filesystem and switched it to have the 
reversed algorithm,
  then generated the table in CRCTable.cpp
* added a binary search for extent tree leaves.
* fixed a check in InodeAllocator::New().


Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp 
2011-01-05 21:06:57 UTC (rev 40128)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp 
2011-01-05 21:56:12 UTC (rev 40129)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2010, Haiku Inc. All rights reserved.
+ * Copyright 2001-2011, Haiku Inc. All rights reserved.
  * This file may be used under the terms of the MIT License.
  *
  * Authors:
@@ -36,7 +36,6 @@
                        status_t        Initialize(Volume* volume, uint32 
blockGroup,
                                                        uint32 numBits);
 
-                       status_t        ScanFreeRanges();
                        bool            IsFull() const;
 
                        status_t        Allocate(Transaction& transaction, 
fsblock_t start,
@@ -58,10 +57,13 @@
                        void            RemovedFromTransaction();
 
 private:
+                       status_t        _ScanFreeRanges();
                        void            _AddFreeRange(uint32 start, uint32 
length);
                        void            _LockInTransaction(Transaction& 
transaction);
+                       status_t        _InitGroup(Transaction& transaction);
+                       bool            _IsSparse();
+                       uint32          _FirstFreeBlock();
 
-
                        Volume*         fVolume;
                        uint32          fBlockGroup;
                        ext2_block_group* fGroupDescriptor;
@@ -130,7 +132,17 @@
 
        fBitmapBlock = 
fGroupDescriptor->BlockBitmap(fVolume->Has64bitFeature());
 
-       status = ScanFreeRanges();
+       if (fGroupDescriptor->Flags() & EXT2_BLOCK_GROUP_BLOCK_UNINIT) {
+               fFreeBits = 
fGroupDescriptor->FreeBlocks(fVolume->Has64bitFeature());
+               fLargestLength = fFreeBits;
+               fLargestStart = _FirstFreeBlock();
+               TRACE("Group %ld is uninit\n", fBlockGroup);
+               return B_OK;
+       }
+       
+       status = _ScanFreeRanges();
+       if (status != B_OK)
+               return status;
 
        if (fGroupDescriptor->FreeBlocks(fVolume->Has64bitFeature())
                != fFreeBits) {
@@ -152,14 +164,16 @@
 
 
 status_t
-AllocationBlockGroup::ScanFreeRanges()
+AllocationBlockGroup::_ScanFreeRanges()
 {
-       TRACE("AllocationBlockGroup::ScanFreeRanges()\n");
+       TRACE("AllocationBlockGroup::_ScanFreeRanges() for group %ld\n",
+               fBlockGroup);
        BitmapBlock block(fVolume, fNumBits);
 
        if (!block.SetTo(fBitmapBlock))
                return B_ERROR;
 
+       fFreeBits = 0;
        uint32 start = 0;
        uint32 end = 0;
 
@@ -201,6 +215,7 @@
                return B_BAD_VALUE;
 
        _LockInTransaction(transaction);
+       _InitGroup(transaction);
 
        BitmapBlock block(fVolume, fNumBits);
 
@@ -252,6 +267,7 @@
 
        if (fLargestLength < fNumBits / 2)
                block.FindLargestUnmarkedRange(fLargestStart, fLargestLength);
+       ASSERT(block.CheckUnmarked(fLargestStart, fLargestLength));
 
        return B_OK;
 }
@@ -272,6 +288,8 @@
                return B_BAD_VALUE;
 
        _LockInTransaction(transaction);
+       if (fGroupDescriptor->Flags() & EXT2_BLOCK_GROUP_BLOCK_UNINIT)
+               panic("AllocationBlockGroup::Free() can't free blocks if 
uninit\n");
 
        BitmapBlock block(fVolume, fNumBits);
 
@@ -402,6 +420,89 @@
 }
 
 
+status_t
+AllocationBlockGroup::_InitGroup(Transaction& transaction)
+{
+       TRACE("AllocationBlockGroup::_InitGroup()\n");
+       uint16 flags = fGroupDescriptor->Flags();
+       if ((flags & EXT2_BLOCK_GROUP_BLOCK_UNINIT) == 0)
+               return B_OK;
+
+       TRACE("AllocationBlockGroup::_InitGroup() initing\n");
+
+       BitmapBlock blockBitmap(fVolume, fNumBits);
+       if (!blockBitmap.SetToWritable(transaction, fBitmapBlock))
+               return B_ERROR;
+       blockBitmap.Mark(0, _FirstFreeBlock(), true);
+       blockBitmap.Unmark(0, fNumBits, true);
+       
+       fGroupDescriptor->SetFlags(flags & ~EXT2_BLOCK_GROUP_BLOCK_UNINIT);
+       fVolume->WriteBlockGroup(transaction, fBlockGroup);
+
+       status_t status = _ScanFreeRanges();
+       if (status != B_OK)
+               return status;
+
+       if (fGroupDescriptor->FreeBlocks(fVolume->Has64bitFeature())
+               != fFreeBits) {
+               ERROR("AllocationBlockGroup(%lu,%lld)::_InitGroup(): Mismatch 
between "
+                       "counted free blocks (%lu/%lu) and what is set on the 
group "
+                       "descriptor (%lu)\n", fBlockGroup, fBitmapBlock, 
fFreeBits,
+                       fNumBits, fGroupDescriptor->FreeBlocks(
+                               fVolume->Has64bitFeature()));
+               return B_BAD_DATA;
+       }
+
+       TRACE("AllocationBlockGroup::_InitGroup() init OK\n");
+
+       return B_OK;
+}
+
+
+bool
+AllocationBlockGroup::_IsSparse()
+{
+       if (fBlockGroup <= 1)
+               return true;
+       if (fBlockGroup & 0x1)
+               return false;
+
+       uint32 i = fBlockGroup;
+       while (i % 7 == 0)
+               i /= 7;
+       if (i == 1)
+               return true;
+
+       i = fBlockGroup;
+       while (i % 5 == 0)
+               i /= 5;
+       if (i == 1)
+               return true;
+
+       i = fBlockGroup;
+       while (i % 3 == 0)
+               i /= 3;
+       if (i == 1)
+               return true;
+
+       return false;
+}
+
+
+uint32
+AllocationBlockGroup::_FirstFreeBlock()
+{
+       uint32 first = 1;
+       if (_IsSparse())
+               first = 0;
+       else if (!fVolume->HasMetaGroupFeature()) {
+               first += fVolume->SuperBlock().ReservedGDTBlocks();
+               first += fVolume->NumGroups();
+       }
+       return first;
+}
+
+
 void
 AllocationBlockGroup::TransactionDone(bool success)
 {

Added: haiku/trunk/src/add-ons/kernel/file_systems/ext2/CRCTable.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/CRCTable.cpp               
                (rev 0)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/CRCTable.cpp       
2011-01-05 21:56:12 UTC (rev 40129)
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2011, Haiku Inc. All rights reserved.
+ * This file may be used under the terms of the MIT License.
+ *
+ * Authors:
+ *             Jérôme Duval
+ */
+
+
+#include <SupportDefs.h>
+
+
+//! CRC 0120001 table, as generated by crc_table.cpp
+static uint16 kCrcTable[256] = { 
+    0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 
+    0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, 
+    0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 
+    0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, 
+    0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 
+    0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, 
+    0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, 
+    0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, 
+    0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, 
+    0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, 
+    0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, 
+    0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, 
+    0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 
+    0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, 
+    0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, 
+    0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, 
+    0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, 
+    0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, 
+    0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 
+    0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, 
+    0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 
+    0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, 
+    0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, 
+    0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, 
+    0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, 
+    0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, 
+    0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 
+    0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, 
+    0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 
+    0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, 
+    0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 
+    0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040 
+};
+
+
+/*! \brief Calculates the UDF crc checksum for the given byte stream.
+
+       Based on crc code from UDF-2.50 6.5, as permitted.
+       This is reversed.
+
+       \param data Pointer to the byte stream.
+       \param length Length of the byte stream in bytes.
+
+       \return The crc checksum, or 0 if an error occurred.
+*/
+uint16
+calculate_crc(uint16 crc, uint8 *data, uint16 length)
+{
+       if (data) {
+               for ( ; length > 0; length--, data++)
+                       crc = kCrcTable[(crc ^ *data) & 0xff] ^ (crc >> 8);
+       }
+       return crc;
+}
+

Added: haiku/trunk/src/add-ons/kernel/file_systems/ext2/CRCTable.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/CRCTable.h                 
        (rev 0)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/CRCTable.h 2011-01-05 
21:56:12 UTC (rev 40129)
@@ -0,0 +1,11 @@
+/*
+ * Copyright 2011, Haiku Inc. All rights reserved.
+ * This file may be used under the terms of the MIT License.
+ *
+ * Authors:
+ *             Jérôme Duval
+ */
+
+uint16 calculate_crc(uint16 crc, uint8 *data, uint16 length);
+
+

Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/ExtentStream.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/ExtentStream.cpp   
2011-01-05 21:06:57 UTC (rev 40128)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/ExtentStream.cpp   
2011-01-05 21:56:12 UTC (rev 40129)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2010, Haiku Inc. All rights reserved.
+ * Copyright 2001-2011, Haiku Inc. All rights reserved.
  * This file may be used under the terms of the MIT License.
  *
  * Authors:
@@ -77,6 +77,41 @@
                        panic("ExtentStream::FindBlock() invalid header\n");
        }
 
+       if (stream->extent_header.NumEntries() > 7) {
+               // binary search when enough entries
+               int32 low = 0;
+               int32 high = stream->extent_header.NumEntries() - 1;
+               int32 middle = 0;
+               while (low <= high) {
+                       middle = (high + low) / 2;
+                       if (stream->extent_entries[middle].LogicalBlock() == 
index)
+                               break;
+                       if (stream->extent_entries[middle].LogicalBlock() < 
index)
+                               low = middle + 1;
+                       else
+                               high = middle - 1;
+               }
+               if (stream->extent_entries[middle].LogicalBlock() > index)
+                       middle--;
+               if (stream->extent_entries[middle].LogicalBlock() 
+                       +  stream->extent_entries[middle].Length() > index) {
+                       // sparse block
+                       TRACE("FindBlock() sparse block index %lld at %ld\n", 
index,
+                               stream->extent_entries[middle].LogicalBlock());
+                       block = 0xffffffff;
+                       return B_OK;
+               }
+
+               fileblock_t diff = index 
+                       - stream->extent_entries[middle].LogicalBlock();
+               block = stream->extent_entries[middle].PhysicalBlock() + diff;
+               if (_count)
+                       *_count = stream->extent_entries[middle].Length() - 
diff;
+               TRACE("FindBlock(offset %lld): %lld %ld\n", offset, 
+                       block, _count != NULL ? *_count : 1);
+               return B_OK;
+       }
+
        for (int32 i = 0; i < stream->extent_header.NumEntries(); i++) {
                if (stream->extent_entries[i].LogicalBlock() > index) {
                        // sparse block

Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/ExtentStream.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/ExtentStream.h     
2011-01-05 21:06:57 UTC (rev 40128)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/ExtentStream.h     
2011-01-05 21:56:12 UTC (rev 40129)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2010, Haiku Inc. All rights reserved.
+ * Copyright 2001-2011, Haiku Inc. All rights reserved.
  * This file may be used under the terms of the MIT License.
  *
  * Authors:
@@ -8,6 +8,7 @@
 #ifndef EXTENTSTREAM_H
 #define EXTENTSTREAM_H
 
+
 #include "ext2.h"
 #include "Transaction.h"
 

Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/HTree.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/HTree.cpp  2011-01-05 
21:06:57 UTC (rev 40128)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/HTree.cpp  2011-01-05 
21:56:12 UTC (rev 40129)
@@ -54,8 +54,7 @@
        fRootEntry(NULL)
 {
        fBlockSize = volume->BlockSize();
-       fIndexed = volume->IndexedDirectories()
-               && (directory->Flags() & EXT2_INODE_INDEXED) != 0;
+       fIndexed = directory->IsIndexed();
 
        ext2_super_block superBlock = volume->SuperBlock();
        fHashSeed[0] = superBlock.HashSeed(0);

Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/Inode.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/Inode.cpp  2011-01-05 
21:06:57 UTC (rev 40128)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/Inode.cpp  2011-01-05 
21:56:12 UTC (rev 40129)
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2011, Jérôme Duval, korli@xxxxxxxxxxxxxxxxx
  * Copyright 2008, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
  * This file may be used under the terms of the MIT License.
  */
@@ -440,7 +441,7 @@
        root->dotdot_entry_name[0] = '.';
        root->dotdot_entry_name[1] = '.';
 
-       parent->Node().SetNumLinks(parent->Node().NumLinks() + 1);
+       parent->IncrementNumLinks(transaction);
 
        return parent->WriteBack(transaction);
 }
@@ -911,3 +912,15 @@
        return B_OK;
 }
 
+
+void
+Inode::IncrementNumLinks(Transaction& transaction)
+{
+       fNode.SetNumLinks(fNode.NumLinks() + 1);
+       if (IsIndexed() && (fNode.NumLinks() >= EXT2_INODE_MAX_LINKS
+               || fNode.NumLinks() == 2)) {
+               fNode.SetNumLinks(1);
+               fVolume->ActivateDirNLink(transaction);
+       }
+}
+

Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/Inode.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/Inode.h    2011-01-05 
21:06:57 UTC (rev 40128)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/Inode.h    2011-01-05 
21:56:12 UTC (rev 40129)
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2011, Jérôme Duval, korli@xxxxxxxxxxxxxxxxx
  * Copyright 2008, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
  * This file may be used under the terms of the MIT License.
  */
@@ -50,6 +51,9 @@
                        bool            IsDeleted() const { return fUnlinked; }
                        bool            HasExtraAttributes() const
                                                        { return 
fHasExtraAttributes; }
+                       bool            IsIndexed() const 
+                                               { return 
fVolume->IndexedDirectories()
+                                                       && (Flags() & 
EXT2_INODE_INDEXED) != 0; }
 
                        mode_t          Mode() const { return fNode.Mode(); }
                        int32           Flags() const { return fNode.Flags(); }
@@ -75,6 +79,7 @@
                                                        fHasExtraAttributes); }
                        void            SetAccessTime(const struct timespec 
*timespec)
                                                { fNode.SetAccessTime(timespec, 
fHasExtraAttributes); }
+                       void            IncrementNumLinks(Transaction& 
transaction);
 
                        //::Volume* _Volume() const { return fVolume; }
                        Volume*         GetVolume() const { return fVolume; }

Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp 
2011-01-05 21:06:57 UTC (rev 40128)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp 
2011-01-05 21:56:12 UTC (rev 40129)
@@ -1,8 +1,9 @@
 /*
- * Copyright 2001-2010, Haiku Inc. All rights reserved.
+ * Copyright 2001-2011, Haiku Inc. All rights reserved.
  * This file may be used under the terms of the MIT License.
  *
  * Authors:
+ *             Jérôme Duval
  *             Janito V. Ferreira Filho
  */
 
@@ -44,7 +45,7 @@
        ino_t& id)
 {
        // Apply allocation policy
-       uint32 preferredBlockGroup = parent == NULL ? parent->ID()
+       uint32 preferredBlockGroup = parent != NULL ? (parent->ID() - 1)
                / parent->GetVolume()->InodesPerGroup() : 0;
        
        return _Allocate(transaction, preferredBlockGroup, S_ISDIR(mode), id);
@@ -65,16 +66,20 @@
        if (status != B_OK)
                return status;
 
+       if (group->Flags() & EXT2_BLOCK_GROUP_INODE_UNINIT)
+               panic("InodeAllocator::Free() can't free inodes if uninit\n");
+
        if (blockGroup == fVolume->NumGroups() - 1)
                numInodes = fVolume->NumInodes() - blockGroup * numInodes;
 
        TRACE("InodeAllocator::Free(): Updating block group data\n");
        group->SetFreeInodes(group->FreeInodes(fVolume->Has64bitFeature()) + 1,
                fVolume->Has64bitFeature());
-       if (isDirectory)
+       if (isDirectory) {
                group->SetUsedDirectories(
                        group->UsedDirectories(fVolume->Has64bitFeature()) - 1,
                        fVolume->Has64bitFeature());
+       }
 
        status = fVolume->WriteBlockGroup(transaction, blockGroup);
        if (status != B_OK)
@@ -104,6 +109,8 @@
                                return status;
                        }
 
+                       fsblock_t block = 
group->InodeBitmap(fVolume->Has64bitFeature());
+                       _InitGroup(transaction, group, block, 
fVolume->InodesPerGroup());
                        uint32 freeInodes = 
group->FreeInodes(fVolume->Has64bitFeature());
                        if (freeInodes != 0) {
                                TRACE("InodeAllocator::_Allocate() freeInodes 
%ld bitmap %lld\n",
@@ -118,8 +125,7 @@
                                if (status != B_OK)
                                        return status;
 
-                               return _MarkInBitmap(transaction, 
-                                       
group->InodeBitmap(fVolume->Has64bitFeature()),
+                               return _MarkInBitmap(transaction, block,
                                        blockGroup, fVolume->InodesPerGroup(), 
id);
                        }
                }
@@ -133,16 +139,27 @@
                                return status;
                        }
 
+                       uint32 numInodes = fVolume->NumInodes() 
+                               - blockGroup * fVolume->InodesPerGroup();
+                       fsblock_t block = 
group->InodeBitmap(fVolume->Has64bitFeature());
+                       _InitGroup(transaction, group, block, numInodes);
                        uint32 freeInodes = 
group->FreeInodes(fVolume->Has64bitFeature());
                        if (freeInodes != 0) {
                                TRACE("InodeAllocator::_Allocate() freeInodes 
%ld\n", freeInodes);
                                group->SetFreeInodes(freeInodes - 1,
                                        fVolume->Has64bitFeature());
+                               if (isDirectory) {
+                                       
group->SetUsedDirectories(group->UsedDirectories(
+                                               fVolume->Has64bitFeature()) + 1,
+                                               fVolume->Has64bitFeature());
+                               }
 
-                               return _MarkInBitmap(transaction, 
-                                       
group->InodeBitmap(fVolume->Has64bitFeature()),
-                                       blockGroup, fVolume->NumInodes()
-                                               - blockGroup * 
fVolume->InodesPerGroup(), id);
+                               status = fVolume->WriteBlockGroup(transaction, 
blockGroup);
+                               if (status != B_OK)
+                                       return status;
+
+                               return _MarkInBitmap(transaction, block,
+                                       blockGroup, numInodes, id);
                        }
                }
 
@@ -209,3 +226,23 @@
 
        return B_OK;
 }
+
+
+status_t
+InodeAllocator::_InitGroup(Transaction& transaction, ext2_block_group* group,
+       fsblock_t bitmapBlock, uint32 numInodes)
+{
+       uint16 flags = group->Flags();
+       if ((flags & EXT2_BLOCK_GROUP_INODE_UNINIT) == 0)
+               return B_OK;
+
+       TRACE("InodeAllocator::_InitGroup() initing group\n");
+       BitmapBlock inodeBitmap(fVolume, numInodes);
+       if (!inodeBitmap.SetToWritable(transaction, bitmapBlock))
+               return B_ERROR;
+       inodeBitmap.Unmark(0, numInodes, true);
+       group->SetFlags(flags & ~EXT2_BLOCK_GROUP_INODE_UNINIT);
+
+       return B_OK;
+}
+

Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/InodeAllocator.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/InodeAllocator.h   
2011-01-05 21:06:57 UTC (rev 40128)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/InodeAllocator.h   
2011-01-05 21:56:12 UTC (rev 40129)
@@ -37,6 +37,9 @@
                                                        uint32 numInodes, 
ino_t& id);
                        status_t        _UnmarkInBitmap(Transaction& 
transaction,
                                                        fsblock_t bitmapBlock, 
uint32 numInodes, ino_t id);
+                       status_t        _InitGroup(Transaction& transaction,
+                                                       ext2_block_group* 
group, fsblock_t bitmapBlock,
+                                                       uint32 numInodes);
 
 
                        Volume*         fVolume;

Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/Jamfile
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/Jamfile    2011-01-05 
21:06:57 UTC (rev 40128)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/Jamfile    2011-01-05 
21:56:12 UTC (rev 40129)
@@ -23,6 +23,7 @@
        BitmapBlock.cpp
        BlockAllocator.cpp
        InodeAllocator.cpp
+       CRCTable.cpp
 
        kernel_interface.cpp
 ;

Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/Volume.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/Volume.cpp 2011-01-05 
21:06:57 UTC (rev 40128)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/Volume.cpp 2011-01-05 
21:56:12 UTC (rev 40129)
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2011, Jérôme Duval, korli@xxxxxxxxxxxxxxxxx
  * Copyright 2008-2010, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
  * This file may be used under the terms of the MIT License.
  */
@@ -21,6 +22,7 @@
 #include <util/AutoLock.h>
 
 #include "CachedBlock.h"
+#include "CRCTable.h"
 #include "Inode.h"
 #include "InodeJournal.h"
 #include "NoJournal.h"
@@ -507,7 +509,8 @@
        uint32 supportedIncompatible = EXT2_INCOMPATIBLE_FEATURE_FILE_TYPE
                | EXT2_INCOMPATIBLE_FEATURE_RECOVER
                | EXT2_INCOMPATIBLE_FEATURE_JOURNAL
-               | EXT2_INCOMPATIBLE_FEATURE_EXTENTS;
+               | EXT2_INCOMPATIBLE_FEATURE_EXTENTS
+               | EXT2_INCOMPATIBLE_FEATURE_FLEX_GROUP;
                /*| EXT2_INCOMPATIBLE_FEATURE_META_GROUP*/;
        uint32 unsupported = superBlock.IncompatibleFeatures() 
                & ~supportedIncompatible;
@@ -527,7 +530,9 @@
        uint32 supportedReadOnly = EXT2_READ_ONLY_FEATURE_SPARSE_SUPER
                | EXT2_READ_ONLY_FEATURE_LARGE_FILE
                | EXT2_READ_ONLY_FEATURE_HUGE_FILE
-               | EXT2_READ_ONLY_FEATURE_EXTRA_ISIZE;
+               | EXT2_READ_ONLY_FEATURE_EXTRA_ISIZE
+               | EXT2_READ_ONLY_FEATURE_DIR_NLINK
+               | EXT2_READ_ONLY_FEATURE_GDT_CSUM;
        // TODO actually implement EXT2_READ_ONLY_FEATURE_SPARSE_SUPER when
        // implementing superblock backup copies
 
@@ -553,6 +558,25 @@
 }
 
 
+uint16
+Volume::_GroupCheckSum(ext2_block_group *group, int32 index)
+{
+       uint16 checksum = 0;
+       if (HasChecksumFeature()) {
+               int32 number = B_HOST_TO_LENDIAN_INT32(index);
+               checksum = calculate_crc(0xffff, fSuperBlock.uuid,
+                       sizeof(fSuperBlock.uuid));
+               checksum = calculate_crc(checksum, (uint8*)&number, 
sizeof(number));
+               checksum = calculate_crc(checksum, (uint8*)group, 30);
+               if (Has64bitFeature()) {
+                       checksum = calculate_crc(checksum, (uint8*)group + 34, 
+                               fGroupDescriptorSize - 34);
+               }
+       }
+       return checksum;
+}
+
+
 /*!    Makes the requested block group available.
        The block groups are loaded on demand, but are kept in memory until the
        volume is unmounted; therefore we don't use the block cache.
@@ -564,6 +588,7 @@
                return B_BAD_VALUE;
 
        int32 blockIndex = index / fGroupsPerBlock;
+       int32 blockOffset = index % fGroupsPerBlock;
 
        MutexLocker _(fLock);
 
@@ -580,12 +605,16 @@
                memcpy(fGroupBlocks[blockIndex], block, fBlockSize);
 
                TRACE("group [%ld]: inode table %lld\n", index, 
((ext2_block_group*)
-                       (fGroupBlocks[blockIndex] + (index % fGroupsPerBlock) 
-                       * 
fGroupDescriptorSize))->InodeTable(Has64bitFeature()));
+                       (fGroupBlocks[blockIndex] + blockOffset 
+                               * 
fGroupDescriptorSize))->InodeTable(Has64bitFeature()));
        }
 
        *_group = (ext2_block_group*)(fGroupBlocks[blockIndex]
-               + (index % fGroupsPerBlock) * fGroupDescriptorSize);
+               + blockOffset * fGroupDescriptorSize);
+       if (HasChecksumFeature() 
+               && (*_group)->checksum != _GroupCheckSum(*_group, index)) {
+               return B_BAD_DATA;
+       }
        return B_OK;
 }
 
@@ -599,12 +628,20 @@
        TRACE("Volume::WriteBlockGroup()\n");
 
        int32 blockIndex = index / fGroupsPerBlock;
+       int32 blockOffset = index % fGroupsPerBlock;
 
        MutexLocker _(fLock);
 
        if (fGroupBlocks[blockIndex] == NULL)
                return B_BAD_VALUE;
 
+       ext2_block_group *group = (ext2_block_group*)(fGroupBlocks[blockIndex]
+               + blockOffset * fGroupDescriptorSize);
+       
+       group->checksum = _GroupCheckSum(group, index);
+       TRACE("Volume::WriteBlockGroup() checksum 0x%x for group %ld\n",
+               group->checksum, index);
+
        CachedBlock cached(this);
        uint8* block = cached.SetToWritable(transaction,
                _GroupDescriptorBlock(blockIndex));
@@ -634,6 +671,20 @@
 
 
 status_t
+Volume::ActivateDirNLink(Transaction& transaction)
+{
+       if ((fSuperBlock.ReadOnlyFeatures() 
+               & EXT2_READ_ONLY_FEATURE_DIR_NLINK) != 0)
+               return B_OK;
+       
+       fSuperBlock.SetReadOnlyFeatures(fSuperBlock.ReadOnlyFeatures()
+               | EXT2_READ_ONLY_FEATURE_DIR_NLINK);
+       
+       return WriteSuperBlock(transaction);
+}
+
+
+status_t
 Volume::SaveOrphan(Transaction& transaction, ino_t newID, ino_t& oldID)
 {
        oldID = fSuperBlock.LastOrphan();

Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/Volume.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/Volume.h   2011-01-05 
21:06:57 UTC (rev 40128)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/Volume.h   2011-01-05 
21:56:12 UTC (rev 40129)
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2011, Jérôme Duval, korli@xxxxxxxxxxxxxxxxx
  * Copyright 2008-2010, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
  * This file may be used under the terms of the MIT License.
  */
@@ -76,20 +77,29 @@
                        Journal*                        GetJournal() { return 
fJournal; }
 
                        bool                            IndexedDirectories() 
const
-                                                                       { 
return (fSuperBlock.CompatibleFeatures()
-                                                                               
& EXT2_FEATURE_DIRECTORY_INDEX) != 0; }
+                                                               { return 
(fSuperBlock.CompatibleFeatures()
+                                                                       & 
EXT2_FEATURE_DIRECTORY_INDEX) != 0; }
                        bool                            Has64bitFeature() const
-                                                                       { 
return (fSuperBlock.CompatibleFeatures()
-                                                                               
& EXT2_INCOMPATIBLE_FEATURE_64BIT) != 0; }
+                                                               { return 
(fSuperBlock.CompatibleFeatures()
+                                                                       & 
EXT2_INCOMPATIBLE_FEATURE_64BIT) != 0; }
                        bool                            HasExtentsFeature() 
const
-                                                                       { 
return (fSuperBlock.IncompatibleFeatures()
-                                                                               
& EXT2_INCOMPATIBLE_FEATURE_EXTENTS) != 0; }
+                                                               { return 
(fSuperBlock.IncompatibleFeatures()
+                                                                       & 
EXT2_INCOMPATIBLE_FEATURE_EXTENTS)
+                                                                       != 0; }
+                       bool                            HasChecksumFeature() 
const
+                                                               { return 
(fSuperBlock.ReadOnlyFeatures()
+                                                                       & 
EXT2_READ_ONLY_FEATURE_GDT_CSUM) != 0; }
+                       bool                            HasMetaGroupFeature() 
const
+                                                               { return 
(fSuperBlock.IncompatibleFeatures()
+                                                                       & 
EXT2_INCOMPATIBLE_FEATURE_META_GROUP)
+                                                                       != 0; }
                        uint8                           DefaultHashVersion() 
const
-                                                                       { 
return fSuperBlock.default_hash_version; }
+                                                               { return 
fSuperBlock.default_hash_version; }
                        bool                            HugeFiles() const
-                                                                       { 
return (fSuperBlock.ReadOnlyFeatures()
-                                                                               
& EXT2_READ_ONLY_FEATURE_HUGE_FILE) != 0; }
+                                                               { return 
(fSuperBlock.ReadOnlyFeatures()
+                                                                       & 
EXT2_READ_ONLY_FEATURE_HUGE_FILE) != 0; }
                        status_t                        
ActivateLargeFiles(Transaction& transaction);
+                       status_t                        
ActivateDirNLink(Transaction& transaction);
 
                        status_t                        SaveOrphan(Transaction& 
transaction,
                                                                        ino_t 
newID, ino_t &oldID);
@@ -131,6 +141,8 @@
                        uint32                          
_GroupDescriptorBlock(uint32 blockIndex);
                        uint16                          _GroupDescriptorSize() 
                                                                        { 
return fGroupDescriptorSize; }
+                       uint16                          
_GroupCheckSum(ext2_block_group *group,
+                                                                       int32 
index);
 
 private:
                        mutex                           fLock;

Added: haiku/trunk/src/add-ons/kernel/file_systems/ext2/crc_table.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/crc_table.cpp              
                (rev 0)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/crc_table.cpp      
2011-01-05 21:56:12 UTC (rev 40129)
@@ -0,0 +1,55 @@
+//----------------------------------------------------------------------
+//  This software is part of the OpenBeOS distribution and is covered 
+//  by the OpenBeOS license.
+//
+//  Copyright (c) 2003 Tyler Dauwalder, tyler@xxxxxxxxxxxxx
+//---------------------------------------------------------------------
+
+/*! \file crc_table.cpp
+
+       Standalone program to generate the CRC table used for calculating
+       UDF tag id CRC values.
+       
+       This code based off of crc code in UDF-2.50 specs, as permitted.
+       See UDF-2.50 6.5 for more information.  
+
+       Reversed version by Jérôme Duval
+*/
+
+#include <stdio.h>
+#include <sys/types.h>
+
+int
+main(int argc, char *argv[]) {
+       ulong crc, poly;
+
+       if (argc != 2) {
+               fprintf(stderr, "USAGE: crc_table <octal polynomial=120001 for 
ext2>\n");
+               return 0;
+       }
+
+       sscanf(argv[1], "%lo", &poly);
+       if (poly & 0xffff0000) {
+               fprintf(stderr, "ERROR: polynomial is too large, sucka.\n");
+               return 0;
+       }
+       
+       printf("//! CRC 0%o table, as generated by crc_table.cpp\n", poly);
+       printf("static uint16 crc_table[256] = { \n");
+       for (int n = 0; n < 256; n++) {
+               if (n%8 == 0)
+                       printf("    ");
+               crc = n;
+               for (int i = 0; i < 8; i++) {
+                       if (crc & 0x0001)
+                               crc = (crc >> 1) ^ poly;
+                       else
+                               crc >>= 1;
+               }
+               printf("0x%04x%s ", crc, (n != 255 ? "," : ""));
+               if (n%8 == 7)
+                       printf("\n");
+       }
+       printf("};\n");
+       return 0;
+}

Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/ext2.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/ext2.h     2011-01-05 
21:06:57 UTC (rev 40128)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/ext2.h     2011-01-05 
21:56:12 UTC (rev 40129)
@@ -60,7 +60,7 @@
        uint32  algorithm_usage_bitmap;
        uint8   preallocated_blocks;
        uint8   preallocated_directory_blocks;
-       uint16  _padding;
+       uint16  reserved_gdt_blocks;
 
        // journaling ext3 support
        uint8   journal_uuid[16];
@@ -127,6 +127,8 @@
                { return B_LENDIAN_TO_HOST_INT32(read_only_features); }
        uint32 IncompatibleFeatures() const
                { return B_LENDIAN_TO_HOST_INT32(incompatible_features); }
+       uint16 ReservedGDTBlocks() const
+               { return B_LENDIAN_TO_HOST_INT16(reserved_gdt_blocks); }
        ino_t  JournalInode() const
                { return B_LENDIAN_TO_HOST_INT32(journal_inode); }
        ino_t  LastOrphan() const
@@ -383,6 +385,7 @@
 } _PACKED;
 
 #define EXT2_INODE_NORMAL_SIZE         128
+#define EXT2_INODE_MAX_LINKS           65000
 
 struct ext2_inode {
        uint16  mode;


Other related posts:

  • » [haiku-commits] r40129 - haiku/trunk/src/add-ons/kernel/file_systems/ext2 - korli