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.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • 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)