X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2FStorage%2FLVM%2Fmain.c;h=d4e9aa4060547614ba4e1e7f4bfc8e97227f0981;hb=fc7371134c3b43b4382655f3b5447749da12b306;hp=0bca233e232321667b5043550e22faf24b9b3055;hpb=513b0638dbbcf84eeb23d9f0d1bcf01d6af2c008;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/Storage/LVM/main.c b/KernelLand/Modules/Storage/LVM/main.c index 0bca233e..d4e9aa40 100644 --- a/KernelLand/Modules/Storage/LVM/main.c +++ b/KernelLand/Modules/Storage/LVM/main.c @@ -15,7 +15,7 @@ // === 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); @@ -25,6 +25,7 @@ size_t LVM_Vol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer); size_t LVM_Vol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer); 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); +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); @@ -39,11 +40,13 @@ tVFS_NodeType gLVM_VolNodeType = { .ReadDir = LVM_Vol_ReadDir, .FindDir = LVM_Vol_FindDir, .Read = LVM_Vol_Read, - .Write = LVM_Vol_Write + .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", @@ -60,9 +63,62 @@ 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 ); + LOG("Removed volume %s", vol->Name); + free(vol); + } + + if( gpLVM_FirstVolume ) + return EBUSY; + + return EOK; } // -------------------------------------------------------------------- @@ -88,6 +144,7 @@ tVFS_Node *LVM_Root_FindDir(tVFS_Node *Node, const char *Name) { if( strcmp(vol->Name, Name) == 0 ) { + vol->DirNode.ReferenceCount ++; return &vol->DirNode; } } @@ -117,6 +174,7 @@ tVFS_Node *LVM_Vol_FindDir(tVFS_Node *Node, const char *Name) { if( strcmp(vol->SubVolumes[i]->Name, Name) == 0 ) { + vol->SubVolumes[i]->Node.ReferenceCount ++; return &vol->SubVolumes[i]->Node; } } @@ -192,6 +250,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 );