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

  • From: korli@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 7 Jan 2011 20:00:23 +0100 (CET)

Author: korli
Date: 2011-01-07 20:00:23 +0100 (Fri, 07 Jan 2011)
New Revision: 40143
Changeset: http://dev.haiku-os.org/changeset/40143
Ticket: http://dev.haiku-os.org/ticket/7069

Modified:
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/ExtentStream.cpp
   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/Volume.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/ext2.h
Log:
* manages blockgroups unused_inodes when the feature is available.
* BitmapBlock::FindMarked/FindUnmarked() tried to find a free bit
  at the end of a full bitmap. This fixes #7069.


Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp    
2011-01-07 16:39:48 UTC (rev 40142)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp    
2011-01-07 19:00:23 UTC (rev 40143)
@@ -422,6 +422,7 @@
                        index++;
                } while (index < maxIndex && data[index] == 0);
 
+               bits = B_LENDIAN_TO_HOST_INT32(data[index]);
                if (index >= maxIndex) {
                        maxBit = fNumBits & 0x1F;
 
@@ -432,10 +433,14 @@
                                pos = fNumBits;
                                return;
                        }
+                       mask = (1 << maxBit) - 1;
+                       if ((bits & mask) == 0) {
+                               pos = fNumBits;
+                               return;
+                       }
                        maxBit++;
                }
 
-               bits = B_LENDIAN_TO_HOST_INT32(data[index]);
                bit = 0;
        }
 
@@ -449,7 +454,7 @@
        }
 
        panic("Couldn't find marked bit inside an int32 which is different than 
"
-               "zero!?\n");
+               "zero!? (%lx)\n", bits);
 }
 
 
@@ -488,6 +493,7 @@
                        index++;
                } while (index < maxIndex && data[index] == 0xFFFFFFFF);
 
+               bits = B_LENDIAN_TO_HOST_INT32(data[index]);
                if (index >= maxIndex) {
                        maxBit = fNumBits & 0x1F;
 
@@ -498,12 +504,17 @@
                                pos = fNumBits;
                                return;
                        }
+                       mask = (1 << maxBit) - 1;
+                       if ((bits & mask) == mask) {
+                               pos = fNumBits;
+                               return;
+                       }
                        maxBit++;
                }
-               bits = B_LENDIAN_TO_HOST_INT32(data[index]);
                bit = 0;
        }
 
+       TRACE("BitmapBlock::FindNextUnmarked(): searching bit at pos %lu\n", 
bit);
        for (; bit < maxBit; ++bit) {
                // Find the unmarked bit
                if ((bits >> bit & 1) == 0) {
@@ -513,7 +524,8 @@
                }
        }
 
-       panic("Couldn't find unmarked bit inside an int32 with value zero!?\n");
+       panic("Couldn't find unmarked bit inside an int32 with value zero!?"
+               " (0x%lx)\n", bits);
 }
 
 

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-07 16:39:48 UTC (rev 40142)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/ExtentStream.cpp   
2011-01-07 19:00:23 UTC (rev 40143)
@@ -93,8 +93,9 @@
                }
                if (stream->extent_entries[middle].LogicalBlock() > index)
                        middle--;
-               if (stream->extent_entries[middle].LogicalBlock() 
-                       +  stream->extent_entries[middle].Length() > index) {
+               fileblock_t diff = index 
+                       - stream->extent_entries[middle].LogicalBlock();
+               if (diff > stream->extent_entries[middle].Length()) {
                        // sparse block
                        TRACE("FindBlock() sparse block index %lld at %ld\n", 
index,
                                stream->extent_entries[middle].LogicalBlock());
@@ -102,8 +103,6 @@
                        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;

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-07 16:39:48 UTC (rev 40142)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp 
2011-01-07 19:00:23 UTC (rev 40143)
@@ -17,11 +17,14 @@
 #include "Volume.h"
 
 
+#undef ASSERT
 //#define TRACE_EXT2
 #ifdef TRACE_EXT2
 #      define TRACE(x...) dprintf("\33[34mext2:\33[0m " x)
+#      define ASSERT(x) { if (!(x)) kernel_debugger("ext2: assert failed: " #x 
"\n"); }
 #else
 #      define TRACE(x...) ;
+#      define ASSERT(x) ;
 #endif
 #define ERROR(x...) dprintf("\33[34mext2:\33[0m " x)
 
@@ -101,80 +104,75 @@
 
        for (int i = 0; i < 2; ++i) {
                for (; blockGroup < lastBlockGroup; ++blockGroup) {
-                       ext2_block_group* group;
+                       if (_AllocateInGroup(transaction, blockGroup,
+                               isDirectory, id, fVolume->InodesPerGroup()) == 
B_OK)
+                               return B_OK;
+               }
 
-                       status_t status = fVolume->GetBlockGroup(blockGroup, 
&group);
-                       if (status != B_OK) {
-                               ERROR("InodeAllocator::_Allocate() 
GetBlockGroup() failed\n");
-                               return status;
-                       }
+               if (i == 0 && _AllocateInGroup(transaction, blockGroup,
+                       isDirectory, id, fVolume->NumInodes() - blockGroup
+                               * fVolume->InodesPerGroup()) == B_OK)
+                       return B_OK;
 
-                       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",
-                                       freeInodes, 
group->InodeBitmap(fVolume->Has64bitFeature()));
-                               group->SetFreeInodes(freeInodes - 1, 
fVolume->Has64bitFeature());
-                               if (isDirectory)
-                                       
group->SetUsedDirectories(group->UsedDirectories(
-                                               fVolume->Has64bitFeature()) + 1,
-                                               fVolume->Has64bitFeature());
+               blockGroup = 0;
+               lastBlockGroup = preferredBlockGroup;
+       }
 
-                               status = fVolume->WriteBlockGroup(transaction, 
blockGroup);
-                               if (status != B_OK)
-                                       return status;
+       ERROR("InodeAllocator::_Allocate() device is full\n");
+       return B_DEVICE_FULL;
+}
 
-                               return _MarkInBitmap(transaction, block,
-                                       blockGroup, fVolume->InodesPerGroup(), 
id);
-                       }
-               }
 
-               if (i == 0) {
-                       ext2_block_group* group;
+status_t
+InodeAllocator::_AllocateInGroup(Transaction& transaction, uint32 blockGroup,
+       bool isDirectory, ino_t& id, uint32 numInodes)
+{
+       ext2_block_group* group;
+       status_t status = fVolume->GetBlockGroup(blockGroup, &group);
+       if (status != B_OK) {
+               ERROR("InodeAllocator::_Allocate() GetBlockGroup() failed\n");
+               return status;
+       }
 
-                       status_t status = fVolume->GetBlockGroup(blockGroup, 
&group);
-                       if (status != B_OK) {
-                               ERROR("InodeAllocator::_Allocate() 
GetBlockGroup() failed\n");
-                               return status;
-                       }
+       fsblock_t block = group->InodeBitmap(fVolume->Has64bitFeature());
+       _InitGroup(transaction, group, block, fVolume->InodesPerGroup());
+       uint32 freeInodes = group->FreeInodes(fVolume->Has64bitFeature());
+       if (freeInodes == 0)
+               return B_DEVICE_FULL;
+       TRACE("InodeAllocator::_Allocate() freeInodes %ld\n",
+               freeInodes);
+       group->SetFreeInodes(freeInodes - 1, fVolume->Has64bitFeature());
+       if (isDirectory) {
+               group->SetUsedDirectories(group->UsedDirectories(
+                       fVolume->Has64bitFeature()) + 1,
+                       fVolume->Has64bitFeature());
+       }
+       
+       uint32 pos = 0;
+       status = _MarkInBitmap(transaction, block, blockGroup, 
+               fVolume->InodesPerGroup(), pos);
+       if (status != B_OK)
+               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());
-                               }
+       if (fVolume->HasChecksumFeature() && pos > (fVolume->InodesPerGroup() - 
1
+               - group->UnusedInodes(fVolume->Has64bitFeature()))) {
+               group->SetUnusedInodes(fVolume->InodesPerGroup() - 1 - pos,
+                       fVolume->Has64bitFeature());
+       }
 
-                               status = fVolume->WriteBlockGroup(transaction, 
blockGroup);
-                               if (status != B_OK)
-                                       return status;
+       status = fVolume->WriteBlockGroup(transaction, blockGroup);
+       if (status != B_OK)
+               return status;
 
-                               return _MarkInBitmap(transaction, block,
-                                       blockGroup, numInodes, id);
-                       }
-               }
+       id = pos + blockGroup * fVolume->InodesPerGroup() + 1;
 
-               blockGroup = 0;
-               lastBlockGroup = preferredBlockGroup;
-       }
-
-       ERROR("InodeAllocator::_Allocate() device is full\n");
-       return B_DEVICE_FULL;
+       return status;
 }
 
 
 status_t
 InodeAllocator::_MarkInBitmap(Transaction& transaction, fsblock_t bitmapBlock,
-       uint32 blockGroup, uint32 numInodes, ino_t& id)
+       uint32 blockGroup, uint32 numInodes, uint32& pos)
 {
        BitmapBlock inodeBitmap(fVolume, numInodes);
 
@@ -184,7 +182,7 @@
                return B_IO_ERROR;
        }
 
-       uint32 pos = 0;
+       pos = 0;
        inodeBitmap.FindNextUnmarked(pos);
 
        if (pos == inodeBitmap.NumBits()) {
@@ -200,8 +198,6 @@
                return B_BAD_DATA;
        }
 
-       id = pos + blockGroup * fVolume->InodesPerGroup() + 1;
-
        return B_OK;
 }
 
@@ -213,13 +209,13 @@
        BitmapBlock inodeBitmap(fVolume, numInodes);
 
        if (!inodeBitmap.SetToWritable(transaction, bitmapBlock)) {
-               TRACE("Unable to open inode bitmap at block %llu\n", 
bitmapBlock);
+               ERROR("Unable to open inode bitmap at block %llu\n", 
bitmapBlock);
                return B_IO_ERROR;
        }
 
        uint32 pos = (id - 1) % fVolume->InodesPerGroup();
        if (!inodeBitmap.Unmark(pos, 1)) {
-               TRACE("Unable to unmark bit %lu in inode bitmap block %llu\n", 
pos,
+               ERROR("Unable to unmark bit %lu in inode bitmap block %llu\n", 
pos,
                        bitmapBlock);
                return B_BAD_DATA;
        }

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-07 16:39:48 UTC (rev 40142)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/InodeAllocator.h   
2011-01-07 19:00:23 UTC (rev 40143)
@@ -32,9 +32,12 @@
                        status_t        _Allocate(Transaction& transaction,
                                                        uint32 
preferredBlockGroup, bool isDirectory,
                                                        ino_t& id);
+                       status_t        _AllocateInGroup(Transaction& 
transaction,
+                                                       uint32 blockGroup, bool 
isDirectory,
+                                                       ino_t& id, uint32 
numInodes);
                        status_t        _MarkInBitmap(Transaction& transaction,
                                                        fsblock_t bitmapBlock, 
uint32 blockGroup,
-                                                       uint32 numInodes, 
ino_t& id);
+                                                       uint32 numInodes, 
uint32& pos);
                        status_t        _UnmarkInBitmap(Transaction& 
transaction,
                                                        fsblock_t bitmapBlock, 
uint32 numInodes, ino_t id);
                        status_t        _InitGroup(Transaction& transaction,

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-07 
16:39:48 UTC (rev 40142)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/Volume.cpp 2011-01-07 
19:00:23 UTC (rev 40143)
@@ -639,8 +639,10 @@
                + blockOffset * fGroupDescriptorSize);
        
        group->checksum = _GroupCheckSum(group, index);
-       TRACE("Volume::WriteBlockGroup() checksum 0x%x for group %ld\n",
-               group->checksum, index);
+       TRACE("Volume::WriteBlockGroup() checksum 0x%x for group %ld "
+               "(free inodes %ld, unused %ld)\n", group->checksum, index,
+               group->FreeInodes(Has64bitFeature()),
+               group->UnusedInodes(Has64bitFeature()));
 
        CachedBlock cached(this);
        uint8* block = cached.SetToWritable(transaction,

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-07 
16:39:48 UTC (rev 40142)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/ext2.h     2011-01-07 
19:00:23 UTC (rev 40143)
@@ -273,6 +273,14 @@
                return dirs;
        }
        uint16 Flags() const { return B_LENDIAN_TO_HOST_INT16(flags); }
+       uint32 UnusedInodes(bool has64bits) const
+       {
+               uint32 inodes = B_LENDIAN_TO_HOST_INT16(unused_inodes);
+               if (has64bits)
+                       inodes |= 
+                               
((uint32)B_LENDIAN_TO_HOST_INT16(unused_inodes_high) << 16);
+               return inodes;
+       }
        
 
        void SetFreeBlocks(uint32 freeBlocks, bool has64bits)
@@ -301,6 +309,13 @@
        {
                flags = B_HOST_TO_LENDIAN_INT16(newFlags);
        }
+
+       void SetUnusedInodes(uint32 unusedInodes, bool has64bits)
+       {
+               unused_inodes = B_HOST_TO_LENDIAN_INT16(unusedInodes) & 0xffff;
+               if (has64bits)
+                       unused_inodes_high = 
B_HOST_TO_LENDIAN_INT16(unusedInodes >> 16);
+       }
 } _PACKED;
 
 #define EXT2_DIRECT_BLOCKS                     12


Other related posts: