X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2FStorage%2FLVM%2Fmain.c;h=501e8a7b8e8df0120c228b9e084c94fc562a7862;hb=13078002b01ee4f63eb2001d2ef479a2a006ea32;hp=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391;hpb=48743e39650eb1ef988380e9d95f27fd40d3a9ce;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/Storage/LVM/main.c b/KernelLand/Modules/Storage/LVM/main.c index e69de29b..501e8a7b 100644 --- a/KernelLand/Modules/Storage/LVM/main.c +++ b/KernelLand/Modules/Storage/LVM/main.c @@ -0,0 +1,278 @@ +/* + * Acess2 Logical Volume Manager + * - By John Hodge (thePowersGang) + * + * main.c + * - LVM Core Code + */ +#define DEBUG 0 +#define VERSION VER2(0,1) +#include "lvm_int.h" +#include +#include +#include + +// === PROTOTYPES === +// --- + int LVM_Initialise(char **Arguments); + int LVM_Cleanup(void); +// --- + 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); + +// === GLOBALS === +MODULE_DEFINE(0, VERSION, LVM, LVM_Initialise, LVM_Cleanup, NULL); +tVFS_NodeType gLVM_RootNodeType = { + .ReadDir = LVM_Root_ReadDir, + .FindDir = LVM_Root_FindDir +}; +tVFS_NodeType gLVM_VolNodeType = { + .ReadDir = LVM_Vol_ReadDir, + .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, + .Close = LVM_CloseNode +}; +tDevFS_Driver gLVM_DevFS = { + NULL, "LVM", + {.Flags = VFS_FFLAG_DIRECTORY, .Type = &gLVM_RootNodeType, .Size = -1} +}; + +tLVM_Vol *gpLVM_FirstVolume; +tLVM_Vol *gpLVM_LastVolume = (void*)&gpLVM_FirstVolume; + +// === CODE === +int LVM_Initialise(char **Arguments) +{ + DevFS_AddDevice( &gLVM_DevFS ); + return 0; +} + +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 +// -------------------------------------------------------------------- +int LVM_Root_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX]) +{ + tLVM_Vol *vol; + + 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) { + strncpy(Dest, vol->Name, FILENAME_MAX); + return 0; + } + else + return -ENOENT; +} +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 ) + { + vol->DirNode.ReferenceCount ++; + return &vol->DirNode; + } + } + return NULL; +} + +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+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, 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; + } + } + + return NULL; +} + +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; + + if( Offset > byte_size ) + return 0; + if( Length > byte_size ) + Length = byte_size; + if( Offset + Length > byte_size ) + Length = byte_size - Offset; + + 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, Uint Flags) +{ + tLVM_SubVolume *sv = Node->ImplPtr; + Uint64 byte_size = sv->BlockCount * sv->Vol->BlockSize; + + if( Offset > byte_size ) + return 0; + if( Length > byte_size ) + Length = byte_size; + if( Offset + Length > byte_size ) + Length = byte_size - Offset; + + Offset += sv->FirstBlock * sv->Vol->BlockSize; + + return DrvUtil_WriteBlock( + Offset, Length, Buffer, + LVM_int_DrvUtil_ReadBlock, LVM_int_DrvUtil_WriteBlock, + sv->Vol->BlockSize, sv->Vol + ); +} + +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 ); +} + +Uint LVM_int_DrvUtil_WriteBlock(Uint64 Address, Uint Count, const void *Buffer, void *Argument) +{ + return LVM_int_WriteVolume( Argument, Address, Count, Buffer ); +} +