X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2FStorage%2FLVM%2Fmain.c;h=501e8a7b8e8df0120c228b9e084c94fc562a7862;hb=e7a76b0d8a0cc6aa77966509780973a6f8216ef7;hp=587689efd9bc6899cce743a8266faf816b535dd9;hpb=1d65dd9606edfcaeef8dfff3724ef6c49180b131;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/Storage/LVM/main.c b/KernelLand/Modules/Storage/LVM/main.c index 587689ef..501e8a7b 100644 --- a/KernelLand/Modules/Storage/LVM/main.c +++ b/KernelLand/Modules/Storage/LVM/main.c @@ -2,8 +2,8 @@ * Acess2 Logical Volume Manager * - By John Hodge (thePowersGang) * - * lvm.h - * - LVM Core definitions + * main.c + * - LVM Core Code */ #define DEBUG 0 #define VERSION VER2(0,1) @@ -15,14 +15,17 @@ // === PROTOTYPES === // --- int LVM_Initialise(char **Arguments); -void LVM_Cleanup(void); + int LVM_Cleanup(void); // --- -char *LVM_Root_ReadDir(tVFS_Node *Node, int ID); -tVFS_Node *LVM_Root_FindDir(tVFS_Node *Node, const char *Name); -char *LVM_Vol_ReadDir(tVFS_Node *Node, int ID); -tVFS_Node *LVM_Vol_FindDir(tVFS_Node *Node, const char *Name); -size_t LVM_SubVol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer); -size_t LVM_SubVol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer); + int LVM_Root_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX]); +tVFS_Node *LVM_Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags); + int LVM_Vol_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX]); +tVFS_Node *LVM_Vol_FindDir(tVFS_Node *Node, const char *Name, Uint Flags); +size_t LVM_Vol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags); +size_t LVM_Vol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags); +size_t LVM_SubVol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags); +size_t LVM_SubVol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags); +void LVM_CloseNode(tVFS_Node *Node); Uint LVM_int_DrvUtil_ReadBlock(Uint64 Address, Uint Count, void *Buffer, void *Argument); Uint LVM_int_DrvUtil_WriteBlock(Uint64 Address, Uint Count, const void *Buffer, void *Argument); @@ -35,15 +38,19 @@ tVFS_NodeType gLVM_RootNodeType = { }; tVFS_NodeType gLVM_VolNodeType = { .ReadDir = LVM_Vol_ReadDir, - .FindDir = LVM_Vol_FindDir + .FindDir = LVM_Vol_FindDir, + .Read = LVM_Vol_Read, + .Write = LVM_Vol_Write, + .Close = LVM_CloseNode }; tVFS_NodeType gLVM_SubVolNodeType = { .Read = LVM_SubVol_Read, - .Write = LVM_SubVol_Write + .Write = LVM_SubVol_Write, + .Close = LVM_CloseNode }; tDevFS_Driver gLVM_DevFS = { NULL, "LVM", - {.Flags = VFS_FFLAG_DIRECTORY, .Type = &gLVM_RootNodeType} + {.Flags = VFS_FFLAG_DIRECTORY, .Type = &gLVM_RootNodeType, .Size = -1} }; tLVM_Vol *gpLVM_FirstVolume; @@ -56,57 +63,129 @@ int LVM_Initialise(char **Arguments) return 0; } -void LVM_Cleanup(void) +int LVM_Cleanup(void) { + // Attempt to destroy all volumes + tLVM_Vol *vol, *prev = NULL, *next; + // TODO: Locks? + for( vol = gpLVM_FirstVolume; vol; prev = vol, vol = next ) + { + next = vol->Next; + int nFree = 0; + + for( int i = 0; i < vol->nSubVolumes; i ++ ) + { + tLVM_SubVolume *sv; + sv = vol->SubVolumes[i]; + if( sv == NULL ) { + nFree ++; + continue; + } + + Mutex_Acquire(&sv->Node.Lock); + if(sv->Node.ReferenceCount == 0) { + nFree ++; + vol->SubVolumes[i] = NULL; + Mutex_Release(&sv->Node.Lock); + } + else { + Mutex_Release(&sv->Node.Lock); + continue ; + } + + Mutex_Acquire(&sv->Node.Lock); + LOG("Removed subvolume %s:%s", vol->Name, sv->Name); + free(sv); + } + + if( nFree != vol->nSubVolumes ) + continue ; + + if(prev) + prev->Next = next; + else + gpLVM_FirstVolume = next; + + Mutex_Acquire(&vol->DirNode.Lock); + Mutex_Acquire(&vol->VolNode.Lock); + if( vol->Type->Cleanup ) + vol->Type->Cleanup( vol->Ptr ); + if( vol->CacheHandle ) + IOCache_Destroy(vol->CacheHandle); + LOG("Removed volume %s", vol->Name); + free(vol); + } + + if( gpLVM_FirstVolume ) + return EBUSY; + + return EOK; } // -------------------------------------------------------------------- // VFS Inteface // -------------------------------------------------------------------- -char *LVM_Root_ReadDir(tVFS_Node *Node, int ID) +int LVM_Root_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX]) { tLVM_Vol *vol; - if( ID < 0 ) return NULL; + if( ID < 0 ) return -EINVAL; + + // TODO: Sub-dirs for 'by-uuid', 'by-label' etc for( vol = gpLVM_FirstVolume; vol && ID --; vol = vol->Next ); - if(vol) - return strdup(vol->Name); + if(vol) { + strncpy(Dest, vol->Name, FILENAME_MAX); + return 0; + } else - return NULL; + return -ENOENT; } -tVFS_Node *LVM_Root_FindDir(tVFS_Node *Node, const char *Name) +tVFS_Node *LVM_Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags) { tLVM_Vol *vol; for( vol = gpLVM_FirstVolume; vol; vol = vol->Next ) { if( strcmp(vol->Name, Name) == 0 ) { - return &vol->Node; + vol->DirNode.ReferenceCount ++; + return &vol->DirNode; } } return NULL; } -char *LVM_Vol_ReadDir(tVFS_Node *Node, int ID) +int LVM_Vol_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX]) { tLVM_Vol *vol = Node->ImplPtr; + const char *src; - if( ID < 0 || ID >= vol->nSubVolumes ) - return NULL; - - return strdup( vol->SubVolumes[ID]->Name ); + if( ID < 0 || ID >= vol->nSubVolumes+1 ) + return -EINVAL; + + if( ID == 0 ) { + src = "ROOT"; + } + else { + src = vol->SubVolumes[ID-1]->Name; + } + strncpy(Dest, src, FILENAME_MAX); + return 0; } -tVFS_Node *LVM_Vol_FindDir(tVFS_Node *Node, const char *Name) +tVFS_Node *LVM_Vol_FindDir(tVFS_Node *Node, const char *Name, Uint Flags) { tLVM_Vol *vol = Node->ImplPtr; + + if( strcmp("ROOT", Name) == 0 ) + return &vol->VolNode; for( int i = 0; i < vol->nSubVolumes; i ++ ) { if( strcmp(vol->SubVolumes[i]->Name, Name) == 0 ) { + vol->SubVolumes[i]->Node.ReferenceCount ++; return &vol->SubVolumes[i]->Node; } } @@ -114,7 +193,30 @@ tVFS_Node *LVM_Vol_FindDir(tVFS_Node *Node, const char *Name) return NULL; } -size_t LVM_SubVol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer) +size_t LVM_Vol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags) +{ + tLVM_Vol *vol = Node->ImplPtr; + Uint64 byte_size = vol->BlockCount * vol->BlockSize; + + if( Offset > byte_size ) + return 0; + if( Length > byte_size ) + Length = byte_size; + if( Offset + Length > byte_size ) + Length = byte_size - Offset; + + return DrvUtil_ReadBlock( + Offset, Length, Buffer, + LVM_int_DrvUtil_ReadBlock, vol->BlockSize, vol + ); +} + +size_t LVM_Vol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags) +{ + return 0; +} + +size_t LVM_SubVol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags) { tLVM_SubVolume *sv = Node->ImplPtr; Uint64 byte_size = sv->BlockCount * sv->Vol->BlockSize; @@ -126,14 +228,19 @@ size_t LVM_SubVol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffe if( Offset + Length > byte_size ) Length = byte_size - Offset; - Offset += sv->FirstBlock * sv->Vol->BlockSize; + LOG("Reading (0x%llx+0x%llx)+0x%x to %p", + (Uint64)(sv->FirstBlock * sv->Vol->BlockSize), Offset, + Length, Buffer + ); + Offset += sv->FirstBlock * sv->Vol->BlockSize; + return DrvUtil_ReadBlock( Offset, Length, Buffer, LVM_int_DrvUtil_ReadBlock, sv->Vol->BlockSize, sv->Vol ); } -size_t LVM_SubVol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer) +size_t LVM_SubVol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags) { tLVM_SubVolume *sv = Node->ImplPtr; Uint64 byte_size = sv->BlockCount * sv->Vol->BlockSize; @@ -154,6 +261,11 @@ size_t LVM_SubVol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void ); } +void LVM_CloseNode(tVFS_Node *Node) +{ + Node->ReferenceCount --; +} + Uint LVM_int_DrvUtil_ReadBlock(Uint64 Address, Uint Count, void *Buffer, void *Argument) { return LVM_int_ReadVolume( Argument, Address, Count, Buffer );