diff -r a41df078684a -r 4122176ea935 userlibandfileserver/fileserver/sfat32/sl_disk.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/userlibandfileserver/fileserver/sfat32/sl_disk.cpp Mon Dec 21 16:14:42 2009 +0000 @@ -0,0 +1,494 @@ +// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// f32\sfat\sl_disk.cpp +// +// + +#include "sl_disk.h" +#include "sl_cache.h" +#include "sl_dir_cache.h" + +/** +@file +*/ + + +//################################################################################################################################ +//# CRawDisk implementation +//################################################################################################################################ + + +/** + Factory function. Constructs objects of the classes derived from CRawDisk. + + @param aOwner reference to the onwning FAT Mount class + @param aLocDrvCaps local drive capabilities from the media driver + @return pointer to the constructed object. May be NULL on error. +*/ +CRawDisk* CRawDisk::NewL(CFatMountCB& aOwner, const TLocalDriveCaps& aLocDrvCaps) +{ + __PRINT1(_L("CRawDisk::NewL() drv:%d"), aOwner.DriveNumber()); + + if(aLocDrvCaps.iMediaAtt & KMediaAttVariableSize) + {//-- this is the RAM drive "attribute" + ASSERT((aLocDrvCaps.iDriveAtt & (KDriveAttInternal|KDriveAttLocal)) && aLocDrvCaps.iType == EMediaRam); + if(!aLocDrvCaps.iBaseAddress) + { + ASSERT(0); + return NULL; + } + + return CRamDisk::NewL(aOwner); + } + + //-- create CAtaDisk by default + return CAtaDisk::NewL(aOwner); +} + + +CRawDisk::CRawDisk(CFatMountCB& aOwner) + { + iFatMount = &aOwner; + } + +/** + Default implementation. Initialises and re-initialises the object. +*/ +void CRawDisk::InitializeL() + { + ASSERT(iFatMount); + } + + +TInt CRawDisk::GetLastErrorInfo(TDes8& /*aErrorInfo*/) const + { + return KErrNotSupported; + } + +//################################################################################################################################ +//## CAtaDisk class implementation +//################################################################################################################################ + +CAtaDisk::CAtaDisk(CFatMountCB& aFatMount) + :CRawDisk(aFatMount), iDrive(aFatMount.DriveInterface()) + { + } + +CAtaDisk::~CAtaDisk() + { + delete ipDirCache; + delete iUidCache; + + } + + +//------------------------------------------------------------------------------------- + +/** + CAtaDisk factory method. + + @param aFatMount reference to the owner. + @return pointer to the constructed object. +*/ +CAtaDisk* CAtaDisk::NewL(CFatMountCB& aFatMount) + { + __PRINT1(_L("CAtaDisk::NewL() drv:%d"), aFatMount.DriveNumber()); + + CAtaDisk* pSelf = new (ELeave) CAtaDisk(aFatMount); + + CleanupStack::PushL(pSelf); + + pSelf->ConstructL(); + pSelf->InitializeL(); + + CleanupStack::Pop(); + + return pSelf; + } + +//------------------------------------------------------------------------------------- + +/** 2nd stage constructor */ +void CAtaDisk::ConstructL() + { + //=========================== create data WT cache that is primarily used for caching exacutable modules' UIDs + const TUint32 KUidCachePageSzLog2 = 9; //-- 512 bytes in page + const TUint32 KUidCachePages = 64; //-- 64 pages; total cache size is 32K + + iUidCache = CMediaWTCache::NewL(iDrive, KUidCachePages, KUidCachePageSzLog2); + + + //=========================== create directory cache + + //-- Get dir. cache parameters from config. They may be set in estart.txt for a specified drive. + const TUint32 KDirCacheSize = iFatMount->FatConfig().DirCacheSize(); //- Total directory cache size, bytes. + const TUint32 KMaxDirCachePageSzLog2 = iFatMount->FatConfig().DirCacheMaxPageSizeLog2(); //- Log2 of the Max. dir. cache page. + + __PRINT2(_L("CAtaDisk::ConstructL() Dir Cache config:%d,%d"),KDirCacheSize,KMaxDirCachePageSzLog2); + + ASSERT(KDirCacheSize >= K1KiloByte && KDirCacheSize <= K1MegaByte); + ASSERT((KMaxDirCachePageSzLog2 >= KDefSectorSzLog2) && (Pow2(KMaxDirCachePageSzLog2) <= KDirCacheSize)); + + //-- calculate the size and number of pages for the dir. cache. + //-- if the mount's cluster size is less than max. page size from config, the page size will be cluster size. + //-- otherwise it will be the value from config. I.e the minimal page size is cluster size; the maximal page size is taken from config. + //-- The number of pages depends on total cache size and page size. + const TUint clustSizeLog2 = iFatMount->ClusterSizeLog2(); //-- current FAT cluster size Log2 + const TUint32 pageSzLog2 = (clustSizeLog2 <= KMaxDirCachePageSzLog2) ? clustSizeLog2 : KMaxDirCachePageSzLog2; + const TUint32 numPages = KDirCacheSize / (Pow2(pageSzLog2)); + + ASSERT(!ipDirCache); + +#ifdef USE_DP_DIR_CACHE + + //=========================== create Demand Paging type of the directory cache + + // initialize cache memory manager as all file systems have mounted by now + if(CCacheMemoryManagerFactory::CacheMemoryManager()) + { + // Note: the configuration data of min and max cache size are aligned with the memory size it + // occupies in kernel as we are using demand paging subsystem for dynamic cache size support. + // Therefore, they are refered as 'Mem Size' in following calculation. + // However, 'Data Size' refers to the logical size of a page, i.e. the actual data size each page + // contains. + // The constraints we have to consider when setting up the dynamic cache: + // 1. each page's data size is aligned with cluster size, unless cluster size is bigger than + // the default maximum page size allowed (typically 32 KB). + // 2. if page's data size is smaller than segment size (typically 4 KB), i.e. the unit size of + // demand paging subsystem's page management, we will still use up the whole segment for + // that page. + // 3. the default min and max cache's memory size is pre-defined in fat_config.cpp file. + // (see KDef_DynamicDirCacheMin & KDef_DynamicDirCacheMax). + + // calculate page data size (logical view of page size) + const TUint32 DefMaxCachePageLog2 = iFatMount->FatConfig().DynamicDirCacheMaxPageSizeLog2(); + const TUint32 PageDataSizeLog2 = clustSizeLog2 < DefMaxCachePageLog2 ? clustSizeLog2 : DefMaxCachePageLog2; + + // calculate page number, based on memory size we have reserved + const TUint32 SegmentSizeLog2 = CCacheMemoryManagerFactory::CacheMemoryManager()->SegmentSizeInBytesLog2(); + const TUint32 PageMemSizeLog2 = PageDataSizeLog2 < SegmentSizeLog2 ? SegmentSizeLog2 : PageDataSizeLog2; + TUint32 CacheSizeMinInPages = iFatMount->FatConfig().DynamicDirCacheSizeMin() >> PageMemSizeLog2; + TUint32 CacheSizeMaxInPages = iFatMount->FatConfig().DynamicDirCacheSizeMax() >> PageMemSizeLog2; + + // cache memory client is connected via name + TBuf<0x20> clientName = _L("CACHE_MEM_CLIENT:"); + clientName.Append('A'+iFatMount->DriveNumber()); + + TRAPD(err, ipDirCache = CDynamicDirCache::NewL(iDrive, CacheSizeMinInPages, CacheSizeMaxInPages, PageDataSizeLog2, clientName)); + if (err == KErrNone) + { + __PRINT4(_L("CDynamicDirCache::NewL(drv:%C, minPageNum:%u, maxPageNum:%u, pageDataSize:%u)\n"), 'A'+iFatMount->DriveNumber(), CacheSizeMinInPages, CacheSizeMaxInPages, 1<DriveNumber(), numPages, 1<InvalidateCache(); + + TInt64 cacheBasePos; + + if(iFatMount->FatType() == EFat32) + { + //-- this is FAT32, all directories including Root are files and aligned to the cluster heap boundary + //-- set dir. cache base position to the cluster heap boundary + const TUint32 offsetMask = (1 << iFatMount->ClusterSizeLog2() )-1; + cacheBasePos = (iFatMount->ClusterBasePosition() & offsetMask); + } + else + { + //-- this is FAT12/16. Root directory is a separate volume object and has no alignment. + //-- set cache base position to its beginning. + cacheBasePos = iFatMount->StartOfRootDirInBytes(); + } + + ipDirCache->SetCacheBasePos(cacheBasePos); + +} + +//------------------------------------------------------------------------------------- + +/** + Read data from the media through LRU data cache cache. + + @param aPos absolute media position + @param aLength how many bytes to read + @param aDes data descriptor + + @leave on error +*/ +void CAtaDisk::ReadCachedL(TInt64 aPos,TInt aLength,TDes8& aDes) const + { + __PRINT3(_L("CAtaDisk::ReadL() pos:%u:%u, len:%u"), I64HIGH(aPos), I64LOW(aPos), aLength); + iUidCache->ReadL(aPos, aLength, aDes); + } + +//------------------------------------------------------------------------------------- + +/** + Write data to the media through LRU data cache + + @param aPos absolute media position + @param aDes data descriptor + + @leave on error +*/ +void CAtaDisk::WriteCachedL(TInt64 aPos, const TDesC8& aDes) + { + __PRINT3(_L("CAtaDisk::WriteL() pos:%u:%u, len:%u"), I64HIGH(aPos), I64LOW(aPos), aDes.Size()); + iUidCache->WriteL(aPos, aDes); + } + + +//------------------------------------------------------------------------------------- + +/** + Read data from the media directly without any caches. + Mostly used by file IO + + @param aPos absolute media position + @param aLength how many bytes to read + @param aTrg Pointer to the data descriptor, i.e. (const TAny*)(&TDes8) + @param aMessage Refrence to server message from request + @param anOffset Offset into read data to write + + @leave on error +*/ +void CAtaDisk::ReadL(TInt64 aPos,TInt aLength,const TAny* aTrg,const RMessagePtr2 &aMessage,TInt anOffset) const + { + + __PRINT4(_L("CAtaDisk::ReadL() pos:%u:%u, len:%u, offset:%u"), I64HIGH(aPos), I64LOW(aPos), aLength, anOffset); + User::LeaveIfError(iDrive.ReadNonCritical(aPos,aLength,aTrg,aMessage,anOffset)); + } + +//------------------------------------------------------------------------------------- + +/** + Write data to the media directly without any cached. + Mostly used by file IO + + This method shall invalidate some data caches to keep them in synch with the media. + + @param aPos Media position in bytes + @param aLength Length in bytes of write + @param aTrg Pointer to the data descriptor, i.e. (const TAny*)(&TDes8) + @param aMessage Refrence to server message from request, contains data + @param anOffset Offset into write data to use in write + + @leave on error +*/ +void CAtaDisk::WriteL(TInt64 aPos,TInt aLength,const TAny* aSrc,const RMessagePtr2 &aMessage,TInt anOffset) + { + __PRINT4(_L("CAtaDisk::WriteL() pos:%u:%u, len:%u, offset:%u"), I64HIGH(aPos), I64LOW(aPos), aLength, anOffset); + + //-- write data to the media directly + User::LeaveIfError(iDrive.WriteNonCritical(aPos,aLength,aSrc,aMessage,anOffset)); + + //-- we need to invalidate UID cache page that corresponds to aPos (if any). This is UID caching specific. UID is stored in the first few bytes of + //-- the executable module and therefore belongs to one cache page only. + //-- If someone writes to the beginning of the exe module file, corresponding UID cache page will be invalidated and re-read from the media later + iUidCache->InvalidateCachePage(aPos); + + //-- invalidate affected(if any) part of the FAT cache in the case if someone used to write data to FAT area, which usually do not happen + iFatMount->FAT().InvalidateCacheL(aPos,aLength); + + } + +//------------------------------------------------------------------------------------- + +/** Get information for last disk error */ +TInt CAtaDisk::GetLastErrorInfo(TDes8& aErrorInfo) const + { + return iDrive.GetLastErrorInfo(aErrorInfo); + } + + +//------------------------------------------------------------------------------------- +/** Invalidate whole UID cache */ +void CAtaDisk::InvalidateUidCache() +{ + ASSERT(iUidCache); + iUidCache->InvalidateCache(); +} + +/** + Invalidate the UID cache page that has aPos cached. + This method doesn't pay attention to the length of the block being invalidated because + UID lives in the very beginning of the exe module and always fits into a single page +*/ +void CAtaDisk::InvalidateUidCachePage(TUint64 aPos) +{ + ASSERT(iUidCache); + iUidCache->InvalidateCachePage(aPos); +} + + +//################################################################################################################################ +//## CRamDisk class implementation +//################################################################################################################################ + + +/** + CRamDisk factory method. + + @param aFatMount reference to the owner. + @return pointer to the constructed object. +*/ +CRamDisk* CRamDisk::NewL(CFatMountCB& aFatMount) + { + __PRINT1(_L("CRamDisk::NewL() drv:%d"), aFatMount.DriveNumber()); + CRamDisk* pSelf = new(ELeave)CRamDisk(aFatMount); + + CleanupStack::PushL(pSelf); + + pSelf->InitializeL(); + + CleanupStack::Pop(); + + return pSelf; + } + +CRamDisk::CRamDisk(CFatMountCB& aFatMount) + :CRawDisk(aFatMount) + { + } + +//------------------------------------------------------------------------------------- + +/** + Initialises and re-initialises the object. +*/ +void CRamDisk::InitializeL() +{ + CRawDisk::InitializeL(); + + //-- set the RAM disk base + TLocalDriveCapsV2 caps; + TPckg capsPckg(caps); + User::LeaveIfError(iFatMount->LocalDrive()->Caps(capsPckg)); + + ASSERT(caps.iMediaAtt & KMediaAttVariableSize); + + //-- set RAM disk base + iRamDiskBase = caps.iBaseAddress; + ASSERT(iRamDiskBase); +} + + + +/** @return the start address of the Ram Drive in low memory */ +TUint8* CRamDisk::RamDiskBase() const + { + return iRamDiskBase; + } + +//------------------------------------------------------------------------------------- +// +// Read aLength of data from the disk +// +void CRamDisk::ReadCachedL(TInt64 aPos,TInt aLength,TDes8& aDes) const + { + + __PRINT3(_L("CRamDisk::ReadL Base 0x%x Pos 0x%x, Len %d"),RamDiskBase(),I64LOW(aPos),aLength); + __ASSERT_ALWAYS((aPos+aLength<=I64INT(iFatMount->Size())) && (aLength>=0),User::Leave(KErrCorrupt)); + Mem::Copy((TUint8*)aDes.Ptr(),RamDiskBase()+I64LOW(aPos),aLength); + aDes.SetLength(aLength); + } + +//------------------------------------------------------------------------------------- +// +// Write aLength of data to the disk +// +void CRamDisk::WriteCachedL(TInt64 aPos,const TDesC8& aDes) + { + + __PRINT3(_L("CRamDisk::WriteL Base 0x%x Pos 0x%x, Len %d"),RamDiskBase(),aPos,aDes.Length()); + __ASSERT_ALWAYS(aPos+aDes.Length()<=I64INT(iFatMount->Size()),User::Leave(KErrCorrupt)); + Mem::Copy(RamDiskBase()+I64LOW(aPos),(TUint8*)aDes.Ptr(),aDes.Length()); + } + + +//------------------------------------------------------------------------------------- +// +// Read from ramDrive into thread relative descriptor +// +void CRamDisk::ReadL(TInt64 aPos,TInt aLength,const TAny* /*aTrg*/,const RMessagePtr2 &aMessage,TInt anOffset) const + { + __PRINT2(_L("CRamDisk::ReadL TAny* Pos 0x%x, Len %d"),aPos,aLength); + __ASSERT_ALWAYS((aPos+aLength<=I64INT(iFatMount->Size())) && (aLength>=0),User::Leave(KErrCorrupt)); + TUint8* pos=RamDiskBase()+I64LOW(aPos); + TPtrC8 buf(pos,aLength); + aMessage.WriteL(0,buf,anOffset); + } + +//------------------------------------------------------------------------------------- +// +// Write from thread relative descriptor into ramDrive +// +void CRamDisk::WriteL(TInt64 aPos,TInt aLength,const TAny* /*aSrc*/,const RMessagePtr2 &aMessage,TInt anOffset) + { + __PRINT2(_L("CRamDisk::WriteL TAny* Pos 0x%x, Len %d"),aPos,aLength); + __ASSERT_ALWAYS(aPos+aLength<=I64INT(iFatMount->Size()),User::Leave(KErrCorrupt)); + TUint8* pos=RamDiskBase()+I64LOW(aPos); + TPtr8 buf(pos,aLength); + aMessage.ReadL(0,buf,anOffset); + } + + + + + + + + + + + + + + + + + + + + + + + + + + +