os/kernelhwsrv/userlibandfileserver/fileserver/sfat32/sl_disk.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // f32\sfat\sl_disk.cpp
    15 // 
    16 //
    17 
    18 #include "sl_disk.h"
    19 #include "sl_cache.h"
    20 #include "sl_dir_cache.h"
    21 
    22 /**
    23 @file
    24 */
    25 
    26 
    27 //################################################################################################################################
    28 //#     CRawDisk implementation
    29 //################################################################################################################################
    30 
    31 
    32 /**
    33     Factory function. Constructs objects of the classes derived from CRawDisk.
    34     
    35     @param  aOwner      reference to the onwning FAT Mount class
    36     @param  aLocDrvCaps local drive capabilities from the media driver
    37     @return pointer to the constructed object. May be NULL on error.
    38 */
    39 CRawDisk* CRawDisk::NewL(CFatMountCB& aOwner, const TLocalDriveCaps& aLocDrvCaps)
    40 {
    41     __PRINT1(_L("CRawDisk::NewL() drv:%d"), aOwner.DriveNumber());
    42 
    43     if(aLocDrvCaps.iMediaAtt & KMediaAttVariableSize)
    44     {//-- this is the RAM drive "attribute"
    45         ASSERT((aLocDrvCaps.iDriveAtt & (KDriveAttInternal|KDriveAttLocal)) && aLocDrvCaps.iType == EMediaRam);
    46         if(!aLocDrvCaps.iBaseAddress)
    47         {
    48             ASSERT(0);
    49             return NULL;
    50         }
    51 
    52         return CRamDisk::NewL(aOwner);
    53     }
    54 
    55     //-- create CAtaDisk by default
    56     return CAtaDisk::NewL(aOwner);
    57 }
    58 
    59 
    60 CRawDisk::CRawDisk(CFatMountCB& aOwner)
    61     {
    62     iFatMount = &aOwner;
    63     }
    64 
    65 /**
    66     Default implementation. Initialises and re-initialises the object.
    67 */
    68 void CRawDisk::InitializeL()
    69     {
    70     ASSERT(iFatMount);
    71     }
    72 
    73 
    74 TInt CRawDisk::GetLastErrorInfo(TDes8& /*aErrorInfo*/) const
    75 	{
    76 	return KErrNotSupported;
    77 	}
    78 
    79 //################################################################################################################################
    80 //##    CAtaDisk class implementation
    81 //################################################################################################################################
    82 
    83 CAtaDisk::CAtaDisk(CFatMountCB& aFatMount)
    84          :CRawDisk(aFatMount), iDrive(aFatMount.DriveInterface())
    85 	{
    86 	}
    87 
    88 CAtaDisk::~CAtaDisk()
    89     {
    90     delete ipDirCache;
    91     delete iUidCache;
    92     
    93     }
    94 
    95 
    96 //-------------------------------------------------------------------------------------
    97 
    98 /**
    99     CAtaDisk factory method.
   100     
   101     @param  aFatMount reference to the owner.
   102     @return pointer to the constructed object.
   103 */
   104 CAtaDisk* CAtaDisk::NewL(CFatMountCB& aFatMount)
   105 	{
   106 	__PRINT1(_L("CAtaDisk::NewL() drv:%d"), aFatMount.DriveNumber());
   107 
   108     CAtaDisk* pSelf = new (ELeave) CAtaDisk(aFatMount);
   109     
   110     CleanupStack::PushL(pSelf);
   111     
   112     pSelf->ConstructL();
   113     pSelf->InitializeL();
   114     
   115     CleanupStack::Pop();
   116 
   117 	return pSelf;
   118 	}
   119 
   120 //-------------------------------------------------------------------------------------
   121 
   122 /** 2nd stage constructor */
   123 void CAtaDisk::ConstructL()
   124     {
   125     //===========================  create data WT cache that is primarily used for caching exacutable modules' UIDs
   126     const TUint32 KUidCachePageSzLog2 = 9; //-- 512 bytes in page 
   127     const TUint32 KUidCachePages = 64;     //-- 64 pages; total cache size is 32K 
   128 
   129     iUidCache = CMediaWTCache::NewL(iDrive, KUidCachePages, KUidCachePageSzLog2);
   130 
   131 
   132     //=========================== create directory cache
   133     
   134     //-- Get dir. cache parameters from config. They may be set in estart.txt for a specified drive.
   135     const TUint32 KDirCacheSize = iFatMount->FatConfig().DirCacheSize(); //- Total directory cache size, bytes.
   136     const TUint32 KMaxDirCachePageSzLog2 = iFatMount->FatConfig().DirCacheMaxPageSizeLog2(); //- Log2 of the Max. dir. cache page.
   137 
   138     __PRINT2(_L("CAtaDisk::ConstructL() Dir Cache config:%d,%d"),KDirCacheSize,KMaxDirCachePageSzLog2);
   139 
   140     ASSERT(KDirCacheSize >= K1KiloByte && KDirCacheSize <= K1MegaByte);
   141     ASSERT((KMaxDirCachePageSzLog2 >= KDefSectorSzLog2) && (Pow2(KMaxDirCachePageSzLog2) <= KDirCacheSize));
   142 
   143     //-- calculate the size and number of pages for the dir. cache. 
   144     //-- if the mount's cluster size is less than max. page size from config, the page size will be cluster size.
   145     //-- 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.
   146     //-- The number of pages depends on total cache size and page size.
   147     const TUint clustSizeLog2 = iFatMount->ClusterSizeLog2(); //-- current FAT cluster size Log2
   148     const TUint32 pageSzLog2 = (clustSizeLog2 <= KMaxDirCachePageSzLog2) ? clustSizeLog2 : KMaxDirCachePageSzLog2;
   149     const TUint32 numPages = KDirCacheSize / (Pow2(pageSzLog2));
   150 
   151     ASSERT(!ipDirCache);
   152 
   153 #ifdef USE_DP_DIR_CACHE
   154 
   155     //=========================== create Demand Paging type of the directory cache
   156 
   157     // initialize cache memory manager as all file systems have mounted by now
   158 	if(CCacheMemoryManagerFactory::CacheMemoryManager())
   159 		{
   160 		// Note: the configuration data of min and max cache size are aligned with the memory size it
   161 		//	occupies in kernel as we are using demand paging subsystem for dynamic cache size support. 
   162 		//  Therefore, they are refered as 'Mem Size' in following calculation.
   163 		//  However, 'Data Size' refers to the logical size of a page, i.e. the actual data size each page
   164 		//  contains.
   165 		// The constraints we have to consider when setting up the dynamic cache:
   166 		// 	1. each page's data size is aligned with cluster size, unless cluster size is bigger than
   167 		//  	the default maximum page size allowed (typically 32 KB).
   168 		// 	2. if page's data size is smaller than segment size (typically 4 KB), i.e. the unit size of 
   169 		//     	demand paging subsystem's page management, we will still use up the whole segment for
   170 		// 		that page.
   171 		//  3. the default min and max cache's memory size is pre-defined in  fat_config.cpp file.
   172 		// 		(see KDef_DynamicDirCacheMin & KDef_DynamicDirCacheMax).
   173 
   174 		// calculate page data size (logical view of page size)
   175 	    const TUint32 DefMaxCachePageLog2 = iFatMount->FatConfig().DynamicDirCacheMaxPageSizeLog2();
   176 	    const TUint32 PageDataSizeLog2 = clustSizeLog2 < DefMaxCachePageLog2 ? clustSizeLog2 : DefMaxCachePageLog2;
   177 	    
   178 		// calculate page number, based on memory size we have reserved
   179 	    const TUint32 SegmentSizeLog2 = CCacheMemoryManagerFactory::CacheMemoryManager()->SegmentSizeInBytesLog2();
   180 	    const TUint32 PageMemSizeLog2 = PageDataSizeLog2 < SegmentSizeLog2 ? SegmentSizeLog2 : PageDataSizeLog2;
   181 	    TUint32 CacheSizeMinInPages = iFatMount->FatConfig().DynamicDirCacheSizeMin() >> PageMemSizeLog2;
   182 	    TUint32 CacheSizeMaxInPages = iFatMount->FatConfig().DynamicDirCacheSizeMax() >> PageMemSizeLog2;
   183 
   184 	    // cache memory client is connected via name 
   185 	    TBuf<0x20> clientName = _L("CACHE_MEM_CLIENT:");
   186 		clientName.Append('A'+iFatMount->DriveNumber());
   187 
   188 		TRAPD(err, ipDirCache = CDynamicDirCache::NewL(iDrive, CacheSizeMinInPages, CacheSizeMaxInPages, PageDataSizeLog2, clientName));
   189 		if (err == KErrNone)
   190 	    	return;
   191 		
   192         //-- fall back to constructing old type of cache
   193 
   194         }
   195 #endif // USE_DP_DIR_CACHE
   196 
   197     //=========================== create legacy type of the directory cache
   198     ASSERT(!ipDirCache);
   199 
   200     ipDirCache = CMediaWTCache::NewL(iDrive, numPages, pageSzLog2);
   201     __PRINT3(_L("CDirCache::NewL(drive: %C, NumPages=%d, PageSize=%u)"), 'A'+iFatMount->DriveNumber(), numPages, 1<<pageSzLog2);
   202     
   203     }
   204 
   205 //-------------------------------------------------------------------------------------
   206 
   207 /**
   208     Initialises and re-initialises the object.
   209 */
   210 void CAtaDisk::InitializeL()
   211 {
   212     CRawDisk::InitializeL();
   213     
   214     //-- there is a little issue here. after formatting FAT mounts's cluster size can change.
   215     //-- dir. cache page size depends on the cluster size. This method doesn't change the dir. cache page size.
   216     //-- At present it is done in CFatMountCB::InitializeL() that deletes this object and then reconstructs it again.
   217 
   218     //-- invalidate directory cache here
   219     ipDirCache->InvalidateCache();
   220     
   221     TInt64  cacheBasePos;
   222     
   223     if(iFatMount->FatType() == EFat32)
   224         {
   225         //-- this is FAT32, all directories including Root are files and aligned to the cluster heap boundary
   226         //-- set dir. cache base position to the cluster heap boundary
   227         const TUint32 offsetMask = (1 << iFatMount->ClusterSizeLog2() )-1;
   228         cacheBasePos = (iFatMount->ClusterBasePosition() & offsetMask);
   229         }
   230     else
   231         {
   232         //-- this is FAT12/16. Root directory is a separate volume object and has no alignment.
   233         //-- set cache base position to its beginning.
   234         cacheBasePos = iFatMount->StartOfRootDirInBytes();
   235         }
   236 
   237     ipDirCache->SetCacheBasePos(cacheBasePos);
   238     
   239 }
   240 
   241 //-------------------------------------------------------------------------------------
   242 
   243 /**
   244     Read data from the media through LRU data cache cache. 
   245 
   246     @param  aPos        absolute media position
   247     @param  aLength     how many bytes to read
   248     @param  aDes        data descriptor
   249 
   250     @leave on error
   251 */
   252 void CAtaDisk::ReadCachedL(TInt64 aPos,TInt aLength,TDes8& aDes) const
   253 	{
   254     __PRINT3(_L("CAtaDisk::ReadL() pos:%u:%u, len:%u"), I64HIGH(aPos), I64LOW(aPos), aLength);
   255     iUidCache->ReadL(aPos, aLength, aDes);
   256 	}
   257 
   258 //-------------------------------------------------------------------------------------
   259 
   260 /**
   261     Write data to the media through LRU data cache
   262 
   263     @param  aPos        absolute media position
   264     @param  aDes        data descriptor
   265 
   266     @leave on error
   267 */
   268 void CAtaDisk::WriteCachedL(TInt64 aPos, const TDesC8& aDes)
   269 	{
   270     __PRINT3(_L("CAtaDisk::WriteL() pos:%u:%u, len:%u"), I64HIGH(aPos), I64LOW(aPos), aDes.Size());
   271     iUidCache->WriteL(aPos, aDes);
   272 	}
   273 
   274 
   275 //-------------------------------------------------------------------------------------
   276 
   277 /**
   278     Read data from the media directly without any caches.
   279     Mostly used by file IO
   280 
   281     @param  aPos        absolute media position
   282     @param  aLength     how many bytes to read
   283 	@param  aTrg		Pointer to the data descriptor, i.e. (const TAny*)(&TDes8)
   284 	@param  aMessage	Refrence to server message from request
   285 	@param  anOffset	Offset into read data to write
   286 
   287     @leave on error
   288 */
   289 void CAtaDisk::ReadL(TInt64 aPos,TInt aLength,const TAny* aTrg,const RMessagePtr2 &aMessage,TInt anOffset) const
   290 	{
   291 
   292 	__PRINT4(_L("CAtaDisk::ReadL() pos:%u:%u, len:%u, offset:%u"), I64HIGH(aPos), I64LOW(aPos), aLength, anOffset);
   293 	User::LeaveIfError(iDrive.ReadNonCritical(aPos,aLength,aTrg,aMessage,anOffset));
   294 	}
   295 
   296 //-------------------------------------------------------------------------------------
   297 
   298 /**
   299     Write data to the media directly without any cached.
   300     Mostly used by file IO
   301 
   302     This method shall invalidate some data caches to keep them in synch with the media.
   303 
   304     @param aPos		Media position in bytes
   305     @param aLength	Length in bytes of write
   306 	@param aTrg		Pointer to the data descriptor, i.e. (const TAny*)(&TDes8)
   307 	@param aMessage	Refrence to server message from request, contains data
   308 	@param anOffset	Offset into write data to use in write
   309 
   310     @leave on error
   311 */
   312 void CAtaDisk::WriteL(TInt64 aPos,TInt aLength,const TAny* aSrc,const RMessagePtr2 &aMessage,TInt anOffset)
   313 	{
   314     __PRINT4(_L("CAtaDisk::WriteL() pos:%u:%u, len:%u, offset:%u"), I64HIGH(aPos), I64LOW(aPos), aLength, anOffset);
   315 
   316 	//-- write data to the media directly
   317     User::LeaveIfError(iDrive.WriteNonCritical(aPos,aLength,aSrc,aMessage,anOffset));
   318 
   319     //-- 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 
   320     //-- the executable module and therefore belongs to one cache page only.
   321     //-- 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
   322     iUidCache->InvalidateCachePage(aPos); 
   323 
   324     //-- 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 
   325     iFatMount->FAT().InvalidateCacheL(aPos,aLength);
   326 
   327 	}
   328 
   329 //-------------------------------------------------------------------------------------
   330 
   331 /** Get information for last disk error */
   332 TInt CAtaDisk::GetLastErrorInfo(TDes8& aErrorInfo) const
   333 	{
   334 	return iDrive.GetLastErrorInfo(aErrorInfo);
   335 	}
   336 
   337 
   338 //-------------------------------------------------------------------------------------
   339 /** Invalidate whole UID cache */
   340 void CAtaDisk::InvalidateUidCache()
   341 {
   342     ASSERT(iUidCache);
   343     iUidCache->InvalidateCache();
   344 }
   345 
   346 /** 
   347     Invalidate the UID cache page that has aPos cached.
   348     This method doesn't pay attention to the length of the block being invalidated because
   349     UID lives in the very beginning of the exe module and always fits into a single page
   350 */
   351 void CAtaDisk::InvalidateUidCachePage(TUint64 aPos)
   352 {
   353     ASSERT(iUidCache);
   354     iUidCache->InvalidateCachePage(aPos);
   355 }
   356 
   357 
   358 //################################################################################################################################
   359 //##    CRamDisk class implementation
   360 //################################################################################################################################
   361 
   362 
   363 /**
   364     CRamDisk factory method.
   365     
   366     @param  aFatMount reference to the owner.
   367     @return pointer to the constructed object.
   368 */
   369 CRamDisk* CRamDisk::NewL(CFatMountCB& aFatMount)
   370 	{
   371     __PRINT1(_L("CRamDisk::NewL() drv:%d"), aFatMount.DriveNumber());
   372 	CRamDisk* pSelf = new(ELeave)CRamDisk(aFatMount);
   373 
   374     CleanupStack::PushL(pSelf);
   375   
   376     pSelf->InitializeL();
   377     
   378     CleanupStack::Pop();
   379 
   380 	return pSelf;
   381 	}
   382 
   383 CRamDisk::CRamDisk(CFatMountCB& aFatMount)
   384 	     :CRawDisk(aFatMount)
   385     {
   386 	}
   387 
   388 //-------------------------------------------------------------------------------------
   389 
   390 /**
   391     Initialises and re-initialises the object.
   392 */
   393 void CRamDisk::InitializeL()
   394 {
   395     CRawDisk::InitializeL();
   396 
   397     //-- set the RAM disk base
   398     TLocalDriveCapsV2 caps;
   399     TPckg<TLocalDriveCapsV2> capsPckg(caps);
   400     User::LeaveIfError(iFatMount->LocalDrive()->Caps(capsPckg));
   401   
   402     ASSERT(caps.iMediaAtt & KMediaAttVariableSize);
   403     
   404     //-- set RAM disk base
   405     iRamDiskBase = caps.iBaseAddress; 
   406     ASSERT(iRamDiskBase);
   407 }
   408 
   409 
   410 
   411 /** @return the start address of the Ram Drive in low memory */
   412 TUint8* CRamDisk::RamDiskBase() const
   413 	{
   414 	return iRamDiskBase;
   415 	}
   416 
   417 //-------------------------------------------------------------------------------------
   418 //
   419 // Read aLength of data from the disk
   420 //
   421 void CRamDisk::ReadCachedL(TInt64 aPos,TInt aLength,TDes8& aDes) const
   422 	{
   423 	
   424 	__PRINT3(_L("CRamDisk::ReadL Base 0x%x Pos 0x%x, Len %d"),RamDiskBase(),I64LOW(aPos),aLength);
   425 	__ASSERT_ALWAYS((aPos+aLength<=I64INT(iFatMount->Size())) && (aLength>=0),User::Leave(KErrCorrupt));
   426 	Mem::Copy((TUint8*)aDes.Ptr(),RamDiskBase()+I64LOW(aPos),aLength);
   427 	aDes.SetLength(aLength);
   428 	}
   429 
   430 //-------------------------------------------------------------------------------------
   431 //
   432 // Write aLength of data to the disk
   433 //
   434 void CRamDisk::WriteCachedL(TInt64 aPos,const TDesC8& aDes)
   435 	{
   436 
   437 	__PRINT3(_L("CRamDisk::WriteL Base 0x%x Pos 0x%x, Len %d"),RamDiskBase(),aPos,aDes.Length());
   438 	__ASSERT_ALWAYS(aPos+aDes.Length()<=I64INT(iFatMount->Size()),User::Leave(KErrCorrupt));
   439 	Mem::Copy(RamDiskBase()+I64LOW(aPos),(TUint8*)aDes.Ptr(),aDes.Length());
   440 	}
   441 	
   442 
   443 //-------------------------------------------------------------------------------------
   444 //
   445 // Read from ramDrive into thread relative descriptor
   446 //
   447 void CRamDisk::ReadL(TInt64 aPos,TInt aLength,const TAny* /*aTrg*/,const RMessagePtr2 &aMessage,TInt anOffset) const
   448 	{
   449 	__PRINT2(_L("CRamDisk::ReadL TAny* Pos 0x%x, Len %d"),aPos,aLength);
   450 	__ASSERT_ALWAYS((aPos+aLength<=I64INT(iFatMount->Size())) && (aLength>=0),User::Leave(KErrCorrupt));
   451 	TUint8* pos=RamDiskBase()+I64LOW(aPos);
   452 	TPtrC8 buf(pos,aLength);
   453 	aMessage.WriteL(0,buf,anOffset);
   454 	}
   455 
   456 //-------------------------------------------------------------------------------------
   457 //
   458 // Write from thread relative descriptor into ramDrive
   459 //
   460 void CRamDisk::WriteL(TInt64 aPos,TInt aLength,const TAny* /*aSrc*/,const RMessagePtr2 &aMessage,TInt anOffset)
   461 	{
   462 	__PRINT2(_L("CRamDisk::WriteL TAny* Pos 0x%x, Len %d"),aPos,aLength);
   463 	__ASSERT_ALWAYS(aPos+aLength<=I64INT(iFatMount->Size()),User::Leave(KErrCorrupt));
   464 	TUint8* pos=RamDiskBase()+I64LOW(aPos);
   465 	TPtr8 buf(pos,aLength);
   466 	aMessage.ReadL(0,buf,anOffset);
   467 	}
   468 
   469 
   470 
   471 
   472 
   473 
   474 
   475 
   476 
   477 
   478 
   479 
   480 
   481 
   482 
   483 
   484 
   485 
   486 
   487 
   488 
   489 
   490 
   491 
   492 
   493 
   494