Updated FAT filesystem driver to not cache the FAT if the disk is too large
authorJohn Hodge <[email protected]>
Sun, 11 Apr 2010 07:17:10 +0000 (15:17 +0800)
committerJohn Hodge <[email protected]>
Sun, 11 Apr 2010 07:17:10 +0000 (15:17 +0800)
Modules/Filesystems/FAT/fat.c

index 491a4d5..25b9cb0 100644 (file)
@@ -60,6 +60,9 @@ tVFS_Node     *FAT_FindDir(tVFS_Node *Node, char *Name);
  int   FAT_Relink(tVFS_Node *node, char *OldName, char *NewName);\r
 void   FAT_CloseFile(tVFS_Node *node);\r
 \r
+// === Options ===\r
+ int   giFAT_MaxCachedClusters = 1024*512/4;\r
+\r
 // === SEMI-GLOBALS ===\r
 MODULE_DEFINE(0, (0<<8)|50 /*v0.50*/, VFAT, FAT_Install, NULL, NULL);\r
 tFAT_VolInfo   gFAT_Disks[8];\r
@@ -176,53 +179,54 @@ tVFS_Node *FAT_InitDevice(char *Device, char **Options)
        \r
        //Allow for Caching the FAT\r
        #if CACHE_FAT\r
+       if( diskInfo->ClusterCount <= giFAT_MaxCachedClusters )\r
        {\r
-       Uint32  Ofs;\r
-       diskInfo->FATCache = (Uint32*)malloc(sizeof(Uint32)*diskInfo->ClusterCount);\r
-       if(diskInfo->FATCache == NULL) {\r
-               Log_Warning("FAT", "Heap Exhausted");\r
-               return NULL;\r
-       }\r
-       Ofs = bs->resvSectCount*512;\r
-       if(diskInfo->type == FAT12)\r
-       {\r
-               Uint32  val;\r
-                int    j;\r
-               char    buf[1536];\r
-               for(i = 0; i < diskInfo->ClusterCount/2; i++) {\r
-                       j = i & 511;    //%512\r
-                       if( j == 0 ) {\r
-                               VFS_ReadAt(diskInfo->fileHandle, Ofs, 3*512, buf);\r
-                               Ofs += 3*512;\r
+               Uint32  Ofs;\r
+               diskInfo->FATCache = (Uint32*)malloc(sizeof(Uint32)*diskInfo->ClusterCount);\r
+               if(diskInfo->FATCache == NULL) {\r
+                       Log_Warning("FAT", "Heap Exhausted");\r
+                       return NULL;\r
+               }\r
+               Ofs = bs->resvSectCount*512;\r
+               if(diskInfo->type == FAT12)\r
+               {\r
+                       Uint32  val;\r
+                        int    j;\r
+                       char    buf[1536];\r
+                       for(i = 0; i < diskInfo->ClusterCount/2; i++) {\r
+                               j = i & 511;    //%512\r
+                               if( j == 0 ) {\r
+                                       VFS_ReadAt(diskInfo->fileHandle, Ofs, 3*512, buf);\r
+                                       Ofs += 3*512;\r
+                               }\r
+                               val = *((int*)(buf+j*3));\r
+                               diskInfo->FATCache[i*2] = val & 0xFFF;\r
+                               diskInfo->FATCache[i*2+1] = (val>>12) & 0xFFF;\r
                        }\r
-                       val = *((int*)(buf+j*3));\r
-                       diskInfo->FATCache[i*2] = val & 0xFFF;\r
-                       diskInfo->FATCache[i*2+1] = (val>>12) & 0xFFF;\r
                }\r
-       }\r
-       else if(diskInfo->type == FAT16)\r
-       {\r
-               Uint16  buf[256];\r
-               for(i=0;i<diskInfo->ClusterCount;i++) {\r
-                       if( (i & 255) == 0 ) {\r
-                               VFS_ReadAt(diskInfo->fileHandle, Ofs, 512, buf);\r
-                               Ofs += 512;\r
+               else if(diskInfo->type == FAT16)\r
+               {\r
+                       Uint16  buf[256];\r
+                       for(i=0;i<diskInfo->ClusterCount;i++) {\r
+                               if( (i & 255) == 0 ) {\r
+                                       VFS_ReadAt(diskInfo->fileHandle, Ofs, 512, buf);\r
+                                       Ofs += 512;\r
+                               }\r
+                               diskInfo->FATCache[i] = buf[i&255];\r
                        }\r
-                       diskInfo->FATCache[i] = buf[i&255];\r
                }\r
-       }\r
-       else if(diskInfo->type == FAT32)\r
-       {\r
-               Uint32  buf[128];\r
-               for(i=0;i<diskInfo->ClusterCount;i++) {\r
-                       if( (i & 127) == 0 ) {\r
-                               VFS_ReadAt(diskInfo->fileHandle, Ofs, 512, buf);\r
-                               Ofs += 512;\r
+               else if(diskInfo->type == FAT32)\r
+               {\r
+                       Uint32  buf[128];\r
+                       for(i=0;i<diskInfo->ClusterCount;i++) {\r
+                               if( (i & 127) == 0 ) {\r
+                                       VFS_ReadAt(diskInfo->fileHandle, Ofs, 512, buf);\r
+                                       Ofs += 512;\r
+                               }\r
+                               diskInfo->FATCache[i] = buf[i&127];\r
                        }\r
-                       diskInfo->FATCache[i] = buf[i&127];\r
                }\r
-       }\r
-       LOG("FAT Fully Cached");\r
+               LOG("FAT Fully Cached");\r
        }\r
        #endif /*CACHE_FAT*/\r
        \r
@@ -362,27 +366,33 @@ int FAT_int_GetAddress(tVFS_Node *Node, Uint64 Offset, Uint64 *Addr, Uint32 *Clu
 Uint32 FAT_int_GetFatValue(tFAT_VolInfo *Disk, Uint32 cluster)\r
 {\r
        Uint32  val = 0;\r
-       #if !CACHE_FAT\r
-       Uint32  ofs = Disk->bootsect.resvSectCount*512;\r
-       #endif\r
+       Uint32  ofs;\r
        ENTER("pDisk xCluster", Disk, cluster);\r
        LOCK( &Disk->lFAT );\r
        #if CACHE_FAT\r
-       val = Disk->FATCache[cluster];\r
-       if(Disk->type == FAT12 && val == EOC_FAT12)     val = -1;\r
-       if(Disk->type == FAT16 && val == EOC_FAT16)     val = -1;\r
-       if(Disk->type == FAT32 && val == EOC_FAT32)     val = -1;\r
-       #else\r
-       if(Disk->type == FAT12) {\r
-               VFS_ReadAt(Disk->fileHandle, ofs+(cluster>>1)*3, 3, &val);\r
-               val = (cluster&1 ? val&0xFFF : val>>12);\r
-               if(val == EOC_FAT12)    val = -1;\r
-       } else if(Disk->type == FAT16) {\r
-               VFS_ReadAt(Disk->fileHandle, ofs+cluster*2, 2, &val);\r
-               if(val == EOC_FAT16)    val = -1;\r
-       } else {\r
-               VFS_ReadAt(Disk->fileHandle, ofs+cluster*4, 4, &val);\r
-               if(val == EOC_FAT32)    val = -1;\r
+       if( Disk->ClusterCount <= giFAT_MaxCachedClusters )\r
+       {\r
+               val = Disk->FATCache[cluster];\r
+               if(Disk->type == FAT12 && val == EOC_FAT12)     val = -1;\r
+               if(Disk->type == FAT16 && val == EOC_FAT16)     val = -1;\r
+               if(Disk->type == FAT32 && val == EOC_FAT32)     val = -1;\r
+       }\r
+       else\r
+       {\r
+       #endif\r
+               ofs = Disk->bootsect.resvSectCount*512;\r
+               if(Disk->type == FAT12) {\r
+                       VFS_ReadAt(Disk->fileHandle, ofs+(cluster>>1)*3, 3, &val);\r
+                       val = (cluster&1 ? val&0xFFF : val>>12);\r
+                       if(val == EOC_FAT12)    val = -1;\r
+               } else if(Disk->type == FAT16) {\r
+                       VFS_ReadAt(Disk->fileHandle, ofs+cluster*2, 2, &val);\r
+                       if(val == EOC_FAT16)    val = -1;\r
+               } else {\r
+                       VFS_ReadAt(Disk->fileHandle, ofs+cluster*4, 4, &val);\r
+                       if(val == EOC_FAT32)    val = -1;\r
+               }\r
+       #if CACHE_FAT\r
        }\r
        #endif /*CACHE_FAT*/\r
        RELEASE( &Disk->lFAT );\r
@@ -398,78 +408,85 @@ Uint32 FAT_int_AllocateCluster(tFAT_VolInfo *Disk, Uint32 Previous)
 {\r
        Uint32  ret = Previous;\r
        #if CACHE_FAT\r
-       Uint32  eoc;\r
-       \r
-       LOCK(Disk->lFAT);\r
-       for(ret = Previous; ret < Disk->ClusterCount; ret++)\r
-       {\r
-               if(Disk->FATCache[ret] == 0)\r
-                       goto append;\r
-       }\r
-       for(ret = 0; ret < Previous; ret++)\r
-       {\r
-               if(Disk->FATCache[ret] == 0)\r
-                       goto append;\r
-       }\r
-       \r
-       RELEASE(Disk->lFAT);\r
-       return 0;\r
-       \r
-append:\r
-       switch(Disk->type)\r
-       {\r
-       case FAT12:     eoc = EOC_FAT12;        break;\r
-       case FAT16:     eoc = EOC_FAT16;        break;\r
-       case FAT32:     eoc = EOC_FAT32;        break;\r
-       default:        return 0;\r
-       }\r
-       \r
-       Disk->FATCache[ret] = eoc;\r
-       Disk->FATCache[Previous] = ret;\r
-       \r
-       RELEASE(Disk->lFAT);\r
-       return ret;\r
-       #else\r
-       Uint32  val;\r
-       //Uint8 buf[512];\r
-       Log_Warning("FAT", "TODO: Implement cluster allocation with non cached FAT");\r
-       return 0;\r
-       \r
-       switch(Disk->type)\r
+       if( Disk->ClusterCount <= giFAT_MaxCachedClusters )\r
        {\r
-       case FAT12:\r
-               VFS_ReadAt(Disk->fileHandle, ofs+(Previous>>1)*3, 3, &val);\r
-               if( Previous & 1 ) {\r
-                       val &= 0xFFF000;\r
-                       val |= ret;\r
+               Uint32  eoc;\r
+               \r
+               LOCK(Disk->lFAT);\r
+               for(ret = Previous; ret < Disk->ClusterCount; ret++)\r
+               {\r
+                       if(Disk->FATCache[ret] == 0)\r
+                               goto append;\r
                }\r
-               else {\r
-                       val &= 0xFFF;\r
-                       val |= ret<<12;\r
+               for(ret = 0; ret < Previous; ret++)\r
+               {\r
+                       if(Disk->FATCache[ret] == 0)\r
+                               goto append;\r
                }\r
-               VFS_WriteAt(Disk->fileHandle, ofs+(Previous>>1)*3, 3, &val);\r
                \r
-               VFS_ReadAt(Disk->fileHandle, ofs+(ret>>1)*3, 3, &val);\r
-               if( Cluster & 1 ) {\r
-                       val &= 0xFFF000;\r
-                       val |= eoc;\r
+               RELEASE(Disk->lFAT);\r
+               return 0;\r
+       \r
+       append:\r
+               switch(Disk->type)\r
+               {\r
+               case FAT12:     eoc = EOC_FAT12;        break;\r
+               case FAT16:     eoc = EOC_FAT16;        break;\r
+               case FAT32:     eoc = EOC_FAT32;        break;\r
+               default:        return 0;\r
                }\r
-               else {\r
-                       val &= 0x000FFF;\r
-                       val |= eoc<<12;\r
+               \r
+               Disk->FATCache[ret] = eoc;\r
+               Disk->FATCache[Previous] = ret;\r
+               \r
+               RELEASE(Disk->lFAT);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+       #endif\r
+               Uint32  val;\r
+               Uint32  ofs = Disk->bootsect.resvSectCount*512;\r
+               Log_Warning("FAT", "TODO: Implement cluster allocation with non cached FAT");\r
+               return 0;\r
+               \r
+               switch(Disk->type)\r
+               {\r
+               case FAT12:\r
+                       VFS_ReadAt(Disk->fileHandle, ofs+(Previous>>1)*3, 3, &val);\r
+                       if( Previous & 1 ) {\r
+                               val &= 0xFFF000;\r
+                               val |= ret;\r
+                       }\r
+                       else {\r
+                               val &= 0xFFF;\r
+                               val |= ret<<12;\r
+                       }\r
+                       VFS_WriteAt(Disk->fileHandle, ofs+(Previous>>1)*3, 3, &val);\r
+                       \r
+                       VFS_ReadAt(Disk->fileHandle, ofs+(ret>>1)*3, 3, &val);\r
+                       if( Cluster & 1 ) {\r
+                               val &= 0xFFF000;\r
+                               val |= eoc;\r
+                       }\r
+                       else {\r
+                               val &= 0x000FFF;\r
+                               val |= eoc<<12;\r
+                       }\r
+                       VFS_WriteAt(Disk->fileHandle, ofs+(ret>>1)*3, 3, &val);\r
+                       break;\r
+               case FAT16:\r
+                       VFS_ReadAt(Disk->fileHandle, ofs+Previous*2, 2, &ret);\r
+                       VFS_WriteAt(Disk->fileHandle, ofs+ret*2, 2, &eoc);\r
+                       break;\r
+               case FAT32:\r
+                       VFS_ReadAt(Disk->fileHandle, ofs+Previous*4, 4, &ret);\r
+                       VFS_WriteAt(Disk->fileHandle, ofs+ret*4, 4, &eoc);\r
+                       break;\r
                }\r
-               VFS_WriteAt(Disk->fileHandle, ofs+(ret>>1)*3, 3, &val);\r
-               break;\r
-       case FAT16:\r
-               VFS_ReadAt(Disk->fileHandle, ofs+Previous*2, 2, &ret);\r
-               VFS_WriteAt(Disk->fileHandle, ofs+ret*2, 2, &eoc);\r
-               break;\r
-       case FAT32:\r
-               VFS_ReadAt(Disk->fileHandle, ofs+Previous*4, 4, &ret);\r
-               VFS_WriteAt(Disk->fileHandle, ofs+ret*4, 4, &eoc);\r
-               break;\r
+               return ret;\r
+       #if CACHE_FAT\r
        }\r
-       return ret;\r
        #endif\r
 }\r
 \r
@@ -481,41 +498,49 @@ Uint32 FAT_int_FreeCluster(tFAT_VolInfo *Disk, Uint32 Cluster)
 {\r
        Uint32  ret;\r
        #if CACHE_FAT\r
-       LOCK(Disk->lFAT);\r
-       \r
-       ret = Disk->FATCache[Cluster];\r
-       Disk->FATCache[Cluster] = 0;\r
-       \r
-       RELEASE(Disk->lFAT);\r
-       #else\r
-       Uint32  val;\r
-       LOCK(Disk->lFAT);\r
-       switch(Disk->type)\r
+       if( Disk->ClusterCount <= giFAT_MaxCachedClusters )\r
        {\r
-       case FAT12:\r
-               VFS_ReadAt(Disk->fileHandle, ofs+(Cluster>>1)*3, 3, &val);\r
-               if( Cluster & 1 ) {\r
-                       ret = val & 0xFFF0000;\r
-                       val &= 0xFFF;\r
-               }\r
-               else {\r
-                       ret = val & 0xFFF;\r
-                       val &= 0xFFF000;\r
+               LOCK(Disk->lFAT);\r
+               \r
+               ret = Disk->FATCache[Cluster];\r
+               Disk->FATCache[Cluster] = 0;\r
+               \r
+               RELEASE(Disk->lFAT);\r
+       }\r
+       else\r
+       {\r
+       #endif\r
+               Uint32  val;\r
+               Uint32  ofs = Disk->bootsect.resvSectCount*512;\r
+               LOCK(Disk->lFAT);\r
+               switch(Disk->type)\r
+               {\r
+               case FAT12:\r
+                       VFS_ReadAt(Disk->fileHandle, ofs+(Cluster>>1)*3, 3, &val);\r
+                       if( Cluster & 1 ) {\r
+                               ret = val & 0xFFF0000;\r
+                               val &= 0xFFF;\r
+                       }\r
+                       else {\r
+                               ret = val & 0xFFF;\r
+                               val &= 0xFFF000;\r
+                       }\r
+                       VFS_WriteAt(Disk->fileHandle, ofs+(Previous>>1)*3, 3, &val);\r
+                       break;\r
+               case FAT16:\r
+                       VFS_ReadAt(Disk->fileHandle, ofs+Previous*2, 2, &ret);\r
+                       val = 0;\r
+                       VFS_WriteAt(Disk->fileHandle, ofs+Cluster*2, 2, &val);\r
+                       break;\r
+               case FAT32:\r
+                       VFS_ReadAt(Disk->fileHandle, ofs+Previous*4, 4, &ret);\r
+                       val = 0;\r
+                       VFS_WriteAt(Disk->fileHandle, ofs+Cluster*2, 2, &val);\r
+                       break;\r
                }\r
-               VFS_WriteAt(Disk->fileHandle, ofs+(Previous>>1)*3, 3, &val);\r
-               break;\r
-       case FAT16:\r
-               VFS_ReadAt(Disk->fileHandle, ofs+Previous*2, 2, &ret);\r
-               val = 0;\r
-               VFS_WriteAt(Disk->fileHandle, ofs+Cluster*2, 2, &val);\r
-               break;\r
-       case FAT32:\r
-               VFS_ReadAt(Disk->fileHandle, ofs+Previous*4, 4, &ret);\r
-               val = 0;\r
-               VFS_WriteAt(Disk->fileHandle, ofs+Cluster*2, 2, &val);\r
-               break;\r
+               RELEASE(Disk->lFAT);\r
+       #if CACHE_FAT\r
        }\r
-       RELEASE(Disk->lFAT);\r
        #endif\r
        if(Disk->type == FAT12 && ret == EOC_FAT12)     ret = -1;\r
        if(Disk->type == FAT16 && ret == EOC_FAT16)     ret = -1;\r
@@ -574,14 +599,14 @@ Uint64 FAT_Read(tVFS_Node *Node, Uint64 offset, Uint64 length, void *buffer)
        \r
        // Sanity Check offset\r
        if(offset > Node->Size) {\r
-               //LOG("Reading past EOF (%i > %i)", offset, node->Size);\r
+               LOG("Reading past EOF (%i > %i)", offset, node->Size);\r
                LEAVE('i', 0);\r
                return 0;\r
        }\r
        // Clamp Size\r
        if(offset + length > Node->Size) {\r
-               //LOG("Reading past EOF (%lli + %lli > %lli), clamped to %lli",\r
-               //      offset, length, node->Size, node->Size - offset);\r
+               LOG("Reading past EOF (%lli + %lli > %lli), clamped to %lli",\r
+                       offset, length, node->Size, node->Size - offset);\r
                length = Node->Size - offset;\r
        }\r
        \r
@@ -639,12 +664,12 @@ Uint64 FAT_Read(tVFS_Node *Node, Uint64 offset, Uint64 length, void *buffer)
        cluster = FAT_int_GetFatValue(disk, cluster);\r
        \r
        #if DEBUG\r
-       LOG("pos=%i", pos);\r
+       LOG("pos = %i", pos);\r
        LOG("Reading the rest of the clusters");\r
        #endif\r
        \r
        \r
-       //Read the rest of the cluster data\r
+       // Read the rest of the cluster data\r
        for( i = 1; i < count-1; i++ )\r
        {\r
                FAT_int_ReadCluster(disk, cluster, bpc, tmpBuf);\r

UCC git Repository :: git.ucc.asn.au