2 * Acess2 Logical Volume Manager
3 * - By John Hodge (thePowersGang)
6 * - LVM Core definitions
9 #define VERSION VER2(0,1)
13 #include <api_drv_disk.h>
17 int LVM_Initialise(char **Arguments);
18 int LVM_Cleanup(void);
20 char *LVM_Root_ReadDir(tVFS_Node *Node, int ID);
21 tVFS_Node *LVM_Root_FindDir(tVFS_Node *Node, const char *Name);
22 char *LVM_Vol_ReadDir(tVFS_Node *Node, int ID);
23 tVFS_Node *LVM_Vol_FindDir(tVFS_Node *Node, const char *Name);
24 size_t LVM_Vol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
25 size_t LVM_Vol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
26 size_t LVM_SubVol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
27 size_t LVM_SubVol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
28 void LVM_CloseNode(tVFS_Node *Node);
30 Uint LVM_int_DrvUtil_ReadBlock(Uint64 Address, Uint Count, void *Buffer, void *Argument);
31 Uint LVM_int_DrvUtil_WriteBlock(Uint64 Address, Uint Count, const void *Buffer, void *Argument);
34 MODULE_DEFINE(0, VERSION, LVM, LVM_Initialise, LVM_Cleanup, NULL);
35 tVFS_NodeType gLVM_RootNodeType = {
36 .ReadDir = LVM_Root_ReadDir,
37 .FindDir = LVM_Root_FindDir
39 tVFS_NodeType gLVM_VolNodeType = {
40 .ReadDir = LVM_Vol_ReadDir,
41 .FindDir = LVM_Vol_FindDir,
43 .Write = LVM_Vol_Write,
44 .Close = LVM_CloseNode
46 tVFS_NodeType gLVM_SubVolNodeType = {
47 .Read = LVM_SubVol_Read,
48 .Write = LVM_SubVol_Write,
49 .Close = LVM_CloseNode
51 tDevFS_Driver gLVM_DevFS = {
53 {.Flags = VFS_FFLAG_DIRECTORY, .Type = &gLVM_RootNodeType, .Size = -1}
56 tLVM_Vol *gpLVM_FirstVolume;
57 tLVM_Vol *gpLVM_LastVolume = (void*)&gpLVM_FirstVolume;
60 int LVM_Initialise(char **Arguments)
62 DevFS_AddDevice( &gLVM_DevFS );
68 // Attempt to destroy all volumes
69 tLVM_Vol *vol, *prev = NULL, *next;
72 for( vol = gpLVM_FirstVolume; vol; prev = vol, vol = next )
77 for( int i = 0; i < vol->nSubVolumes; i ++ )
80 sv = vol->SubVolumes[i];
86 Mutex_Acquire(&sv->Node.Lock);
87 if(sv->Node.ReferenceCount == 0) {
89 vol->SubVolumes[i] = NULL;
90 Mutex_Release(&sv->Node.Lock);
93 Mutex_Release(&sv->Node.Lock);
97 Mutex_Acquire(&sv->Node.Lock);
98 LOG("Removed subvolume %s:%s", vol->Name, sv->Name);
102 if( nFree != vol->nSubVolumes )
108 gpLVM_FirstVolume = next;
110 Mutex_Acquire(&vol->DirNode.Lock);
111 Mutex_Acquire(&vol->VolNode.Lock);
112 if( vol->Type->Cleanup )
113 vol->Type->Cleanup( vol->Ptr );
114 LOG("Removed volume %s", vol->Name);
118 if( gpLVM_FirstVolume )
124 // --------------------------------------------------------------------
126 // --------------------------------------------------------------------
127 char *LVM_Root_ReadDir(tVFS_Node *Node, int ID)
131 if( ID < 0 ) return NULL;
133 for( vol = gpLVM_FirstVolume; vol && ID --; vol = vol->Next );
136 return strdup(vol->Name);
140 tVFS_Node *LVM_Root_FindDir(tVFS_Node *Node, const char *Name)
143 for( vol = gpLVM_FirstVolume; vol; vol = vol->Next )
145 if( strcmp(vol->Name, Name) == 0 )
147 vol->DirNode.ReferenceCount ++;
148 return &vol->DirNode;
154 char *LVM_Vol_ReadDir(tVFS_Node *Node, int ID)
156 tLVM_Vol *vol = Node->ImplPtr;
158 if( ID < 0 || ID >= vol->nSubVolumes+1 )
162 return strdup("ROOT");
164 return strdup( vol->SubVolumes[ID-1]->Name );
166 tVFS_Node *LVM_Vol_FindDir(tVFS_Node *Node, const char *Name)
168 tLVM_Vol *vol = Node->ImplPtr;
170 if( strcmp("ROOT", Name) == 0 )
171 return &vol->VolNode;
173 for( int i = 0; i < vol->nSubVolumes; i ++ )
175 if( strcmp(vol->SubVolumes[i]->Name, Name) == 0 )
177 vol->SubVolumes[i]->Node.ReferenceCount ++;
178 return &vol->SubVolumes[i]->Node;
185 size_t LVM_Vol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
187 tLVM_Vol *vol = Node->ImplPtr;
188 Uint64 byte_size = vol->BlockCount * vol->BlockSize;
190 if( Offset > byte_size )
192 if( Length > byte_size )
194 if( Offset + Length > byte_size )
195 Length = byte_size - Offset;
197 return DrvUtil_ReadBlock(
198 Offset, Length, Buffer,
199 LVM_int_DrvUtil_ReadBlock, vol->BlockSize, vol
203 size_t LVM_Vol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
208 size_t LVM_SubVol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
210 tLVM_SubVolume *sv = Node->ImplPtr;
211 Uint64 byte_size = sv->BlockCount * sv->Vol->BlockSize;
213 if( Offset > byte_size )
215 if( Length > byte_size )
217 if( Offset + Length > byte_size )
218 Length = byte_size - Offset;
220 LOG("Reading (0x%llx+0x%llx)+0x%x to %p",
221 (Uint64)(sv->FirstBlock * sv->Vol->BlockSize), Offset,
225 Offset += sv->FirstBlock * sv->Vol->BlockSize;
227 return DrvUtil_ReadBlock(
228 Offset, Length, Buffer,
229 LVM_int_DrvUtil_ReadBlock, sv->Vol->BlockSize, sv->Vol
232 size_t LVM_SubVol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
234 tLVM_SubVolume *sv = Node->ImplPtr;
235 Uint64 byte_size = sv->BlockCount * sv->Vol->BlockSize;
237 if( Offset > byte_size )
239 if( Length > byte_size )
241 if( Offset + Length > byte_size )
242 Length = byte_size - Offset;
244 Offset += sv->FirstBlock * sv->Vol->BlockSize;
246 return DrvUtil_WriteBlock(
247 Offset, Length, Buffer,
248 LVM_int_DrvUtil_ReadBlock, LVM_int_DrvUtil_WriteBlock,
249 sv->Vol->BlockSize, sv->Vol
253 void LVM_CloseNode(tVFS_Node *Node)
255 Node->ReferenceCount --;
258 Uint LVM_int_DrvUtil_ReadBlock(Uint64 Address, Uint Count, void *Buffer, void *Argument)
260 return LVM_int_ReadVolume( Argument, Address, Count, Buffer );
263 Uint LVM_int_DrvUtil_WriteBlock(Uint64 Address, Uint Count, const void *Buffer, void *Argument)
265 return LVM_int_WriteVolume( Argument, Address, Count, Buffer );