Modules/LVM - Seriously working on it after the network API change
[tpg/acess2.git] / KernelLand / Modules / Storage / LVM / volumes.c
1 /*
2  * Acess2 Logical Volume Manager
3  * - By John Hodge (thePowersGang)
4  *
5  * volumes.c
6  * - Volume management
7  */
8 #include "lvm_int.h"
9
10 // === PROTOTYPES ===
11  int    LVM_int_VFSReadEmul(void *Arg, Uint64 BlockStart, size_t BlockCount, void *Dest);
12  int    LVM_int_VFSWriteEmul(void *Arg, Uint64 BlockStart, size_t BlockCount, const void *Source);
13
14 // === CODE ===
15 // --------------------------------------------------------------------
16 // Managment / Initialisation
17 // --------------------------------------------------------------------
18 int LVM_AddVolumeVFS(const char *Name, int FD)
19 {
20         // Assuming 512-byte blocks, not a good idea
21         return LVM_AddVolume(Name, (void*)(Uint)FD, 512, LVM_int_VFSReadEmul, LVM_int_VFSWriteEmul);
22 }
23
24 int LVM_AddVolume(const char *Name, void *Ptr, size_t BlockSize, tLVM_ReadFcn Read, tLVM_WriteFcn Write)
25 {
26         tLVM_Vol        dummy_vol;
27         tLVM_Vol        *real_vol;
28         tLVM_Format     *type;
29         void    *first_block;
30
31         dummy_vol.Ptr = Ptr;
32         dummy_vol.Read = Read;
33         dummy_vol.Write = Write;
34         dummy_vol.BlockSize = BlockSize;
35
36         // Read the first block of the volume   
37         first_block = malloc(BlockSize);
38         Read(Ptr, 0, 1, first_block);
39         
40         // Determine Type
41         // TODO: Determine type
42         type = &gLVM_MBRType;
43
44         // Type->CountSubvolumes
45         dummy_vol.nSubVolumes = type->CountSubvolumes(&dummy_vol, first_block);
46         
47         // Create real volume descriptor
48         // TODO: If this needs to be rescanned later, having the subvolume list separate might be an idea
49         real_vol = malloc( sizeof(tLVM_Vol) + strlen(Name) + 1 + sizeof(tLVM_SubVolume*) * dummy_vol.nSubVolumes );
50         real_vol->Ptr = Ptr;
51         real_vol->Read = Read;
52         real_vol->Write = Write;
53         real_vol->BlockSize = BlockSize;
54         real_vol->nSubVolumes = dummy_vol.nSubVolumes;
55         real_vol->SubVolumes = (void*)( real_vol->Name + strlen(Name) + 1 );
56         strcpy(real_vol->Name, Name);
57         memset(real_vol->SubVolumes, 0, sizeof(tLVM_SubVolume*) * real_vol->nSubVolumes);
58         // - VFS Nodes
59         memset(&real_vol->DirNode, 0, sizeof(tVFS_Node));
60         real_vol->DirNode.Type = &gLVM_VolNodeType;
61         real_vol->DirNode.ImplPtr = real_vol;
62         real_vol->DirNode.Flags = VFS_FFLAG_DIRECTORY;
63         memset(&real_vol->VolNode, 0, sizeof(tVFS_Node));
64         real_vol->VolNode.Type = &gLVM_VolNodeType;
65         real_vol->VolNode.ImplPtr = real_vol;
66         real_vol->VolNode.Flags = VFS_FFLAG_DIRECTORY;
67
68         // Type->PopulateSubvolumes
69         type->PopulateSubvolumes(real_vol, first_block);
70         free(first_block);
71
72         // Add to volume list
73         gpLVM_LastVolume->Next = real_vol;
74         gpLVM_LastVolume = real_vol;
75
76         return 0;
77 }
78
79 void LVM_int_SetSubvolume_Anon(tLVM_Vol *Volume, int Index, Uint64 FirstBlock, Uint64 BlockCount)
80 {
81         tLVM_SubVolume  *sv;
82          int    namelen;
83
84         if( Index < 0 || Index >= Volume->nSubVolumes ) {
85                 Log_Warning("LVM", "SV ID is out of range (0 < %i < %i)",
86                         Index, Volume->nSubVolumes);
87                 return ;
88         }
89
90         if( Volume->SubVolumes[Index] ) {
91                 Log_Warning("LVM", "Attempt to set SV %i of %p twice", Index, Volume);
92                 return ;
93         }
94         
95         namelen = snprintf(NULL, 0, "%i", Index);
96
97         sv = malloc( sizeof(tLVM_SubVolume) + namelen + 1 );
98         if(!sv) {
99                 // Oh, f*ck
100                 return ;
101         }
102         Volume->SubVolumes[Index] = sv; 
103
104         sv->Vol = Volume;
105         sprintf(sv->Name, "%i", Index);
106         sv->FirstBlock = FirstBlock;
107         sv->BlockCount = BlockCount;
108         memset(&sv->Node, 0, sizeof(tVFS_Node));
109         
110         sv->Node.ImplPtr = sv;
111         sv->Node.Type = &gLVM_SubVolNodeType;
112 }
113
114 // --------------------------------------------------------------------
115 // IO
116 // --------------------------------------------------------------------
117 size_t LVM_int_ReadVolume(tLVM_Vol *Volume, Uint64 BlockNum, size_t BlockCount, void *Dest)
118 {
119         return Volume->Read(Volume->Ptr, BlockNum, BlockCount, Dest);
120 }
121
122 size_t LVM_int_WriteVolume(tLVM_Vol *Volume, Uint64 BlockNum, size_t BlockCount, const void *Src)
123 {
124         return Volume->Write(Volume->Ptr, BlockNum, BlockCount, Src);   
125 }
126
127 int LVM_int_VFSReadEmul(void *Arg, Uint64 BlockStart, size_t BlockCount, void *Dest)
128 {
129         size_t  blocksize;
130         size_t  rv;
131
132         blocksize = 512;        // TODO: Don't assume   
133
134         rv = VFS_ReadAt( (int)(Uint)Arg, BlockStart * blocksize, BlockCount * blocksize, Dest );
135         rv /= blocksize;
136         return rv;
137 }
138
139 int LVM_int_VFSWriteEmul(void *Arg, Uint64 BlockStart, size_t BlockCount, const void *Source)
140 {
141         size_t  blocksize;
142         size_t  rv;
143
144         blocksize = 512;        // TODO: Don't assume   
145
146         rv = VFS_WriteAt( (int)(Uint)Arg, BlockStart * blocksize, BlockCount * blocksize, Source );
147         rv /= blocksize;
148         return rv;
149 }
150

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