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 int LVM_Root_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX]);
21 tVFS_Node *LVM_Root_FindDir(tVFS_Node *Node, const char *Name);
22 int LVM_Vol_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX]);
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 int LVM_Root_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX])
131 if( ID < 0 ) return -EINVAL;
133 for( vol = gpLVM_FirstVolume; vol && ID --; vol = vol->Next );
136 strncpy(Dest, vol->Name, FILENAME_MAX);
142 tVFS_Node *LVM_Root_FindDir(tVFS_Node *Node, const char *Name)
145 for( vol = gpLVM_FirstVolume; vol; vol = vol->Next )
147 if( strcmp(vol->Name, Name) == 0 )
149 vol->DirNode.ReferenceCount ++;
150 return &vol->DirNode;
156 int LVM_Vol_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX])
158 tLVM_Vol *vol = Node->ImplPtr;
161 if( ID < 0 || ID >= vol->nSubVolumes+1 )
168 src = vol->SubVolumes[ID-1]->Name;
170 strncpy(Dest, src, FILENAME_MAX);
173 tVFS_Node *LVM_Vol_FindDir(tVFS_Node *Node, const char *Name)
175 tLVM_Vol *vol = Node->ImplPtr;
177 if( strcmp("ROOT", Name) == 0 )
178 return &vol->VolNode;
180 for( int i = 0; i < vol->nSubVolumes; i ++ )
182 if( strcmp(vol->SubVolumes[i]->Name, Name) == 0 )
184 vol->SubVolumes[i]->Node.ReferenceCount ++;
185 return &vol->SubVolumes[i]->Node;
192 size_t LVM_Vol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
194 tLVM_Vol *vol = Node->ImplPtr;
195 Uint64 byte_size = vol->BlockCount * vol->BlockSize;
197 if( Offset > byte_size )
199 if( Length > byte_size )
201 if( Offset + Length > byte_size )
202 Length = byte_size - Offset;
204 return DrvUtil_ReadBlock(
205 Offset, Length, Buffer,
206 LVM_int_DrvUtil_ReadBlock, vol->BlockSize, vol
210 size_t LVM_Vol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
215 size_t LVM_SubVol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
217 tLVM_SubVolume *sv = Node->ImplPtr;
218 Uint64 byte_size = sv->BlockCount * sv->Vol->BlockSize;
220 if( Offset > byte_size )
222 if( Length > byte_size )
224 if( Offset + Length > byte_size )
225 Length = byte_size - Offset;
227 LOG("Reading (0x%llx+0x%llx)+0x%x to %p",
228 (Uint64)(sv->FirstBlock * sv->Vol->BlockSize), Offset,
232 Offset += sv->FirstBlock * sv->Vol->BlockSize;
234 return DrvUtil_ReadBlock(
235 Offset, Length, Buffer,
236 LVM_int_DrvUtil_ReadBlock, sv->Vol->BlockSize, sv->Vol
239 size_t LVM_SubVol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
241 tLVM_SubVolume *sv = Node->ImplPtr;
242 Uint64 byte_size = sv->BlockCount * sv->Vol->BlockSize;
244 if( Offset > byte_size )
246 if( Length > byte_size )
248 if( Offset + Length > byte_size )
249 Length = byte_size - Offset;
251 Offset += sv->FirstBlock * sv->Vol->BlockSize;
253 return DrvUtil_WriteBlock(
254 Offset, Length, Buffer,
255 LVM_int_DrvUtil_ReadBlock, LVM_int_DrvUtil_WriteBlock,
256 sv->Vol->BlockSize, sv->Vol
260 void LVM_CloseNode(tVFS_Node *Node)
262 Node->ReferenceCount --;
265 Uint LVM_int_DrvUtil_ReadBlock(Uint64 Address, Uint Count, void *Buffer, void *Argument)
267 return LVM_int_ReadVolume( Argument, Address, Count, Buffer );
270 Uint LVM_int_DrvUtil_WriteBlock(Uint64 Address, Uint Count, const void *Buffer, void *Argument)
272 return LVM_int_WriteVolume( Argument, Address, Count, Buffer );