Changeset 858
- Timestamp:
- 08/21/08 21:52:46 (3 years ago)
- Location:
- Whitix/trunk/fs/ext3
- Files:
-
- 5 modified
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
Whitix/trunk/fs/ext3/Makefile
r703 r858 1 1 DEPTH=../../ 2 MODULES = super.sys inode.sys 2 MODULES = super.sys inode.sys file.sys ialloc.sys balloc.sys 3 3 4 4 build: $(MODULES) 5 5 ld $(LD_R_FLAGS) $(MODULES) -o ext3.sys 6 6 7 modules_install: 8 cp ext3.sys ../../CdRoot/System/Modules/Filesystems 9 7 10 include $(DEPTH)make.inc 8 11 -include $(DEPS) -
Whitix/trunk/fs/ext3/ext3.h
r608 r858 20 20 #define EXT3_H 21 21 22 #include <fs/journal.h> 22 23 #include <fs/vfs.h> 23 24 #include <init.h> 24 25 26 /* EXT3 features */ 27 #define EXT3_FEATURE_COMPAT_JOURNAL 0x4 28 29 #define EXT3_FEATURE_COMPAT(sb, feature) ((sb)->featureCompat & (feature)) 30 31 /* Journal block defines. */ 32 #define EXT3_SINGLE_DATA_TRANS 8 33 #define EXT3_DATA_TRANS (3*EXT3_SINGLE_DATA_TRANS-2) 34 #define EXT3_RESERVE_TRANS_BLOCKS 12 35 #define EXT3_DELETE_TRANS_BLOCKS (2*EXT3_DATA_TRANS+64) 36 25 37 struct Ext3SuperBlock 26 38 { 27 DWORD iNodesCount; /* Inodes Count */28 DWORD blocksCount; /* Blocks Count */29 DWORD reservedBlocks; /* Reserved Blocks Count */30 DWORD freeBlocks; /* Free Blocks Count */31 DWORD freeInodes; /* Free inode Count */32 DWORD firstDataBlock; /* First Data Block */33 DWORD logBlockSize; /* Block Size as a power of 2. The unit is 1024. Thus39 DWORD iNodesCount; /* Inodes Count */ 40 DWORD blocksCount; /* Blocks Count */ 41 DWORD reservedBlocks; /* Reserved Blocks Count */ 42 DWORD freeBlocks; /* Free Blocks Count */ 43 DWORD freeInodes; /* Free inode Count */ 44 DWORD firstDataBlock; /* First Data Block */ 45 DWORD logBlockSize; /* Block Size as a power of 2. The unit is 1024. Thus 34 46 0 == 1024 , 1 = 2048 , 2 = 4096*/ 35 DWORD logFragSize; /* Fragments are not yet implemented int ext3. So47 DWORD logFragSize; /* Fragments are not yet implemented int ext3. So 36 48 logFragSize .equal. logBlockSize */ 37 DWORD blocksPerGrp; /* Number of Blocks in each block group */49 DWORD blocksPerGrp; /* Number of Blocks in each block group */ 38 50 DWORD fragsPerGrp; /* Number of Fragments in each block group */ 39 51 DWORD iNodesPerGrp; /* Number of Inodes in each block group */ … … 87 99 { 88 100 DWORD iNodesCount,groupCount,iNodesPerGrp; 101 DWORD firstDataBlock, blocksPerGrp; 89 102 struct Buffer** descs; 103 104 DWORD sbSector; 105 struct Buffer* sbBuffer; 106 struct Ext3SuperBlock* super; 107 108 struct Journal* journal; 90 109 }; 91 110 … … 93 112 { 94 113 DWORD blocks[15]; 114 DWORD blockGroup; 95 115 }; 96 116 … … 98 118 99 119 /* 100 * Each block group has its own group d iscriptor120 * Each block group has its own group descriptor 101 121 */ 102 122 struct Ext3GroupDesc … … 107 127 WORD freeBlocks; // Number of free blocks in the group 108 128 WORD freeINodes; // Number of free inodes in the group 109 WORD usedDirs; // Number of director yin the group129 WORD usedDirs; // Number of directories in the group 110 130 WORD pad; // Alignment to WORD 111 131 DWORD reserved[3]; // Null to pad out 24 bytes. … … 137 157 }PACKED; 138 158 159 #define EXT3_DIR_REC_LEN(nameLen) (((nameLen) + 8 + 3) & ~3) 160 161 #define EXT3_FT_UNKNOWN 0 162 #define EXT3_FT_FILE 1 163 #define EXT3_FT_DIR 2 164 165 static inline DWORD Ext3SetFileType(DWORD mode) 166 { 167 if (mode & VFS_ATTR_FILE) 168 return EXT3_FT_FILE; 169 else if (mode & VFS_ATTR_DIR) 170 return EXT3_FT_DIR; 171 else 172 return EXT3_FT_UNKNOWN; 173 } 174 139 175 /* 140 176 * DirEntry describes Directory, which are special kind of file … … 144 180 { 145 181 DWORD iNodeNum; // Inode number 146 WORD recLen; // Directo y entry length182 WORD recLen; // Directory entry length 147 183 BYTE nameLen;// filename length 148 184 BYTE fileType; // file type … … 152 188 /* Common functions */ 153 189 int Ext3ReadVNode(struct VNode* vNode); 190 int Ext3WriteVNode(struct VNode* vNode); 191 int Ext3DirtyVNode(struct VNode* vNode); 154 192 int Ext3Lookup(struct VNode** retVal,struct VNode* dir,char* name,int nameLength); 155 193 int Ext3ReadDir(struct File* file,void* dirEntries); 156 int Ext3BlockMap(struct VNode* vNode,int block); 157 struct Buffer* Ext3BlockRead(struct VNode* vNode,int block); 158 int Ext3Read(struct File* file,BYTE* buffer,DWORD len); 194 int Ext3BlockMap(struct VNode* vNode, DWORD block, int flags); 195 struct Buffer* Ext3BlockRead(struct VNode* vNode,int block, int create); 196 int Ext3Create(struct VNode** retVal,struct VNode* dir,char* name,int nameLength); 197 int Ext3Truncate(struct VNode* vNode, int size); 198 int Ext3MkDir(struct VNode** retVal,struct VNode* dir,char* name,int nameLength); 199 struct VNode* Ext3CreateINode(struct JournalHandle* handle, struct VNode* dir, int isDir); 200 int Ext3Remove(struct VNode* dir, char* name, int nameLength); 201 int Ext3RemoveDir(struct VNode* dir, char* name, int nameLength); 202 203 int Ext3FileWrite(struct File* file,BYTE* buffer,DWORD len); 204 205 /* balloc.c */ 206 struct Ext3GroupDesc* Ext3GetGroupDesc(struct VfsSuperBlock* superBlock, DWORD groupNo, 207 struct Buffer** buffer); 208 int Ext3BlockMapHandle(struct JournalHandle* handle, struct VNode* vNode, DWORD block, int flags); 209 int Ext3BlockTruncate(struct VNode* vNode, int size); 159 210 160 211 extern struct VNodeOps ext3VNodeOps; … … 167 218 #define DESCS_PER_BLOCK(s) (BYTES_PER_SECTOR(s)/sizeof(struct Ext3GroupDesc)) 168 219 #define INODES_PER_BLOCK(s) (BYTES_PER_SECTOR(s)/sizeof(struct Ext3INode)) 220 #define EXT3_SUPERINFO(s) ((struct Ext3SbInfo*)((s)->privData)) 221 #define EXT3_JOURNAL(vNode) (EXT3_SUPERINFO((vNode)->superBlock)->journal) 222 223 #define EXT3_INFO(vNode) ((struct Ext3INodeInfo*)(vNode->extraInfo)) 169 224 170 225 #define EXT3_SB_MAGIC 0xEF53 -
Whitix/trunk/fs/ext3/file.c
r1 r858 1 /* This file is part of Whitix. 2 * 3 * Whitix is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation; either version 2 of the License, or 6 * (at your option) any later version. 7 * 8 * Whitix is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with Whitix; if not, write to the Free Software 15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 * 17 */ 18 19 #include "ext3.h" 20 21 #include <print.h> 22 23 int Ext3FileWrite(struct File* file, BYTE* buffer, DWORD size) 24 { 25 return FileGenericWrite(file, buffer, size); 26 } -
Whitix/trunk/fs/ext3/inode.c
r705 r858 1 /* This file is part of Whitix. 2 * 3 * Whitix is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation; either version 2 of the License, or 6 * (at your option) any later version. 7 * 8 * Whitix is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with Whitix; if not, write to the Free Software 15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 * 17 */ 18 1 19 #include <console.h> 2 20 #include <malloc.h> … … 6 24 #include "ext3.h" 7 25 26 int Ext3INodeGetLoc(struct VNode* vNode, struct Buffer** buffer, struct Ext3INode** iNode) 27 { 28 DWORD vNo=vNode->id-1; 29 struct Ext3SbInfo* sbInfo=EXT3_SUPERINFO(vNode->superBlock); 30 DWORD blockGroup,groupDesc,desc, block; 31 struct Ext3GroupDesc* groupDescs; 32 33 if (vNo > sbInfo->iNodesCount) 34 return -EINVAL; 35 36 blockGroup=vNo/sbInfo->iNodesPerGrp; 37 38 if (blockGroup >= sbInfo->groupCount) 39 return -EINVAL; 40 41 /* Get the group descriptor for the inode */ 42 groupDesc=blockGroup/DESCS_PER_BLOCK(vNode->superBlock); 43 desc=blockGroup & (DESCS_PER_BLOCK(vNode->superBlock)-1); 44 45 groupDescs=(struct Ext3GroupDesc*)(sbInfo->descs[groupDesc]->data); 46 47 if (!groupDescs) 48 return -EFAULT; 49 50 block=groupDescs[desc].iNodeTable+((vNo % sbInfo->iNodesPerGrp)/INODES_PER_BLOCK(vNode->superBlock)); 51 52 *buffer=BlockRead(vNode->superBlock->sDevice, block); 53 54 if (!*buffer) 55 return -EIO; 56 57 *iNode=(((struct Ext3INode*)(*buffer)->data)+(vNo % INODES_PER_BLOCK(vNode->superBlock))); 58 59 return 0; 60 } 61 8 62 int Ext3ReadVNode(struct VNode* vNode) 9 63 { 10 struct Ext3SbInfo* sbInfo=(struct Ext3SbInfo*)vNode->superBlock->privData;11 int blockGroup,groupDesc,desc,block,i;12 struct Ext3GroupDesc* groupDescs;13 64 struct Buffer* buffer; 14 65 struct Ext3INode* iNode; 15 66 struct Ext3INodeInfo* iNodeInfo; 16 DWORD vNo=vNode->id-1; 17 18 if (vNo > sbInfo->iNodesCount) 19 return -EINVAL; 20 21 blockGroup=vNo/sbInfo->iNodesPerGrp; 22 23 if (blockGroup >= sbInfo->groupCount) 24 return -EINVAL; 25 26 /* Get the group descriptor for the inode */ 27 groupDesc=blockGroup/DESCS_PER_BLOCK(vNode->superBlock); 28 desc=blockGroup % DESCS_PER_BLOCK(vNode->superBlock); 29 groupDescs=(struct Ext3GroupDesc*)(sbInfo->descs[groupDesc]->data); 30 31 block=groupDescs[desc].iNodeTable+((vNo % sbInfo->iNodesPerGrp)/INODES_PER_BLOCK(vNode->superBlock)); 32 33 buffer=BlockRead(vNode->superBlock->sDevice,block); 34 35 if (!buffer) 36 return -EIO; 37 38 iNode=((struct Ext3INode*)buffer->data+(vNo % INODES_PER_BLOCK(vNode->superBlock))); 67 int i, err; 68 69 err=Ext3INodeGetLoc(vNode, &buffer, &iNode); 70 71 if (err) 72 return err; 39 73 40 74 iNodeInfo=(struct Ext3INodeInfo*)malloc(sizeof(struct Ext3INodeInfo)); 41 vNode->extraInfo=iNodeInfo; 75 42 76 if (!iNodeInfo) 43 77 { … … 45 79 return -ENOMEM; 46 80 } 47 48 /* Copy over the blocks */ 49 for (i=0; i<15; i++) 50 iNodeInfo->blocks[i]=iNode->blocks[i]; 81 82 /* Copy EXT3-specific data first. */ 83 iNodeInfo->blockGroup=(vNode->id-1)/EXT3_SUPERINFO(vNode->superBlock)->iNodesPerGrp; 84 85 memcpy(iNodeInfo->blocks, iNode->blocks, 15*sizeof(DWORD)); 51 86 52 87 /* Copy the iNode times over */ … … 58 93 vNode->fileOps=&ext3FileOps; 59 94 vNode->mode=VFS_ATTR_WRITE | VFS_ATTR_READ; 95 vNode->extraInfo=iNodeInfo; 96 60 97 if ((iNode->mode & 0xF000) == 0x4000) 61 98 vNode->mode|=VFS_ATTR_DIR; … … 69 106 } 70 107 71 int Ext3Lookup(struct VNode** retVal,struct VNode* dir,char* name,int nameLength) 72 { 73 int i=0; 74 struct Ext3DirEntry* ext3Entry; 108 int Ext3WriteVNode(struct VNode* vNode) 109 { 110 int err; 111 112 /* Force a commit to the journal, to make sure this vNode is written to disk. */ 113 err=JournalForceCommit(EXT3_JOURNAL(vNode)); 114 115 return err; 116 } 117 118 int Ext3INodeReserveWrite(struct JournalHandle* handle, struct VNode* vNode, 119 struct Buffer** buffer, struct Ext3INode** iNode) 120 { 121 int err; 122 123 /* Fill in buffer and iNode first, before signalling to the journal that we're 124 * going to write at that disk location. */ 125 126 err=Ext3INodeGetLoc(vNode, buffer, iNode); 127 128 if (!err) 129 err=JournalGetWriteAccess(handle, *buffer); 130 131 return err; 132 } 133 134 int Ext3INodeUpdate(struct JournalHandle* handle, struct VNode* vNode, 135 struct Buffer* buffer, struct Ext3INode* iNode) 136 { 137 struct Ext3INodeInfo* info=EXT3_INFO(vNode); 138 139 if (handle) 140 { 141 /* Call GetWriteAccess? */ 142 } 143 144 /* Fill in the raw inode structure. */ 145 iNode->aTime=vNode->aTime.seconds; 146 iNode->cTime=vNode->cTime.seconds; 147 iNode->mTime=vNode->mTime.seconds; 148 iNode->size=vNode->size; 149 150 if (vNode->mode & VFS_ATTR_DIR) 151 iNode->mode=0x4000; 152 else if (vNode->mode & VFS_ATTR_FILE) 153 iNode->mode=0x8000; 154 155 iNode->linksCount=1; 156 iNode->blocksCount=((vNode->size+BYTES_PER_SECTOR(vNode->superBlock)-1)/BYTES_PER_SECTOR(vNode->superBlock)); 157 158 int i; 159 for (i=0; i<15; i++) 160 iNode->blocks[i]=info->blocks[i]; 161 162 /* TODO: Complete. */ 163 164 // KePrint("Update\n"); 165 166 JournalDirtyMetadata(handle, buffer); 167 168 // BufferRelease(buffer); 169 170 return 0; 171 } 172 173 int Ext3DirtyVNode(struct VNode* vNode) 174 { 175 struct JournalHandle* handle; 176 struct Buffer* buffer; 177 struct Ext3INode* iNode; 178 int err=0; 179 180 handle=JournalStart(EXT3_JOURNAL(vNode), 2); 181 182 if (handle) 183 { 184 err=Ext3INodeReserveWrite(handle, vNode, &buffer, &iNode); 185 186 if (!err) 187 { 188 BufferGet(buffer); 189 err=Ext3INodeUpdate(handle, vNode, buffer, iNode); 190 BufferRelease(buffer); 191 } 192 } 193 194 JournalStop(handle); 195 196 return err; 197 } 198 199 int Ext3FindEntry(struct VNode* dir, char* name, int nameLength, struct Ext3DirEntry** ext3Entry, 200 struct Buffer** buffer) 201 { 202 DWORD i=0; 203 struct Ext3DirEntry* entry; 75 204 int bytesPerSec=BYTES_PER_SECTOR(dir->superBlock); 76 77 while (i <dir->size)205 206 while (i < dir->size) 78 207 { 79 208 int block=i/bytesPerSec; … … 81 210 82 211 /* Read in the sector in question, and scan it for the directory entry */ 83 struct Buffer* buff=Ext3BlockRead(dir, block);212 struct Buffer* buff=Ext3BlockRead(dir, block, 0); 84 213 85 214 while (i < dir->size && offset < bytesPerSec) 86 215 { 87 e xt3Entry=(struct Ext3DirEntry*)(buff->data+(i % bytesPerSec));88 89 if (e xt3Entry->nameLen == nameLength)216 entry=(struct Ext3DirEntry*)(buff->data+(i % bytesPerSec)); 217 218 if (entry->nameLen == nameLength) 90 219 { 91 220 /* No need to go through comparing it all just to find it's a different length */ 92 if (!strncmp(e xt3Entry->name,name,nameLength))221 if (!strncmp(entry->name,name,nameLength)) 93 222 { 94 /* Found the directory entry */ 95 *retVal=VNodeGet(dir->superBlock,ext3Entry->iNodeNum); 223 *ext3Entry=entry; 224 225 if (buffer) 226 *buffer=buff; 227 96 228 return 0; 97 229 } 98 230 } 99 231 100 offset+=ext3Entry->recLen; 101 i+=ext3Entry->recLen; 102 } 103 104 } 232 offset += entry->recLen; 233 i += entry->recLen; 234 } 235 236 } 237 105 238 return -ENOENT; 106 239 } 107 240 108 int Ext3BlockMap(struct VNode* vNode,int block) 109 { 110 struct Ext3INodeInfo* iNodeInfo=(struct Ext3INodeInfo*)vNode->extraInfo; 111 struct Buffer* buff; 112 113 if (block < 12) 114 { 115 if (!iNodeInfo->blocks[block]) 116 { 117 KePrint("Ext3: BlockMap, iNodeInfo->blocks[block] = 0\n"); 241 static int Ext3AddEntry(struct JournalHandle* handle, char* name, int nameLength, 242 struct VNode* dir, struct VNode* vNode) 243 { 244 struct Buffer* buffer; 245 int offset=0, recLen; 246 struct Ext3DirEntry* entry; 247 248 // KePrint("Here\n"); 249 250 buffer=Ext3BlockRead(dir, 0, 1); 251 252 if (!buffer) 253 return -EIO; 254 255 recLen=EXT3_DIR_REC_LEN(nameLength); 256 257 entry=(struct Ext3DirEntry*)buffer->data; 258 259 while (1) 260 { 261 if ((char*)entry >= (char*)(BYTES_PER_SECTOR(vNode->superBlock)+buffer->data)) 262 { 263 KePrint("New block?\n"); 118 264 cli(); hlt(); 119 265 } 120 121 /* The first 12 blocks in the inode structure are direct blocks */ 122 return iNodeInfo->blocks[block]; 123 } 124 125 block-=12; 126 if (block < (BYTES_PER_SECTOR(vNode->superBlock)/sizeof(unsigned long))) 127 { 128 int sector=iNodeInfo->blocks[12]; 129 buff=BlockRead(vNode->superBlock->sDevice,sector); 130 if (!buff) 131 return -EIO; 132 133 DWORD* data=(DWORD*)buff->data; 134 135 return data[block]; 136 } 137 138 KePrint("Ext3BlockMap: block >= 256+12\n"); 266 267 KePrint("%u %u\n", entry->iNodeNum, entry->recLen); 268 269 if ((entry->iNodeNum == 0 && entry->recLen >= recLen) || 270 (entry->recLen >= EXT3_DIR_REC_LEN(entry->nameLen) + recLen)) 271 { 272 JournalGetWriteAccess(handle, buffer); 273 274 if (entry->iNodeNum) 275 { 276 struct Ext3DirEntry* next; 277 278 next=(struct Ext3DirEntry*)((char*)entry+EXT3_DIR_REC_LEN(entry->nameLen)); 279 next->recLen=entry->recLen-EXT3_DIR_REC_LEN(entry->nameLen); 280 entry->recLen=EXT3_DIR_REC_LEN(entry->nameLen); 281 282 KePrint("de: (%u %u) %u\n", entry->recLen, entry->nameLen, next->recLen); 283 entry=next; 284 } 285 286 entry->fileType=EXT3_FT_UNKNOWN; 287 288 if (vNode) 289 { 290 entry->iNodeNum=vNode->id; 291 entry->fileType=Ext3SetFileType(vNode->mode); 292 } 293 294 entry->nameLen=nameLength; 295 memcpy(entry->name, name, nameLength); 296 297 JournalDirtyMetadata(handle, buffer); 298 return 0; 299 } 300 301 offset+=entry->recLen; 302 entry=(struct Ext3DirEntry*)(((char*)entry)+entry->recLen); 303 } 304 305 KePrint("Out?\n"); 139 306 cli(); hlt(); 140 307 308 return 0; 309 } 310 311 static int Ext3AddNonDirEntry(struct JournalHandle* handle, char* name, int nameLength, 312 struct VNode* dir, struct VNode* vNode) 313 { 314 int err; 315 316 err=Ext3AddEntry(handle, name, nameLength, dir, vNode); 317 318 if (!err) 319 { 320 err=Ext3DirtyVNode(vNode); 321 } 322 323 return err; 324 } 325 326 int Ext3Create(struct VNode** retVal,struct VNode* dir,char* name,int nameLength) 327 { 328 struct JournalHandle* handle; 329 struct VNode* vNode; 330 int err; 331 332 handle=JournalStart(EXT3_JOURNAL(dir), EXT3_DATA_TRANS + 3); 333 334 vNode=Ext3CreateINode(handle, dir, 0); 335 336 /* Create directory entry. */ 337 err=Ext3AddNonDirEntry(handle, name, nameLength, dir, vNode); 338 339 /* Add orphan entry. */ 340 341 JournalStop(handle); 342 343 *retVal=vNode; 344 345 return err; 346 } 347 348 int Ext3RemoveEntry(struct JournalHandle* handle, struct Buffer* buffer, struct Ext3DirEntry* entry) 349 { 350 DWORD i=0; 351 struct Ext3DirEntry* curr=(struct Ext3DirEntry*)buffer->data, *prev=NULL; 352 353 while (i < buffer->device->softBlockSize) 354 { 355 if (entry == curr) 356 { 357 JournalGetWriteAccess(handle, buffer); 358 359 if (prev) 360 prev->recLen=prev->recLen+curr->recLen; 361 else 362 curr->iNodeNum=0; 363 364 JournalDirtyMetadata(handle, buffer); 365 return 0; 366 } 367 368 i+=curr->recLen; 369 prev=curr; 370 curr=(struct Ext3DirEntry*)(((DWORD)curr)+curr->recLen); 371 } 372 373 return -ENOENT; 374 } 375 376 int Ext3Remove(struct VNode* dir, char* name, int nameLength) 377 { 378 struct JournalHandle* handle; 379 struct VNode* vNode; 380 struct Ext3DirEntry* ext3Entry; 381 struct Buffer* buffer; 382 int err; 383 384 handle=JournalStart(EXT3_JOURNAL(dir), EXT3_DELETE_TRANS_BLOCKS); 385 386 err=Ext3FindEntry(dir, name, nameLength, &ext3Entry, &buffer); 387 388 if (err) 389 goto fail; 390 391 err=Ext3RemoveEntry(handle, buffer, ext3Entry); 392 393 /* Add to orphan list. */ 394 395 fail: 396 JournalStop(handle); 397 398 return err; 399 } 400 401 int Ext3Lookup(struct VNode** retVal,struct VNode* dir,char* name,int nameLength) 402 { 403 int ret; 404 struct Ext3DirEntry* ext3Entry; 405 406 ret=Ext3FindEntry(dir, name, nameLength, &ext3Entry, NULL); 407 408 if (!ret) 409 *retVal=VNodeGet(dir->superBlock, ext3Entry->iNodeNum); 410 411 return ret; 412 } 413 414 #define EXT3_DIO_CREDITS (EXT3_RESERVE_TRANS_BLOCKS+32) 415 416 int Ext3BlockMap(struct VNode* vNode, DWORD block, int flags) 417 { 418 struct JournalHandle* handle=JournalCurrHandle(); 419 int ret=0; 420 421 if (flags & VFS_MAP_CREATE) 422 { 423 handle=JournalStart(EXT3_JOURNAL(vNode), EXT3_RESERVE_TRANS_BLOCKS); 424 #if 0 425 if (handle->numBlocks <= EXT3_RESERVE_TRANS_BLOCKS) 426 { 427 ret=JournalExtend(handle, EXT3_DIO_CREDITS); 428 429 if (ret) 430 { 431 ret=JournalRestart(handle, EXT3_DIO_CREDITS); 432 } 433 } 434 #endif 435 } 436 437 if (!ret) 438 { 439 // KePrint("Ext3BlockMap(%u, %d)\n", block, flags); 440 ret=Ext3BlockMapHandle(handle, vNode, block, flags); 441 } 442 443 if (flags & VFS_MAP_CREATE) 444 { 445 JournalStop(handle); 446 } 447 448 return ret; 449 } 450 451 int Ext3Truncate(struct VNode* vNode, int size) 452 { 453 if (size > vNode->size) 454 { 455 KePrint("Ext3Truncate, %d, %d\n", size, vNode->size); 456 }else if (size < vNode->size) 457 { 458 return Ext3BlockTruncate(vNode, size); 459 } 460 141 461 return 0; 142 462 } … … 156 476 ***********************************************************************/ 157 477 158 struct Buffer* Ext3BlockRead(struct VNode* vNode, int block)159 { 160 int realBlock=Ext3BlockMap(vNode,block );161 if (realBlock == -1)478 struct Buffer* Ext3BlockRead(struct VNode* vNode, int block, int flags) 479 { 480 int realBlock=Ext3BlockMap(vNode,block, flags); 481 if (realBlock < 0) 162 482 return NULL; 163 483 … … 178 498 offset=(file->position % bytesPerSec); 179 499 block=file->position/bytesPerSec; 180 buff=Ext3BlockRead(file->vNode,block );500 buff=Ext3BlockRead(file->vNode,block, 0); 181 501 if (!buff) 182 502 return -EIO; … … 185 505 { 186 506 ext3Entry=(struct Ext3DirEntry*)(buff->data+offset); 507 508 // KePrint("%u %u, %s (%u %u)\n", file->position, file->vNode->size, ext3Entry->name, ext3Entry->nameLen, ext3Entry->recLen); 187 509 188 510 if (LIKELY(ext3Entry->iNodeNum)) … … 200 522 return 0; 201 523 } 524 525 /******************************************************************************* 526 * 527 * FUNCTION: Ext3MkDir 528 * 529 * DESCRIPTION: Make a directory in dir with name 'name'. 530 * 531 * PARAMETERS: retVal - new vNode that points to the new directory. 532 * dir - the directory to create the new directory in 533 * name - name of the new directory 534 * nameLength - length in bytes of the new name. 535 * 536 * RETURNS: Various errors. 537 * 538 ******************************************************************************/ 539 540 int Ext3MkDir(struct VNode** retVal,struct VNode* dir,char* name,int nameLength) 541 { 542 struct VNode* vNode; 543 struct JournalHandle* handle; 544 struct Buffer* buffer; 545 struct Ext3DirEntry* entry; 546 547 handle=JournalStart(EXT3_JOURNAL(dir), EXT3_DATA_TRANS); 548 549 if (!handle) 550 return -EIO; 551 552 vNode=Ext3CreateINode(handle, dir, 1); 553 vNode->size=BYTES_PER_SECTOR(dir->superBlock); 554 555 buffer=Ext3BlockRead(vNode, 0, 1); 556 557 /* Add . and .. entries. */ 558 entry=(struct Ext3DirEntry*)(buffer->data); 559 560 /* . */ 561 entry->iNodeNum=vNode->id; 562 entry->nameLen=1; 563 entry->recLen=EXT3_DIR_REC_LEN(entry->nameLen); 564 strcpy(entry->name, "."); 565 entry->fileType=EXT3_FT_DIR; 566 567 /* .. */ 568 entry=(struct Ext3DirEntry*)((char*)entry+entry->recLen); 569 entry->iNodeNum=dir->id; 570 entry->nameLen=2; 571 entry->recLen=BYTES_PER_SECTOR(vNode->superBlock)-EXT3_DIR_REC_LEN(1); 572 strcpy(entry->name, ".."); 573 entry->fileType=EXT3_FT_DIR; 574 575 JournalGetWriteAccess(handle, buffer); 576 JournalDirtyMetadata(handle, buffer); 577 578 Ext3DirtyVNode(vNode); 579 580 Ext3AddEntry(handle, name, nameLength, dir, vNode); 581 582 JournalStop(handle); 583 BufferRelease(buffer); 584 585 *retVal=vNode; 586 587 return 0; 588 } 589 590 int Ext3RemoveDir(struct VNode* dir, char* name, int nameLength) 591 { 592 return -ENOTIMPL; 593 } -
Whitix/trunk/fs/ext3/super.c
r608 r858 21 21 #include <malloc.h> 22 22 #include <error.h> 23 #include <print.h> 24 25 int Ext3FreeSuper(struct VfsSuperBlock* superBlock); 23 26 24 27 struct SuperBlockOps ext3SbOps={ 25 28 .readVNode = Ext3ReadVNode, 29 .writeVNode = Ext3WriteVNode, 30 .dirtyVNode = Ext3DirtyVNode, 31 .freeSuper = Ext3FreeSuper, 26 32 }; 27 33 … … 29 35 .lookup = Ext3Lookup, 30 36 .blockMap = Ext3BlockMap, 37 .create = Ext3Create, 38 .remove = Ext3Remove, 39 .truncate = Ext3Truncate, 40 .mkDir = Ext3MkDir, 41 .rmDir = Ext3RemoveDir, 31 42 }; 32 43 … … 34 45 .readDir = Ext3ReadDir, 35 46 .read = FileGenericRead, 36 }; 47 .write = Ext3FileWrite, 48 }; 49 50 int Ext3FreeSuper(struct VfsSuperBlock* superBlock) 51 { 52 struct Ext3SbInfo* sb=EXT3_SUPERINFO(superBlock); 53 54 if (sb && sb->journal) 55 JournalDestroy(sb->journal); 56 57 if (sb) 58 free(sb); 59 60 return 0; 61 } 62 63 int Ext3JournalSetup(struct VfsSuperBlock* superBlock, struct Ext3SuperBlock* sb, DWORD iNo) 64 { 65 struct VNode* journal; 66 67 journal=VNodeGet(superBlock, iNo); 68 69 if (!journal) 70 { 71 KePrint("EXT3: no journal found\n"); 72 return 0; 73 } 74 75 if (!journal->size) 76 { 77 KePrint(KERN_ERROR "EXT3: Zero length journal present\n"); 78 return -EINVAL; 79 } 80 81 /* The journal node must be used (i.e. linked to somewhere). Check! */ 82 83 KePrint("EXT3: Found journal at %#X: size = %#X\n", iNo, journal->size); 84 85 /* Let the journal layer handle the replaying. */ 86 EXT3_SUPERINFO(superBlock)->journal=JournalCreate(journal); 87 88 if (!journal) 89 return -EIO; 90 91 JournalSetUuid(EXT3_SUPERINFO(superBlock)->journal, sb->journalUuid); 92 93 return 0; 94 } 95 96 int Ext3JournalInit(struct VfsSuperBlock* superBlock, struct Ext3SuperBlock* sb) 97 { 98 /* TODO: Recovery? */ 99 100 if (sb->journalINum) 101 { 102 return Ext3JournalSetup(superBlock, sb, sb->journalINum); 103 }else 104 KePrint("Ext3JournalInit: get dev journal\n"); 105 106 return -ENOTIMPL; 107 } 108 109 DWORD Ext3GetDescriptorLoc(struct VfsSuperBlock* superBlock, int i) 110 { 111 struct Ext3SbInfo* sb=EXT3_SUPERINFO(superBlock); 112 // unsigned long block; 113 114 return sb->sbSector+i+1; 115 116 /* Check features for meta block group */ 117 #if 0 118 block=DESCS_PER_BLOCK(superBlock)*i; 119 120 return sb->firstDataBlock+(block*sb->blocksPerGrp); 121 #endif 122 } 123 124 int Ext3ReadSuperBlock(struct VfsSuperBlock* superBlock, struct Ext3SbInfo* sbInfo) 125 { 126 int sector, offset; 127 128 sector=1*1024/BYTES_PER_SECTOR(superBlock); 129 offset=(1*1024) % BYTES_PER_SECTOR(superBlock); 130 131 sbInfo->sbBuffer=BlockRead(superBlock->sDevice, sector); 132 133 if (!sbInfo->sbBuffer) 134 return -EIO; 135 136 sbInfo->super=(struct Ext3SuperBlock*)((sbInfo->sbBuffer->data)+offset); 137 sbInfo->sbSector=sector; 138 139 return 0; 140 } 37 141 38 142 struct VfsSuperBlock* Ext3ReadSuper(struct StorageDevice* dev,int flags,char* data) … … 40 144 struct VfsSuperBlock* retVal; 41 145 struct Buffer* buff; 42 struct Ext3SuperBlock *sb;146 struct Ext3SuperBlock sb; 43 147 struct Ext3SbInfo* sbInfo; 44 148 int descCount,i; … … 54 158 goto error; 55 159 56 sb=(struct Ext3SuperBlock*)buff->data; 160 /* The buffer will be freed if we set the block size to something other than 161 * 1024, so save the data off now. 162 */ 163 164 memcpy(&sb, buff->data, sizeof(struct Ext3SuperBlock)); 57 165 58 166 /* Sanity check. */ 59 if (sb ->magic != EXT3_SB_MAGIC)167 if (sb.magic != EXT3_SB_MAGIC) 60 168 goto blockReadError; 61 169 … … 63 171 if (!retVal) 64 172 goto blockReadError; 173 174 /* Ext3 block sizes are a multiple of 1024. */ 175 BlockSetSize(dev,1024 << sb.logBlockSize); 65 176 66 177 /* Copy some useful information over into the private superblock structure. */ … … 69 180 goto superFreeError; 70 181 71 sbInfo->iNodesCount=sb->iNodesCount; 72 sbInfo->groupCount=(sb->blocksCount-sb->firstDataBlock+sb->blocksPerGrp-1)/sb->blocksPerGrp; 73 sbInfo->iNodesPerGrp=sb->iNodesPerGrp; 182 sbInfo->iNodesCount=sb.iNodesCount; 183 sbInfo->blocksPerGrp=sb.blocksPerGrp; 184 sbInfo->groupCount=(sb.blocksCount-sb.firstDataBlock+sb.blocksPerGrp-1)/sb.blocksPerGrp; 185 sbInfo->iNodesPerGrp=sb.iNodesPerGrp; 186 187 sbInfo->firstDataBlock=sb.firstDataBlock; 188 189 /* Read in the superblock again. */ 190 Ext3ReadSuperBlock(retVal, sbInfo); 191 192 /* And set the Ext3-specific parts of the superblock structure. */ 193 retVal->privData=sbInfo; 194 retVal->sbOps=&ext3SbOps; 74 195 75 196 /* Read in the block descriptors as pointers to buffers. */ … … 77 198 sbInfo->descs=(struct Buffer**)malloc(descCount*sizeof(struct Buffer*)); 78 199 200 if (!descCount) 201 goto superFreeError; 202 79 203 for (i=0; i<descCount; i++) 80 sbInfo->descs[i]=BlockRead(dev,2+i); 81 82 /* And set the Ext3-specific parts of the superblock structure. */ 83 retVal->privData=sbInfo; 84 retVal->sbOps=&ext3SbOps; 85 86 /* For now */ 87 retVal->flags|=SB_RDONLY; 88 89 /* Ext3 block sizes are a multiple of 1024. */ 90 BlockSetSize(dev,1024 << sb->logBlockSize); 204 sbInfo->descs[i]=BlockRead(dev, Ext3GetDescriptorLoc(retVal, i)); 205 206 /* If we have a journal, read it in. We read the journal in before the root 207 * node, because it may have been modified in the journal. */ 208 209 if (EXT3_FEATURE_COMPAT(&sb, EXT3_FEATURE_COMPAT_JOURNAL)) 210 { 211 if (Ext3JournalInit(retVal, &sb)) 212 goto descsFree; 213 214 /* Write journal superblock. */ 215 } 91 216 92 217 retVal->mount=VNodeGet(retVal, EXT3_ROOT_VNO);
