From bffac877be10357e17ba29ffce8978efc405afdd Mon Sep 17 00:00:00 2001 From: John Hodge Date: Tue, 28 Aug 2012 09:30:56 +0800 Subject: [PATCH] Modules/Ext2 - Adding inode creation/writeback on file close - Also added VFS_CleanupNode (does nothing atm) --- KernelLand/Kernel/vfs/main.c | 6 + KernelLand/Modules/Filesystems/Ext2/dir.c | 83 +----------- KernelLand/Modules/Filesystems/Ext2/ext2.c | 120 +++++++++++++++++- .../Modules/Filesystems/Ext2/ext2_common.h | 6 + .../Modules/Filesystems/FAT/nodecache.c | 1 + 5 files changed, 129 insertions(+), 87 deletions(-) diff --git a/KernelLand/Kernel/vfs/main.c b/KernelLand/Kernel/vfs/main.c index fb1da898..0261eca3 100644 --- a/KernelLand/Kernel/vfs/main.c +++ b/KernelLand/Kernel/vfs/main.c @@ -172,3 +172,9 @@ void VFS_UpdateDriverFile(void) if(gsVFS_DriverFile) free(gsVFS_DriverFile); gsVFS_DriverFile = buf; } + +void VFS_CleanupNode(tVFS_Node *Node) +{ + +} + diff --git a/KernelLand/Modules/Filesystems/Ext2/dir.c b/KernelLand/Modules/Filesystems/Ext2/dir.c index de0b30a5..33df8472 100644 --- a/KernelLand/Modules/Filesystems/Ext2/dir.c +++ b/KernelLand/Modules/Filesystems/Ext2/dir.c @@ -5,7 +5,7 @@ * dir.c * - Directory Handling */ -#define DEBUG 1 +#define DEBUG 0 #define VERBOSE 0 #include "ext2_common.h" @@ -18,8 +18,6 @@ tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *FileName); tVFS_Node *Ext2_MkNod(tVFS_Node *Node, const char *Name, Uint Flags); int Ext2_Unlink(tVFS_Node *Node, const char *OldName); int Ext2_Link(tVFS_Node *Parent, const char *Name, tVFS_Node *Node); -// --- Helpers --- -tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId); // === GLOBALS === tVFS_NodeType gExt2_DirType = { @@ -234,7 +232,6 @@ int Ext2_Unlink(tVFS_Node *Node, const char *OldName) */ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child) { - #if 1 tExt2_Disk *disk = Node->ImplPtr; tExt2_Inode inode; tExt2_DirEnt *dirent; @@ -401,83 +398,5 @@ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child) Mutex_Release(&Node->Lock); LEAVE('i', 0); return 0; - #else - Log_Warning("Ext2", "TODO: Impliment Ext2_Link"); - return 1; - #endif -} - -// ---- INTERNAL FUNCTIONS ---- -/** - * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID) - * \brief Create a new VFS Node - */ -tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID) -{ - tExt2_Inode inode; - tVFS_Node retNode; - tVFS_Node *tmpNode; - - if( !Ext2_int_ReadInode(Disk, InodeID, &inode) ) - return NULL; - - if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) ) - return tmpNode; - - memset(&retNode, 0, sizeof(retNode)); - - // Set identifiers - retNode.Inode = InodeID; - retNode.ImplPtr = Disk; - retNode.ImplInt = inode.i_links_count; - - // Set file length - retNode.Size = inode.i_size; - - // Set Access Permissions - retNode.UID = inode.i_uid; - retNode.GID = inode.i_gid; - retNode.NumACLs = 3; - retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid); - - // Set Function Pointers - retNode.Type = &gExt2_FileType; - - switch(inode.i_mode & EXT2_S_IFMT) - { - // Symbolic Link - case EXT2_S_IFLNK: - retNode.Flags = VFS_FFLAG_SYMLINK; - break; - // Regular File - case EXT2_S_IFREG: - retNode.Flags = 0; - retNode.Size |= (Uint64)inode.i_dir_acl << 32; - break; - // Directory - case EXT2_S_IFDIR: - retNode.Type = &gExt2_DirType; - retNode.Flags = VFS_FFLAG_DIRECTORY; - retNode.Data = calloc( sizeof(Uint16), DivUp(retNode.Size, Disk->BlockSize) ); - break; - // Unknown, Write protect it to be safe - default: - retNode.Flags = VFS_FFLAG_READONLY; - break; - } - - // Set Timestamps - retNode.ATime = inode.i_atime * 1000; - retNode.MTime = inode.i_mtime * 1000; - retNode.CTime = inode.i_ctime * 1000; - - // 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; } diff --git a/KernelLand/Modules/Filesystems/Ext2/ext2.c b/KernelLand/Modules/Filesystems/Ext2/ext2.c index adf91635..4d13f1ed 100644 --- a/KernelLand/Modules/Filesystems/Ext2/ext2.c +++ b/KernelLand/Modules/Filesystems/Ext2/ext2.c @@ -13,9 +13,6 @@ #define MIN_BLOCKS_PER_GROUP 2 #define MAX_BLOCK_LOG_SIZE 10 // 1024 << 10 = 1MiB -// === IMPORTS === -extern tVFS_NodeType gExt2_DirType; - // === PROTOTYPES === int Ext2_Install(char **Arguments); int Ext2_Cleanup(void); @@ -236,7 +233,8 @@ void Ext2_CloseFile(tVFS_Node *Node) if( Node->Flags & VFS_FFLAG_DIRTY ) { // Commit changes - Log_Warning("Ext2", "TODO: Commit node changes"); + Ext2_int_WritebackNode(disk, Node); + Node->Flags &= ~VFS_FFLAG_DIRTY; } int was_not_referenced = (Node->ImplInt == 0); @@ -247,7 +245,7 @@ void Ext2_CloseFile(tVFS_Node *Node) { LOG("Removng inode"); // Remove inode - Log_Warning("Ext2", "TODO: Remove inode when not referenced"); + Log_Warning("Ext2", "TODO: Remove inode when not referenced (%x)", (Uint32)Node->Inode); } if( acls != &gVFS_ACL_EveryoneRW ) { free(acls); @@ -325,6 +323,118 @@ int Ext2_int_WriteInode(tExt2_Disk *Disk, Uint32 InodeId, tExt2_Inode *Inode) return 1; } +/** + * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID) + * \brief Create a new VFS Node + */ +tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID) +{ + tExt2_Inode inode; + tVFS_Node retNode; + tVFS_Node *tmpNode; + + if( !Ext2_int_ReadInode(Disk, InodeID, &inode) ) + return NULL; + + if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) ) + return tmpNode; + + memset(&retNode, 0, sizeof(retNode)); + + // Set identifiers + retNode.Inode = InodeID; + retNode.ImplPtr = Disk; + retNode.ImplInt = inode.i_links_count; + if( inode.i_links_count == 0 ) { + Log_Notice("Ext2", "Inode %p:%x is not referenced, bug?", Disk, InodeID); + } + + // Set file length + retNode.Size = inode.i_size; + + // Set Access Permissions + retNode.UID = inode.i_uid; + retNode.GID = inode.i_gid; + retNode.NumACLs = 3; + retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid); + + // Set Function Pointers + retNode.Type = &gExt2_FileType; + + switch(inode.i_mode & EXT2_S_IFMT) + { + // Symbolic Link + case EXT2_S_IFLNK: + retNode.Flags = VFS_FFLAG_SYMLINK; + break; + // Regular File + case EXT2_S_IFREG: + retNode.Flags = 0; + retNode.Size |= (Uint64)inode.i_dir_acl << 32; + break; + // Directory + case EXT2_S_IFDIR: + retNode.Type = &gExt2_DirType; + retNode.Flags = VFS_FFLAG_DIRECTORY; + retNode.Data = calloc( sizeof(Uint16), DivUp(retNode.Size, Disk->BlockSize) ); + break; + // Unknown, Write protect it to be safe + default: + retNode.Flags = VFS_FFLAG_READONLY; + break; + } + + // Set Timestamps + retNode.ATime = inode.i_atime * 1000; + retNode.MTime = inode.i_mtime * 1000; + retNode.CTime = inode.i_ctime * 1000; + + // Save in node cache and return saved node + return Inode_CacheNode(Disk->CacheID, &retNode); +} + +int Ext2_int_WritebackNode(tExt2_Disk *Disk, tVFS_Node *Node) +{ + tExt2_Inode inode; + + if( Disk != Node->ImplPtr ) { + Log_Error("Ext2", "Ext2_int_WritebackNode - Disk != Node->ImplPtr"); + return -1; + } + + if( Node->Flags & VFS_FFLAG_SYMLINK ) { + inode.i_mode = EXT2_S_IFLNK; + } + else if( Node->Flags & VFS_FFLAG_DIRECTORY ) { + inode.i_mode = EXT2_S_IFDIR; + } + else if( Node->Flags & VFS_FFLAG_READONLY ) { + Log_Notice("Ext2", "Not writing back readonly inode %p:%x", Disk, Node->Inode); + return 1; + } + else { + inode.i_mode = EXT2_S_IFREG; + inode.i_dir_acl = Node->Size >> 32; + } + + inode.i_size = Node->Size & 0xFFFFFFFF; + inode.i_links_count = Node->ImplInt; + + inode.i_uid = Node->UID; + inode.i_gid = Node->GID; + + inode.i_atime = Node->ATime / 1000; + inode.i_mtime = Node->MTime / 1000; + inode.i_ctime = Node->CTime / 1000; + + // TODO: Compact ACLs into unix mode + Log_Warning("Ext2", "TODO: Support converting Acess ACLs into unix modes"); + + Ext2_int_WriteInode(Disk, Node->Inode, &inode); + + return 0; +} + /** * \fn Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum) * \brief Get the address of a block from an inode's list diff --git a/KernelLand/Modules/Filesystems/Ext2/ext2_common.h b/KernelLand/Modules/Filesystems/Ext2/ext2_common.h index 5515429f..4c8c45e2 100644 --- a/KernelLand/Modules/Filesystems/Ext2/ext2_common.h +++ b/KernelLand/Modules/Filesystems/Ext2/ext2_common.h @@ -23,6 +23,10 @@ typedef struct { tExt2_Group Groups[]; } tExt2_Disk; +// === GLOBALS === +extern tVFS_NodeType gExt2_FileType; +extern tVFS_NodeType gExt2_DirType; + // === FUNCTIONS === // --- Common --- extern void Ext2_CloseFile(tVFS_Node *Node); @@ -37,6 +41,8 @@ extern int Ext2_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]); extern tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *FileName); extern tVFS_Node *Ext2_MkNod(tVFS_Node *Node, const char *Name, Uint Flags); extern int Ext2_Link(tVFS_Node *Parent, const char *Name, tVFS_Node *Node); +extern tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId); +extern int Ext2_int_WritebackNode(tExt2_Disk *Disk, tVFS_Node *Node); // --- Read --- extern size_t Ext2_Read(tVFS_Node *node, off_t offset, size_t length, void *buffer); // --- Write --- diff --git a/KernelLand/Modules/Filesystems/FAT/nodecache.c b/KernelLand/Modules/Filesystems/FAT/nodecache.c index a0b3b316..1ad26e56 100644 --- a/KernelLand/Modules/Filesystems/FAT/nodecache.c +++ b/KernelLand/Modules/Filesystems/FAT/nodecache.c @@ -223,6 +223,7 @@ int FAT_int_DerefNode(tVFS_Node *Node) // Already out of the list :) if(cnode->Node.Data) free(cnode->Node.Data); + VFS_CleanupNode(&cnode->Node); free(cnode); bFreed = 1; } -- 2.20.1