Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1121 lines
30 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992.
  5. //
  6. // File: difat.cxx
  7. //
  8. // Contents: Double Indirected Fat Code
  9. //
  10. // Classes: None.
  11. //
  12. // Functions:
  13. //
  14. // History: 11-May-92 PhilipLa Created.
  15. //
  16. //--------------------------------------------------------------------------
  17. #include <msfhead.cxx>
  18. #pragma hdrstop
  19. #include <difat.hxx>
  20. #include <mread.hxx>
  21. #ifdef DIFAT_OPTIMIZATIONS
  22. #define OPTIMIZE_LOOKUP
  23. #define OPTIMIZE_FIXUP
  24. #endif
  25. //+-------------------------------------------------------------------------
  26. //
  27. // Method: CDIFat::CDIFat, public
  28. //
  29. // Synopsis: CDIFat copy constructor
  30. //
  31. // Arguments: [fatOld] -- reference to CDIFat to be copied.
  32. //
  33. // History: 11-May-92 PhilipLa Created.
  34. //
  35. //--------------------------------------------------------------------------
  36. CDIFat::CDIFat(CDIFat *pfatOld)
  37. : _pmsParent(NULL),
  38. _fv(SIDDIF)
  39. {
  40. #ifdef DIFAT_LOOKUP_ARRAY
  41. _cUnmarked = 0;
  42. _fDoingFixup = FALSE;
  43. #endif
  44. }
  45. //+-------------------------------------------------------------------------
  46. //
  47. // Method: CDIFat::CDIFat, public
  48. //
  49. // Synopsis: CDIFat constructor
  50. //
  51. // Arguments: [pmsParent] -- Pointer to parent CMStream
  52. //
  53. // History: 11-May-92 PhilipLa Created.
  54. //
  55. //--------------------------------------------------------------------------
  56. CDIFat::CDIFat()
  57. : _pmsParent(NULL),
  58. _fv(SIDDIF)
  59. {
  60. msfDebugOut((DEB_ITRACE,"In CDIFat constructor\n"));
  61. _cfsTable = 0;
  62. #ifdef DIFAT_LOOKUP_ARRAY
  63. _cUnmarked = 0;
  64. _fDoingFixup = FALSE;
  65. #endif
  66. msfDebugOut((DEB_ITRACE,"Out CDIFat constructor\n"));
  67. }
  68. //+---------------------------------------------------------------------------
  69. //
  70. // Member: CDIFat::Empty, public
  71. //
  72. // Synopsis: Empty all the control structures of this instance
  73. //
  74. // Arguments: None.
  75. //
  76. // Returns: void.
  77. //
  78. // History: 04-Dec-92 PhilipLa Created
  79. //
  80. //----------------------------------------------------------------------------
  81. void CDIFat::Empty(void)
  82. {
  83. _fv.Empty();
  84. _pmsParent = NULL;
  85. _cfsTable = 0;
  86. }
  87. //+-------------------------------------------------------------------------
  88. //
  89. // Method: CIDFat::Flush, private
  90. //
  91. // Synopsis: Flush a sector to disk
  92. //
  93. // Arguments: [oSect] -- Indicated which sector to flush
  94. //
  95. // Returns: S_OK if call completed OK.
  96. //
  97. // Algorithm: Write sector up to parent mstream.
  98. //
  99. // History: 11-May-92 PhilipLa Created.
  100. //
  101. // Notes:
  102. //
  103. //--------------------------------------------------------------------------
  104. SCODE CDIFat::Flush(void)
  105. {
  106. return _fv.Flush();
  107. }
  108. //+-------------------------------------------------------------------------
  109. //
  110. // Method: CDIFat::GetFatSect, public
  111. //
  112. // Synopsis: Given an offset into the Fat chain, return the sector
  113. // value for that FatSect.
  114. //
  115. // Arguments: [oSect] -- offset in Fat chain
  116. //
  117. // Returns: Sector value of FatSect.
  118. //
  119. // Algorithm: If sector is stored in the header, retrieve it from
  120. // there.
  121. // If not, retrieve it from the FatVector.
  122. //
  123. // History: 11-May-92 PhilipLa Created.
  124. //
  125. //--------------------------------------------------------------------------
  126. SCODE CDIFat::GetFatSect(const FSINDEX oSect, SECT *psect)
  127. {
  128. SCODE sc = S_OK;
  129. SECT sectReturn;
  130. msfDebugOut((DEB_ITRACE,"In CDIFat::GetFatSect(%lu)\n",oSect));
  131. if (oSect < CSECTFAT)
  132. {
  133. msfDebugOut((DEB_ITRACE,"Getting sect from header\n"));
  134. sectReturn = _pmsParent->GetHeader()->GetFatSect(oSect);
  135. }
  136. else
  137. {
  138. FSINDEX ipfs;
  139. FSOFFSET isect;
  140. SectToPair(oSect,&ipfs,&isect);
  141. msfAssert(ipfs < _cfsTable);
  142. CFatSect *pfs;
  143. msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
  144. sectReturn = pfs->GetSect(isect);
  145. _fv.ReleaseTable(ipfs);
  146. }
  147. msfDebugOut((DEB_ITRACE,"Out CDIFat::GetFatSect(%lu)=>%lu\n",oSect,sectReturn));
  148. *psect = sectReturn;
  149. Err:
  150. return sc;
  151. }
  152. //+-------------------------------------------------------------------------
  153. //
  154. // Method: CDIFat::SetFatSect, public
  155. //
  156. // Synopsis: Given an offset into the Fat chain, set the sector
  157. // value.
  158. //
  159. // Arguments: [oSect] -- Offset into fat chain
  160. // [sect] -- New sector value for that offset.
  161. //
  162. // Returns: S_OK if call completed OK.
  163. //
  164. // Algorithm: If the sector is stored in the header, set it and
  165. // flush the header.
  166. // Otherwise, if the sector will not fit in the current
  167. // CFatVector, resize it.
  168. // Set the sector in the FatVector and flush it.
  169. //
  170. // History: 11-May-92 PhilipLa Created.
  171. //
  172. //--------------------------------------------------------------------------
  173. SCODE CDIFat::SetFatSect(const FSINDEX oSect, const SECT sect)
  174. {
  175. msfDebugOut((DEB_ITRACE,"In CDIFat::SetFatSect(%lu,%lu)\n",oSect,sect));
  176. SCODE sc = S_OK;
  177. if (oSect < CSECTFAT)
  178. {
  179. msfDebugOut((DEB_ITRACE,"Setting sect in header: %lu, %lu\n",oSect,sect));
  180. _pmsParent->GetHeader()->SetFatSect(oSect, sect);
  181. }
  182. else
  183. {
  184. FSINDEX ipfs;
  185. FSOFFSET isect;
  186. SectToPair(oSect,&ipfs,&isect);
  187. if (ipfs >= _cfsTable)
  188. {
  189. msfChk(Resize(_cfsTable + 1));
  190. }
  191. CFatSect *pfs;
  192. msfChk(_fv.GetTable(ipfs, FB_DIRTY, &pfs));
  193. pfs->SetSect(isect, sect);
  194. _fv.ReleaseTable(ipfs);
  195. msfDebugOut((DEB_ITRACE,"In CDIFat::SetFatSect(%lu,%lu)\n",oSect,sect));
  196. }
  197. Err:
  198. return sc;
  199. }
  200. //+-------------------------------------------------------------------------
  201. //
  202. // Method: CDIFat::GetSect, public
  203. //
  204. // Synopsis: Given an offset into the DIFat chain, return the
  205. // sector value
  206. //
  207. // Arguments: [oSect] -- Offset into DIFat chain.
  208. //
  209. // Returns: Sector value for given offset.
  210. //
  211. // Algorithm: Retrieve the information from the NextFat fields of
  212. // the CFatVector
  213. //
  214. // History: 11-May-92 PhilipLa Created.
  215. //
  216. //--------------------------------------------------------------------------
  217. SCODE CDIFat::GetSect(const FSINDEX oSect, SECT *psect)
  218. {
  219. SCODE sc = S_OK;
  220. SECT sectReturn;
  221. msfDebugOut((DEB_ITRACE,"In CDIFat::GetSect(%lu)\n",oSect));
  222. msfAssert(oSect < _cfsTable);
  223. sectReturn = _pmsParent->GetHeader()->GetDifStart();
  224. //Possible optimization here: Do some sort of check to
  225. //find the last page that's actually cached in the vector,
  226. //then start the loop from there. Probably not a terribly
  227. //important optimization, but it is possible.
  228. for (FSINDEX oCurrent = 0; oCurrent < oSect; oCurrent++)
  229. {
  230. msfAssert(sectReturn != ENDOFCHAIN);
  231. CFatSect *pfs;
  232. msfChk(_fv.GetTableWithSect(oCurrent,
  233. FB_NONE,
  234. sectReturn,
  235. (void **)&pfs));
  236. sectReturn = pfs->GetNextFat(_fv.GetSectTable());
  237. _fv.ReleaseTable(oCurrent);
  238. }
  239. msfDebugOut((DEB_ITRACE,"Out CDIFat::GetSect(%lu)=>%lu\n",oSect,sectReturn));
  240. *psect = sectReturn;
  241. Err:
  242. return sc;
  243. }
  244. //+-------------------------------------------------------------------------
  245. //
  246. // Method: CDIFat::Init, public
  247. //
  248. // Synopsis: Init function for previously stored DIFat.
  249. //
  250. // Arguments: [cFatSect] -- Length of DIFat in sectors
  251. //
  252. // Returns: S_OK if call completed properly.
  253. //
  254. // Algorithm: *Finish This*
  255. //
  256. // History: 11-May-92 PhilipLa Created.
  257. //
  258. //--------------------------------------------------------------------------
  259. SCODE CDIFat::Init(CMStream * pmsParent, const FSINDEX cFatSect)
  260. {
  261. msfDebugOut((DEB_ITRACE,"In CDIFat::Init(%lu)\n",cFatSect));
  262. SCODE sc;
  263. _pmsParent = P_TO_BP(CBasedMStreamPtr, pmsParent);
  264. ULONG cbSector = pmsParent->GetSectorSize();
  265. _fv.InitCommon(
  266. (FSOFFSET)(cbSector / sizeof(SECT)),
  267. (FSOFFSET)((cbSector / sizeof(SECT)) - 1));
  268. msfChk(_fv.Init(pmsParent, cFatSect));
  269. _cfsTable = cFatSect;
  270. msfDebugOut((DEB_ITRACE,"Out CDIFat::Init(%lu)\n",cFatSect));
  271. Err:
  272. return sc;
  273. }
  274. //+-------------------------------------------------------------------------
  275. //
  276. // Method: CDIFat::InitNew, public
  277. //
  278. // Synopsis: Init function for new DIFat
  279. //
  280. // Arguments: [pmsParent] -- Pointer to parent multistream
  281. //
  282. // Returns: S_OK if call completed successfully.
  283. //
  284. // History: 11-May-92 PhilipLa Created.
  285. //
  286. //--------------------------------------------------------------------------
  287. SCODE CDIFat::InitNew(CMStream *pmsParent)
  288. {
  289. _pmsParent = P_TO_BP(CBasedMStreamPtr, pmsParent);
  290. ULONG cbSector = pmsParent->GetSectorSize();
  291. _fv.InitCommon(
  292. (FSOFFSET)(cbSector / sizeof(SECT)),
  293. (FSOFFSET)((cbSector / sizeof(SECT)) - 1));
  294. _fv.Init(pmsParent, 0);
  295. _cfsTable = 0;
  296. return S_OK;
  297. }
  298. //+-------------------------------------------------------------------------
  299. //
  300. // Method: CDIFat::InitConvert, public
  301. //
  302. // Synopsis: Init function for conversion
  303. //
  304. // Arguments: [sectMax] -- Last used sector in existing file
  305. //
  306. // Returns: S_OK if call completed OK.
  307. //
  308. // Algorithm: *Finish This*
  309. //
  310. // History: 02-Jun-92 PhilipLa Created.
  311. //
  312. // Notes:
  313. //
  314. //--------------------------------------------------------------------------
  315. SCODE CDIFat::InitConvert(CMStream *pmsParent, SECT sectMax)
  316. {
  317. msfDebugOut((DEB_ITRACE,"In CDIFat::InitConvert(%lu)\n",sectMax));
  318. SCODE sc;
  319. _pmsParent = P_TO_BP(CBasedMStreamPtr, pmsParent);
  320. USHORT cbSector = pmsParent->GetSectorSize();
  321. FSOFFSET csectPer = cbSector / sizeof(SECT);
  322. cbSector = pmsParent->GetSectorSize();
  323. _fv.InitCommon(cbSector / sizeof(SECT), (cbSector / sizeof(SECT)) - 1);
  324. FSINDEX csectFat = 0;
  325. FSINDEX csectFatLast;
  326. FSINDEX csectDif = 0;
  327. FSINDEX csectDifLast;
  328. do
  329. {
  330. //Number of fat sectors needed to represent:
  331. // Number of Data Sectors (sectMax) +
  332. // Number of Fat Sectors (csectFat) +
  333. // Number of DIF sectors (csectDif) +
  334. // Number of Directory Sectors (1)
  335. //We must use a loop here, since the fat must be large
  336. // enough to represent itself and the DIFat. See
  337. // CFat::InitConvert for a more lengthy discussion of
  338. // this method.
  339. csectFatLast = csectFat;
  340. csectFat = (sectMax + csectFatLast + csectDif + 1 + csectPer - 1) /
  341. csectPer;
  342. csectDifLast = csectDif;
  343. if (csectFat < CSECTFAT)
  344. {
  345. csectDif = 0;
  346. }
  347. else
  348. {
  349. FSOFFSET ciSect;
  350. SectToPair(csectFat, &csectDif, &ciSect);
  351. csectDif++;
  352. }
  353. }
  354. while ((csectDif != csectDifLast) || (csectFat != csectFatLast));
  355. _cfsTable = csectDif;
  356. msfChk(_fv.Init(pmsParent, _cfsTable));
  357. pmsParent->GetHeader()->SetDifLength(_cfsTable);
  358. if (_cfsTable > 0)
  359. {
  360. pmsParent->GetHeader()->SetDifStart(sectMax);
  361. FSINDEX i;
  362. for (i = 0; i < _cfsTable; i++)
  363. {
  364. CFatSect *pfs;
  365. msfChk(_fv.GetTable(i, FB_NEW, &pfs));
  366. _fv.SetSect(i, sectMax);
  367. sectMax++;
  368. pfs->SetNextFat(_fv.GetSectTable(),sectMax);
  369. _fv.ReleaseTable(i);
  370. }
  371. }
  372. msfDebugOut((DEB_ITRACE,"Out CDIFat::InitConvert()\n"));
  373. Err:
  374. return sc;
  375. }
  376. //+-------------------------------------------------------------------------
  377. //
  378. // Method: CDIFat::Remap, public
  379. //
  380. // Synopsis: Remap a Fat sector for copy-on-write
  381. //
  382. // Arguments: [oSect] -- Offset into fat chain to be remapped.
  383. // [psectReturn] -- pointer to return value
  384. //
  385. // Returns: S_OK if call was successful.
  386. //
  387. // Algorithm: *Finish This*
  388. //
  389. // History: 11-May-92 PhilipLa Created.
  390. //
  391. // Notes:
  392. //
  393. //--------------------------------------------------------------------------
  394. SCODE CDIFat::Remap(const FSINDEX oSect, SECT * psectReturn)
  395. {
  396. msfDebugOut((DEB_ITRACE,"In CDIFat::Remap(%lu)\n",oSect));
  397. SCODE sc = S_OK;
  398. SECT sectNew;
  399. SECT sectTemp;
  400. msfChk(GetFatSect(oSect, &sectTemp));
  401. msfChk(_pmsParent->GetFat()->QueryRemapped(sectTemp));
  402. if (sc == S_FALSE)
  403. {
  404. msfChk(_pmsParent->GetFat()->GetFree(1, &sectNew, GF_READONLY));
  405. #ifdef DIFAT_LOOKUP_ARRAY
  406. CacheUnmarkedSect(sectNew, FATSECT, sectTemp);
  407. #endif
  408. msfDebugOut((DEB_ITRACE,"Remapping fat sector %lu from %lu to %lu\n",oSect,sectTemp,sectNew));
  409. msfChk(SetFatSect(oSect, sectNew));
  410. }
  411. else
  412. {
  413. sectNew = ENDOFCHAIN;
  414. }
  415. msfDebugOut((DEB_ITRACE,"In CDIFat::Remap(%lu)=>%lu\n",oSect,sectNew));
  416. *psectReturn = sectNew;
  417. Err:
  418. return sc;
  419. }
  420. //+-------------------------------------------------------------------------
  421. //
  422. // Method: CDIFat::RemapSelf, public
  423. //
  424. // Synopsis: Remap the entire DIFat for copy-on-write.
  425. //
  426. // Arguments: None.
  427. //
  428. // Returns: S_OK if DIFat was remapped successfully.
  429. //
  430. // Algorithm: *Finish This*
  431. //
  432. // History: 11-May-92 PhilipLa Created.
  433. //
  434. // Notes:
  435. //
  436. //--------------------------------------------------------------------------
  437. SCODE CDIFat::RemapSelf(VOID)
  438. {
  439. msfDebugOut((DEB_ITRACE,"In CDIFat::RemapSelf()\n"));
  440. SECT sectNew, sect;
  441. SCODE sc = S_OK;
  442. CFatSect *pfs;
  443. FSINDEX i = 0;
  444. if (_cfsTable > 0)
  445. {
  446. sect = _pmsParent->GetHeader()->GetDifStart();
  447. msfChk(_fv.GetTable(0, FB_DIRTY, &pfs));
  448. msfChkTo(Err_Rel0, _pmsParent->GetFat()->GetFree(1, &sectNew, GF_READONLY));
  449. #ifdef DIFAT_LOOKUP_ARRAY
  450. SECT sectOld;
  451. sectOld = _pmsParent->GetHeader()->GetDifStart();
  452. CacheUnmarkedSect(sectNew, DIFSECT, sectOld);
  453. #endif
  454. _pmsParent->GetHeader()->SetDifStart(sectNew);
  455. _fv.SetSect(0, sectNew);
  456. _fv.ReleaseTable(0);
  457. }
  458. for (i = 1; i < _cfsTable; i++)
  459. {
  460. CFatSect *pfs2;
  461. msfChk(_fv.GetTable(i - 1, FB_DIRTY, &pfs));
  462. msfChkTo(Err_Rel1, _fv.GetTable(i, FB_DIRTY, &pfs2));
  463. msfChkTo(Err_Rel, _pmsParent->GetFat()->GetFree(
  464. 1,
  465. &sectNew,
  466. GF_READONLY));
  467. #ifdef DIFAT_LOOKUP_ARRAY
  468. SECT sectOld;
  469. sectOld = pfs->GetNextFat(_fv.GetSectTable());
  470. CacheUnmarkedSect(sectNew, DIFSECT, sectOld);
  471. #endif
  472. pfs->SetNextFat(_fv.GetSectTable(), sectNew);
  473. _fv.SetSect(i, sectNew);
  474. _fv.ReleaseTable(i - 1);
  475. _fv.ReleaseTable(i);
  476. }
  477. msfDebugOut((DEB_ITRACE,"In CDIFat::RemapSelf()\n"));
  478. Err:
  479. return sc;
  480. Err_Rel0:
  481. _fv.ReleaseTable(0);
  482. return sc;
  483. Err_Rel:
  484. _fv.ReleaseTable(i);
  485. Err_Rel1:
  486. _fv.ReleaseTable(i - 1);
  487. return sc;
  488. }
  489. //+-------------------------------------------------------------------------
  490. //
  491. // Method: CDIFat::Resize, private
  492. //
  493. // Synopsis: Resize an existing DIFat.
  494. //
  495. // Arguments: [fsiSize] -- New size for object
  496. //
  497. // Returns: Nothing right now.
  498. //
  499. // Algorithm: *Finish This*
  500. //
  501. // History: 11-May-92 PhilipLa Created.
  502. //
  503. // Notes:
  504. //
  505. //--------------------------------------------------------------------------
  506. SCODE CDIFat::Resize(FSINDEX fsiSize)
  507. {
  508. msfDebugOut((DEB_ITRACE,"In CDIFat::Resize(%lu)\n",fsiSize));
  509. msfAssert(fsiSize == _cfsTable + 1);
  510. SCODE sc;
  511. msfChk(_fv.Resize(fsiSize));
  512. ULONG ipfs;
  513. ipfs = fsiSize - 1;
  514. CFatSect *pfs1;
  515. msfChk(_fv.GetTable(ipfs, FB_NEW, &pfs1));
  516. FSINDEX csect;
  517. csect = _cfsTable;
  518. _cfsTable = fsiSize;
  519. SECT sectNew;
  520. #ifdef USE_NOSCRATCH
  521. //If we're in no-scratch mode, passing GF_WRITE to the fat here can
  522. // cause a nasty loop on Resize(). Do a read-only GetFree in that
  523. // case, and don't try to update the fat.
  524. if ((_pmsParent->HasNoScratch()
  525. #ifdef USE_NOSNAPSHOT
  526. ||
  527. (_pmsParent->GetFat()->GetNoSnapshotFree() != ENDOFCHAIN)
  528. #endif
  529. ))
  530. {
  531. msfChk(_pmsParent->GetFat()->GetFree(1, &sectNew, GF_READONLY));
  532. #ifdef DIFAT_LOOKUP_ARRAY
  533. CacheUnmarkedSect(sectNew, DIFSECT, ENDOFCHAIN);
  534. #endif
  535. }
  536. else
  537. {
  538. #endif
  539. msfChk(_pmsParent->GetFat()->GetFree(1, &sectNew, GF_WRITE));
  540. msfChk(_pmsParent->GetFat()->SetNext(sectNew, DIFSECT));
  541. #ifdef USE_NOSCRATCH
  542. }
  543. #endif
  544. #if DBG == 1
  545. STATSTG stat;
  546. msfHChk(_pmsParent->GetILB()->Stat(&stat, STATFLAG_NONAME));
  547. #ifdef LARGE_DOCFILE
  548. //msfAssert(
  549. // ConvertSectOffset(sectNew + 1, 0, _pmsParent->GetSectorShift()) <=
  550. // stat.cbSize.QuadPart);
  551. #else
  552. //msfAssert(
  553. // ConvertSectOffset(sectNew + 1, 0, _pmsParent->GetSectorShift()) <=
  554. // ULIGetLow(stat.cbSize));
  555. #endif
  556. #endif
  557. _fv.SetSect(ipfs, sectNew);
  558. _fv.ReleaseTable(ipfs);
  559. if (csect == 0)
  560. {
  561. _pmsParent->GetHeader()->SetDifStart(sectNew);
  562. }
  563. else
  564. {
  565. CFatSect *pfs;
  566. msfChk(_fv.GetTable(csect - 1, FB_DIRTY, &pfs));
  567. pfs->SetNextFat(_fv.GetSectTable(),sectNew);
  568. _fv.ReleaseTable(csect - 1);
  569. }
  570. _pmsParent->GetHeader()->SetDifLength(_cfsTable);
  571. msfDebugOut((DEB_ITRACE,"Out CDIFat::Resize(%lu)\n",fsiSize));
  572. Err:
  573. return sc;
  574. }
  575. //+---------------------------------------------------------------------------
  576. //
  577. // Member: CDIFat::Lookup, public
  578. //
  579. // Synopsis: Lookup a sector and see if it is in the DIFat. If it
  580. // is, return FATSECT if it is allocated to a fat sector
  581. // or DIFSECT if it is allocated to the DIF.
  582. //
  583. // Arguments: [sect] -- Sector to look up
  584. // [psectRet] -- Location for return value
  585. // [fReadOnly] -- If FALSE, decrement the dirty count
  586. // after returning the page.
  587. //
  588. // Returns: Appropriate status code
  589. //
  590. // Modifies:
  591. //
  592. // History: 23-Feb-93 PhilipLa Created
  593. //
  594. // Notes:
  595. //
  596. //----------------------------------------------------------------------------
  597. SCODE CDIFat::Lookup(const SECT sect, SECT *psectRet)
  598. {
  599. SCODE sc = S_OK;
  600. *psectRet = FREESECT;
  601. #ifdef DIFAT_LOOKUP_ARRAY
  602. if (_cUnmarked <= DIFAT_ARRAY_SIZE)
  603. {
  604. for (USHORT iArray = 0; iArray < _cUnmarked; iArray++)
  605. {
  606. if (_sectUnmarked[iArray] == sect)
  607. {
  608. *psectRet = _sectMarkTo[iArray];
  609. return S_OK;
  610. }
  611. }
  612. return S_OK;
  613. }
  614. #endif
  615. for (FSINDEX i = 0; i < _pmsParent->GetHeader()->GetDifLength(); i++)
  616. {
  617. SECT sectDif;
  618. msfChk(GetSect(i, &sectDif));
  619. if (sectDif == sect)
  620. {
  621. *psectRet = DIFSECT;
  622. return S_OK;
  623. }
  624. }
  625. #ifdef OPTIMIZE_LOOKUP
  626. CFatSect *pfs;
  627. pfs = NULL;
  628. FSINDEX ipfsLast;
  629. ipfsLast = (FSOFFSET) -1;
  630. FSINDEX ipfs = 0;
  631. FSOFFSET isect;
  632. #endif
  633. for (i = 0; i < _pmsParent->GetHeader()->GetFatLength(); i++)
  634. {
  635. #ifndef OPTIMIZE_LOOKUP
  636. SECT sectFat;
  637. msfChk(GetFatSect(i, &sectFat));
  638. if (sectFat == sect)
  639. {
  640. *psectRet = FATSECT;
  641. return S_OK;
  642. }
  643. #else
  644. SECT sectFat;
  645. if (i < CSECTFAT)
  646. {
  647. sectFat = _pmsParent->GetHeader()->GetFatSect(i);
  648. }
  649. else
  650. {
  651. SectToPair(i, &ipfs, &isect);
  652. if (ipfs != ipfsLast)
  653. {
  654. if (pfs != NULL)
  655. {
  656. _fv.ReleaseTable(ipfsLast);
  657. }
  658. msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
  659. }
  660. sectFat = pfs->GetSect(isect);
  661. ipfsLast = ipfs;
  662. }
  663. if (sect == sectFat)
  664. {
  665. if (pfs != NULL)
  666. {
  667. _fv.ReleaseTable(ipfs);
  668. }
  669. *psectRet = FATSECT;
  670. return S_OK;
  671. }
  672. #endif
  673. }
  674. #ifdef OPTIMIZE_LOOKUP
  675. if (pfs != NULL)
  676. {
  677. _fv.ReleaseTable(ipfs);
  678. }
  679. #endif
  680. Err:
  681. return sc;
  682. }
  683. //+---------------------------------------------------------------------------
  684. //
  685. // Member: CDIFat::Fixup, public
  686. //
  687. // Synopsis: Fixup the Fat after a copy-on-write commit.
  688. //
  689. // Arguments: [pmsShadow] -- Pointer to shadow multistream
  690. //
  691. // Returns: Appropriate status code
  692. //
  693. // Modifies:
  694. //
  695. // History: 23-Feb-93 PhilipLa Created
  696. //
  697. // Notes:
  698. //
  699. //----------------------------------------------------------------------------
  700. SCODE CDIFat::Fixup(CMStream *pmsShadow)
  701. {
  702. SCODE sc = S_OK;
  703. BOOL fChanged;
  704. CFat *pfat = _pmsParent->GetFat();
  705. #if DBG == 1
  706. pfat->CheckFreeCount();
  707. #endif
  708. #ifdef DIFAT_LOOKUP_ARRAY
  709. if (_fDoingFixup)
  710. return S_OK;
  711. _fDoingFixup = TRUE;
  712. if (_cUnmarked <= DIFAT_ARRAY_SIZE)
  713. {
  714. for (USHORT iArray = 0;
  715. (iArray < _cUnmarked) && (_cUnmarked <= DIFAT_ARRAY_SIZE);
  716. iArray++)
  717. {
  718. //sectNew may be out of the range of the current fat.
  719. //Check and resize if necessary. This is needed for
  720. //no-scratch mode.
  721. FSINDEX ipfs;
  722. FSOFFSET isect;
  723. pfat->SectToPair(_sectUnmarked[iArray], &ipfs, &isect);
  724. if (ipfs >= pfat->GetFatVectorLength())
  725. {
  726. msfChk(pfat->Resize(ipfs + 1));
  727. }
  728. msfChk(pfat->SetNext(_sectUnmarked[iArray],
  729. _sectMarkTo[iArray]));
  730. if (_sectFree[iArray] != ENDOFCHAIN)
  731. {
  732. msfChk(pfat->SetNext(_sectFree[iArray], FREESECT));
  733. }
  734. }
  735. }
  736. if (_cUnmarked <= DIFAT_ARRAY_SIZE)
  737. {
  738. _cUnmarked = 0;
  739. pfat->ResetUnmarkedSects();
  740. _fDoingFixup = FALSE;
  741. return S_OK;
  742. }
  743. #endif
  744. #ifdef USE_NOSCRATCH
  745. if (pmsShadow != NULL)
  746. {
  747. #endif
  748. CDIFat *pdifOld = pmsShadow->GetDIFat();
  749. FSINDEX cFatOld = pmsShadow->GetHeader()->GetFatLength();
  750. FSINDEX cDifOld = pmsShadow->GetHeader()->GetDifLength();
  751. for (FSINDEX i = 0; i < _pmsParent->GetHeader()->GetDifLength(); i++)
  752. {
  753. SECT sectNew;
  754. SECT sectOld = ENDOFCHAIN;
  755. SECT sectCurrent;
  756. msfChk(GetSect(i, &sectNew));
  757. if (i < cDifOld)
  758. msfChk(pdifOld->GetSect(i, &sectOld));
  759. if ((sectNew != sectOld) || (sectOld == ENDOFCHAIN))
  760. {
  761. #ifdef USE_NOSCRATCH
  762. //sectNew may be out of the range of the current fat.
  763. //Check and resize if necessary.
  764. FSINDEX ipfs;
  765. FSOFFSET isect;
  766. pfat->SectToPair(sectNew, &ipfs, &isect);
  767. if (ipfs >= pfat->GetFatVectorLength())
  768. {
  769. msfChk(pfat->Resize(ipfs + 1));
  770. }
  771. #endif
  772. msfChk(pfat->GetNext(sectNew, &sectCurrent));
  773. if (sectCurrent != DIFSECT)
  774. {
  775. msfChk(pfat->SetNext(sectNew, DIFSECT));
  776. }
  777. if (sectOld != ENDOFCHAIN)
  778. {
  779. //sectOld should always be within the range of the
  780. //fat, so we don't need to check and resize here.
  781. msfChk(pfat->GetNext(sectOld, &sectCurrent));
  782. if (sectCurrent != FREESECT)
  783. {
  784. msfChk(pfat->SetNext(sectOld, FREESECT));
  785. }
  786. }
  787. }
  788. }
  789. do
  790. {
  791. fChanged = FALSE;
  792. #ifdef OPTIMIZE_FIXUP
  793. CFatSect *pfs;
  794. pfs = NULL;
  795. FSINDEX ipfsLast;
  796. ipfsLast = (FSOFFSET) - 1;
  797. FSINDEX ipfs;
  798. FSOFFSET isect;
  799. CFatSect *pfsShadow;
  800. pfsShadow = NULL;
  801. FSINDEX ipfsLastShadow;
  802. ipfsLastShadow = (FSOFFSET) - 1;
  803. FSINDEX ipfsShadow;
  804. FSOFFSET isectShadow;
  805. #endif
  806. for (i = 0; i < _pmsParent->GetHeader()->GetFatLength(); i++)
  807. {
  808. SECT sectNew;
  809. SECT sectCurrent;
  810. SECT sectOld = ENDOFCHAIN;
  811. #ifndef OPTIMIZE_FIXUP
  812. msfChk(GetFatSect(i, &sectNew));
  813. #else
  814. if (i < CSECTFAT)
  815. {
  816. sectNew = _pmsParent->GetHeader()->GetFatSect(i);
  817. }
  818. else
  819. {
  820. SectToPair(i, &ipfs, &isect);
  821. if (ipfs != ipfsLast)
  822. {
  823. if (pfs != NULL)
  824. {
  825. _fv.ReleaseTable(ipfsLast);
  826. }
  827. msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
  828. }
  829. sectNew = pfs->GetSect(isect);
  830. ipfsLast = ipfs;
  831. }
  832. #endif
  833. #ifndef OPTIMIZE_FIXUP
  834. if (i < cFatOld)
  835. msfChk(pdifOld->GetFatSect(i, &sectOld));
  836. #else
  837. if (i < cFatOld)
  838. {
  839. if (i < CSECTFAT)
  840. {
  841. sectOld = pmsShadow->GetHeader()->GetFatSect(i);
  842. }
  843. else
  844. {
  845. SectToPair(i, &ipfsShadow, &isectShadow);
  846. if (ipfsShadow != ipfsLastShadow)
  847. {
  848. if (pfsShadow != NULL)
  849. {
  850. pdifOld->_fv.ReleaseTable(ipfsLastShadow);
  851. }
  852. msfChk(pdifOld->_fv.GetTable(ipfsShadow,
  853. FB_NONE,
  854. &pfsShadow));
  855. }
  856. sectOld = pfsShadow->GetSect(isectShadow);
  857. ipfsLastShadow = ipfsShadow;
  858. }
  859. }
  860. #endif
  861. if ((sectNew != sectOld) || (sectOld == ENDOFCHAIN))
  862. {
  863. //Sector has been remapped.
  864. #ifdef USE_NOSCRATCH
  865. //sectNew may be outside the range of the current
  866. //fat. Check and resize if necessary.
  867. //If we resize, set fChanged, since we may need to
  868. //go through again.
  869. FSINDEX ipfs2;
  870. FSOFFSET isect2;
  871. pfat->SectToPair(sectNew, &ipfs2, &isect2);
  872. if (ipfs2 >= pfat->GetFatVectorLength())
  873. {
  874. msfChk(pfat->Resize(ipfs2 + 1));
  875. fChanged = TRUE;
  876. }
  877. #endif
  878. msfChk(pfat->GetNext(sectNew, &sectCurrent));
  879. if (sectCurrent != FATSECT)
  880. {
  881. msfChk(pfat->SetNext(sectNew, FATSECT));
  882. fChanged = TRUE;
  883. }
  884. if (sectOld != ENDOFCHAIN)
  885. {
  886. //sectOld is always inside the existing fat,
  887. //so we don't need to check and resize.
  888. msfChk(pfat->GetNext(sectOld, &sectCurrent));
  889. if (sectCurrent != FREESECT)
  890. {
  891. msfChk(pfat->SetNext(sectOld, FREESECT));
  892. fChanged = TRUE;
  893. }
  894. }
  895. }
  896. }
  897. #ifdef OPTIMIZE_FIXUP
  898. if (pfs != NULL)
  899. _fv.ReleaseTable(ipfsLast);
  900. if (pfsShadow != NULL)
  901. pdifOld->_fv.ReleaseTable(ipfsLastShadow);
  902. #endif
  903. }
  904. while (fChanged);
  905. #ifdef USE_NOSCRATCH
  906. }
  907. else
  908. {
  909. //This is for fixing the fat while in overwrite mode with
  910. // no-scratch.
  911. do
  912. {
  913. fChanged = FALSE;
  914. for (FSINDEX i = 0;
  915. i < _pmsParent->GetHeader()->GetFatLength();
  916. i++)
  917. {
  918. SECT sectNew;
  919. SECT sectCurrent;
  920. msfChk(GetFatSect(i, &sectNew));
  921. //sectNew may be outside the range of the current fat. If
  922. //so, resize the fat.
  923. FSINDEX ipfs;
  924. FSOFFSET isect;
  925. pfat->SectToPair(sectNew, &ipfs, &isect);
  926. if (ipfs >= pfat->GetFatVectorLength())
  927. {
  928. msfChk(pfat->Resize(ipfs + 1));
  929. fChanged = TRUE;
  930. }
  931. msfChk(pfat->GetNext(sectNew, &sectCurrent));
  932. if (sectCurrent != FATSECT)
  933. {
  934. msfChk(pfat->SetNext(sectNew, FATSECT));
  935. fChanged = TRUE;
  936. }
  937. }
  938. }
  939. while (fChanged);
  940. }
  941. #endif
  942. pfat->ResetUnmarkedSects();
  943. #ifdef DIFAT_LOOKUP_ARRAY
  944. _cUnmarked = 0;
  945. #endif
  946. Err:
  947. #ifdef DIFAT_LOOKUP_ARRAY
  948. _fDoingFixup = FALSE;
  949. #endif
  950. #if DBG == 1
  951. pfat->CheckFreeCount();
  952. #endif
  953. return sc;
  954. }