?? volume.c
字號(hào):
pbgbs = (PVOID)LocalReAlloc((HLOCAL)pbgbs,
pdsk->d_diActive.di_bytes_per_sect,
LMEM_MOVEABLE);
if (pbgbs) {
DEBUGALLOC(pdsk->d_diActive.di_bytes_per_sect - cbSecOrig);
*ppbgbs = pbgbs; // update the caller's buffer address, too
}
else {
dwError = GetLastError();
DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: out of memory, volume deemed invalid (%d)\n"), dwError));
pvol->v_flags |= VOLF_INVALID;
goto exit;
}
}
}
else {
// If SetDiskInfo returned an error, then revert to the
// size originally reported, but continue trying to mount.
pdsk->d_diActive.di_bytes_per_sect = cbSecOrig;
DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: SetDiskInfo call to driver failed (%d)\n"), GetLastError()));
}
}
// Perform some trial reads now (first sector of first FAT, first
// sector of second FAT if one exists, and anything else we think of).
// We will clear VOLF_INVALID only on success. NOTE that we can now reuse
// the sector containing the BPB; we've extracted everything we needed
// from it.
#ifdef FAT32
if (pvol->v_flags & VOLF_32BIT_FAT) {
PBIGFATBOOTFSINFO pFSInfo;
dwError = ReadWriteDisk(pvol,
pdsk->d_hdsk,
DISK_IOCTL_READ,
&pdsk->d_diActive,
pvol->v_secVolBias + 1,
1,
pbgbs);
if (dwError != ERROR_SUCCESS
||
*(PDWORD)((PBYTE)pbgbs + 0) != SECONDBOOTSECSIG
||
*(PDWORD)((PBYTE)pbgbs + OFFSETTRLSIG) != BOOTSECTRAILSIG)
{
DEBUGMSGBREAK(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: error verifying extended boot sector, volume deemed invalid (%d)\n"), dwError));
pvol->v_flags |= VOLF_INVALID;
goto exit;
}
// If secFSInfo happens to be 1 (which is typical), then there's no need
// to perform another read, since it's the same sector we just read (above).
if (pvol->v_secFSInfo != 1) {
dwError = ReadWriteDisk(pvol,
pdsk->d_hdsk,
DISK_IOCTL_READ,
&pdsk->d_diActive,
pvol->v_secVolBias + pvol->v_secFSInfo,
1,
pbgbs);
}
if (dwError != ERROR_SUCCESS
||
*(PDWORD)((PBYTE)pbgbs + 0) != SECONDBOOTSECSIG
||
*(PDWORD)((PBYTE)pbgbs + OFFSETTRLSIG) != BOOTSECTRAILSIG
||
(pFSInfo = (PBIGFATBOOTFSINFO)((PBYTE)pbgbs + OFFSETFSINFOFRMSECSTRT))->bfFSInf_Sig != FSINFOSIG)
{
DEBUGMSGBREAK(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: error verifying FS info sector, volume deemed invalid (%d)\n"), dwError));
pvol->v_flags |= VOLF_INVALID;
goto exit;
}
// If we're still here, then assume that we can use the BIGFATBOOTFSINFO fields,
// if they look valid....
if (pFSInfo->bfFSInf_free_clus_cnt < pvol->v_clusMax &&
pFSInfo->bfFSInf_next_free_clus <= pvol->v_clusMax) {
pvol->v_cclusFree = pFSInfo->bfFSInf_free_clus_cnt;
pvol->v_clusAlloc = pFSInfo->bfFSInf_next_free_clus;
}
else {
// Note that if the FSInfo fields are simply UNKNOWN_CLUSTER, then my assumption
// is that they simply haven't been initialized yet (as opposed to being truly bogus).
DEBUGMSG((ZONE_INIT || ZONE_ERRORS) &&
pFSInfo->bfFSInf_free_clus_cnt != UNKNOWN_CLUSTER &&
pFSInfo->bfFSInf_next_free_clus != UNKNOWN_CLUSTER, (DBGTEXT("FATFS!TestVolume: FS info data suspicious (%x,%x), ignoring...\n"), pFSInfo->bfFSInf_free_clus_cnt, pFSInfo->bfFSInf_next_free_clus));
}
}
#endif // FAT32
dwError = ReadWriteDisk(pvol,
pdsk->d_hdsk,
DISK_IOCTL_READ,
&pdsk->d_diActive,
pvol->v_secBlkBias + 0,
1,
pbgbs);
if (dwError != ERROR_SUCCESS || !ValidateFATSector(pvol, pbgbs))
{
DEBUGMSGBREAK(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: error reading first FAT, volume deemed invalid (%d)\n"), dwError));
pvol->v_flags |= VOLF_INVALID;
goto exit;
}
if (pvol->v_flags & VOLF_BACKUP_FAT) {
dwError = ReadWriteDisk(pvol,
pdsk->d_hdsk,
DISK_IOCTL_READ,
&pdsk->d_diActive,
pvol->v_secBlkBias + pvol->v_csecFAT,
1,
pbgbs);
if (dwError != ERROR_SUCCESS || !ValidateFATSector(pvol, pbgbs))
{
DEBUGMSGBREAK(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: error reading backup FAT, volume deemed invalid (%d)\n"), dwError));
pvol->v_flags |= VOLF_INVALID;
goto exit;
}
}
// Verify we can read the last sector in the last cluster of the volume too...
#if 0
dwError = ReadWriteDisk(pvol,
pdsk->d_hdsk,
DISK_IOCTL_READ,
&pdsk->d_diActive,
CLUSTERTOSECTOR(pvol, pvol->v_clusMax) +
(1 << pvol->v_log2csecClus) - 1,
1,
pbgbs);
if (dwError != ERROR_SUCCESS)
{
DEBUGMSGBREAK(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: error reading last sector, volume deemed invalid (%d)\n"), dwError));
pvol->v_flags |= VOLF_INVALID;
goto exit;
}
#endif
// If we modified the drive parameters but the volume isn't valid anyway, restore the default parameters.
exit:
if ((pvol->v_flags & (VOLF_MODDISKINFO | VOLF_INVALID)) == (VOLF_MODDISKINFO | VOLF_INVALID)) {
pvol->v_flags &= ~VOLF_MODDISKINFO;
pdsk->d_diActive.di_bytes_per_sect = cbSecOrig;
SetDiskInfo(pdsk->d_hdsk, &pdsk->d_diActive);
}
return dwError;
}
/* RefreshVolume - Refresh a VOLUME's handles
*
* ENTRY
* pvol - pointer to VOLUME
*
* EXIT
* Stream handles are restored, provided the volume is valid AND
* the streams appear to be in the same state we left them.
*/
void RefreshVolume(PVOLUME pvol)
{
PDSTREAM pstm, pstmEnd;
if (!(pvol->v_flags & (VOLF_REMOUNTED | VOLF_RECYCLED)))
return;
ASSERT(OWNCRITICALSECTION(&pvol->v_cs));
// Walk the open stream list, regenerate each stream, then walk the
// open handle list for each successfully regenerated stream, and clear
// the unmounted bit for each open handle.
// First, make sure the VISITED bit is clear in every stream currently
// open on this volume.
EnterCriticalSection(&pvol->v_csStms);
pstm = pvol->v_dlOpenStreams.pstmNext;
pstmEnd = (PDSTREAM)&pvol->v_dlOpenStreams;
while (pstm != pstmEnd) {
pstm->s_flags &= ~STF_VISITED;
pstm = pstm->s_dlOpenStreams.pstmNext;
}
// Now find the next unvisited stream. Note that every iteration of the
// loop starts with the volume critical section held.
restart:
pstm = pvol->v_dlOpenStreams.pstmNext;
while (pstm != pstmEnd) {
if (pstm->s_flags & STF_VISITED) {
pstm = pstm->s_dlOpenStreams.pstmNext;
continue;
}
pstm->s_flags |= STF_VISITED;
// Add a ref to insure that the stream can't go away once we
// let go of the volume's critical section.
pstm->s_refs++;
LeaveCriticalSection(&pvol->v_csStms);
EnterCriticalSection(&pstm->s_cs);
// Find/read the block containing this stream's DIRENTRY, unless
// it's a VOLUME-based stream, in which case we'll just automatically
// remount it.
ASSERT(pstm->s_pvol == pvol);
// Volume handles are always remounted, regardless
if (pstm->s_flags & STF_VOLUME)
pstm->s_flags &= ~STF_UNMOUNTED;
if ((pstm->s_flags & STF_UNMOUNTED) && !(pvol->v_flags & VOLF_INVALID)) {
PBUF pbuf;
ASSERT(pstm->s_blkDir != INVALID_BLOCK);
if (FindBuffer(pvol, pstm->s_blkDir, NULL, FALSE, &pbuf) == ERROR_SUCCESS) {
PDIRENTRY pde;
pde = (PDIRENTRY)(pbuf->b_pdata + pstm->s_offDir);
// Check the 8.3 name first...
if (memcmp(pde->de_name, pstm->s_achOEM, sizeof(pde->de_name)) == 0) {
DWORD clusEntry = GETDIRENTRYCLUSTER(pstm->s_pvol, pde);
if (clusEntry == NO_CLUSTER)
clusEntry = UNKNOWN_CLUSTER;
if ((pstm->s_flags & STF_DIRTY) ||
pde->de_attr == pstm->s_attr &&
pde->de_size == pstm->s_size && clusEntry == pstm->s_clusFirst)
{
pstm->s_flags &= ~STF_UNMOUNTED;
}
}
UnholdBuffer(pbuf);
}
}
// If the stream is now (re)mounted, make sure all its handles are (re)mounted also.
if (!(pstm->s_flags & STF_UNMOUNTED)) {
PFHANDLE pfh, pfhEnd;
pfh = pstm->s_dlOpenHandles.pfhNext;
pfhEnd = (PFHANDLE)&pstm->s_dlOpenHandles;
while (pfh != pfhEnd) {
pfh->fh_flags &= ~FHF_UNMOUNTED;
pfh = pfh->fh_dlOpenHandles.pfhNext;
}
}
CloseStream(pstm);
EnterCriticalSection(&pvol->v_csStms);
goto restart;
}
LeaveCriticalSection(&pvol->v_csStms);
// Make sure the buffer pool is clean too, now that we've finished
// resurrecting and committing all resurrectable streams.
if (CommitVolumeBuffers(pvol) == ERROR_SUCCESS) {
DEBUGMSG(ZONE_INIT && (pvol->v_flags & VOLF_DIRTY),(DBGTEXT("FATFS!RefreshVolume: dirty data successfully committed\n")));
pvol->v_flags &= ~VOLF_DIRTY;
}
else
DEBUGMSG(ZONE_INIT,(DBGTEXT("FATFS!RefreshVolume: unable to commit dirty data to volume 0x%08x\n"), pvol));
}
DWORD LockVolume(PVOLUME pvol, DWORD dwFlags)
{
DWORD dwError = ERROR_SUCCESS;
// pvol->v_flags |= dwFlags;
// return dwError;
EnterCriticalSection(&pvol->v_cs);
// Since VOLF_LOCKED is the concatenation of all lock flags, LockVolume
// is disallowed if any lock of any kind is already in effect. This
// simplification should be fine for our purposes.
if (!(pvol->v_flags & VOLF_LOCKED)) {
pvol->v_flags |= dwFlags;
if (CheckStreamHandles(pvol, NULL)) {
pvol->v_flags &= ~dwFlags;
dwError = ERROR_ACCESS_DENIED;
}
}
else
dwError = ERROR_DRIVE_LOCKED;
LeaveCriticalSection(&pvol->v_cs);
// If successful, wait until all threads are done before returning.
// Easiest way to do this is simulate a quick power-off/power-on sequence.
// Since the volume's LOCKED bit is already set, we don't need to worry about
// any new calls doing anything until the volume is unlocked.
if (!dwError && cFATThreads > 1) {
FAT_Notify(pvol, FSNOTIFY_POWER_OFF);
FAT_Notify(pvol, FSNOTIFY_DEVICES_ON);
}
return dwError;
}
/* UnlockVolume - Unlock a previously locked VOLUME
*
* ENTRY
* pvol -> VOLUME structure
*
* EXIT
* None
*/
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -