Modules/Ext2 - Fixed bugs in read/write support
authorJohn Hodge <[email protected]>
Tue, 30 Jul 2013 02:59:15 +0000 (10:59 +0800)
committerJohn Hodge <[email protected]>
Tue, 30 Jul 2013 02:59:15 +0000 (10:59 +0800)
KernelLand/Modules/Filesystems/Ext2/dir.c
KernelLand/Modules/Filesystems/Ext2/ext2.c
KernelLand/Modules/Filesystems/Ext2/ext2_common.h
KernelLand/Modules/Filesystems/Ext2/read.c
KernelLand/Modules/Filesystems/Ext2/write.c

index a0a5f14..f04a60c 100644 (file)
@@ -44,7 +44,7 @@ tVFS_NodeType gExt2_FileType = {
  */
 int Ext2_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
 {
-       tExt2_Inode     inode;
+       tExt2_Inode     *inode = (void*)(Node+1);
        tExt2_DirEnt    dirent;
        Uint64  Base;   // Block's Base Address
         int    block = 0;
@@ -56,17 +56,16 @@ int Ext2_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
        ENTER("pNode iPos", Node, Pos);
        
        // Read directory's inode
-       Ext2_int_ReadInode(disk, Node->Inode, &inode);
-       size = inode.i_size;
+       size = inode->i_size;
        
-       LOG("inode={.i_block[0]= 0x%x, .i_size=0x%x}", inode.i_block[0], inode.i_size);
+       LOG("inode={.i_block[0]= 0x%x, .i_size=0x%x}", inode->i_block[0], inode->i_size);
        
        // Find Entry
        // Get First Block
        // - Do this ourselves as it is a simple operation
-       Base = inode.i_block[0] * disk->BlockSize;
+       Base = inode->i_block[0] * disk->BlockSize;
        // Scan directory
-       while(Pos -- && size > 0 && size <= inode.i_size)
+       while(Pos -- && size > 0 && size <= inode->i_size)
        {
                VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);
                ofs += dirent.rec_len;
@@ -80,7 +79,7 @@ int Ext2_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
                                        entNum-1, Node->Inode);
                        }
                        ofs = 0;
-                       Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );
+                       Base = Ext2_int_GetBlockAddr( disk, inode->i_block, block );
                        if( Base == 0 ) {
                                size = 0;
                                break;
@@ -89,7 +88,7 @@ int Ext2_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
        }
        
        // Check for the end of the list
-       if(size <= 0 || size > inode.i_size) {
+       if(size <= 0 || size > inode->i_size) {
                LEAVE('i', -ENOENT);
                return -ENOENT;
        }
@@ -127,7 +126,7 @@ int Ext2_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
 tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags)
 {
        tExt2_Disk      *disk = Node->ImplPtr;
-       tExt2_Inode     inode;
+       tExt2_Inode     *inode = (void*)(Node+1);
        tExt2_DirEnt    dirent;
        Uint64  Base;   // Block's Base Address
         int    block = 0;
@@ -137,12 +136,11 @@ tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags)
         int    filenameLen = strlen(Filename);
        
        // Read directory's inode
-       Ext2_int_ReadInode(disk, Node->Inode, &inode);
-       size = inode.i_size;
+       size = inode->i_size;
        
        // Get First Block
        // - Do this ourselves as it is a simple operation
-       Base = inode.i_block[0] * disk->BlockSize;
+       Base = inode->i_block[0] * disk->BlockSize;
        // Find File
        while(size > 0)
        {
@@ -163,7 +161,7 @@ tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags)
                                        entNum-1, Node->Inode);
                        }
                        ofs = 0;
-                       Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );
+                       Base = Ext2_int_GetBlockAddr( disk, inode->i_block, block );
                }
        }
        
@@ -231,7 +229,7 @@ int Ext2_Unlink(tVFS_Node *Node, const char *OldName)
 int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child)
 {      
        tExt2_Disk      *disk = Node->ImplPtr;
-       tExt2_Inode     inode;
+       tExt2_Inode     *inode = (void*)(Node+1);
        tExt2_DirEnt    *dirent;
        tExt2_DirEnt    newEntry;
        Uint64  base;   // Block's Base Address
@@ -246,19 +244,15 @@ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child)
        
        void *blockData = malloc(disk->BlockSize);
        
-       // Read child inode (get's the file type)
-       Ext2_int_ReadInode(disk, Child->Inode, &inode);
-       
        // Create a stub entry
        newEntry.inode = Child->Inode;
        newEntry.name_len = strlen(Name);
        newEntry.rec_len = ((newEntry.name_len+3)&~3) + EXT2_DIRENT_SIZE;
-       newEntry.type = inode.i_mode >> 12;
+       newEntry.type = inode->i_mode >> 12;
        memcpy(newEntry.name, Name, newEntry.name_len);
        
        // Read directory's inode
-       Ext2_int_ReadInode(disk, Node->Inode, &inode);
-       size = inode.i_size;
+       size = inode->i_size;
        
        // Get a lock on the inode
        //Ext2_int_LockInode(disk, Node->Inode);
@@ -269,7 +263,7 @@ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child)
 
        // Get First Block
        // - Do this ourselves as it is a simple operation
-       base = inode.i_block[0] * disk->BlockSize;
+       base = inode->i_block[0] * disk->BlockSize;
        VFS_ReadAt( disk->FD, base, disk->BlockSize, blockData );
        block = 0;
        nEntries = 0;
@@ -330,7 +324,7 @@ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child)
                //      BLOCK_DIR_OFS(Node->Data, block) = nEntries;
                        block ++;
                        ofs = 0;
-                       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+                       base = Ext2_int_GetBlockAddr(disk, inode->i_block, block);
                        VFS_ReadAt( disk->FD, base, disk->BlockSize, blockData );
                }
        }
@@ -349,7 +343,7 @@ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child)
        if( bestMatch >= 0 )
        {
                // Read-Modify-Write
-               base = Ext2_int_GetBlockAddr(disk, inode.i_block, bestBlock);
+               base = Ext2_int_GetBlockAddr(disk, inode->i_block, bestBlock);
                VFS_ReadAt( disk->FD, base, disk->BlockSize, blockData );
                dirent = blockData + bestOfs;
                // Shorten a pre-existing entry
@@ -377,7 +371,7 @@ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child)
        else {
                // Allocate block, Write
                Uint32 newblock = Ext2_int_AllocateBlock(disk, base / disk->BlockSize);
-               Ext2_int_AppendBlock(disk, &inode, newblock);
+               Ext2_int_AppendBlock(Node, inode, newblock);
                base = newblock * disk->BlockSize;
                Node->Size += newEntry.rec_len;
                Node->Flags |= VFS_FFLAG_DIRTY;
index 3a9a080..eacf87b 100644 (file)
 tVFS_Node      *Ext2_InitDevice(const char *Device, const char **Options);\r
 void   Ext2_Unmount(tVFS_Node *Node);\r
 void   Ext2_CloseFile(tVFS_Node *Node);\r
+tVFS_Node      *Ext2_GetNodeFromINode(tVFS_Node *RootNode, Uint64 Inode);\r
 // - Internal Helpers\r
  int   Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode);\r
+void   Ext2_int_DumpInode(tExt2_Disk *Disk, Uint32 InodeID, tExt2_Inode *Inode);\r
 Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum);\r
 Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent);\r
 void   Ext2_int_DereferenceInode(tExt2_Disk *Disk, Uint32 Inode);\r
@@ -37,7 +39,7 @@ tVFS_Driver   gExt2_FSInfo = {
        .Detect = Ext2_Detect,\r
        .InitDevice = Ext2_InitDevice,\r
        .Unmount = Ext2_Unmount,\r
-       .GetNodeFromINode = NULL\r
+       .GetNodeFromINode = Ext2_GetNodeFromINode\r
        };\r
 \r
 // === CODE ===\r
@@ -96,7 +98,6 @@ tVFS_Node *Ext2_InitDevice(const char *Device, const char **Options)
         int    fd;\r
         int    groupCount;\r
        tExt2_SuperBlock        sb;\r
-       tExt2_Inode     inode;\r
        \r
        ENTER("sDevice pOptions", Device, Options);\r
        \r
@@ -169,7 +170,7 @@ tVFS_Node *Ext2_InitDevice(const char *Device, const char **Options)
        LOG(".bg_inode_table = 0x%x", disk->Groups[1].bg_inode_table);\r
        \r
        // Get root Inode\r
-       Ext2_int_ReadInode(disk, 2, &inode);\r
+       Ext2_int_ReadInode(disk, 2, &disk->RootInode);\r
        \r
        // Create Root Node\r
        memset(&disk->RootNode, 0, sizeof(tVFS_Node));\r
@@ -181,14 +182,14 @@ tVFS_Node *Ext2_InitDevice(const char *Device, const char **Options)
        disk->RootNode.Type = &gExt2_DirType;\r
        \r
        // Complete root node\r
-       disk->RootNode.UID = inode.i_uid;\r
-       disk->RootNode.GID = inode.i_gid;\r
+       disk->RootNode.UID = disk->RootInode.i_uid;\r
+       disk->RootNode.GID = disk->RootInode.i_gid;\r
        disk->RootNode.NumACLs = 1;\r
        disk->RootNode.ACLs = &gVFS_ACL_EveryoneRW;\r
        \r
        #if DEBUG\r
-       LOG("inode.i_size = 0x%x", inode.i_size);\r
-       LOG("inode.i_block[0] = 0x%x", inode.i_block[0]);\r
+       LOG("inode.i_size = 0x%x", disk->RootInode.i_size);\r
+       LOG("inode.i_block[0] = 0x%x", disk->RootInode.i_block[0]);\r
        #endif\r
        \r
        LEAVE('p', &disk->RootNode);\r
@@ -260,6 +261,11 @@ void Ext2_CloseFile(tVFS_Node *Node)
        return ;\r
 }\r
 \r
+tVFS_Node *Ext2_GetNodeFromINode(tVFS_Node *RootNode, Uint64 Inode)\r
+{\r
+       return Ext2_int_CreateNode(RootNode->ImplPtr, Inode);\r
+}\r
+\r
 //==================================\r
 //=       INTERNAL FUNCTIONS       =\r
 //==================================\r
@@ -304,7 +310,9 @@ int Ext2_int_WriteInode(tExt2_Disk *Disk, Uint32 InodeId, tExt2_Inode *Inode)
                LEAVE('i', 0);\r
                return 0;\r
        }\r
-       \r
+\r
+       Ext2_int_DumpInode(Disk, InodeId, Inode);       \r
+\r
        InodeId --;     // Inodes are numbered starting at 1\r
        \r
        group = InodeId / Disk->SuperBlock.s_inodes_per_group;\r
@@ -329,112 +337,134 @@ int Ext2_int_WriteInode(tExt2_Disk *Disk, Uint32 InodeId, tExt2_Inode *Inode)
  */\r
 tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID)\r
 {\r
-       tExt2_Inode     inode;\r
-       tVFS_Node       retNode;\r
-       tVFS_Node       *tmpNode;\r
-       \r
-       if( !Ext2_int_ReadInode(Disk, InodeID, &inode) )\r
+       struct {\r
+               tVFS_Node       retNode;\r
+               tExt2_Inode     inode;\r
+       } data;\r
+       tVFS_Node       *node = &data.retNode;\r
+       tExt2_Inode     *in = &data.inode;\r
+       \r
+       if( !Ext2_int_ReadInode(Disk, InodeID, &data.inode) )\r
                return NULL;\r
        \r
-       if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) )\r
-               return tmpNode;\r
+       if( (node = Inode_GetCache(Disk->CacheID, InodeID)) )\r
+               return node;\r
+       node = &data.retNode;\r
 \r
-       memset(&retNode, 0, sizeof(retNode));   \r
+       memset(node, 0, sizeof(*node));\r
        \r
        // Set identifiers\r
-       retNode.Inode = InodeID;\r
-       retNode.ImplPtr = Disk;\r
-       retNode.ImplInt = inode.i_links_count;\r
-       if( inode.i_links_count == 0 ) {\r
+       node->Inode = InodeID;\r
+       node->ImplPtr = Disk;\r
+       node->ImplInt = in->i_links_count;\r
+       if( in->i_links_count == 0 ) {\r
                Log_Notice("Ext2", "Inode %p:%x is not referenced, bug?", Disk, InodeID);\r
        }\r
        \r
        // Set file length\r
-       retNode.Size = inode.i_size;\r
+       node->Size = in->i_size;\r
        \r
        // Set Access Permissions\r
-       retNode.UID = inode.i_uid;\r
-       retNode.GID = inode.i_gid;\r
-       retNode.NumACLs = 3;\r
-       retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid);\r
+       node->UID = in->i_uid;\r
+       node->GID = in->i_gid;\r
+       node->NumACLs = 3;\r
+       node->ACLs = VFS_UnixToAcessACL(in->i_mode & 0777, in->i_uid, in->i_gid);\r
        \r
        //  Set Function Pointers\r
-       retNode.Type = &gExt2_FileType;\r
+       node->Type = &gExt2_FileType;\r
        \r
-       switch(inode.i_mode & EXT2_S_IFMT)\r
+       switch(in->i_mode & EXT2_S_IFMT)\r
        {\r
        // Symbolic Link\r
        case EXT2_S_IFLNK:\r
-               retNode.Flags = VFS_FFLAG_SYMLINK;\r
+               node->Flags = VFS_FFLAG_SYMLINK;\r
                break;\r
        // Regular File\r
        case EXT2_S_IFREG:\r
-               retNode.Flags = 0;\r
-               retNode.Size |= (Uint64)inode.i_dir_acl << 32;\r
+               node->Flags = 0;\r
+               node->Size |= (Uint64)in->i_dir_acl << 32;\r
                break;\r
        // Directory\r
        case EXT2_S_IFDIR:\r
-               retNode.Type = &gExt2_DirType;\r
-               retNode.Flags = VFS_FFLAG_DIRECTORY;\r
-               retNode.Data = calloc( sizeof(Uint16), DivUp(retNode.Size, Disk->BlockSize) );\r
+               node->Type = &gExt2_DirType;\r
+               node->Flags = VFS_FFLAG_DIRECTORY;\r
+               node->Data = calloc( sizeof(Uint16), DivUp(node->Size, Disk->BlockSize) );\r
                break;\r
        // Unknown, Write protect it to be safe \r
        default:\r
-               retNode.Flags = VFS_FFLAG_READONLY;\r
+               node->Flags = VFS_FFLAG_READONLY;\r
                break;\r
        }\r
        \r
        // Set Timestamps\r
-       retNode.ATime = inode.i_atime * 1000;\r
-       retNode.MTime = inode.i_mtime * 1000;\r
-       retNode.CTime = inode.i_ctime * 1000;\r
+       node->ATime = in->i_atime * 1000;\r
+       node->MTime = in->i_mtime * 1000;\r
+       node->CTime = in->i_ctime * 1000;\r
        \r
        // Save in node cache and return saved node\r
-       return Inode_CacheNode(Disk->CacheID, &retNode);\r
+       return Inode_CacheNodeEx(Disk->CacheID, &data.retNode, sizeof(data));\r
 }\r
 \r
 int Ext2_int_WritebackNode(tExt2_Disk *Disk, tVFS_Node *Node)\r
 {\r
-       tExt2_Inode     inode = {0};\r
+       tExt2_Inode     *inode = (void*)(Node+1);\r
 \r
        if( Disk != Node->ImplPtr ) {\r
                Log_Error("Ext2", "Ext2_int_WritebackNode - Disk != Node->ImplPtr");\r
                return -1;\r
        }\r
-       \r
+\r
        if( Node->Flags & VFS_FFLAG_SYMLINK ) {\r
-               inode.i_mode = EXT2_S_IFLNK;\r
+               inode->i_mode = EXT2_S_IFLNK;\r
        }\r
        else if( Node->Flags & VFS_FFLAG_DIRECTORY ) {\r
-               inode.i_mode = EXT2_S_IFDIR;\r
+               inode->i_mode = EXT2_S_IFDIR;\r
        }\r
        else if( Node->Flags & VFS_FFLAG_READONLY ) {\r
                Log_Notice("Ext2", "Not writing back readonly inode %p:%x", Disk, Node->Inode);\r
                return 1;\r
        }\r
        else {\r
-               inode.i_mode = EXT2_S_IFREG;\r
-               inode.i_dir_acl = Node->Size >> 32;\r
+               inode->i_mode = EXT2_S_IFREG;\r
+               inode->i_dir_acl = Node->Size >> 32;\r
        }\r
 \r
-       inode.i_size = Node->Size & 0xFFFFFFFF;\r
-       inode.i_links_count = Node->ImplInt;\r
+       inode->i_size = Node->Size & 0xFFFFFFFF;\r
+       inode->i_links_count = Node->ImplInt;\r
 \r
-       inode.i_uid = Node->UID;\r
-       inode.i_gid = Node->GID;\r
+       inode->i_uid = Node->UID;\r
+       inode->i_gid = Node->GID;\r
 \r
-       inode.i_atime = Node->ATime / 1000;\r
-       inode.i_mtime = Node->MTime / 1000;\r
-       inode.i_ctime = Node->CTime / 1000;\r
+       inode->i_atime = Node->ATime / 1000;\r
+       inode->i_mtime = Node->MTime / 1000;\r
+       inode->i_ctime = Node->CTime / 1000;\r
 \r
        // TODO: Compact ACLs into unix mode\r
        Log_Warning("Ext2", "TODO: Support converting Acess ACLs into unix modes");\r
+       inode->i_mode |= 777;\r
 \r
-       Ext2_int_WriteInode(Disk, Node->Inode, &inode);\r
+       Ext2_int_WriteInode(Disk, Node->Inode, inode);\r
 \r
        return 0;\r
 }\r
 \r
+void Ext2_int_DumpInode(tExt2_Disk *Disk, Uint32 InodeID, tExt2_Inode *Inode)\r
+{\r
+       LOG("%p[Inode %i] = {", Disk, InodeID);\r
+       LOG(" .i_mode = 0%04o", Inode->i_mode);\r
+       LOG(" .i_uid:i_gid = %i:%i", Inode->i_uid, Inode->i_gid);\r
+       LOG(" .i_size = 0x%x", Inode->i_size);\r
+       LOG(" .i_block[0:3] = {0x%x,0x%x,0x%x,0x%x}",\r
+               Inode->i_block[0], Inode->i_block[1], Inode->i_block[2], Inode->i_block[3]);\r
+       LOG(" .i_block[4:7] = {0x%x,0x%x,0x%x,0x%x}",\r
+               Inode->i_block[4], Inode->i_block[5], Inode->i_block[6], Inode->i_block[7]);\r
+       LOG(" .i_block[8:11] = {0x%x,0x%x,0x%x,0x%x}",\r
+               Inode->i_block[8], Inode->i_block[6], Inode->i_block[10], Inode->i_block[11]);\r
+       LOG(" .i_block[12:14] = {0x%x,0x%x,0x%x}",\r
+               Inode->i_block[12], Inode->i_block[13], Inode->i_block[14]);\r
+       LOG("}");\r
+}\r
+\r
 /**\r
  * \fn Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
  * \brief Get the address of a block from an inode's list\r
index 04fcae4..d4cdec9 100644 (file)
@@ -15,6 +15,7 @@ typedef struct {
         int    FD;
        tInodeCache     *CacheID;
        tVFS_Node       RootNode;
+       tExt2_Inode     RootInode;
        
        tExt2_SuperBlock        SuperBlock;
        Uint    BlockSize;
@@ -49,6 +50,6 @@ extern size_t Ext2_Read(tVFS_Node *node, off_t offset, size_t length, void *buff
 extern size_t  Ext2_Write(tVFS_Node *node, off_t offset, size_t length, const void *buffer, Uint Flags);
 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);
+extern int     Ext2_int_AppendBlock(tVFS_Node *Node, tExt2_Inode *Inode, Uint32 Block);
 
 #endif
index c77f06f..76ee993 100644 (file)
@@ -7,7 +7,7 @@
  * \brief Second Extended Filesystem Driver
  * \todo Implement file full write support
  */
-#define DEBUG  1
+#define DEBUG  0
 #define VERBOSE        0
 #include "ext2_common.h"
 
 size_t Ext2_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
 {
        tExt2_Disk      *disk = Node->ImplPtr;
-       tExt2_Inode     inode;
+       tExt2_Inode     *inode = (void*)(Node+1);
        Uint64  base;
        Uint    block;
        Uint64  remLen;
        
-       ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
-       
-       // Get Inode
-       Ext2_int_ReadInode(disk, Node->Inode, &inode);
+       ENTER("pNode XOffset xLength pBuffer", Node, Offset, Length, Buffer);
        
        // Sanity Checks
-       if(Offset >= inode.i_size) {
+       if(Offset >= inode->i_size) {
                LEAVE('i', 0);
                return 0;
        }
-       if(Offset + Length > inode.i_size)
-               Length = inode.i_size - Offset;
+       if(Offset + Length > inode->i_size)
+               Length = inode->i_size - Offset;
        
        block = Offset / disk->BlockSize;
-       Offset = Offset / disk->BlockSize;
-       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+       Offset = Offset % disk->BlockSize;
+       base = Ext2_int_GetBlockAddr(disk, inode->i_block, block);
        if(base == 0) {
-               Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode);
+               Log_Warning("EXT2", "NULL Block Detected in INode 0x%llx (Block %i)", Node->Inode, block);
                LEAVE('i', 0);
                return 0;
        }
@@ -64,7 +61,7 @@ size_t Ext2_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uin
        // Read middle blocks
        while(remLen > disk->BlockSize)
        {
-               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+               base = Ext2_int_GetBlockAddr(disk, inode->i_block, block);
                if(base == 0) {
                        Log_Warning("EXT2", "NULL Block Detected in INode 0x%llx", Node->Inode);
                        LEAVE('i', 0);
@@ -77,7 +74,7 @@ size_t Ext2_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uin
        }
        
        // Read last block
-       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+       base = Ext2_int_GetBlockAddr(disk, inode->i_block, block);
        VFS_ReadAt( disk->FD, base, remLen, Buffer);
        
        LEAVE('X', Length);
index 022bc96..78cf36c 100644 (file)
@@ -7,14 +7,13 @@
  * \brief Second Extended Filesystem Driver
  * \todo Implement file full write support
  */
-#define DEBUG  1
+#define DEBUG  0
 #define VERBOSE        0
 #include "ext2_common.h"
 
 // === PROTOYPES ===
 Uint32         Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock);
 void   Ext2_int_DeallocateBlock(tExt2_Disk *Disk, Uint32 Block);
- int   Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block);
 
 // === CODE ===
 /**
@@ -23,7 +22,7 @@ void  Ext2_int_DeallocateBlock(tExt2_Disk *Disk, Uint32 Block);
 size_t Ext2_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)
 {
        tExt2_Disk      *disk = Node->ImplPtr;
-       tExt2_Inode     inode;
+       tExt2_Inode     *inode = (void*)(Node+1);
        Uint64  base;
        Uint64  retLen;
        Uint    block;
@@ -33,13 +32,12 @@ size_t Ext2_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buff
        //Debug_HexDump("Ext2_Write", Buffer, Length);
 
        // TODO: Handle (Flags & VFS_IOFLAG_NOBLOCK)    
-
-       Ext2_int_ReadInode(disk, Node->Inode, &inode);
        
        // Get the ammount of space already allocated
        // - Round size up to block size
        // - block size is a power of two, so this will work
-       allocSize = (inode.i_size + disk->BlockSize-1) & ~(disk->BlockSize-1);
+       allocSize = (inode->i_size + disk->BlockSize-1) & ~(disk->BlockSize-1);
+       LOG("allocSize = %llx, Offset=%llx", allocSize, Offset);
        
        // Are we writing to inside the allocated space?
        if( Offset > allocSize )        return 0;
@@ -56,7 +54,7 @@ size_t Ext2_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buff
                // Within the allocated space
                block = Offset / disk->BlockSize;
                Offset %= disk->BlockSize;
-               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+               base = Ext2_int_GetBlockAddr(disk, inode->i_block, block);
                
                // Write only block (if only one)
                if(Offset + retLen <= disk->BlockSize) {
@@ -74,7 +72,7 @@ size_t Ext2_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buff
                // Write middle blocks
                while(retLen > disk->BlockSize)
                {
-                       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+                       base = Ext2_int_GetBlockAddr(disk, inode->i_block, block);
                        VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer);
                        Buffer += disk->BlockSize;
                        retLen -= disk->BlockSize;
@@ -82,25 +80,24 @@ size_t Ext2_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buff
                }
                
                // Write last block
-               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+               base = Ext2_int_GetBlockAddr(disk, inode->i_block, block);
                VFS_WriteAt(disk->FD, base, retLen, Buffer);
                if(!bNewBlocks) return Length;  // Writing in only allocated space
        }
        else
-               base = Ext2_int_GetBlockAddr(disk, inode.i_block, allocSize/disk->BlockSize-1);
+               base = Ext2_int_GetBlockAddr(disk, inode->i_block, allocSize/disk->BlockSize-1);
        
 addBlocks:
-       Log_Notice("EXT2", "File extending is untested");
-       
        // Allocate blocks and copy data to them
        retLen = Length - (allocSize-Offset);
-       while( retLen > disk->BlockSize )
+       while( retLen >  )
        {
+               size_t  blk_len = (retLen < disk->BlockSize ? retLen : disk->BlockSize);
                // Allocate a block
                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(Node, inode, block) ) {
                        Log_Warning("Ext2", "Appending %x to inode %p:%X failed",
                                block, disk, Node->Inode);
                        Ext2_int_DeallocateBlock(disk, block);
@@ -108,34 +105,24 @@ addBlocks:
                }
                // Copy data to the node
                base = block * disk->BlockSize;
-               VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer);
+               VFS_WriteAt(disk->FD, base, blk_len, Buffer);
                // Update pointer and size remaining
-               inode.i_size += disk->BlockSize;
-               Buffer += disk->BlockSize;
-               retLen -= disk->BlockSize;
-       }
-       // Last block :D
-       block = Ext2_int_AllocateBlock(disk, base/disk->BlockSize);
-       if(!block)      goto ret;
-       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;
+               Buffer += blk_len;
+               retLen -= blk_len;
        }
-       base = block * disk->BlockSize;
-       VFS_WriteAt(disk->FD, base, retLen, Buffer);
-       
-       // TODO: When should the size update be committed?
-       inode.i_size += retLen;
-       Node->Size += retLen;
-       Node->Flags |= VFS_FFLAG_DIRTY;
-       
-       retLen = 0;
 
-ret:   // Makes sure the changes to the inode are committed
-       Ext2_int_WriteInode(disk, Node->Inode, &inode);
-       return Length - retLen;
+
+ret:
+       retLen = Length - retLen;
+       if( retLen )
+       {
+               // TODO: When should the size update be committed?
+               inode->i_size += retLen;
+               Node->Size += retLen;
+               Node->Flags |= VFS_FFLAG_DIRTY;
+               //Ext2_int_WriteInode(disk, Node->Inode, inode);
+       }
+       return retLen;
 }
 
 /**
@@ -159,9 +146,10 @@ Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
 
        // First: Check the next block after `PrevBlock`
         int    iblock = (PrevBlock + 1) % Disk->SuperBlock.s_blocks_per_group;
+       //LOG("iblock = %i, Disk=%p, blockgroup=%i", iblock, Disk, blockgroup);
        if( iblock != 0 && Disk->Groups[blockgroup].bg_free_blocks_count > 0 )
        {
-               LOG("Checking %i:%i", blockgroup, iblock);
+               //LOG("Checking %i:%i", blockgroup, iblock);
                
                bg = &Disk->Groups[blockgroup];
                
@@ -174,7 +162,7 @@ Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
                Uint64  vol_ofs = Disk->BlockSize*bg->bg_block_bitmap+ofs;
                VFS_ReadAt(Disk->FD, vol_ofs, sector_size, buf);
 
-               LOG("buf@%llx[%i] = %02x (& %02x)", vol_ofs, byte, buf[byte], bit);
+               //LOG("buf@%llx[%i] = %02x (& %02x)", vol_ofs, byte, buf[byte], bit);
        
                if( (buf[byte] & bit) == 0 )
                {
@@ -208,7 +196,7 @@ Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
                        Disk);
                return 0;
        }
-       LOG("BG%i has free blocks", blockgroup);
+       //LOG("BG%i has free blocks", blockgroup);
 
        // Search the bitmap for a free block
        bg = &Disk->Groups[blockgroup]; 
@@ -224,7 +212,7 @@ Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
                        ;
                if( byte < sector_size )
                {
-                       LOG("buf@%llx[%i] = %02x", vol_ofs, byte, buf[byte]);
+                       //LOG("buf@%llx[%i] = %02x", vol_ofs, byte, buf[byte]);
                        for( bit = 0; bit < 8 && buf[byte] & (1 << bit); bit ++)
                                ;
                        ASSERT(bit != 8);
@@ -239,7 +227,7 @@ Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
                        #endif
 
                        Uint32  ret = blockgroup * Disk->SuperBlock.s_blocks_per_group + byte * 8 + bit;
-                       Log_Debug("Ext2", "Ext2_int_AllocateBlock - Allocated 0x%x", ret);
+                       LOG("Allocated 0x%x", ret);
                        return ret;
                }
        } while(ofs < Disk->SuperBlock.s_blocks_per_group / 8);
@@ -260,14 +248,17 @@ void Ext2_int_DeallocateBlock(tExt2_Disk *Disk, Uint32 Block)
 /**
  * \brief Append a block to an inode
  */
-int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block)
+int Ext2_int_AppendBlock(tVFS_Node *Node, tExt2_Inode *Inode, Uint32 Block)
 {
+       tExt2_Disk      *Disk = Node->ImplPtr;
         int    nBlocks;
         int    dwPerBlock = Disk->BlockSize / 4;
        Uint32  *blocks;
        Uint32  id1, id2;
        
        nBlocks = (Inode->i_size + Disk->BlockSize - 1) / Disk->BlockSize;
+
+       LOG("Append 0x%x to inode [%i]", Block, nBlocks);
        
        // Direct Blocks
        if( nBlocks < 12 ) {
@@ -282,6 +273,7 @@ int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block)
        // Single Indirect
        if( nBlocks < dwPerBlock)
        {
+               LOG("Indirect 1 %i", nBlocks);
                // Allocate/Get Indirect block
                if( nBlocks == 0 ) {
                        Inode->i_block[12] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
@@ -298,14 +290,16 @@ int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block)
                blocks[nBlocks] = Block;
                
                VFS_WriteAt(Disk->FD, Inode->i_block[12]*Disk->BlockSize, Disk->BlockSize, blocks);
+               Node->Flags |= VFS_FFLAG_DIRTY;
                free(blocks);
                return 0;
        }
        
-       nBlocks += dwPerBlock;
+       nBlocks -= dwPerBlock;
        // Double Indirect
        if( nBlocks < dwPerBlock*dwPerBlock )
        {
+               LOG("Indirect 2 %i/%i", nBlocks/dwPerBlock, nBlocks%dwPerBlock);
                // Allocate/Get Indirect block
                if( nBlocks == 0 ) {
                        Inode->i_block[13] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
@@ -315,6 +309,7 @@ int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block)
                                return 1;
                        }
                        memset(blocks, 0, Disk->BlockSize);
+                       Node->Flags |= VFS_FFLAG_DIRTY;
                }
                else
                        VFS_ReadAt(Disk->FD, Inode->i_block[13]*Disk->BlockSize, Disk->BlockSize, blocks);
@@ -357,6 +352,7 @@ int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block)
                                return 1;
                        }
                        memset(blocks, 0, Disk->BlockSize);
+                       Node->Flags |= VFS_FFLAG_DIRTY;
                }
                else
                        VFS_ReadAt(Disk->FD, Inode->i_block[14]*Disk->BlockSize, Disk->BlockSize, blocks);

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