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 // TODO: Sub-dirs for 'by-uuid', 'by-label' etc
135 for( vol = gpLVM_FirstVolume; vol && ID --; vol = vol->Next );
138 strncpy(Dest, vol->Name, FILENAME_MAX);
144 tVFS_Node *LVM_Root_FindDir(tVFS_Node *Node, const char *Name)
147 for( vol = gpLVM_FirstVolume; vol; vol = vol->Next )
149 if( strcmp(vol->Name, Name) == 0 )
151 vol->DirNode.ReferenceCount ++;
152 return &vol->DirNode;
158 int LVM_Vol_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX])
160 tLVM_Vol *vol = Node->ImplPtr;
163 if( ID < 0 || ID >= vol->nSubVolumes+1 )
170 src = vol->SubVolumes[ID-1]->Name;
172 strncpy(Dest, src, FILENAME_MAX);
175 tVFS_Node *LVM_Vol_FindDir(tVFS_Node *Node, const char *Name)
177 tLVM_Vol *vol = Node->ImplPtr;
179 if( strcmp("ROOT", Name) == 0 )
180 return &vol->VolNode;
182 for( int i = 0; i < vol->nSubVolumes; i ++ )
184 if( strcmp(vol->SubVolumes[i]->Name, Name) == 0 )
186 vol->SubVolumes[i]->Node.ReferenceCount ++;
187 return &vol->SubVolumes[i]->Node;
194 size_t LVM_Vol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
196 tLVM_Vol *vol = Node->ImplPtr;
197 Uint64 byte_size = vol->BlockCount * vol->BlockSize;
199 if( Offset > byte_size )
201 if( Length > byte_size )
203 if( Offset + Length > byte_size )
204 Length = byte_size - Offset;
206 return DrvUtil_ReadBlock(
207 Offset, Length, Buffer,
208 LVM_int_DrvUtil_ReadBlock, vol->BlockSize, vol
212 size_t LVM_Vol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
217 size_t LVM_SubVol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
219 tLVM_SubVolume *sv = Node->ImplPtr;
220 Uint64 byte_size = sv->BlockCount * sv->Vol->BlockSize;
222 if( Offset > byte_size )
224 if( Length > byte_size )
226 if( Offset + Length > byte_size )
227 Length = byte_size - Offset;
229 LOG("Reading (0x%llx+0x%llx)+0x%x to %p",
230 (Uint64)(sv->FirstBlock * sv->Vol->BlockSize), Offset,
234 Offset += sv->FirstBlock * sv->Vol->BlockSize;
236 return DrvUtil_ReadBlock(
237 Offset, Length, Buffer,
238 LVM_int_DrvUtil_ReadBlock, sv->Vol->BlockSize, sv->Vol
241 size_t LVM_SubVol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
243 tLVM_SubVolume *sv = Node->ImplPtr;
244 Uint64 byte_size = sv->BlockCount * sv->Vol->BlockSize;
246 if( Offset > byte_size )
248 if( Length > byte_size )
250 if( Offset + Length > byte_size )
251 Length = byte_size - Offset;
253 Offset += sv->FirstBlock * sv->Vol->BlockSize;
255 return DrvUtil_WriteBlock(
256 Offset, Length, Buffer,
257 LVM_int_DrvUtil_ReadBlock, LVM_int_DrvUtil_WriteBlock,
258 sv->Vol->BlockSize, sv->Vol
262 void LVM_CloseNode(tVFS_Node *Node)
264 Node->ReferenceCount --;
267 Uint LVM_int_DrvUtil_ReadBlock(Uint64 Address, Uint Count, void *Buffer, void *Argument)
269 return LVM_int_ReadVolume( Argument, Address, Count, Buffer );
272 Uint LVM_int_DrvUtil_WriteBlock(Uint64 Address, Uint Count, const void *Buffer, void *Argument)
274 return LVM_int_WriteVolume( Argument, Address, Count, Buffer );