Changeset 1912

Show
Ignore:
Timestamp:
02/24/09 20:57:26 (3 years ago)
Author:
mwhitworth
Message:

Add support for keep track of free clusters in a FAT32 filesystem, add WriteSuper function and ReadFsInfo.

Location:
Whitix/trunk/fs/fat
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • Whitix/trunk/fs/fat/fat.c

    r1909 r1912  
    229229        struct Buffer* buff; 
    230230 
     231        DWORD freeClusters = sbInfo->freeClusters; 
     232         
    231233        /* Cannot allocate clusters to the root directory in FAT12/16 */ 
    232234        if (sbInfo->fatType != 32 && vNode->id == FAT_ROOT_ID) 
     
    283285                *lastCluster=ret; 
    284286 
     287        freeClusters--; 
     288         
     289        /* If we've got FAT32 and a valid number of free clusters, update it. */ 
     290        if (sbInfo->fatType == 32 && sbInfo->freeClusters != -1) 
     291        { 
     292                sbInfo->freeClusters = freeClusters; 
     293                SuperSetDirty(vNode->superBlock); 
     294        }        
     295 
    285296        return 0; 
    286297} 
     
    294305        int fromNum = number; 
    295306 
     307        DWORD freeClusters = sbInfo->freeClusters; 
     308 
    296309        if (sbInfo->fatType != 32 && !vNode->id) 
    297310                return -EPERM; 
     
    307320                { 
    308321                        cluster=FatAccess(vNode->superBlock, cluster,-1); 
     322                         
     323                        freeClusters++; 
     324                         
    309325                        if (cluster >= sbInfo->invalidCluster) 
    310                         { 
    311                                 KePrint("FatRemoveClusters: %d\n",number); 
    312326                                return -EINVAL; 
    313                         } 
    314327 
    315328                        --number; 
     
    331344                fatVNodeInfo->startCluster=0; /* Since it doesn't have one anymore */ 
    332345 
     346        /* If we've got FAT32 and a valid number of free clusters, update it. */ 
     347        if (sbInfo->fatType == 32 && sbInfo->freeClusters != -1) 
     348        { 
     349                sbInfo->freeClusters = freeClusters; 
     350                SuperSetDirty(vNode->superBlock); 
     351        } 
     352 
    333353        return 0; 
    334354} 
  • Whitix/trunk/fs/fat/fat.h

    r1668 r1912  
    125125}PACKED; 
    126126 
     127struct FatFsInfo 
     128{ 
     129        DWORD reserved1; 
     130        DWORD signature; 
     131        DWORD freeClusters; 
     132        DWORD nextCluster; 
     133        DWORD reserved2; 
     134}; 
     135 
    127136struct FatDirEntry 
    128137{ 
     
    155164struct FatSbInfo 
    156165{ 
    157         DWORD fatStart,fatLength,rootDirStart,rootDirLength, rootDirEnts; 
    158         DWORD firstDataSector,totalDataSectors,clusterLength,secsPerClus; 
    159         DWORD fatType,invalidCluster,numFats; 
     166        /* FAT information */ 
     167        DWORD fatStart, fatLength, fatType, invalidCluster, numFats; 
     168         
     169        /* Root directory information */ 
     170        DWORD rootDirStart, rootDirLength, rootDirEnts; 
     171         
     172        /* Data sector and cluster layout */ 
     173        DWORD firstDataSector,totalDataSectors, clusterLength, secsPerClus; 
     174         
     175        /* Values that are only updated on FAT32 */ 
     176        DWORD freeClusters, fsInfoSector; 
    160177}; 
    161178 
  • Whitix/trunk/fs/fat/super.c

    r1909 r1912  
    2727#include "fat.h" 
    2828 
     29int FatWriteSuper(struct VfsSuperBlock* superBlock); 
     30 
    2931struct SuperBlockOps fatSbOps= 
    3032{ 
    3133        .readVNode = FatReadVNode, 
    3234        .writeVNode = FatWriteVNode, 
     35        .writeSuper = FatWriteSuper, 
    3336}; 
    3437 
     
    4447}; 
    4548 
     49/* Update the freeClusters in the FsInfo sector on FAT32 */ 
     50int FatWriteSuper(struct VfsSuperBlock* superBlock) 
     51{ 
     52        struct FatSbInfo* sbInfo; 
     53        struct FatFsInfo* info; 
     54        struct Buffer* buff; 
     55        DWORD prevSize = superBlock->sDevice->softBlockSize; 
     56         
     57        sbInfo = FatGetSbPriv(superBlock); 
     58 
     59        if (sbInfo->fatType != 32) 
     60                return 0; 
     61         
     62        /* Need this to write the correct FsInfo sector. It will throw all blocks 
     63         * out of cache, but if we're calling this, we're either syncing or 
     64         * freeing the super typically. 
     65         */ 
     66          
     67        BlockSetSize(superBlock->sDevice, superBlock->sDevice->blockSize); 
     68         
     69        buff = BlockRead(superBlock->sDevice, sbInfo->fsInfoSector); 
     70         
     71        info = (struct FatFsInfo*)(buff->data + 0x1E0); 
     72        info->freeClusters = sbInfo->freeClusters; 
     73         
     74        BlockWrite(buff->device, buff); 
     75         
     76        BlockSetSize(superBlock->sDevice, prevSize); 
     77         
     78        return 0; 
     79} 
     80 
     81int FatReadFsInfo(struct VfsSuperBlock* superBlock, unsigned long fsInfoSector) 
     82{ 
     83        struct Buffer* buff; 
     84        struct FatFsInfo* info; 
     85        struct FatSbInfo* sbInfo; 
     86        BYTE* data; 
     87        int ret = 0; 
     88                 
     89        buff = BlockRead(superBlock->sDevice, fsInfoSector); 
     90         
     91        if (!buff) 
     92                return -EIO; 
     93 
     94        data = (BYTE*)(buff->data); 
     95        info = (struct FatFsInfo*)(data + 0x1E0); 
     96                 
     97        /* Four byte signature at start of fsInfo sector. */ 
     98        if (data[0] != 0x52 || data[1] != 0x52 || data[2] != 0x61 || data[3] != 0x41) 
     99        { 
     100                ret = -EINVAL; 
     101                goto out; 
     102        } 
     103         
     104        /* TODO: Check info->signature? */ 
     105         
     106        /* Boot record signature at end of fsInfo sector. */ 
     107        if (data[510] != 0x55 || data[511] != 0xAA) 
     108        { 
     109                ret = -EINVAL; 
     110                goto out; 
     111        } 
     112         
     113        /* Store the number of free clusters, and update it again in WriteSuper. */ 
     114        sbInfo = FatGetSbPriv(superBlock); 
     115         
     116        sbInfo->freeClusters = info->freeClusters; 
     117        sbInfo->fsInfoSector = fsInfoSector; 
     118         
     119        KePrint("sbInfo->freeClusters = %#X\n", sbInfo->freeClusters); 
     120         
     121out: 
     122        if (ret) 
     123                KePrint(KERN_DEBUG "FAT: Invalid FAT32 filesystem.\n"); 
     124                 
     125        BlockFree(buff); 
     126        return ret; 
     127} 
     128 
    46129struct VfsSuperBlock* FatReadSuper(struct StorageDevice* dev,int flags,char* data) 
    47130{ 
     
    55138                return NULL; 
    56139 
    57         /* The soft block size at the start does not matter, so long as it is above 512, 
    58          * which is guaranteed. */ 
    59  
    60         buff=BlockRead(dev, 0); 
     140        /* This fixes issue #110. The soft block size at the start should be the 
     141         * device's sector size as we may read the second sector of the disk in  
     142         * FatReadFsInfo. */ 
     143          
     144        if (BlockSetSize(dev, dev->blockSize)) 
     145                return NULL; 
     146 
     147        buff = BlockRead(dev, 0); 
     148         
    61149        if (!buff) 
    62150        { 
     
    67155        bootSec=(struct FatBootSector*)(buff->data); 
    68156 
    69         if (bootSec->bytesPerSec != 512 && bootSec->bytesPerSec != 1024 && bootSec->bytesPerSec != 2048 && bootSec->bytesPerSec 
    70                 != 4096) 
     157        if (bootSec->bytesPerSec != 512 && bootSec->bytesPerSec != 1024 && bootSec->bytesPerSec != 2048 && bootSec->bytesPerSec != 4096) 
    71158        { 
    72159                BlockFree(buff); 
     
    125212                fatSbInfo->invalidCluster=0x0FFFFFF8; 
    126213        } 
    127  
     214         
     215        /* Read the FsInfo structure if this is a FAT32 filesystem, so we can keep 
     216         * track of the free clusters and update it when necessary. */ 
     217        if (fatSbInfo->fatType == 32) 
     218        { 
     219                if (FatReadFsInfo(retVal, bootSec->fsInfo)) 
     220                        goto fail; 
     221        } 
     222         
    128223        KePrint(KERN_DEBUG "FAT: drive is a FAT%u volume\n",(DWORD)fatSbInfo->fatType); 
    129224 
     
    131226                goto fail; 
    132227 
    133         retVal->mount=VNodeGet(retVal, FAT_ROOT_ID); 
     228        retVal->mount = VNodeGet(retVal, FAT_ROOT_ID); 
    134229 
    135230        if (!retVal->mount)