Modules/LVM - Catches for stupid coding
[tpg/acess2.git] / KernelLand / Modules / Storage / LVM / main.c
index 39ce9a9..d4e9aa4 100644 (file)
@@ -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,15 +40,17 @@ 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",
-       {.Flags = VFS_FFLAG_DIRECTORY, .Type = &gLVM_RootNodeType}
+       {.Flags = VFS_FFLAG_DIRECTORY, .Type = &gLVM_RootNodeType, .Size = -1}
 };
 
 tLVM_Vol       *gpLVM_FirstVolume;
@@ -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;
                }
        }
@@ -102,7 +159,7 @@ char *LVM_Vol_ReadDir(tVFS_Node *Node, int ID)
                return NULL;
 
        if( ID == 0 )
-               return strdup(".volume");
+               return strdup("ROOT");
        else
                return strdup( vol->SubVolumes[ID-1]->Name );
 }
@@ -110,13 +167,14 @@ tVFS_Node *LVM_Vol_FindDir(tVFS_Node *Node, const char *Name)
 {
        tLVM_Vol        *vol = Node->ImplPtr;
 
-       if( strcmp(".volume", Name) == 0 )
+       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;
                }
        }
@@ -159,8 +217,13 @@ 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
@@ -187,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 );

UCC git Repository :: git.ucc.asn.au