Changeset 858

Show
Ignore:
Timestamp:
08/21/08 21:52:46 (3 years ago)
Author:
mwhitworth
Message:

Merge ext3 into trunk.

Location:
Whitix/trunk/fs/ext3
Files:
5 modified
2 copied

Legend:

Unmodified
Added
Removed
  • Whitix/trunk/fs/ext3/Makefile

    r703 r858  
    11DEPTH=../../ 
    2 MODULES = super.sys inode.sys 
     2MODULES = super.sys inode.sys file.sys ialloc.sys balloc.sys 
    33 
    44build: $(MODULES) 
    55        ld $(LD_R_FLAGS) $(MODULES) -o ext3.sys 
    66 
     7modules_install: 
     8        cp ext3.sys ../../CdRoot/System/Modules/Filesystems 
     9 
    710include $(DEPTH)make.inc 
    811-include $(DEPS) 
  • Whitix/trunk/fs/ext3/ext3.h

    r608 r858  
    2020#define EXT3_H 
    2121 
     22#include <fs/journal.h> 
    2223#include <fs/vfs.h> 
    2324#include <init.h> 
    2425 
     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 
    2537struct Ext3SuperBlock 
    2638{ 
    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. Thus  
     39        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  
    3446        0 == 1024 , 1 = 2048 , 2 = 4096*/ 
    35         DWORD logFragSize; /* Fragments are not yet implemented int ext3. So  
     47        DWORD logFragSize;              /* Fragments are not yet implemented int ext3. So  
    3648        logFragSize .equal. logBlockSize */ 
    37         DWORD blocksPerGrp; /* Number of Blocks in each block group */ 
     49        DWORD blocksPerGrp;     /* Number of Blocks in each block group */ 
    3850        DWORD fragsPerGrp; /* Number of Fragments in each block group */ 
    3951        DWORD iNodesPerGrp; /* Number of Inodes in each block group */ 
     
    8799{ 
    88100        DWORD iNodesCount,groupCount,iNodesPerGrp; 
     101        DWORD firstDataBlock, blocksPerGrp; 
    89102        struct Buffer** descs; 
     103         
     104        DWORD sbSector; 
     105        struct Buffer* sbBuffer; 
     106        struct Ext3SuperBlock* super; 
     107         
     108        struct Journal* journal; 
    90109}; 
    91110 
     
    93112{ 
    94113        DWORD blocks[15]; 
     114        DWORD blockGroup; 
    95115}; 
    96116 
     
    98118 
    99119/*   
    100  * Each block group has its own group discriptor 
     120 * Each block group has its own group descriptor 
    101121 */ 
    102122struct Ext3GroupDesc 
     
    107127        WORD freeBlocks; // Number of free blocks in the group 
    108128        WORD freeINodes; // Number of free inodes in the group 
    109         WORD usedDirs; // Number of directory in the group 
     129        WORD usedDirs; // Number of directories in the group 
    110130        WORD pad; //  Alignment to WORD 
    111131        DWORD reserved[3]; // Null to pad out 24 bytes. 
     
    137157}PACKED; 
    138158 
     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 
     165static 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 
    139175/* 
    140176 * DirEntry describes Directory, which are special kind of file 
     
    144180{ 
    145181        DWORD iNodeNum; // Inode number 
    146         WORD recLen; // Directoy entry length 
     182        WORD recLen; // Directory entry length 
    147183        BYTE nameLen;// filename length 
    148184        BYTE fileType; // file type 
     
    152188/* Common functions */ 
    153189int Ext3ReadVNode(struct VNode* vNode); 
     190int Ext3WriteVNode(struct VNode* vNode); 
     191int Ext3DirtyVNode(struct VNode* vNode); 
    154192int Ext3Lookup(struct VNode** retVal,struct VNode* dir,char* name,int nameLength); 
    155193int 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); 
     194int Ext3BlockMap(struct VNode* vNode, DWORD block, int flags); 
     195struct Buffer* Ext3BlockRead(struct VNode* vNode,int block, int create); 
     196int Ext3Create(struct VNode** retVal,struct VNode* dir,char* name,int nameLength); 
     197int Ext3Truncate(struct VNode* vNode, int size); 
     198int Ext3MkDir(struct VNode** retVal,struct VNode* dir,char* name,int nameLength); 
     199struct VNode* Ext3CreateINode(struct JournalHandle* handle, struct VNode* dir, int isDir); 
     200int Ext3Remove(struct VNode* dir, char* name, int nameLength); 
     201int Ext3RemoveDir(struct VNode* dir, char* name, int nameLength); 
     202 
     203int Ext3FileWrite(struct File* file,BYTE* buffer,DWORD len); 
     204 
     205/* balloc.c */ 
     206struct Ext3GroupDesc* Ext3GetGroupDesc(struct VfsSuperBlock* superBlock, DWORD groupNo, 
     207        struct Buffer** buffer); 
     208int Ext3BlockMapHandle(struct JournalHandle* handle, struct VNode* vNode, DWORD block, int flags); 
     209int Ext3BlockTruncate(struct VNode* vNode, int size); 
    159210 
    160211extern struct VNodeOps ext3VNodeOps; 
     
    167218#define DESCS_PER_BLOCK(s) (BYTES_PER_SECTOR(s)/sizeof(struct Ext3GroupDesc)) 
    168219#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)) 
    169224 
    170225#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 
     23int 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 
    119#include <console.h> 
    220#include <malloc.h> 
     
    624#include "ext3.h" 
    725 
     26int 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 
    862int Ext3ReadVNode(struct VNode* vNode) 
    963{ 
    10         struct Ext3SbInfo* sbInfo=(struct Ext3SbInfo*)vNode->superBlock->privData; 
    11         int blockGroup,groupDesc,desc,block,i; 
    12         struct Ext3GroupDesc* groupDescs; 
    1364        struct Buffer* buffer; 
    1465        struct Ext3INode* iNode; 
    1566        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; 
    3973 
    4074        iNodeInfo=(struct Ext3INodeInfo*)malloc(sizeof(struct Ext3INodeInfo)); 
    41         vNode->extraInfo=iNodeInfo; 
     75 
    4276        if (!iNodeInfo) 
    4377        { 
     
    4579                return -ENOMEM; 
    4680        } 
    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)); 
    5186 
    5287        /* Copy the iNode times over */ 
     
    5893        vNode->fileOps=&ext3FileOps; 
    5994        vNode->mode=VFS_ATTR_WRITE | VFS_ATTR_READ; 
     95        vNode->extraInfo=iNodeInfo; 
     96 
    6097        if ((iNode->mode & 0xF000) == 0x4000) 
    6198                vNode->mode|=VFS_ATTR_DIR; 
     
    69106} 
    70107 
    71 int Ext3Lookup(struct VNode** retVal,struct VNode* dir,char* name,int nameLength) 
    72 { 
    73         int i=0; 
    74         struct Ext3DirEntry* ext3Entry; 
     108int 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 
     118int 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 
     134int 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 
     173int 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 
     199int Ext3FindEntry(struct VNode* dir, char* name, int nameLength, struct Ext3DirEntry** ext3Entry, 
     200        struct Buffer** buffer) 
     201{ 
     202        DWORD i=0; 
     203        struct Ext3DirEntry* entry; 
    75204        int bytesPerSec=BYTES_PER_SECTOR(dir->superBlock); 
    76  
    77         while (i<dir->size) 
     205         
     206        while (i < dir->size) 
    78207        { 
    79208                int block=i/bytesPerSec; 
     
    81210 
    82211                /* 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); 
    84213 
    85214                while (i < dir->size && offset < bytesPerSec) 
    86215                { 
    87                         ext3Entry=(struct Ext3DirEntry*)(buff->data+(i % bytesPerSec)); 
    88  
    89                         if (ext3Entry->nameLen == nameLength) 
     216                        entry=(struct Ext3DirEntry*)(buff->data+(i % bytesPerSec)); 
     217 
     218                        if (entry->nameLen == nameLength) 
    90219                        { 
    91220                                /* No need to go through comparing it all just to find it's a different length */ 
    92                                 if (!strncmp(ext3Entry->name,name,nameLength)) 
     221                                if (!strncmp(entry->name,name,nameLength)) 
    93222                                { 
    94                                         /* Found the directory entry */ 
    95                                         *retVal=VNodeGet(dir->superBlock,ext3Entry->iNodeNum); 
     223                                        *ext3Entry=entry; 
     224                                         
     225                                        if (buffer) 
     226                                                *buffer=buff; 
     227                                                 
    96228                                        return 0; 
    97229                                } 
    98230                        } 
    99231 
    100                         offset+=ext3Entry->recLen; 
    101                         i+=ext3Entry->recLen; 
    102                 } 
    103  
    104         } 
     232                        offset += entry->recLen; 
     233                        i += entry->recLen; 
     234                } 
     235 
     236        } 
     237         
    105238        return -ENOENT; 
    106239} 
    107240 
    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"); 
     241static 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"); 
    118264                        cli(); hlt(); 
    119265                } 
    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"); 
    139306        cli(); hlt(); 
    140  
     307         
     308        return 0; 
     309} 
     310 
     311static 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 
     326int 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 
     348int 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 
     376int 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         
     395fail: 
     396        JournalStop(handle); 
     397         
     398        return err; 
     399} 
     400 
     401int 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 
     416int 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 
     451int 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         
    141461        return 0; 
    142462} 
     
    156476 ***********************************************************************/ 
    157477 
    158 struct Buffer* Ext3BlockRead(struct VNode* vNode,int block) 
    159 { 
    160         int realBlock=Ext3BlockMap(vNode,block); 
    161         if (realBlock == -1) 
     478struct Buffer* Ext3BlockRead(struct VNode* vNode, int block, int flags) 
     479{ 
     480        int realBlock=Ext3BlockMap(vNode,block, flags); 
     481        if (realBlock < 0) 
    162482                return NULL; 
    163483         
     
    178498                offset=(file->position % bytesPerSec); 
    179499                block=file->position/bytesPerSec; 
    180                 buff=Ext3BlockRead(file->vNode,block); 
     500                buff=Ext3BlockRead(file->vNode,block, 0); 
    181501                if (!buff) 
    182502                        return -EIO; 
     
    185505                { 
    186506                        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); 
    187509 
    188510                        if (LIKELY(ext3Entry->iNodeNum)) 
     
    200522        return 0; 
    201523} 
     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  
     540int 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 
     590int Ext3RemoveDir(struct VNode* dir, char* name, int nameLength) 
     591{ 
     592        return -ENOTIMPL; 
     593} 
  • Whitix/trunk/fs/ext3/super.c

    r608 r858  
    2121#include <malloc.h> 
    2222#include <error.h> 
     23#include <print.h> 
     24 
     25int Ext3FreeSuper(struct VfsSuperBlock* superBlock); 
    2326 
    2427struct SuperBlockOps ext3SbOps={ 
    2528        .readVNode = Ext3ReadVNode, 
     29        .writeVNode = Ext3WriteVNode, 
     30        .dirtyVNode = Ext3DirtyVNode, 
     31        .freeSuper = Ext3FreeSuper, 
    2632}; 
    2733 
     
    2935        .lookup = Ext3Lookup, 
    3036        .blockMap = Ext3BlockMap, 
     37        .create = Ext3Create, 
     38        .remove = Ext3Remove, 
     39        .truncate = Ext3Truncate, 
     40        .mkDir = Ext3MkDir, 
     41        .rmDir = Ext3RemoveDir, 
    3142}; 
    3243 
     
    3445        .readDir = Ext3ReadDir, 
    3546        .read = FileGenericRead, 
    36 }; 
     47        .write = Ext3FileWrite, 
     48}; 
     49 
     50int 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 
     63int 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 
     96int 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 
     109DWORD 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 
     124int 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} 
    37141 
    38142struct VfsSuperBlock* Ext3ReadSuper(struct StorageDevice* dev,int flags,char* data) 
     
    40144        struct VfsSuperBlock* retVal; 
    41145        struct Buffer* buff; 
    42         struct Ext3SuperBlock* sb; 
     146        struct Ext3SuperBlock sb; 
    43147        struct Ext3SbInfo* sbInfo; 
    44148        int descCount,i; 
     
    54158                goto error; 
    55159 
    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)); 
    57165 
    58166        /* Sanity check. */ 
    59         if (sb->magic != EXT3_SB_MAGIC) 
     167        if (sb.magic != EXT3_SB_MAGIC) 
    60168                goto blockReadError; 
    61169 
     
    63171        if (!retVal) 
    64172                goto blockReadError; 
     173 
     174        /* Ext3 block sizes are a multiple of 1024. */ 
     175        BlockSetSize(dev,1024 << sb.logBlockSize); 
    65176 
    66177        /* Copy some useful information over into the private superblock structure. */ 
     
    69180                goto superFreeError; 
    70181 
    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; 
    74195 
    75196        /* Read in the block descriptors as pointers to buffers. */ 
     
    77198        sbInfo->descs=(struct Buffer**)malloc(descCount*sizeof(struct Buffer*)); 
    78199 
     200        if (!descCount) 
     201                goto superFreeError; 
     202 
    79203        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        } 
    91216 
    92217        retVal->mount=VNodeGet(retVal, EXT3_ROOT_VNO);