From: John Hodge Date: Sun, 22 Jun 2014 15:16:49 +0000 (+0800) Subject: Kernel/VFS - Truncate support, mmap fixes X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=c1b33e91984102c1aa9a2ffe19f02c315b481726;p=tpg%2Facess2.git Kernel/VFS - Truncate support, mmap fixes --- diff --git a/KernelLand/Kernel/arch/x86/proc.c b/KernelLand/Kernel/arch/x86/proc.c index 460c920b..999ac679 100644 --- a/KernelLand/Kernel/arch/x86/proc.c +++ b/KernelLand/Kernel/arch/x86/proc.c @@ -481,7 +481,6 @@ tPID Proc_Clone(Uint Flags) tThread *cur = Proc_GetCurThread(); Uint eip; - Log_Warning("Proc", "Proc_Clone is deprecated"); // Sanity, please if( !(Flags & CLONE_VM) ) { Log_Error("Proc", "Proc_Clone: Don't leave CLONE_VM unset, use Proc_NewKThread instead"); diff --git a/KernelLand/Kernel/drv/dgram_pipe.c b/KernelLand/Kernel/drv/dgram_pipe.c index 9e0c52d8..667190eb 100644 --- a/KernelLand/Kernel/drv/dgram_pipe.c +++ b/KernelLand/Kernel/drv/dgram_pipe.c @@ -86,6 +86,7 @@ tVFS_NodeType gIPCPipe_ServerNodeType = { }; tVFS_NodeType gIPCPipe_ChannelNodeType = { .TypeName = "IPC Pipe - Channel", + .Flags = VFS_NODETYPEFLAG_STREAM, .Read = IPCPipe_Client_Read, .Write = IPCPipe_Client_Write, .Close = IPCPipe_Client_Close @@ -211,8 +212,10 @@ tVFS_Node *IPCPipe_Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags) new_client->Server = srv; new_client->ClientEP.Node.Type = &gIPCPipe_ChannelNodeType; new_client->ClientEP.Node.ImplPtr = new_client; + new_client->ClientEP.Node.Size = -1; new_client->ServerEP.Node.Type = &gIPCPipe_ChannelNodeType; new_client->ServerEP.Node.ImplPtr = new_client; + new_client->ServerEP.Node.Size = -1; // Append to server list RWLock_AcquireWrite(&srv->lChannelList); diff --git a/KernelLand/Kernel/drv/pty.c b/KernelLand/Kernel/drv/pty.c index d6713f9c..2e793236 100644 --- a/KernelLand/Kernel/drv/pty.c +++ b/KernelLand/Kernel/drv/pty.c @@ -85,6 +85,7 @@ tVFS_NodeType gPTY_NodeType_Root = { }; tVFS_NodeType gPTY_NodeType_Client = { .TypeName = "PTY-Client", + .Flags = VFS_NODETYPEFLAG_STREAM, .Read = PTY_ReadClient, .Write = PTY_WriteClient, .IOCtl = PTY_IOCtl, @@ -93,6 +94,7 @@ tVFS_NodeType gPTY_NodeType_Client = { }; tVFS_NodeType gPTY_NodeType_Server = { .TypeName = "PTY-Server", + .Flags = VFS_NODETYPEFLAG_STREAM, .Read = PTY_ReadServer, .Write = PTY_WriteServer, .IOCtl = PTY_IOCtl, @@ -235,6 +237,7 @@ tPTY *PTY_Create(const char *Name, void *Handle, tPTY_OutputFcn Output, tPTY_Req if( InitialMode ) ret->Mode = *InitialMode; // - Client node + ret->ClientNode.Size = -1; ret->ClientNode.ImplPtr = ret; ret->ClientNode.Type = &gPTY_NodeType_Client; ret->ClientNode.UID = Threads_GetUID(); diff --git a/KernelLand/Kernel/drv/zero-one.c b/KernelLand/Kernel/drv/zero-one.c index fa2b502f..b21d1eff 100644 --- a/KernelLand/Kernel/drv/zero-one.c +++ b/KernelLand/Kernel/drv/zero-one.c @@ -23,33 +23,38 @@ size_t CoreDevs_Read_GRandom(tVFS_Node *Node, off_t Offset, size_t Length, void MODULE_DEFINE(0, 0x0100, CoreDevs, CoreDevs_Install, NULL, NULL); tVFS_NodeType gCoreDevs_NT_Null = { .TypeName = "CoreDevs-null", + .Flags = VFS_NODETYPEFLAG_STREAM, .Read = CoreDevs_Read_Null, .Write = CoreDevs_Write }; tVFS_NodeType gCoreDevs_NT_Zero = { .TypeName = "CoreDevs-zero", + .Flags = VFS_NODETYPEFLAG_STREAM, .Read = CoreDevs_Read_Zero, .Write = CoreDevs_Write }; tVFS_NodeType gCoreDevs_NT_One = { .TypeName = "CoreDevs-one", + .Flags = VFS_NODETYPEFLAG_STREAM, .Read = CoreDevs_Read_One, .Write = CoreDevs_Write }; tVFS_NodeType gCoreDevs_NT_FRandom = { .TypeName = "CoreDevs-frandom", + .Flags = VFS_NODETYPEFLAG_STREAM, .Read = CoreDevs_Read_FRandom, .Write = CoreDevs_Write }; tVFS_NodeType gCoreDevs_NT_GRandom = { .TypeName = "CoreDevs-grandom", + .Flags = VFS_NODETYPEFLAG_STREAM, .Read = CoreDevs_Read_GRandom, .Write = CoreDevs_Write }; tDevFS_Driver gCoreDevs_Null = { NULL, "null", { - .Size = 0, .NumACLs = 1, + .Size = -1, .NumACLs = 1, .ACLs = &gVFS_ACL_EveryoneRW, .Type = &gCoreDevs_NT_Null } @@ -57,7 +62,7 @@ tDevFS_Driver gCoreDevs_Null = { tDevFS_Driver gCoreDevs_Zero = { NULL, "zero", { - .Size = 0, .NumACLs = 1, + .Size = -1, .NumACLs = 1, .ACLs = &gVFS_ACL_EveryoneRW, .Type = &gCoreDevs_NT_Zero } @@ -65,7 +70,7 @@ tDevFS_Driver gCoreDevs_Zero = { tDevFS_Driver gCoreDevs_One = { NULL, "one", { - .Size = 0, .NumACLs = 1, + .Size = -1, .NumACLs = 1, .ACLs = &gVFS_ACL_EveryoneRW, .Type = &gCoreDevs_NT_One } @@ -73,7 +78,7 @@ tDevFS_Driver gCoreDevs_One = { tDevFS_Driver gCoreDevs_FRandom = { NULL, "frandom", { - .Size = 0, .NumACLs = 1, + .Size = -1, .NumACLs = 1, .ACLs = &gVFS_ACL_EveryoneRW, .Type = &gCoreDevs_NT_FRandom, .DataAvaliable = 1 @@ -82,7 +87,7 @@ tDevFS_Driver gCoreDevs_FRandom = { tDevFS_Driver gCoreDevs_GRandom = { NULL, "grandom", { - .Size = 0, .NumACLs = 1, + .Size = -1, .NumACLs = 1, .ACLs = &gVFS_ACL_EveryoneRW, .Type = &gCoreDevs_NT_GRandom, .DataAvaliable = 1 diff --git a/KernelLand/Kernel/include/syscalls.h b/KernelLand/Kernel/include/syscalls.h index 2a880f64..0ad44133 100644 --- a/KernelLand/Kernel/include/syscalls.h +++ b/KernelLand/Kernel/include/syscalls.h @@ -56,25 +56,28 @@ #define SYS_READAT 72 // Read from an open file (with offset) #define SYS_WRITE 73 // Write to an open file #define SYS_WRITEAT 74 // Write to an open file (with offset) -#define SYS_IOCTL 75 // Perform an IOCtl Call -#define SYS_SEEK 76 // Seek to a new position in the file -#define SYS_READDIR 77 // Read from an open directory -#define SYS_GETACL 78 // Get an ACL Value -#define SYS_SETACL 79 // Set an ACL Value -#define SYS_FINFO 80 // Get file information -#define SYS_MKDIR 81 // Create a new directory -#define SYS_LINK 82 // Create a new link to a file -#define SYS_SYMLINK 83 // Create a symbolic link -#define SYS_UNLINK 84 // Delete a file -#define SYS_TELL 85 // Return the current file position -#define SYS_CHDIR 86 // Change current directory -#define SYS_GETCWD 87 // Get current directory -#define SYS_MOUNT 88 // Mount a filesystem -#define SYS_SELECT 89 // Wait for file handles -#define SYS_MARSHALFD 90 // Create a reference to a FD suitable for handing to another process -#define SYS_UNMARSHALFD 91 // Accept a marshaled FD +#define SYS_TRUNCATE 75 // Change the size of an open file +#define SYS_IOCTL 76 // Perform an IOCtl Call +#define SYS_SEEK 77 // Seek to a new position in the file +#define SYS_READDIR 78 // Read from an open directory +#define SYS_GETACL 79 // Get an ACL Value +#define SYS_SETACL 80 // Set an ACL Value +#define SYS_FINFO 81 // Get file information +#define SYS_MKDIR 82 // Create a new directory +#define SYS_LINK 83 // Create a new link to a file +#define SYS_SYMLINK 84 // Create a symbolic link +#define SYS_UNLINK 85 // Delete a file +#define SYS_TELL 86 // Return the current file position +#define SYS_CHDIR 87 // Change current directory +#define SYS_GETCWD 88 // Get current directory +#define SYS_MOUNT 89 // Mount a filesystem +#define SYS_SELECT 90 // Wait for file handles +#define SYS_MMAP 91 // Map a file into this address space +#define SYS_MUNMAP 92 // Unmap a file +#define SYS_MARSHALFD 93 // Create a reference to a FD suitable for handing to another process +#define SYS_UNMARSHALFD 94 // Accept a marshaled FD -#define NUM_SYSCALLS 92 +#define NUM_SYSCALLS 95 #define SYS_DEBUG 0x100 #define SYS_DEBUGHEX 0x101 @@ -155,6 +158,7 @@ static const char *cSYSCALL_NAMES[] = { "SYS_READAT", "SYS_WRITE", "SYS_WRITEAT", + "SYS_TRUNCATE", "SYS_IOCTL", "SYS_SEEK", "SYS_READDIR", @@ -170,6 +174,8 @@ static const char *cSYSCALL_NAMES[] = { "SYS_GETCWD", "SYS_MOUNT", "SYS_SELECT", + "SYS_MMAP", + "SYS_MUNMAP", "SYS_MARSHALFD", "SYS_UNMARSHALFD", diff --git a/KernelLand/Kernel/include/syscalls.inc.asm b/KernelLand/Kernel/include/syscalls.inc.asm index 656526ca..35743b10 100644 --- a/KernelLand/Kernel/include/syscalls.inc.asm +++ b/KernelLand/Kernel/include/syscalls.inc.asm @@ -48,20 +48,23 @@ %define SYS_READAT 72 ;Read from an open file (with offset) %define SYS_WRITE 73 ;Write to an open file %define SYS_WRITEAT 74 ;Write to an open file (with offset) -%define SYS_IOCTL 75 ;Perform an IOCtl Call -%define SYS_SEEK 76 ;Seek to a new position in the file -%define SYS_READDIR 77 ;Read from an open directory -%define SYS_GETACL 78 ;Get an ACL Value -%define SYS_SETACL 79 ;Set an ACL Value -%define SYS_FINFO 80 ;Get file information -%define SYS_MKDIR 81 ;Create a new directory -%define SYS_LINK 82 ;Create a new link to a file -%define SYS_SYMLINK 83 ;Create a symbolic link -%define SYS_UNLINK 84 ;Delete a file -%define SYS_TELL 85 ;Return the current file position -%define SYS_CHDIR 86 ;Change current directory -%define SYS_GETCWD 87 ;Get current directory -%define SYS_MOUNT 88 ;Mount a filesystem -%define SYS_SELECT 89 ;Wait for file handles -%define SYS_MARSHALFD 90 ;Create a reference to a FD suitable for handing to another process -%define SYS_UNMARSHALFD 91 ;Accept a marshaled FD +%define SYS_TRUNCATE 75 ;Change the size of an open file +%define SYS_IOCTL 76 ;Perform an IOCtl Call +%define SYS_SEEK 77 ;Seek to a new position in the file +%define SYS_READDIR 78 ;Read from an open directory +%define SYS_GETACL 79 ;Get an ACL Value +%define SYS_SETACL 80 ;Set an ACL Value +%define SYS_FINFO 81 ;Get file information +%define SYS_MKDIR 82 ;Create a new directory +%define SYS_LINK 83 ;Create a new link to a file +%define SYS_SYMLINK 84 ;Create a symbolic link +%define SYS_UNLINK 85 ;Delete a file +%define SYS_TELL 86 ;Return the current file position +%define SYS_CHDIR 87 ;Change current directory +%define SYS_GETCWD 88 ;Get current directory +%define SYS_MOUNT 89 ;Mount a filesystem +%define SYS_SELECT 90 ;Wait for file handles +%define SYS_MMAP 91 ;Map a file into this address space +%define SYS_MUNMAP 92 ;Unmap a file +%define SYS_MARSHALFD 93 ;Create a reference to a FD suitable for handing to another process +%define SYS_UNMARSHALFD 94 ;Accept a marshaled FD diff --git a/KernelLand/Kernel/include/vfs.h b/KernelLand/Kernel/include/vfs.h index 4be24c38..72c6cbd3 100644 --- a/KernelLand/Kernel/include/vfs.h +++ b/KernelLand/Kernel/include/vfs.h @@ -216,6 +216,21 @@ typedef struct sVFS_Node * \} */ +/** + * \name tVFS_NodeType.Type flags + * \brief Flags for node types + * \{ + */ +//\! Calls to VFS_Write should not generate calls to .Trunctate +//\! +//\! If this flag is set, writing over the end of the file will not call .Truncate automatically +#define VFS_NODETYPEFLAG_NOAUTOEXPAND 0x001 +//\! Node type describes a stream (offset ignored, seeking disallowed) +#define VFS_NODETYPEFLAG_STREAM 0x002 +/** + * \} + */ + /** * \brief Functions for a specific node type */ @@ -226,6 +241,11 @@ struct sVFS_NodeType */ const char *TypeName; + /** + * \brief Flags describing operational quirks + */ + unsigned int Flags; + /** * \name Common Functions * \brief Functions that are used no matter the value of .Flags @@ -295,6 +315,17 @@ struct sVFS_NodeType */ int (*MMap)(struct sVFS_Node *Node, off_t Offset, int Length, void *Dest); + /** + * \brief Resize a file + * \param Node Pointer to this node + * \param NewSize New file size + * \return Actual new file size + * \note If NULL, \a Write may be called with Offset + Length > Size + * + * Called to increase/decrease the size of a file. If the + */ + off_t (*Truncate)(struct sVFS_Node *Node, off_t NewSize); + /** * \} */ diff --git a/KernelLand/Kernel/include/vfs_ext.h b/KernelLand/Kernel/include/vfs_ext.h index 99a64e3b..42d98654 100644 --- a/KernelLand/Kernel/include/vfs_ext.h +++ b/KernelLand/Kernel/include/vfs_ext.h @@ -328,6 +328,16 @@ extern size_t VFS_ReadAt(int FD, Uint64 Offset, size_t Length, void *Buffer); */ extern size_t VFS_WriteAt(int FD, Uint64 Offset, size_t Length, const void *Buffer); +/** + * \brief Set the valid size of a file + * \param FD File descriptor + * \param Size New file size + * \return Actual new file size (-1 if error occurred) + * + * \note Not all files support this call (will return ENOTIMPL) + */ +extern off_t VFS_Truncate(int FD, off_t Size); + /** * \brief Sends an IOCtl request to the driver * \param FD File handle returned by ::VFS_Open diff --git a/KernelLand/Kernel/syscalls.c b/KernelLand/Kernel/syscalls.c index 75ed8745..5f52e0ee 100644 --- a/KernelLand/Kernel/syscalls.c +++ b/KernelLand/Kernel/syscalls.c @@ -293,6 +293,17 @@ void SyscallHandler(tSyscallRegs *Regs) #endif break; + case SYS_TRUNCATE: + ret = VFS_Truncate( + Regs->Arg1, + #if BITS == 32 + ARG64(2,3) + #else + Regs->Arg2 + #endif + ); + break; + case SYS_FINFO: CHECK_NUM_NONULL( (void*)Regs->Arg2, sizeof(tFInfo) + Regs->Arg3*sizeof(tVFS_ACL) ); // FP, Dest, MaxACLs @@ -394,6 +405,21 @@ void SyscallHandler(tSyscallRegs *Regs) ); break; + case SYS_MMAP: + ret = (tVAddr)VFS_MMap( + (void*)Regs->Arg1, Regs->Arg2, + Regs->Arg3&0xFFFF, Regs->Arg3>>16, + Regs->Arg4, + #if BITS == 32 + ARG64(5,6) + #else + Regs->Arg5 + #endif + ); + break; + case SYS_MUNMAP: + ret = VFS_MUnmap( (void*)Regs->Arg1, Regs->Arg2 ); + break; // Create a directory case SYS_MKDIR: diff --git a/KernelLand/Kernel/syscalls.lst b/KernelLand/Kernel/syscalls.lst index d3b45573..bea821b5 100644 --- a/KernelLand/Kernel/syscalls.lst +++ b/KernelLand/Kernel/syscalls.lst @@ -56,6 +56,7 @@ SYS_READ Read from an open file SYS_READAT Read from an open file (with offset) SYS_WRITE Write to an open file SYS_WRITEAT Write to an open file (with offset) +SYS_TRUNCATE Change the size of an open file SYS_IOCTL Perform an IOCtl Call SYS_SEEK Seek to a new position in the file SYS_READDIR Read from an open directory @@ -71,7 +72,8 @@ SYS_CHDIR Change current directory SYS_GETCWD Get current directory SYS_MOUNT Mount a filesystem SYS_SELECT Wait for file handles - +SYS_MMAP Map a file into this address space +SYS_MUNMAP Unmap a file SYS_MARSHALFD Create a reference to a FD suitable for handing to another process SYS_UNMARSHALFD Accept a marshaled FD diff --git a/KernelLand/Kernel/vfs/io.c b/KernelLand/Kernel/vfs/io.c index 271e920d..cb0140ac 100644 --- a/KernelLand/Kernel/vfs/io.c +++ b/KernelLand/Kernel/vfs/io.c @@ -100,16 +100,32 @@ size_t VFS_ReadAt(int FD, Uint64 Offset, size_t Length, void *Buffer) */ size_t VFS_Write(int FD, size_t Length, const void *Buffer) { - tVFS_Handle *h; - size_t ret; - - h = VFS_GetHandle(FD); + tVFS_Handle *h = VFS_GetHandle(FD); if(!h) { LOG("FD%i is not open", FD); errno = EBADF; return -1; } + size_t ret = VFS_WriteAt(FD, h->Position, Length, Buffer); + if(ret == (size_t)-1) return -1; + + if( !(h->Node->Type->Flags & VFS_NODETYPEFLAG_STREAM) ) + h->Position += ret; + return ret; +} + +/** + * \fn Uint64 VFS_WriteAt(int FD, Uint64 Offset, Uint64 Length, const void *Buffer) + * \brief Write data to a file at a given offset + */ +size_t VFS_WriteAt(int FD, Uint64 Offset, size_t Length, const void *Buffer) +{ + LOG("FD=%i,Offset=%lli,Length=%i,Buffer=%p", + FD, Offset, Length, Buffer); + tVFS_Handle *h = VFS_GetHandle(FD); + if(!h) return -1; + if( !(h->Mode & VFS_OPENFLAG_WRITE) ) { LOG("FD%i not opened for writing", FD); errno = EBADF; @@ -121,57 +137,63 @@ size_t VFS_Write(int FD, size_t Length, const void *Buffer) return -1; } - if( !h->Node->Type || !h->Node->Type->Write ) { + const tVFS_NodeType* nodetype = h->Node->Type; + if(!nodetype || !nodetype->Write) { LOG("FD%i has no write method", FD); errno = EINTERNAL; return 0; } - - if( !MM_GetPhysAddr(h->Node->Type->Write) ) { + + if( !MM_GetPhysAddr(nodetype->Write) ) { Log_Error("VFS", "Node type %p(%s) write method is junk %p", - h->Node->Type, h->Node->Type->TypeName, - h->Node->Type->Write); + nodetype, nodetype->TypeName, nodetype->Write); errno = EINTERNAL; return -1; } - Uint flags = 0; - flags |= (h->Mode & VFS_OPENFLAG_NONBLOCK) ? VFS_IOFLAG_NOBLOCK : 0; - ret = h->Node->Type->Write(h->Node, h->Position, Length, Buffer, flags); - if(ret != Length) LOG("%i/%i written", ret, Length); - if(ret == (size_t)-1) return -1; - - h->Position += ret; - return ret; -} - -/** - * \fn Uint64 VFS_WriteAt(int FD, Uint64 Offset, Uint64 Length, const void *Buffer) - * \brief Write data to a file at a given offset - */ -size_t VFS_WriteAt(int FD, Uint64 Offset, size_t Length, const void *Buffer) -{ - tVFS_Handle *h; - size_t ret; - - h = VFS_GetHandle(FD); - if(!h) return -1; - - if( !(h->Mode & VFS_OPENFLAG_WRITE) ) return -1; - if( h->Node->Flags & VFS_FFLAG_DIRECTORY ) return -1; - - if(!h->Node->Type || !h->Node->Type->Write) return 0; - - if( !MM_GetPhysAddr(h->Node->Type->Write) ) { - Log_Error("VFS", "Node type %p(%s) write method is junk %p", - h->Node->Type, h->Node->Type->TypeName, - h->Node->Type->Write); - return -1; + // Bounds checks + if( h->Node->Size != (Uint64)-1 && Offset > h->Node->Size ) { + Log_Notice("VFS", "Write starting past EOF of FD%x (%lli > %lli)", + FD, Offset, h->Node->Size); + //errno = ESPIPE; + return 0; + } + if( Offset + Length > h->Node->Size ) + { + // Going OOB + if( !nodetype->Truncate ) + { + LOG("No .Truncate method, emiting write past EOF"); + } + else if( nodetype->Flags & VFS_NODETYPEFLAG_NOAUTOEXPAND ) + { + LOG("NOAUTOEXPAND set, truncating length from %i to %i", + Length, h->Node->Size - Offset); + Length = h->Node->Size - Offset; + } + else if( nodetype->Truncate(h->Node, Offset + Length) != Offset + Length ) + { + // oh... fail? Truncate to current size + LOG(".Truncate failed, truncating length from %i to %i", + Length, h->Node->Size - Offset); + Length = h->Node->Size - Offset; + } + else + { + // Expansion, node size should now fit + LOG("Expanded file"); + } } + + // Create flag set Uint flags = 0; flags |= (h->Mode & VFS_OPENFLAG_NONBLOCK) ? VFS_IOFLAG_NOBLOCK : 0; - ret = h->Node->Type->Write(h->Node, Offset, Length, Buffer, flags); + + // Dispatch the read! + size_t ret = nodetype->Write(h->Node, Offset, Length, Buffer, flags); if(ret == (size_t)-1) return -1; + if(ret != Length) LOG("%i/%i written", ret, Length); + return ret; } @@ -198,11 +220,14 @@ Uint64 VFS_Tell(int FD) */ int VFS_Seek(int FD, Sint64 Offset, int Whence) { - tVFS_Handle *h; - - h = VFS_GetHandle(FD); + tVFS_Handle *h = VFS_GetHandle(FD); if(!h) return -1; + if( (h->Node->Type->Flags & VFS_NODETYPEFLAG_STREAM) ) { + LOG("Seeking in stream"); + return -1; + } + // Set relative to current position if(Whence == 0) { LOG("(FD%x)->Position += %lli", FD, Offset); @@ -225,15 +250,33 @@ int VFS_Seek(int FD, Sint64 Offset, int Whence) return 0; } +/* + * Truncate/Expand a file's allocation + */ +off_t VFS_Truncate(int FD, off_t Size) +{ + tVFS_Handle *h = VFS_GetHandle(FD); + if(!h) { + errno = EBADF; + return -1; + } + + if( !h->Node->Type->Truncate) + { + errno = ENOTIMPL; + return -1; + } + + return h->Node->Type->Truncate(h->Node, Size); +} + /** * \fn int VFS_IOCtl(int FD, int ID, void *Buffer) * \brief Call an IO Control on a file */ int VFS_IOCtl(int FD, int ID, void *Buffer) { - tVFS_Handle *h; - - h = VFS_GetHandle(FD); + tVFS_Handle *h = VFS_GetHandle(FD); if(!h) { LOG("FD%i is invalid", FD); errno = EINVAL; diff --git a/KernelLand/Kernel/vfs/mmap.c b/KernelLand/Kernel/vfs/mmap.c index b6d5c2d9..9a7fa44b 100644 --- a/KernelLand/Kernel/vfs/mmap.c +++ b/KernelLand/Kernel/vfs/mmap.c @@ -25,32 +25,40 @@ struct sVFS_MMapPageBlock // === PROTOTYPES === //void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD, Uint64 Offset); void *VFS_MMap_Anon(void *Destination, size_t Length, Uint FlagsSet, Uint FlagsMask); +int VFS_MMap_MapPage(tVFS_Node *Node, unsigned int PageNum, tVFS_MMapPageBlock *pb, void *mapping_dest, unsigned int Protection); //int VFS_MUnmap(void *Addr, size_t Length); // === CODE === void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD, Uint64 Offset) { - tVAddr mapping_base; - int npages, pagenum; - tVFS_MMapPageBlock *pb, *prev; - ENTER("pDestHint iLength xProtection xFlags xFD XOffset", DestHint, Length, Protection, Flags, FD, Offset); if( Flags & MMAP_MAP_ANONYMOUS ) Offset = (tVAddr)DestHint & 0xFFF; - npages = ((Offset & (PAGE_SIZE-1)) + Length + (PAGE_SIZE - 1)) / PAGE_SIZE; - pagenum = Offset / PAGE_SIZE; + unsigned int npages = ((Offset & (PAGE_SIZE-1)) + Length + (PAGE_SIZE - 1)) / PAGE_SIZE; + unsigned int pagenum = Offset / PAGE_SIZE; - mapping_base = (tVAddr)DestHint; - tPage *mapping_dest = (void*)(mapping_base & ~(PAGE_SIZE-1)); + tVAddr mapping_base = (tVAddr)DestHint; - if( DestHint == NULL ) + if( Flags & MMAP_MAP_FIXED ) + { + ASSERT( (Flags & MMAP_MAP_FIXED) && DestHint != NULL ); + // Keep and use the hint + // - TODO: Validate that the region pointed to by the hint is correct + } + else { - // TODO: Locate space for the allocation - LEAVE('n'); - return NULL; + Log_Warning("VFS", "MMap: TODO Handle non-fixed mappings"); + if( DestHint == NULL ) + { + // TODO: Locate space for the allocation + Log_Warning("VFS", "Mmap: Handle NULL destination hint"); + LEAVE('n'); + return NULL; + } } + tPage *mapping_dest = (void*)(mapping_base & ~(PAGE_SIZE-1)); // Handle anonymous mappings if( Flags & MMAP_MAP_ANONYMOUS ) @@ -67,14 +75,14 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD, Mutex_Acquire( &h->Node->Lock ); + tVFS_MMapPageBlock *pb, **pb_pnp = (tVFS_MMapPageBlock**)&h->Node->MMapInfo; // Search for existing mapping for each page // - Sorted list of 16 page blocks - for( - pb = h->Node->MMapInfo, prev = NULL; - pb && pb->BaseOffset + MMAP_PAGES_PER_BLOCK <= pagenum; - prev = pb, pb = pb->Next - ) - ; + for( pb = h->Node->MMapInfo; pb; pb_pnp = &pb->Next, pb = pb->Next ) + { + if( pb->BaseOffset + MMAP_PAGES_PER_BLOCK <= pagenum ) + break; + } LOG("pb = %p, pb->BaseOffset = %X", pb, pb ? pb->BaseOffset : 0); @@ -89,74 +97,22 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD, } pb->Next = old_pb; pb->BaseOffset = pagenum - pagenum % MMAP_PAGES_PER_BLOCK; - if(prev) - prev->Next = pb; - else - h->Node->MMapInfo = pb; + *pb_pnp = pb; } // - Map (and allocate) pages while( npages -- ) { - assert( pagenum >= pb->BaseOffset ); - assert( pagenum - pb->BaseOffset < MMAP_PAGES_PER_BLOCK ); + ASSERTC( pagenum, >=, pb->BaseOffset ); + ASSERTC( pagenum - pb->BaseOffset, <, MMAP_PAGES_PER_BLOCK ); if( MM_GetPhysAddr( mapping_dest ) == 0 ) { - if( pb->PhysAddrs[pagenum - pb->BaseOffset] == 0 ) - { - tVFS_NodeType *nt = h->Node->Type; - if( !nt ) - { - // TODO: error - } - else if( nt->MMap ) - nt->MMap(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE, mapping_dest); - else - { - int read_len; - // Allocate pages and read data - if( MM_Allocate(mapping_dest) == 0 ) { - // TODO: Unwrap - Mutex_Release( &h->Node->Lock ); - LEAVE('n'); - return NULL; - } - // TODO: Clip read length - read_len = nt->Read(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE, - mapping_dest, 0); - // TODO: This was commented out, why? - if( read_len != PAGE_SIZE ) { - memset( (char*)mapping_dest + read_len, 0, PAGE_SIZE-read_len ); - } - } - pb->PhysAddrs[pagenum - pb->BaseOffset] = MM_GetPhysAddr( mapping_dest ); - MM_SetPageNode( pb->PhysAddrs[pagenum - pb->BaseOffset], h->Node ); - MM_RefPhys( pb->PhysAddrs[pagenum - pb->BaseOffset] ); - LOG("Read and map %X to %p (%P)", pagenum*PAGE_SIZE, mapping_dest, - pb->PhysAddrs[pagenum - pb->BaseOffset]); - } - else + LOG("Map page to %p", mapping_dest); + if( VFS_MMap_MapPage(h->Node, pagenum, pb, mapping_dest, Protection) ) { - MM_Map( mapping_dest, pb->PhysAddrs[pagenum - pb->BaseOffset] ); - MM_RefPhys( pb->PhysAddrs[pagenum - pb->BaseOffset] ); - LOG("Cached map %X to %p (%P)", pagenum*PAGE_SIZE, mapping_dest, - pb->PhysAddrs[pagenum - pb->BaseOffset]); - } - h->Node->ReferenceCount ++; - - // Set flags - if( !(Protection & MMAP_PROT_WRITE) ) { - MM_SetFlags(mapping_dest, MM_PFLAG_RO, MM_PFLAG_RO); - } - else { - MM_SetFlags(mapping_dest, 0, MM_PFLAG_RO); - } - - if( Protection & MMAP_PROT_EXEC ) { - MM_SetFlags(mapping_dest, MM_PFLAG_EXEC, MM_PFLAG_EXEC); - } - else { - MM_SetFlags(mapping_dest, 0, MM_PFLAG_EXEC); + Mutex_Release( &h->Node->Lock ); + LEAVE('n'); + return NULL; } } else @@ -167,25 +123,27 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD, MM_SetFlags(mapping_dest, 0, MM_PFLAG_RO); } } - if( Flags & MMAP_MAP_PRIVATE ) + if( Flags & MMAP_MAP_PRIVATE ) { + // TODO: Don't allow the page to change underneath either MM_SetFlags(mapping_dest, MM_PFLAG_COW, MM_PFLAG_COW); + } pagenum ++; mapping_dest ++; // Roll on to next block if needed if(pagenum - pb->BaseOffset == MMAP_PAGES_PER_BLOCK) { - if( pb->Next && pb->Next->BaseOffset == pagenum ) - pb = pb->Next; - else + if( !pb->Next || pb->Next->BaseOffset != pagenum ) { - tVFS_MMapPageBlock *oldpb = pb; - pb = malloc( sizeof(tVFS_MMapPageBlock) ); - pb->Next = oldpb->Next; - pb->BaseOffset = pagenum; - memset(pb->PhysAddrs, 0, sizeof(pb->PhysAddrs)); - oldpb->Next = pb; + if( pb->Next ) ASSERTC(pb->Next->BaseOffset % MMAP_PAGES_PER_BLOCK, ==, 0); + tVFS_MMapPageBlock *newpb = malloc( sizeof(tVFS_MMapPageBlock) ); + newpb->Next = pb->Next; + newpb->BaseOffset = pagenum; + memset(newpb->PhysAddrs, 0, sizeof(newpb->PhysAddrs)); + pb->Next = newpb; } + + pb = pb->Next; } } @@ -263,6 +221,66 @@ void *VFS_MMap_Anon(void *Destination, size_t Length, Uint FlagsSet, Uint FlagsM return Destination; } +int VFS_MMap_MapPage(tVFS_Node *Node, unsigned int pagenum, tVFS_MMapPageBlock *pb, void *mapping_dest, unsigned int Protection) +{ + if( pb->PhysAddrs[pagenum - pb->BaseOffset] != 0 ) + { + MM_Map( mapping_dest, pb->PhysAddrs[pagenum - pb->BaseOffset] ); + MM_RefPhys( pb->PhysAddrs[pagenum - pb->BaseOffset] ); + LOG("Cached map %X to %p (%P)", pagenum*PAGE_SIZE, mapping_dest, + pb->PhysAddrs[pagenum - pb->BaseOffset]); + } + else + { + tVFS_NodeType *nt = Node->Type; + if( !nt ) + { + // TODO: error + } + else if( nt->MMap ) + nt->MMap(Node, pagenum*PAGE_SIZE, PAGE_SIZE, mapping_dest); + else + { + int read_len; + // Allocate pages and read data + if( MM_Allocate(mapping_dest) == 0 ) { + // TODO: Unwrap + return 1; + } + // TODO: Clip read length + read_len = nt->Read(Node, pagenum*PAGE_SIZE, PAGE_SIZE, mapping_dest, 0); + // TODO: This was commented out, why? + if( read_len != PAGE_SIZE ) { + memset( (char*)mapping_dest + read_len, 0, PAGE_SIZE-read_len ); + } + } + pb->PhysAddrs[pagenum - pb->BaseOffset] = MM_GetPhysAddr( mapping_dest ); + MM_SetPageNode( pb->PhysAddrs[pagenum - pb->BaseOffset], Node ); + MM_RefPhys( pb->PhysAddrs[pagenum - pb->BaseOffset] ); + LOG("Read and map %X to %p (%P)", pagenum*PAGE_SIZE, mapping_dest, + pb->PhysAddrs[pagenum - pb->BaseOffset]); + } + // TODO: Huh? + Node->ReferenceCount ++; + + // Set flags + if( !(Protection & MMAP_PROT_WRITE) ) { + MM_SetFlags(mapping_dest, MM_PFLAG_RO, MM_PFLAG_RO); + } + else { + MM_SetFlags(mapping_dest, 0, MM_PFLAG_RO); + } + + if( Protection & MMAP_PROT_EXEC ) { + MM_SetFlags(mapping_dest, MM_PFLAG_EXEC, MM_PFLAG_EXEC); + } + else { + MM_SetFlags(mapping_dest, 0, MM_PFLAG_EXEC); + } + + return 0; +} + int VFS_MUnmap(void *Addr, size_t Length) { return 0; diff --git a/KernelLand/Modules/Display/VESA/main.c b/KernelLand/Modules/Display/VESA/main.c index 0af86cbd..62fb25a2 100644 --- a/KernelLand/Modules/Display/VESA/main.c +++ b/KernelLand/Modules/Display/VESA/main.c @@ -461,9 +461,9 @@ int Vesa_Int_SetMode(int mode) Mutex_Release( &glVesa_Lock ); - // TODO: Disableable backbuffer - gVesa_BufInfo.BackBuffer = realloc(gVesa_BufInfo.BackBuffer, - modeptr->height * modeptr->pitch); + // TODO: Allow disabling of back-buffer + gVesa_DriverStruct.RootNode.Size = modeptr->height * modeptr->pitch; + gVesa_BufInfo.BackBuffer = realloc(gVesa_BufInfo.BackBuffer, modeptr->height * modeptr->pitch); gVesa_BufInfo.Framebuffer = gpVesa_Framebuffer; gVesa_BufInfo.Pitch = modeptr->pitch; gVesa_BufInfo.Width = modeptr->width; diff --git a/KernelLand/Modules/IPStack/tcp.c b/KernelLand/Modules/IPStack/tcp.c index b7890ad8..fcfdaaa4 100644 --- a/KernelLand/Modules/IPStack/tcp.c +++ b/KernelLand/Modules/IPStack/tcp.c @@ -67,6 +67,7 @@ tVFS_NodeType gTCP_ServerNodeType = { }; tVFS_NodeType gTCP_ClientNodeType = { .TypeName = "TCP Client/Connection", + .Flags = VFS_NODETYPEFLAG_STREAM, .Read = TCP_Client_Read, .Write = TCP_Client_Write, .IOCtl = TCP_Client_IOCtl, diff --git a/KernelLand/Modules/IPStack/udp.c b/KernelLand/Modules/IPStack/udp.c index 325a09e8..67f60561 100644 --- a/KernelLand/Modules/IPStack/udp.c +++ b/KernelLand/Modules/IPStack/udp.c @@ -33,6 +33,8 @@ Uint16 UDP_int_FinaliseChecksum(Uint16 Value); // === GLOBALS === tVFS_NodeType gUDP_NodeType = { + .TypeName = "UDP", + .Flags = VFS_NODETYPEFLAG_STREAM, .Read = UDP_Channel_Read, .Write = UDP_Channel_Write, .IOCtl = UDP_Channel_IOCtl, @@ -189,6 +191,7 @@ tVFS_Node *UDP_Channel_Init(tInterface *Interface) tUDPChannel *new; new = calloc( sizeof(tUDPChannel), 1 ); new->Interface = Interface; + new->Node.Size = -1; new->Node.ImplPtr = new; new->Node.NumACLs = 1; new->Node.ACLs = &gVFS_ACL_EveryoneRW; diff --git a/Usermode/Libraries/ld-acess.so_src/arch/syscalls.s.h b/Usermode/Libraries/ld-acess.so_src/arch/syscalls.s.h index 4dc545d2..c783a9b9 100644 --- a/Usermode/Libraries/ld-acess.so_src/arch/syscalls.s.h +++ b/Usermode/Libraries/ld-acess.so_src/arch/syscalls.s.h @@ -55,6 +55,7 @@ SYSCALL3(_SysRead, SYS_READ) // int, uint, void* SYSCALL5(_SysReadAt, SYS_READAT) // int, uint, uint64, void* SYSCALL3(_SysWrite, SYS_WRITE) // int, uint, void* SYSCALL5(_SysWriteAt, SYS_WRITEAT) // int, uint, uint64, void* +SYSCALL3(_SysTruncate, SYS_TRUNCATE) // int, uint64 SYSCALL4(_SysSeek, SYS_SEEK) // int, uint64_t, int SYSCALL1(_SysTell, SYS_TELL) // int SYSCALL3(_SysFInfo, SYS_FINFO) // int, void*, int @@ -68,3 +69,9 @@ SYSCALL6(_SysSelect, SYS_SELECT) // int, fd_set*, fd_set*, fd_set*, tTime*, uint SYSCALL1(_SysMkDir, SYS_MKDIR) // const char* SYSCALL1(_SysUnlink, SYS_UNLINK) // const char* +SYSCALL6(_SysMMap, SYS_MMAP) +SYSCALL2(_SysMUnMap, SYS_MUNMAP) + +SYSCALL1(_SysMarshalFD, SYS_MARSHALFD) +SYSCALL2(_SysUnMarshalFD, SYS_UNMARSHALFD) + diff --git a/Usermode/Libraries/ld-acess.so_src/include_exp/acess/sys.h b/Usermode/Libraries/ld-acess.so_src/include_exp/acess/sys.h index 31d74c4a..0643ba46 100644 --- a/Usermode/Libraries/ld-acess.so_src/include_exp/acess/sys.h +++ b/Usermode/Libraries/ld-acess.so_src/include_exp/acess/sys.h @@ -40,6 +40,14 @@ extern "C" { #define FILEFLAG_SYMLINK 0x20 #define CLONE_VM 0x10 +#define MMAP_PROT_READ 0x001 //!< Readable memory +#define MMAP_PROT_WRITE 0x002 //!< Writable memory +#define MMAP_PROT_EXEC 0x004 //!< Executable memory +#define MMAP_MAP_SHARED 0x001 //!< Shared with all other users of the FD +#define MMAP_MAP_PRIVATE 0x002 //!< Local (COW) copy +#define MMAP_MAP_FIXED 0x004 //!< Load to a fixed address +#define MMAP_MAP_ANONYMOUS 0x008 //!< Not associated with a FD + #ifdef ARCHDIR_is_native # include "_native_syscallmod.h" #endif @@ -90,6 +98,7 @@ extern int _SysCopyFD(int srcfd, int dstfd); extern int _SysFDFlags(int fd, int mask, int newflags); extern size_t _SysRead(int fd, void *buffer, size_t length); extern size_t _SysReadAt(int fd, uint64_t offset, size_t length, void *buffer); +extern uint64_t _SysTruncate(int fd, uint64_t size); extern int _SysClose(int fd); extern int _SysFDCtl(int fd, int option, ...); extern size_t _SysWrite(int fd, const void *buffer, size_t length); @@ -105,6 +114,11 @@ extern int _SysSelect(int nfds, fd_set *read, fd_set *write, fd_set *err, int64_ //#define select(nfs, rdfds, wrfds, erfds, timeout) _SysSelect(nfs, rdfds, wrfds, erfds, timeout, 0) extern int _SysMkDir(const char *dirname); extern int _SysUnlink(const char *pathname); +extern void* _SysMMap(void *addr, size_t length, unsigned int _flags, int fd, uint64_t offset); +#define _SysMMap(addr,length,flags,prot,fd,offset) _SysMMap(addr,length,(flags|(prot<<16)), fd, offset) +extern int _SysMUnMap(void *addr, size_t length); +extern uint64_t _SysMarshalFD(int FD); +extern int _SysUnMarshalFD(uint64_t Handle); // --- IPC --- extern int _SysSendMessage(int dest, size_t length, const void *Data);