3 * Ext2 Driver Version 1
7 * \brief Second Extended Filesystem Driver
8 * \todo Implement file full write support
12 #include "ext2_common.h"
15 Uint64 Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);
16 Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock);
20 * \fn Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
21 * \brief Write to a file
23 Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
25 tExt2_Disk *disk = Node->ImplPtr;
33 Debug_HexDump("Ext2_Write", Buffer, Length);
35 Ext2_int_GetInode(Node, &inode);
37 // Get the ammount of space already allocated
38 // - Round size up to block size
39 // - block size is a power of two, so this will work
40 allocSize = (inode.i_size + disk->BlockSize) & ~(disk->BlockSize-1);
42 // Are we writing to inside the allocated space?
43 if( Offset < allocSize )
45 // Will we go out of it?
46 if(Offset + Length > allocSize) {
48 retLen = allocSize - Offset;
52 // Within the allocated space
53 block = Offset / disk->BlockSize;
54 Offset %= disk->BlockSize;
55 base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
57 // Write only block (if only one)
58 if(Offset + retLen <= disk->BlockSize) {
59 VFS_WriteAt(disk->FD, base+Offset, retLen, Buffer);
60 if(!bNewBlocks) return Length;
61 goto addBlocks; // Ugh! A goto, but it seems unavoidable
65 VFS_WriteAt(disk->FD, base+Offset, disk->BlockSize-Offset, Buffer);
66 Buffer += disk->BlockSize-Offset;
67 retLen -= disk->BlockSize-Offset;
70 // Write middle blocks
71 while(retLen > disk->BlockSize)
73 base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
74 VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer);
75 Buffer += disk->BlockSize;
76 retLen -= disk->BlockSize;
81 base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
82 VFS_WriteAt(disk->FD, base, retLen, Buffer);
83 if(!bNewBlocks) return Length; // Writing in only allocated space
87 ///\todo Implement block allocation
88 Warning("[EXT2] File extending is not yet supported");
94 * \fn Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
95 * \brief Allocate a block from the best possible location
96 * \param Disk EXT2 Disk Information Structure
97 * \param PrevBlock Previous block ID in the file
99 Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
101 int bpg = Disk->SuperBlock.s_blocks_per_group;
102 Uint blockgroup = PrevBlock / bpg;
103 Uint bitmap[Disk->BlockSize/sizeof(Uint)];
104 Uint bitsperblock = 8*Disk->BlockSize;
108 // Are there any free blocks?
109 if(Disk->SuperBlock.s_free_blocks_count == 0) return 0;
111 if(Disk->Groups[blockgroup].bg_free_blocks_count > 0)
113 // Search block group's bitmap
114 for(i = 0; i < bpg; i++)
116 // Get the block in the bitmap block
117 j = i & (bitsperblock-1);
123 (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,
130 if( bitmap[j/32] == -1 ) {
136 if( bitmap[j/32] & (1 << (j%32)) )
143 Warning("[EXT2 ] Inconsistency detected, Group Free Block count is non-zero when no free blocks exist");
144 goto checkAll; // Search the entire filesystem for a free block
145 // Goto needed for neatness
149 bitmap[j/32] |= (1 << (j%32));
152 (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,
157 Disk->Groups[blockgroup].bg_free_blocks_count --;
158 #if EXT2_UPDATE_WRITEBACK
159 //Ext2_int_UpdateBlockGroup(blockgroup);
165 Warning("[EXT2 ] TODO - Implement using blocks outside the current block group");
169 // Reduce global count
170 Disk->SuperBlock.s_free_blocks_count --;
171 #if EXT2_UPDATE_WRITEBACK
172 Ext2_int_UpdateSuperblock(Disk);