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);
29 Uint LVM_int_DrvUtil_ReadBlock(Uint64 Address, Uint Count, void *Buffer, void *Argument);
30 Uint LVM_int_DrvUtil_WriteBlock(Uint64 Address, Uint Count, const void *Buffer, void *Argument);
33 MODULE_DEFINE(0, VERSION, LVM, LVM_Initialise, LVM_Cleanup, NULL);
34 tVFS_NodeType gLVM_RootNodeType = {
35 .ReadDir = LVM_Root_ReadDir,
36 .FindDir = LVM_Root_FindDir
38 tVFS_NodeType gLVM_VolNodeType = {
39 .ReadDir = LVM_Vol_ReadDir,
40 .FindDir = LVM_Vol_FindDir,
42 .Write = LVM_Vol_Write
44 tVFS_NodeType gLVM_SubVolNodeType = {
45 .Read = LVM_SubVol_Read,
46 .Write = LVM_SubVol_Write
48 tDevFS_Driver gLVM_DevFS = {
50 {.Flags = VFS_FFLAG_DIRECTORY, .Type = &gLVM_RootNodeType, .Size = -1}
53 tLVM_Vol *gpLVM_FirstVolume;
54 tLVM_Vol *gpLVM_LastVolume = (void*)&gpLVM_FirstVolume;
57 int LVM_Initialise(char **Arguments)
59 DevFS_AddDevice( &gLVM_DevFS );
65 // Attempt to destroy all volumes
66 tLVM_Vol *vol, *prev = NULL, *next;
69 for( vol = gpLVM_FirstVolume; vol; prev = vol, vol = next )
74 for( int i = 0; i < vol->nSubVolumes; i ++ )
77 sv = vol->SubVolumes[i];
83 Mutex_Acquire(&sv->Node.Lock);
84 if(sv->Node.ReferenceCount == 0) {
86 vol->SubVolumes[i] = NULL;
88 Mutex_Release(&sv->Node.Lock);
90 Mutex_Acquire(&sv->Node.Lock);
91 LOG("Removed subvolume %s:%s", vol->Name, sv->Name);
95 if( nFree != vol->nSubVolumes )
101 gpLVM_FirstVolume = next;
103 Mutex_Acquire(&vol->DirNode.Lock);
104 Mutex_Acquire(&vol->VolNode.Lock);
105 if( vol->Type->Cleanup )
106 vol->Type->Cleanup( vol->Ptr );
107 LOG("Removed volume %s", vol->Name);
111 if( gpLVM_FirstVolume )
117 // --------------------------------------------------------------------
119 // --------------------------------------------------------------------
120 char *LVM_Root_ReadDir(tVFS_Node *Node, int ID)
124 if( ID < 0 ) return NULL;
126 for( vol = gpLVM_FirstVolume; vol && ID --; vol = vol->Next );
129 return strdup(vol->Name);
133 tVFS_Node *LVM_Root_FindDir(tVFS_Node *Node, const char *Name)
136 for( vol = gpLVM_FirstVolume; vol; vol = vol->Next )
138 if( strcmp(vol->Name, Name) == 0 )
140 return &vol->DirNode;
146 char *LVM_Vol_ReadDir(tVFS_Node *Node, int ID)
148 tLVM_Vol *vol = Node->ImplPtr;
150 if( ID < 0 || ID >= vol->nSubVolumes+1 )
154 return strdup(".volume");
156 return strdup( vol->SubVolumes[ID-1]->Name );
158 tVFS_Node *LVM_Vol_FindDir(tVFS_Node *Node, const char *Name)
160 tLVM_Vol *vol = Node->ImplPtr;
162 if( strcmp(".volume", Name) == 0 )
163 return &vol->VolNode;
165 for( int i = 0; i < vol->nSubVolumes; i ++ )
167 if( strcmp(vol->SubVolumes[i]->Name, Name) == 0 )
169 return &vol->SubVolumes[i]->Node;
176 size_t LVM_Vol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
178 tLVM_Vol *vol = Node->ImplPtr;
179 Uint64 byte_size = vol->BlockCount * vol->BlockSize;
181 if( Offset > byte_size )
183 if( Length > byte_size )
185 if( Offset + Length > byte_size )
186 Length = byte_size - Offset;
188 return DrvUtil_ReadBlock(
189 Offset, Length, Buffer,
190 LVM_int_DrvUtil_ReadBlock, vol->BlockSize, vol
194 size_t LVM_Vol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
199 size_t LVM_SubVol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
201 tLVM_SubVolume *sv = Node->ImplPtr;
202 Uint64 byte_size = sv->BlockCount * sv->Vol->BlockSize;
204 if( Offset > byte_size )
206 if( Length > byte_size )
208 if( Offset + Length > byte_size )
209 Length = byte_size - Offset;
211 LOG("Reading (0x%llx+0x%llx)+0x%x to %p",
212 (Uint64)(sv->FirstBlock * sv->Vol->BlockSize), Offset,
216 Offset += sv->FirstBlock * sv->Vol->BlockSize;
218 return DrvUtil_ReadBlock(
219 Offset, Length, Buffer,
220 LVM_int_DrvUtil_ReadBlock, sv->Vol->BlockSize, sv->Vol
223 size_t LVM_SubVol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
225 tLVM_SubVolume *sv = Node->ImplPtr;
226 Uint64 byte_size = sv->BlockCount * sv->Vol->BlockSize;
228 if( Offset > byte_size )
230 if( Length > byte_size )
232 if( Offset + Length > byte_size )
233 Length = byte_size - Offset;
235 Offset += sv->FirstBlock * sv->Vol->BlockSize;
237 return DrvUtil_WriteBlock(
238 Offset, Length, Buffer,
239 LVM_int_DrvUtil_ReadBlock, LVM_int_DrvUtil_WriteBlock,
240 sv->Vol->BlockSize, sv->Vol
244 Uint LVM_int_DrvUtil_ReadBlock(Uint64 Address, Uint Count, void *Buffer, void *Argument)
246 return LVM_int_ReadVolume( Argument, Address, Count, Buffer );
249 Uint LVM_int_DrvUtil_WriteBlock(Uint64 Address, Uint Count, const void *Buffer, void *Argument)
251 return LVM_int_WriteVolume( Argument, Address, Count, Buffer );