Modules/Ext2 - Experimental write support coming along
authorJohn Hodge <[email protected]>
Mon, 20 Aug 2012 04:27:04 +0000 (12:27 +0800)
committerJohn Hodge <[email protected]>
Mon, 20 Aug 2012 04:27:04 +0000 (12:27 +0800)
KernelLand/Modules/Filesystems/Ext2/dir.c
KernelLand/Modules/Filesystems/Ext2/ext2.c
KernelLand/Modules/Filesystems/Ext2/ext2_common.h
KernelLand/Modules/Filesystems/Ext2/ext2fs.h
KernelLand/Modules/Filesystems/Ext2/write.c

index 40cdddd..ef347ad 100644 (file)
@@ -10,7 +10,7 @@
 #include "ext2_common.h"
 
 // === MACROS ===
-#define BLOCK_DIR_OFS(_data, _block)   ((Uint16*)(_data)[(_block)])
+#define BLOCK_DIR_OFS(_data, _block)   (((Uint16*)(_data))[(_block)])
 
 // === PROTOTYPES ===
 char   *Ext2_ReadDir(tVFS_Node *Node, int Pos);
@@ -183,11 +183,15 @@ int Ext2_MkNod(tVFS_Node *Parent, const char *Name, Uint Flags)
        
        Uint64 inodeNum = Ext2_int_AllocateInode(Parent->ImplPtr, Parent->Inode);
        if( inodeNum == 0 ) {
+               LOG("Inode allocation failed");
+               LEAVE('i', -1);
                return -1;
        }
        tVFS_Node *child = Ext2_int_CreateNode(Parent->ImplPtr, inodeNum);
        if( !child ) {
                Ext2_int_DereferenceInode(Parent->ImplPtr, inodeNum);
+               Log_Warning("Ext2", "Ext2_MkNod - Node creation failed");
+               LEAVE('i', -1);
                return -1;
        }
 
@@ -216,6 +220,7 @@ int Ext2_MkNod(tVFS_Node *Parent, const char *Name, Uint Flags)
  */
 int Ext2_Unlink(tVFS_Node *Node, const char *OldName)
 {
+       Log_Warning("Ext2", "TODO: Impliment Ext2_Unlink");
        return 1;
 }
 
@@ -228,17 +233,20 @@ int Ext2_Unlink(tVFS_Node *Node, const char *OldName)
  */
 int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child)
 {      
-       #if 0
+       #if 1
        tExt2_Disk      *disk = Node->ImplPtr;
        tExt2_Inode     inode;
-       tExt2_DirEnt    dirent;
+       tExt2_DirEnt    *dirent;
        tExt2_DirEnt    newEntry;
-       Uint64  Base;   // Block's Base Address
+       Uint64  base;   // Block's Base Address
         int    block = 0, ofs = 0;
        Uint    size;
        void    *blockData;
-        int    bestMatch = -1, bestSize, bestBlock, bestOfs;
+        int    bestMatch = -1, bestSize, bestBlock, bestOfs, bestNeedsSplit;
         int    nEntries;
+
+       ENTER("pNode sName pChild",
+               Node, Name, Child);
        
        blockData = malloc(disk->BlockSize);
        
@@ -248,7 +256,7 @@ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child)
        // Create a stub entry
        newEntry.inode = Child->Inode;
        newEntry.name_len = strlen(Name);
-       newEntry.rec_len = (newEntry.name_len+3+8)&~3;
+       newEntry.rec_len = ((newEntry.name_len+3)&~3) + EXT2_DIRENT_SIZE;
        newEntry.type = inode.i_mode >> 12;
        memcpy(newEntry.name, Name, newEntry.name_len);
        
@@ -257,8 +265,12 @@ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child)
        size = inode.i_size;
        
        // Get a lock on the inode
-       Ext2_int_LockInode(disk, Node->Inode);
-       
+       //Ext2_int_LockInode(disk, Node->Inode);
+       Mutex_Acquire(&Node->Lock);
+
+//     if( !Node->Data ) {
+//     }
+
        // Get First Block
        // - Do this ourselves as it is a simple operation
        base = inode.i_block[0] * disk->BlockSize;
@@ -274,10 +286,12 @@ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child)
                                "Directory entry %i of inode 0x%x extends over a block boundary",
                                nEntries, (Uint)Node->Inode);
                }
-               else {
-               
+               else
+               {
+                       LOG("Entry %i: %x %i bytes", nEntries, dirent->type, dirent->rec_len);
                        // Free entry
-                       if(dirent->type == 0) {
+                       if(dirent->type == 0)
+                       {
                                if( dirent->rec_len >= newEntry.rec_len
                                 && (bestMatch == -1 || bestSize > dirent->rec_len) )
                                {
@@ -285,23 +299,40 @@ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child)
                                        bestSize = dirent->rec_len;
                                        bestBlock = block;
                                        bestOfs = ofs;
+                                       bestNeedsSplit = 0;
                                }
                        }
                        // Non free - check name to avoid duplicates
-                       else {
+                       else
+                       {
+                               LOG(" name='%.*s'", dirent->name_len, dirent->name);
                                if(strncmp(Name, dirent->name, dirent->name_len) == 0) {
-                                       Ext2_int_UnlockInode(disk, Node->Inode);
+                                       //Ext2_int_UnlockInode(disk, Node->Inode);
+                                       Mutex_Release(&Node->Lock);
+                                       LEAVE('i', 1);
                                        return 1;       // ERR_???
                                }
+                               
+                                int    spare_space = dirent->rec_len - (dirent->name_len + EXT2_DIRENT_SIZE);
+                               if( spare_space > newEntry.rec_len
+                                && (bestMatch == -1 || bestSize > spare_space) )
+                               {
+                                       bestMatch = nEntries;
+                                       bestSize = spare_space;
+                                       bestBlock = block;
+                                       bestOfs = ofs;
+                                       bestNeedsSplit = 1;
+                               }
                        }
                }
                
                // Increment the pointer
                nEntries ++;
                ofs += dirent->rec_len;
-               if( ofs >= disk->BlockSize ) {
+               size -= dirent->rec_len;
+               if( size > 0 && ofs >= disk->BlockSize ) {
                        // Read the next block if needed
-                       BLOCK_DIR_OFS(Node->Data, block) = nEntries;
+               //      BLOCK_DIR_OFS(Node->Data, block) = nEntries;
                        block ++;
                        ofs = 0;
                        base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
@@ -309,26 +340,66 @@ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child)
                }
        }
        
+       LOG("bestMatch = %i", bestMatch);
+       // If EOF was reached with no space, check if we can fit one on the end
+       if( bestMatch < 0 && ofs + newEntry.rec_len < disk->BlockSize ) {
+               Node->Size += newEntry.rec_len;
+               Node->Flags |= VFS_FFLAG_DIRTY;
+               bestBlock = block;
+               bestOfs = ofs;
+               bestSize = newEntry.rec_len;
+               bestNeedsSplit = 0;
+       }
        // Check if a free slot was found
-       if( bestMatch >= 0 ) {
+       if( bestMatch >= 0 )
+       {
                // Read-Modify-Write
-               bestBlock = Ext2_int_GetBlockAddr(disk, inode.i_block, bestBlock);
-               if( block > 0 )
-                       bestMatch = BLOCK_DIR_OFS(Node->Data, bestBlock);
+               base = Ext2_int_GetBlockAddr(disk, inode.i_block, bestBlock);
                VFS_ReadAt( disk->FD, base, disk->BlockSize, blockData );
                dirent = blockData + bestOfs;
-               memcpy(dirent, newEntry, newEntry.rec_len);
+               // Shorten a pre-existing entry
+               if(bestNeedsSplit)
+               {
+                       dirent->rec_len = EXT2_DIRENT_SIZE + dirent->name_len;
+                       bestOfs += dirent->rec_len;
+                       //bestSize -= dirent->rec_len; // (not needed, bestSize is the spare space after)
+                       dirent = blockData + bestOfs;
+               }
+               // Insert new file entry
+               memcpy(dirent, &newEntry, newEntry.rec_len);
+               // Create a new blank entry
+               if( bestSize != newEntry.rec_len )
+               {
+                       bestOfs += newEntry.rec_len;
+                       dirent = blockData + bestOfs;
+
+                       dirent->rec_len = bestSize - newEntry.rec_len;                  
+                       dirent->type = 0;
+               }
+               // Save changes
                VFS_WriteAt( disk->FD, base, disk->BlockSize, blockData );
        }
        else {
                // Allocate block, Write
-               block = Ext2_int_AllocateBlock(Disk, block);
-               Log_Warning("EXT2", "");
+               Uint32 newblock = Ext2_int_AllocateBlock(disk, base / disk->BlockSize);
+               Ext2_int_AppendBlock(disk, &inode, newblock);
+               base = newblock * disk->BlockSize;
+               Node->Size += newEntry.rec_len;
+               Node->Flags |= VFS_FFLAG_DIRTY;
+               memcpy(blockData, &newEntry, newEntry.rec_len);
+               memset(blockData + newEntry.rec_len, 0, disk->BlockSize - newEntry.rec_len);
+               VFS_WriteAt( disk->FD, base, disk->BlockSize, blockData );
        }
 
-       Ext2_int_UnlockInode(disk, Node->Inode);
+       Child->ImplInt ++;
+       Child->Flags |= VFS_FFLAG_DIRTY;
+
+       //Ext2_int_UnlockInode(disk, Node->Inode);
+       Mutex_Release(&Node->Lock);
+       LEAVE('i', 0);
        return 0;
        #else
+       Log_Warning("Ext2", "TODO: Impliment Ext2_Link");
        return 1;
        #endif
 }
@@ -400,3 +471,10 @@ tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID)
        // Save in node cache and return saved node
        return Inode_CacheNode(Disk->CacheID, &retNode);
 }
+
+int Ext2_int_WritebackNode(tExt2_Disk *Disk, tVFS_Node *Node)
+{
+       Log_Warning("Ext2","TODO: Impliment Ext2_int_WritebackNode");
+       return 0;
+}
+
index 38041a4..5015e14 100644 (file)
@@ -10,6 +10,9 @@
 #include "ext2_common.h"\r
 #include <modules.h>\r
 \r
+#define MIN_BLOCKS_PER_GROUP   2\r
+#define MAX_BLOCK_LOG_SIZE     10      // 1024 << 10 = 1MiB\r
+\r
 // === IMPORTS ===\r
 extern tVFS_NodeType   gExt2_DirType;\r
 \r
@@ -119,7 +122,13 @@ tVFS_Node *Ext2_InitDevice(const char *Device, const char **Options)
                LEAVE('n');\r
                return NULL;\r
        }\r
-       \r
+\r
+       if( sb.s_blocks_per_group < MIN_BLOCKS_PER_GROUP ) {\r
+               Log_Warning("Ext2", "Blocks per group is too small (%i < %i)",\r
+                       sb.s_blocks_per_group, MIN_BLOCKS_PER_GROUP);\r
+               goto _error;\r
+       }       \r
+\r
        // Get Group count\r
        groupCount = DivUp(sb.s_blocks_count, sb.s_blocks_per_group);\r
        LOG("groupCount = %i", groupCount);\r
@@ -140,6 +149,11 @@ tVFS_Node *Ext2_InitDevice(const char *Device, const char **Options)
        disk->CacheID = Inode_GetHandle();\r
        \r
        // Get Block Size\r
+       if( sb.s_log_block_size > MAX_BLOCK_LOG_SIZE ) {\r
+               Log_Warning("Ext2", "Block size (log2) too large (%i > %i)",\r
+                       sb.s_log_block_size, MAX_BLOCK_LOG_SIZE);\r
+               goto _error;\r
+       }\r
        disk->BlockSize = 1024 << sb.s_log_block_size;\r
        LOG("Disk->BlockSie = 0x%x (1024 << %i)", disk->BlockSize, sb.s_log_block_size);\r
        \r
@@ -186,6 +200,11 @@ tVFS_Node *Ext2_InitDevice(const char *Device, const char **Options)
        \r
        LEAVE('p', &disk->RootNode);\r
        return &disk->RootNode;\r
+_error:\r
+       free(disk);\r
+       VFS_Close(fd);\r
+       LEAVE('n');\r
+       return NULL;\r
 }\r
 \r
 /**\r
@@ -366,8 +385,67 @@ Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)
  */\r
 Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
 {\r
-//     Uint    block = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group;\r
-       Log_Warning("EXT2", "Ext2_int_AllocateInode is unimplemented");\r
+       Uint    start_group = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group;\r
+       Uint    group = start_group;\r
+\r
+       if( Disk->SuperBlock.s_free_inodes_count == 0 ) \r
+       {\r
+               Log_Notice("Ext2", "Ext2_int_AllocateInode - Out of inodes on %p", Disk);\r
+               return 0;\r
+       }\r
+\r
+       while( group < Disk->GroupCount && Disk->Groups[group].bg_free_inodes_count == 0 )\r
+               group ++;\r
+       if( group == Disk->GroupCount )\r
+       {\r
+               group = 0;\r
+               while( group < start_group && Disk->Groups[group].bg_free_inodes_count == 0 )\r
+                       group ++;\r
+       }\r
+       \r
+       if( Disk->Groups[group].bg_free_inodes_count == 0 )\r
+       {\r
+               Log_Notice("Ext2", "Ext2_int_AllocateInode - Out of inodes on %p, but superblock says some free", Disk);\r
+               return 0;\r
+       }\r
+\r
+       // Load bitmap for group\r
+       //  (s_inodes_per_group / 8) bytes worth\r
+       // - Allocate a buffer the size of a sector/block\r
+       // - Read in part of the bitmap\r
+       // - Search for a free inode\r
+       tExt2_Group     *bg = &Disk->Groups[group];\r
+        int    ofs = 0;\r
+       do {\r
+               const int sector_size = 512;\r
+               Uint8 buf[sector_size];\r
+               VFS_ReadAt(Disk->FD, Disk->BlockSize*bg->bg_inode_bitmap+ofs, sector_size, buf);\r
+\r
+               int byte, bit;\r
+               for( byte = 0; byte < sector_size && buf[byte] != 0xFF; byte ++ )\r
+                       ;\r
+               if( byte < sector_size )\r
+               {\r
+                       for( bit = 0; bit < 8 && buf[byte] & (1 << bit); bit ++)\r
+                               ;\r
+                       ASSERT(bit != 8);\r
+                       buf[byte] |= 1 << bit;\r
+                       VFS_WriteAt(Disk->FD, Disk->BlockSize*bg->bg_inode_bitmap+ofs, sector_size, buf);\r
+\r
+                       bg->bg_free_inodes_count --;\r
+                       Disk->SuperBlock.s_free_inodes_count --;\r
+\r
+                       Uint32  ret = group * Disk->SuperBlock.s_inodes_per_group + byte * 8 + bit + 1;\r
+                       Log_Debug("Ext2", "Ext2_int_AllocateInode - Allocated 0x%x", ret);\r
+                       return ret;\r
+               }\r
+\r
+               ofs += sector_size;\r
+       } while(ofs < Disk->SuperBlock.s_inodes_per_group / 8);\r
+\r
+       Log_Notice("Ext2", "Ext2_int_AllocateInode - Out of inodes in group %p:%i but header reported free",\r
+               Disk, group);\r
+\r
        return 0;\r
 }\r
 \r
@@ -376,7 +454,7 @@ Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)
  */\r
 void Ext2_int_DereferenceInode(tExt2_Disk *Disk, Uint32 Inode)\r
 {\r
-       \r
+       Log_Warning("Ext2", "TODO: Impliment Ext2_int_DereferenceInode");\r
 }\r
 \r
 /**\r
index 1d994dd..57b7493 100644 (file)
@@ -2,10 +2,6 @@
  * Acess OS
  * Ext2 Driver Version 1
  */
-/**
- * \file ext2_common.h
- * \brief Second Extended Filesystem Driver
- */
 #ifndef _EXT2_COMMON_H
 #define _EXT2_COMMON_H
 #include <acess.h>
@@ -45,5 +41,8 @@ extern int    Ext2_Link(tVFS_Node *Parent, const char *Name, tVFS_Node *Node);
 extern size_t  Ext2_Read(tVFS_Node *node, off_t offset, size_t length, void *buffer);
 // --- Write ---
 extern size_t  Ext2_Write(tVFS_Node *node, off_t offset, size_t length, const void *buffer);
+extern Uint32  Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 LastBlock);
+extern void    Ext2_int_DeallocateBlock(tExt2_Disk *Disk, Uint32 Block);
+extern int     Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block);
 
 #endif
index a3aa301..4f9210e 100644 (file)
@@ -157,6 +157,6 @@ struct ext2_dir_entry_s {
        Uint8   type;           //!< File Type (Duplicate of ext2_inode_s.i_mode)\r
        char    name[EXT2_NAME_LEN+1];          //!< File name\r
 };\r
-#define EXT2_DIRENT_SIZE       (sizeof(struct ext2_dir_entry_s)-EXT2_NAME_LEN+1)\r
+#define EXT2_DIRENT_SIZE       (sizeof(struct ext2_dir_entry_s)-(EXT2_NAME_LEN+1))\r
 \r
 #endif\r
index 22e256b..766a0e6 100644 (file)
@@ -98,7 +98,9 @@ addBlocks:
                block = Ext2_int_AllocateBlock(disk, base/disk->BlockSize);
                if(!block)      return Length - retLen;
                // Add it to this inode
-               if( !Ext2_int_AppendBlock(disk, &inode, block) ) {
+               if( Ext2_int_AppendBlock(disk, &inode, block) ) {
+                       Log_Warning("Ext2", "Appending %x to inode %p:%X failed",
+                               block, disk, Node->Inode);
                        Ext2_int_DeallocateBlock(disk, block);
                        goto ret;
                }
@@ -113,7 +115,9 @@ addBlocks:
        // Last block :D
        block = Ext2_int_AllocateBlock(disk, base/disk->BlockSize);
        if(!block)      goto ret;
-       if( !Ext2_int_AppendBlock(disk, &inode, block) ) {
+       if( Ext2_int_AppendBlock(disk, &inode, block) ) {
+               Log_Warning("Ext2", "Appending %x to inode %p:%X failed",
+                       block, disk, Node->Inode);
                Ext2_int_DeallocateBlock(disk, block);
                goto ret;
        }
@@ -141,80 +145,96 @@ ret:      // Makes sure the changes to the inode are committed
 Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
 {
         int    bpg = Disk->SuperBlock.s_blocks_per_group;
-       Uint    blockgroup = PrevBlock / bpg;
-       Uint    bitmap[Disk->BlockSize/sizeof(Uint)];
-       Uint    bitsperblock = 8*Disk->BlockSize;
-        int    i, j = 0;
-       Uint    block;
-       
+       Uint    firstgroup = PrevBlock / bpg;
+       Uint    blockgroup = firstgroup;
+       tExt2_Group     *bg;
+
+       // TODO: Need to do locking on the bitmaps      
+
        // Are there any free blocks?
-       if(Disk->SuperBlock.s_free_blocks_count == 0)   return 0;
-       
-       if(Disk->Groups[blockgroup].bg_free_blocks_count > 0)
+       if(Disk->SuperBlock.s_free_blocks_count == 0)
+               return 0;
+
+       // First: Check the next block after \a PrevBlock
+       if( (PrevBlock + 1) % Disk->SuperBlock.s_blocks_per_group != 0
+        && Disk->Groups[blockgroup].bg_free_blocks_count > 0 )
        {
-               // Search block group's bitmap
-               for(i = 0; i < bpg; i++)
+               bg = &Disk->Groups[blockgroup];
+               const int sector_size = 512;
+               Uint8 buf[sector_size];
+                int    iblock = (PrevBlock + 1) % Disk->SuperBlock.s_blocks_per_group;
+                int    byte = iblock / 8;
+                int    ofs = byte / sector_size * sector_size;
+               byte %= sector_size;
+               VFS_ReadAt(Disk->FD, Disk->BlockSize*bg->bg_block_bitmap+ofs, sector_size, buf);
+               
+               if( (buf[byte] & (1 << (iblock%8))) == 0 )
                {
-                       // Get the block in the bitmap block
-                       j = i & (bitsperblock-1);
-                       
-                       // Read in if needed
-                       if(j == 0) {
-                               VFS_ReadAt(
-                                       Disk->FD,
-                                       (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,
-                                       Disk->BlockSize,
-                                       bitmap
-                                       );
-                       }
-                       
-                       // Fast Check
-                       if( bitmap[j/32] == 0xFFFFFFFF ) {
-                               j = (j + 31) & ~31;
-                               continue;
-                       }
-                       
-                       // Is the bit set?
-                       if( bitmap[j/32] & (1 << (j%32)) )
-                               continue;
-                       
-                       // Ooh! We found one
-                       break;
-               }
-               if( i < bpg ) {
-                       Warning("[EXT2 ] Inconsistency detected, Group Free Block count is non-zero when no free blocks exist");
-                       goto    checkAll;       // Search the entire filesystem for a free block
-                       // Goto needed for neatness
+                       // Free block - nice and contig allocation
+                       buf[byte] |= (1 << (iblock%8));
+                       VFS_WriteAt(Disk->FD, Disk->BlockSize*bg->bg_block_bitmap+ofs, sector_size, buf);
+
+                       bg->bg_free_blocks_count --;
+                       Disk->SuperBlock.s_free_blocks_count --;
+                       #if EXT2_UPDATE_WRITEBACK
+                       Ext2_int_UpdateSuperblock(Disk);
+                       #endif
+                       return PrevBlock + 1;
                }
-               
-               // Mark as used
-               bitmap[j/32] |= (1 << (j%32));
-               VFS_WriteAt(
-                       Disk->FD,
-                       (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,
-                       Disk->BlockSize,
-                       bitmap
-                       );
-               block = i;
-               Disk->Groups[blockgroup].bg_free_blocks_count --;
-               #if EXT2_UPDATE_WRITEBACK
-               //Ext2_int_UpdateBlockGroup(Disk, blockgroup);
-               #endif
+               // Used... darnit
+               // Fall through and search further
        }
-       else
+
+       // Second: Search for a group with free blocks
+       while( blockgroup < Disk->GroupCount && Disk->Groups[blockgroup].bg_free_blocks_count == 0 )
+               blockgroup ++;
+       if( Disk->Groups[blockgroup].bg_free_blocks_count == 0 )
        {
-       checkAll:
-               Log_Warning("EXT2", "TODO - Implement using blocks outside the current block group");
+               blockgroup = 0;
+               while( blockgroup < firstgroup && Disk->Groups[blockgroup].bg_free_blocks_count == 0 )
+                       blockgroup ++;
+       }
+       if( Disk->Groups[blockgroup].bg_free_blocks_count == 0 ) {
+               Log_Notice("Ext2", "Ext2_int_AllocateBlock - Out of blockss on %p, but superblock says some free",
+                       Disk);
                return 0;
        }
+
+       // Search the bitmap for a free block
+       bg = &Disk->Groups[blockgroup]; 
+        int    ofs = 0;
+       do {
+               const int sector_size = 512;
+               Uint8 buf[sector_size];
+               VFS_ReadAt(Disk->FD, Disk->BlockSize*bg->bg_block_bitmap+ofs, sector_size, buf);
+
+               int byte, bit;
+               for( byte = 0; byte < sector_size && buf[byte] != 0xFF; byte ++ )
+                       ;
+               if( byte < sector_size )
+               {
+                       for( bit = 0; bit < 8 && buf[byte] & (1 << bit); bit ++)
+                               ;
+                       ASSERT(bit != 8);
+                       buf[byte] |= 1 << bit;
+                       VFS_WriteAt(Disk->FD, Disk->BlockSize*bg->bg_block_bitmap+ofs, sector_size, buf);
+
+                       bg->bg_free_blocks_count --;
+                       Disk->SuperBlock.s_free_blocks_count --;
+
+                       #if EXT2_UPDATE_WRITEBACK
+                       Ext2_int_UpdateSuperblock(Disk);
+                       #endif
+
+                       Uint32  ret = blockgroup * Disk->SuperBlock.s_blocks_per_group + byte * 8 + bit;
+                       Log_Debug("Ext2", "Ext2_int_AllocateBlock - Allocated 0x%x", ret);
+                       return ret;
+               }
+       } while(ofs < Disk->SuperBlock.s_blocks_per_group / 8);
        
-       // Reduce global count
-       Disk->SuperBlock.s_free_blocks_count --;
-       #if EXT2_UPDATE_WRITEBACK
-       Ext2_int_UpdateSuperblock(Disk);
-       #endif
-       
-       return block;
+       Log_Notice("Ext2", "Ext2_int_AllocateBlock - Out of block in group %p:%i but header reported free",
+               Disk, blockgroup);
+       return 0;
 }
 
 /**
@@ -222,6 +242,7 @@ Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
  */
 void Ext2_int_DeallocateBlock(tExt2_Disk *Disk, Uint32 Block)
 {
+       Log_Warning("Ext2", "TODO: Impliment Ext2_int_DeallocateBlock");
 }
 
 /**
@@ -253,6 +274,7 @@ int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block)
                if( nBlocks == 0 ) {
                        Inode->i_block[12] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
                        if( !Inode->i_block[12] ) {
+                               Log_Warning("Ext2", "Allocating indirect block failed");
                                free(blocks);
                                return 1;
                        }
@@ -276,6 +298,7 @@ int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block)
                if( nBlocks == 0 ) {
                        Inode->i_block[13] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
                        if( !Inode->i_block[13] ) {
+                               Log_Warning("Ext2", "Allocating double indirect block failed");
                                free(blocks);
                                return 1;
                        }
@@ -289,6 +312,7 @@ int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block)
                        id1 = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
                        if( !id1 ) {
                                free(blocks);
+                               Log_Warning("Ext2", "Allocating double indirect block (l2) failed");
                                return 1;
                        }
                        blocks[nBlocks/dwPerBlock] = id1;
@@ -316,6 +340,7 @@ int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block)
                if( nBlocks == 0 ) {
                        Inode->i_block[14] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
                        if( !Inode->i_block[14] ) {
+                               Log_Warning("Ext2", "Allocating triple indirect block failed");
                                free(blocks);
                                return 1;
                        }
@@ -329,6 +354,7 @@ int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block)
                {
                        id1 = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
                        if( !id1 ) {
+                               Log_Warning("Ext2", "Allocating triple indirect block (l2) failed");
                                free(blocks);
                                return 1;
                        }
@@ -346,6 +372,7 @@ int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block)
                if( nBlocks % dwPerBlock == 0 ) {
                        id2 = Ext2_int_AllocateBlock(Disk, id1);
                        if( !id2 ) {
+                               Log_Warning("Ext2", "Allocating triple indirect block (l3) failed");
                                free(blocks);
                                return 1;
                        }
@@ -366,7 +393,7 @@ int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block)
                return 0;
        }
        
-       Warning("[EXT2 ] Inode %i cannot have a block appended to it, all indirects used");
+       Log_Warning("Ext2", "Inode ?? cannot have a block appended to it, all indirects used");
        free(blocks);
        return 1;
 }

UCC git Repository :: git.ucc.asn.au