1 using System;
  2 using System.Collections;
  3 using System.Threading;
  4 using cmsx.machine;
  5 
  6 namespace cmsx.kernel
  7 {
  8     public class BlockBitmap
  9     {
 10         public nothrow BlockBitmap(int fsNumber_) : fsNumber(fsNumber_)
 11         {
 12         }
 13         public int AllocateBlockNumber()
 14         {
 15             if (Log())
 16             {
 17                 LogMessage("fs.root.bbm.allocateblocknumber""begin");
 18             }
 19             FileSystem* fs = GetMountTable().GetFileSystem(fsNumber);
 20             Block* sb = fs->GetBlockManager()->ReadBlock(BlockKey(0fsNumber)null);
 21             BlockPutter superBlockPutter(sb);
 22             SuperBlock* superBlock = cast<SuperBlock*>(sb);
 23             int firstNumber = superBlock->GetFirstBlockBitmapBlockNumber();
 24             int n = superBlock->GetNumBlockBitmapBlocks();
 25             for (int i = 0; i < n; ++i;)
 26             {
 27                 Block* block = null;
 28                 if (superBlock->GetLastBlockNumber() < firstNumber + i)
 29                 {
 30                     block = fs->GetBlockManager()->GetBlock(BlockKey(firstNumber + ifsNumber)superBlock);
 31                     block->Clear();
 32                 }
 33                 else
 34                 {
 35                     block = fs->GetBlockManager()->ReadBlock(BlockKey(firstNumber + ifsNumber)superBlock);
 36                 }
 37                 BlockPutter putter(block);
 38                 BitmapBlock* bitmapBlock = cast<BitmapBlock*>(block);
 39                 int index = bitmapBlock->GetFirstZeroBitIndex();
 40                 if (index != -1)
 41                 {
 42                     bitmapBlock->SetBit(index);
 43                     int blockNumber = superBlock->GetFirstDataBlockNumber() + i * numBitsInBitmapBlock + index;
 44                     if (Log())
 45                     {
 46                         LogMessage("fs.root.bbm.allocateblocknumber""end.blocknumber=" + ToString(blockNumber));
 47                     }
 48                     fs->GetBlockManager()->WriteBlock(blocksuperBlock);
 49                     return blockNumber;
 50                 }
 51             }
 52             throw SystemError(ERLIMITEXCEEDED"file system " + ToString(fsNumber) + " has no free blocks");
 53         }
 54         public void SetBlockFree(int blockNumber)
 55         {
 56             if (Log())
 57             {
 58                 LogMessage("fs.root.bbm.setblockfree""begin.blocknumber=" + ToString(blockNumber));
 59             }
 60             FileSystem* fs = GetMountTable().GetFileSystem(fsNumber);
 61             Block* sb = fs->GetBlockManager()->ReadBlock(BlockKey(0fsNumber)null);
 62             BlockPutter superBlockPutter(sb);
 63             SuperBlock* superBlock = cast<SuperBlock*>(sb);
 64             blockNumber = blockNumber - superBlock->GetFirstDataBlockNumber();
 65             int firstNumber = superBlock->GetFirstBlockBitmapBlockNumber();
 66             int bitmapBlockIndex = blockNumber / numBitsInBitmapBlock;
 67             Block* block = fs->GetBlockManager()->ReadBlock(BlockKey(firstNumber + bitmapBlockIndexsuperBlock->Key().fsNumber)superBlock);
 68             BlockPutter putter(block);
 69             BitmapBlock* bitmapBlock = cast<BitmapBlock*>(block);
 70             int index = blockNumber % numBitsInBitmapBlock;
 71             bitmapBlock->ResetBit(index);
 72             fs->GetBlockManager()->WriteBlock(blocksuperBlock);
 73             if (Log())
 74             {
 75                 LogMessage("fs.root.bbm.setblockfree""end." + block->ToString());
 76             }
 77         }
 78         private int fsNumber;
 79     }
 80 
 81     public class BlockCache
 82     {
 83         public nothrow BlockCache(BlockManager* manager_int maxCachedBlocks) : manager(manager_)
 84         {
 85             for (int i = 0; i < maxCachedBlocks; ++i;)
 86             {
 87                 Block* block = new Block(BlockKey()managerthis);
 88                 blocks.Add(UniquePtr<Block>(block));
 89                 freeBlockList.Add(block);
 90                 block->SetIterator(LinkedList<Block*>.Iterator(&freeBlockListfreeBlockList.Tail()));
 91             }
 92         }
 93         public void RemoveBlockFromFreeList(Block* block)
 94         {
 95             LinkedList<Block*>.Iterator iterator = block->GetIterator();
 96             if (iterator != freeBlockList.End())
 97             {
 98                 freeBlockList.Remove(iterator);
 99                 block->SetIterator(freeBlockList.End());
100             }
101         }
102         public void PutBlockToFreeList(Block* blockbool tail)
103         {
104             if (tail)
105             {
106                 freeBlockList.Add(block);
107                 block->SetIterator(LinkedList<Block*>.Iterator(&freeBlockListfreeBlockList.Tail()));
108             }
109             else
110             {
111                 LinkedList<Block*>.Iterator iterator = freeBlockList.InsertFront(block);
112                 block->SetIterator(iterator);
113             }
114         }
115         public nothrow LinkedList<Block*>* GetFreeBlockList() const
116         {
117             return &freeBlockList;
118         }
119         public void AddWaitingProcess(Process* process)
120         {
121             waitingProcesses.Add(process);
122         }
123         public nothrow List<Process*> GetWaitingProcesses()
124         {
125             List<Process*> processes;
126             Swap(processeswaitingProcesses);
127             return processes;
128         }
129         public nothrow void AddDirtyBlock(Block* dirtyBlock)
130         {
131             dirtyBlocks.Insert(dirtyBlock);
132         }
133         public void Flush()
134         {
135             for (Block* block : dirtyBlocks)
136             {
137                 if (block->GetFlag(Block.Flags.dirty))
138                 {
139                     manager->WriteBlock(blocknull);
140                 }
141             }
142         }
143         private BlockManager* manager;
144         private List<UniquePtr<Block>> blocks;
145         private LinkedList<Block*> freeBlockList;
146         private List<Process*> waitingProcesses;
147         private Set<Block*> dirtyBlocks;
148     }
149 
150     public class RootBlockManager : BlockManager
151     {
152         public nothrow RootBlockManager() :  cache(thismaxCachedBlocks)
153         {
154         }
155         public override nothrow string Name() const
156         {
157             return "fs.root.bmgr";
158         }
159         public override Block* GetBlock(const BlockKey& keySuperBlock* sbbool sleepbool setOwner)
160         {
161             if (Log())
162             {
163                 LogMessage("fs.root.bmgr.getblock.begin"key.ToString());
164             }
165             while (true)
166             {
167                 HashMap<BlockKeyBlock*BlockKeyHash>.ConstIterator it = blockMap.CFind(key);
168                 if (it != blockMap.CEnd())
169                 {
170                     Block* block = it->second;
171                     if (block->GetFlag(Block.Flags.locked))
172                     {
173                         if (!sleep)
174                         {
175                             return null;
176                         }
177                         void* fiberData = OsGetFiberData();
178                         Process* process = cast<Process*>(fiberData);
179                         if (block->Owner() != process)
180                         {
181                             block->AddWaitingProcess(process);
182                             SleepProcess(processblockUnlockedEventcast<ulong>(cast<void*>(block))0u);
183                             continue;
184                         }
185                         else
186                         {
187                             if (Log())
188                             {
189                                 LogMessage("fs.root.bmgr.getblock.end.found.sameOwner"block->ToString());
190                             }
191                             return block;
192                         }
193                     }
194                     else
195                     {
196                         block->SetFlag(Block.Flags.locked);
197                         if (setOwner)
198                         {
199                             void* fiberData = OsGetFiberData();
200                             Process* process = cast<Process*>(fiberData);
201                             block->SetOwner(process);
202                         }
203                         else
204                         {
205                             block->SetOwner(null);
206                         }
207                         RemoveBlockFromFreeList(block);
208                         if (Log())
209                         {
210                             LogMessage("fs.root.bmgr.getblock.end.found.notLocked"block->ToString());
211                         }
212                         return block;
213                     }
214                 }
215                 else
216                 {
217                     LinkedList<Block*>* list = cache.GetFreeBlockList();
218                     #assert(list != null);
219                     if (list->IsEmpty())
220                     {
221                         if (!sleep)
222                         {
223                             return null;
224                         }
225                         void* fiberData = OsGetFiberData();
226                         Process* process = cast<Process*>(fiberData);
227                         AddWaitingProcess(process);
228                         SleepProcess(processanyBlockFreeEvent0u0u);
229                         continue;
230                     }
231                     else
232                     {
233                         Block* block = list->Front();
234                         list->RemoveFirst();
235                         block->SetIterator(list->End());
236                         if (block->GetFlag(Block.Flags.dirty))
237                         {
238                             WriteBlock(blocksb);
239                         }
240                         blockMap.Remove(block->Key());
241                         block->SetKey(key);
242                         blockMap[key] = block;
243                         block->ResetFlags();
244                         block->SetFlag(Block.Flags.locked);
245                         if (setOwner)
246                         {
247                             void* fiberData = OsGetFiberData();
248                             Process* process = cast<Process*>(fiberData);
249                             block->SetOwner(process);
250                         }
251                         else
252                         {
253                             block->SetOwner(null);
254                         }
255                         if (Log())
256                         {
257                             LogMessage("fs.root.bmgr.getblock.end.free"block->ToString());
258                         }
259                         return block;
260                     }
261                 }
262             }
263         }
264         public override nothrow void PutBlock(Block* block)
265         {
266             if (Log())
267             {
268                 LogMessage("fs.root.bmgr.putblock.begin"block->ToString());
269             }
270             if (block->GetFlag(Block.Flags.valid) && !block->GetFlag(Block.Flags.old))
271             {
272                 PutBlockToFreeList(blocktrue);
273             }
274             else
275             {
276                 PutBlockToFreeList(blockfalse);
277             }
278             List<Process*> anyProcesses = GetWaitingProcesses();
279             Kernel& kernel = GetKernel();
280             ProcessTable& processTable = kernel.GetProcessTable();
281             for (Process* process : anyProcesses)
282             {
283                 WakeUpProcess(processTableprocess);
284             }
285             List<Process*> blockProcesses = block->GetWaitingProcesses();
286             for (Process* process : blockProcesses)
287             {
288                 WakeUpProcess(processTableprocess);
289             }
290             block->ResetFlag(Block.Flags.locked);
291             block->ResetOwner();
292             if (Log())
293             {
294                 LogMessage("fs.root.bmgr.putblock.end"block->ToString());
295             }
296         }
297         public override nothrow Block* ReadBlock(const BlockKey& keySuperBlock* sb)
298         {
299             if (Log())
300             {
301                 LogMessage("fs.root.bmgr.readblock.begin"key.ToString());
302             }
303             Block* block = GetBlock(keysb);
304             if (block->GetFlag(Block.Flags.valid))
305             {
306                 if (Log())
307                 {
308                     LogMessage("fs.root.bmgr.readblock.end.cache"block->ToString());
309                 }
310                 return block;
311             }
312             long bytesRead = GetDiskDriver().Read(block);
313             block->SetFlag(Block.Flags.valid);
314             if (Log())
315             {
316                 LogMessage("fs.root.bmgr.readblock.end.read"block->ToString());
317             }
318             return block;
319         }
320         public override void WriteBlock(Block* blockSuperBlock* superBlock)
321         {
322             if (Log())
323             {
324                 LogMessage("fs.root.bmgr.writeblock.begin"block->ToString());
325             }
326             long bytesWritten = GetDiskDriver().Write(block);
327             if (block->GetFlag(Block.Flags.dirty))
328             {
329                 block->ResetFlag(Block.Flags.dirty);
330                 block->SetFlag(Block.Flags.old);
331             }
332             int blockNumber = block->Key().blockNumber;
333             FileSystem* fs = GetMountTable().GetFileSystem(block->Key().fsNumber);
334             fs->SetLastBlockNumber(blockNumbersuperBlock);
335             if (Log())
336             {
337                 LogMessage("fs.root.bmgr.writeblock.end"block->ToString());
338             }
339         }
340         public override void FreeBlocks(INode* inode)
341         {
342             if (Log())
343             {
344                 LogMessage("fs.root.bmgr.freeblocks.begin"inode->ToString());
345             }
346             FileSystem* fs = GetMountTable().GetFileSystem(inode->Key().fsNumber);
347             for (int i = 0; i < numDirectBlockNumbers; ++i;)
348             {
349                 int blockNumber = inode->GetDirectBlockNumber(i);
350                 if (blockNumber != 0)
351                 {
352                     Block* block = GetBlock(BlockKey(blockNumberinode->Key().fsNumber)null);
353                     block->Clear();
354                     BlockPutter putter(block);
355                     WriteBlock(blocknull);
356                     fs->SetBlockFree(blockNumber);
357                     inode->SetDirectBlockNumber(i0);
358                 }
359             }
360             int singleIndirectBlockNumber = inode->GetSingleIndirectBlockNumber();
361             if (singleIndirectBlockNumber != 0)
362             {
363                 Block* block = ReadBlock(BlockKey(singleIndirectBlockNumberinode->Key().fsNumber)null);
364                 BlockPutter putter(block);
365                 BlockNumberBlock* singleIndirectBlock = cast<BlockNumberBlock*>(block);
366                 for (int i = 0; i < numBlockNumbersInBlock; ++i;)
367                 {
368                     int blockNumber = singleIndirectBlock->GetBlockNumber(i);
369                     if (blockNumber != 0)
370                     {
371                         Block* block = GetBlock(BlockKey(blockNumberinode->Key().fsNumber)null);
372                         block->Clear();
373                         BlockPutter putter(block);
374                         WriteBlock(blocknull);
375                         fs->SetBlockFree(blockNumber);
376                     }
377                 }
378                 singleIndirectBlock->Clear();
379                 WriteBlock(singleIndirectBlocknull);
380                 fs->SetBlockFree(singleIndirectBlockNumber);
381                 inode->SetSingleIndirectBlockNumber(0);
382             }
383             int doubleIndirectBlockNumber = inode->GetDoubleIndirectBlockNumber();
384             if (doubleIndirectBlockNumber != 0)
385             {
386                 Block* block = ReadBlock(BlockKey(doubleIndirectBlockNumberinode->Key().fsNumber)null);
387                 BlockPutter putter(block);
388                 BlockNumberBlock* doubleIndirectBlock = cast<BlockNumberBlock*>(block);
389                 for (int i = 0; i < numBlockNumbersInBlock; ++i;)
390                 {
391                     int singleIndirectBlockNumber = doubleIndirectBlock->GetBlockNumber(i);
392                     if (singleIndirectBlockNumber != 0)
393                     {
394                         Block* block = ReadBlock(BlockKey(singleIndirectBlockNumberinode->Key().fsNumber)null);
395                         BlockPutter putter(block);
396                         BlockNumberBlock* singleIndirectBlock = cast<BlockNumberBlock*>(block);
397                         for (int i = 0; i < numBlockNumbersInBlock; ++i;)
398                         {
399                             int blockNumber = singleIndirectBlock->GetBlockNumber(i);
400                             if (blockNumber != 0)
401                             {
402                                 Block* block = GetBlock(BlockKey(blockNumberinode->Key().fsNumber)null);
403                                 block->Clear();
404                                 BlockPutter putter(block);
405                                 WriteBlock(blocknull);
406                                 fs->SetBlockFree(blockNumber);
407                             }
408                         }
409                         singleIndirectBlock->Clear();
410                         WriteBlock(singleIndirectBlocknull);
411                         fs->SetBlockFree(singleIndirectBlockNumber);
412                     }
413                 }
414                 doubleIndirectBlock->Clear();
415                 WriteBlock(doubleIndirectBlocknull);
416                 fs->SetBlockFree(doubleIndirectBlockNumber);
417                 inode->SetDoubleIndirectBlockNumber(0);
418             }
419             int tripleIndirectBlockNumber = inode->GetTripleIndirectBlockNumber();
420             if (tripleIndirectBlockNumber != 0)
421             {
422                 Block* block = ReadBlock(BlockKey(tripleIndirectBlockNumberinode->Key().fsNumber)null);
423                 BlockPutter putter(block);
424                 BlockNumberBlock* tripleIndirectBlock = cast<BlockNumberBlock*>(block);
425                 for (int i = 0; i < numBlockNumbersInBlock; ++i;)
426                 {
427                     int doubleIndirectBlockNumber = tripleIndirectBlock->GetBlockNumber(i);
428                     if (doubleIndirectBlockNumber != 0)
429                     {
430                         Block* block = ReadBlock(BlockKey(doubleIndirectBlockNumberinode->Key().fsNumber)null);
431                         BlockPutter putter(block);
432                         BlockNumberBlock* doubleIndirectBlock = cast<BlockNumberBlock*>(block);
433                         for (int i = 0; i < numBlockNumbersInBlock; ++i;)
434                         {
435                             int singleIndirectBlockNumber = doubleIndirectBlock->GetBlockNumber(i);
436                             if (singleIndirectBlockNumber != 0)
437                             {
438                                 Block* block = ReadBlock(BlockKey(singleIndirectBlockNumberinode->Key().fsNumber)null);
439                                 BlockPutter putter(block);
440                                 BlockNumberBlock* singleIndirectBlock = cast<BlockNumberBlock*>(block);
441                                 for (int i = 0; i < numBlockNumbersInBlock; ++i;)
442                                 {
443                                     int blockNumber = singleIndirectBlock->GetBlockNumber(i);
444                                     if (blockNumber != 0)
445                                     {
446                                         Block* block = GetBlock(BlockKey(blockNumberinode->Key().fsNumber)null);
447                                         block->Clear();
448                                         BlockPutter putter(block);
449                                         WriteBlock(blocknull);
450                                         fs->SetBlockFree(blockNumber);
451                                     }
452                                 }
453                                 singleIndirectBlock->Clear();
454                                 WriteBlock(singleIndirectBlocknull);
455                                 fs->SetBlockFree(singleIndirectBlockNumber);
456                             }
457                         }
458                         doubleIndirectBlock->Clear();
459                         WriteBlock(doubleIndirectBlocknull);
460                         fs->SetBlockFree(doubleIndirectBlockNumber);
461                     }
462                 }
463                 tripleIndirectBlock->Clear();
464                 WriteBlock(tripleIndirectBlocknull);
465                 fs->SetBlockFree(tripleIndirectBlockNumber);
466                 inode->SetTripleIndirectBlockNumber(0);
467             }
468             if (Log())
469             {
470                 LogMessage("fs.root.bmgr.freeblocks.end"inode->ToString());
471             }
472         }
473         public override int GetBlockNumber(INode* inodeint logicalBlockNumber) const
474         {
475             if (logicalBlockNumber < numDirectBlockNumbers)
476             {
477                 int blockNumber = inode->GetDirectBlockNumber(logicalBlockNumber);
478                 if (blockNumber == 0)
479                 {
480                     return -1;
481                 }
482                 else
483                 {
484                     return blockNumber;
485                 }
486             }
487             else
488             {
489                 logicalBlockNumber = logicalBlockNumber - numDirectBlockNumbers;
490                 if (logicalBlockNumber < numBlockNumbersInBlock)
491                 {
492                     int singleIndirectBlockNumber = inode->GetSingleIndirectBlockNumber();
493                     if (singleIndirectBlockNumber == 0)
494                     {
495                         return -1;
496                     }
497                     Block* block = ReadBlock(BlockKey(singleIndirectBlockNumberinode->Key().fsNumber)null);
498                     BlockPutter putter(block);
499                     BlockNumberBlock* singleIndirectBlock = cast<BlockNumberBlock*>(block);
500                     int blockNumber = singleIndirectBlock->GetBlockNumber(logicalBlockNumber);
501                     if (blockNumber == 0)
502                     {
503                         return -1;
504                     }
505                     else
506                     {
507                         return blockNumber;
508                     }
509                 }
510                 else
511                 {
512                     logicalBlockNumber = logicalBlockNumber - numBlockNumbersInBlock;
513                     if (logicalBlockNumber < numBlockNumbersInBlock * numBlockNumbersInBlock)
514                     {
515                         int doubleIndirectBlockNumber = inode->GetDoubleIndirectBlockNumber();
516                         if (doubleIndirectBlockNumber == 0)
517                         {
518                             return -1;
519                         }
520                         Block* block = ReadBlock(BlockKey(doubleIndirectBlockNumberinode->Key().fsNumber)null);
521                         BlockPutter putter(block);
522                         BlockNumberBlock* doubleIndirectBlock = cast<BlockNumberBlock*>(block);
523                         int singleIndirectBlockNumber = doubleIndirectBlock->GetBlockNumber(logicalBlockNumber / numBlockNumbersInBlock);
524                         if (singleIndirectBlockNumber == 0)
525                         {
526                             return -1;
527                         }
528                         else
529                         {
530                             Block* block = ReadBlock(BlockKey(singleIndirectBlockNumberinode->Key().fsNumber)null);
531                             BlockPutter putter(block);
532                             BlockNumberBlock* singleIndirectBlock = cast<BlockNumberBlock*>(block);
533                             int blockNumber = singleIndirectBlock->GetBlockNumber(logicalBlockNumber % numBlockNumbersInBlock);
534                             if (blockNumber == 0)
535                             {
536                                 return -1;
537                             }
538                             else
539                             {
540                                 return blockNumber;
541                             }
542                         }
543                     }
544                     else
545                     {
546                         logicalBlockNumber = logicalBlockNumber - numBlockNumbersInBlock * numBlockNumbersInBlock;
547                         if (logicalBlockNumber < numBlockNumbersInBlock * numBlockNumbersInBlock * numBlockNumbersInBlock)
548                         {
549                             int tripleIndirectBlockNumber = inode->GetTripleIndirectBlockNumber();
550                             if (tripleIndirectBlockNumber == 0)
551                             {
552                                 return -1;
553                             }
554                             Block* block = ReadBlock(BlockKey(tripleIndirectBlockNumberinode->Key().fsNumber)null);
555                             BlockPutter putter(block);
556                             BlockNumberBlock* tripleIndirectBlock = cast<BlockNumberBlock*>(block);
557                             int doubleIndirectBlockNumber = tripleIndirectBlock->GetBlockNumber(logicalBlockNumber / (numBlockNumbersInBlock * numBlockNumbersInBlock));
558                             if (doubleIndirectBlockNumber == 0)
559                             {
560                                 return -1;
561                             }
562                             else
563                             {
564                                 Block* block = ReadBlock(BlockKey(doubleIndirectBlockNumberinode->Key().fsNumber)null);
565                                 BlockPutter putter(block);
566                                 BlockNumberBlock* doubleIndirectBlock = cast<BlockNumberBlock*>(block);
567                                 int singleIndirectBlockNumber = doubleIndirectBlock->GetBlockNumber((logicalBlockNumber % (numBlockNumbersInBlock * numBlockNumbersInBlock)) / numBlockNumbersInBlock);
568                                 if (singleIndirectBlockNumber == 0)
569                                 {
570                                     return -1;
571                                 }
572                                 else
573                                 {
574                                     Block* block = ReadBlock(BlockKey(singleIndirectBlockNumberinode->Key().fsNumber)null);
575                                     BlockPutter putter(block);
576                                     BlockNumberBlock* singleIndirectBlock = cast<BlockNumberBlock*>(block);
577                                     int blockNumber = singleIndirectBlock->GetBlockNumber((logicalBlockNumber % (numBlockNumbersInBlock * numBlockNumbersInBlock)) % numBlockNumbersInBlock);
578                                     if (blockNumber == 0)
579                                     {
580                                         return -1;
581                                     }
582                                     else
583                                     {
584                                         return blockNumber;
585                                     }
586                                 }
587                             }
588                         }
589                         else
590                         {
591                             return -1;
592                         }
593                     }
594                 }
595             }
596         }
597         public override void GetBlockNumber(INode* inodelong offsetint& blockNumberint& blockOffsetbool allocate)
598         {
599             if (Log())
600             {
601                 LogMessage("fs.root.bmgr.getblocknumber.begin"inode->ToString() + ".offset=" + ToString(offset) + ".allocate=" + ToString(allocate));
602             }
603             int logicalBlockNumber = cast<int>(offset / blockSize);
604             blockOffset = cast<int>(offset % blockSize);
605             if (logicalBlockNumber < numDirectBlockNumbers)
606             {
607                 blockNumber = inode->GetDirectBlockNumber(logicalBlockNumber);
608                 if (blockNumber == 0)
609                 {
610                     if (allocate)
611                     {
612                         FileSystem* fs = GetMountTable().GetFileSystem(inode->Key().fsNumber);
613                         blockNumber = fs->AllocateBlockNumber();
614                         inode->SetDirectBlockNumber(logicalBlockNumberblockNumber);
615                     }
616                     else
617                     {
618                         if (Log())
619                         {
620                             LogMessage("fs.root.bmgr.getblocknumber.end""blocknumber=" + ToString(blockNumber) + ".blockoffset=" + ToString(blockOffset));
621                         }
622                         return;
623                     }
624                 }
625             }
626             else
627             {
628                 logicalBlockNumber = logicalBlockNumber - numDirectBlockNumbers;
629                 if (logicalBlockNumber < numBlockNumbersInBlock)
630                 {
631                     int singleIndirectBlockNumber = inode->GetSingleIndirectBlockNumber();
632                     if (singleIndirectBlockNumber == 0)
633                     {
634                         if (allocate)
635                         {
636                             FileSystem* fs = GetMountTable().GetFileSystem(inode->Key().fsNumber);
637                             singleIndirectBlockNumber = fs->AllocateBlockNumber();
638                             inode->SetSingleIndirectBlockNumber(singleIndirectBlockNumber);
639                             Block* block = GetBlock(BlockKey(singleIndirectBlockNumberinode->Key().fsNumber)null);
640                             block->Clear();
641                             BlockPutter putter(block);
642                             WriteBlock(blocknull);
643                         }
644                         else
645                         {
646                             blockNumber = 0;
647                             if (Log())
648                             {
649                                 LogMessage("fs.root.bmgr.getblocknumber.end""blocknumber=" + ToString(blockNumber) + ".blockoffset=" + ToString(blockOffset));
650                             }
651                             return;
652                         }
653                     }
654                     Block* block = ReadBlock(BlockKey(singleIndirectBlockNumberinode->Key().fsNumber)null);
655                     BlockPutter putter(block);
656                     BlockNumberBlock* singleIndirectBlock = cast<BlockNumberBlock*>(block);
657                     blockNumber = singleIndirectBlock->GetBlockNumber(logicalBlockNumber);
658                     if (blockNumber == 0)
659                     {
660                         if (allocate)
661                         {
662                             FileSystem* fs = GetMountTable().GetFileSystem(inode->Key().fsNumber);
663                             blockNumber = fs->AllocateBlockNumber();
664                             singleIndirectBlock->SetBlockNumber(logicalBlockNumberblockNumber);
665                             WriteBlock(singleIndirectBlocknull);
666                         }
667                         else
668                         {
669                             if (Log())
670                             {
671                                 LogMessage("fs.root.bmgr.getblocknumber.end""blocknumber=" + ToString(blockNumber) + ".blockoffset=" + ToString(blockOffset));
672                             }
673                             return;
674                         }
675                     }
676                 }
677                 else
678                 {
679                     logicalBlockNumber = logicalBlockNumber - numBlockNumbersInBlock;
680                     if (logicalBlockNumber < numBlockNumbersInBlock * numBlockNumbersInBlock)
681                     {
682                         int doubleIndirectBlockNumber = inode->GetDoubleIndirectBlockNumber();
683                         if (doubleIndirectBlockNumber == 0)
684                         {
685                             if (allocate)
686                             {
687                                 FileSystem* fs = GetMountTable().GetFileSystem(inode->Key().fsNumber);
688                                 doubleIndirectBlockNumber = fs->AllocateBlockNumber();
689                                 inode->SetDoubleIndirectBlockNumber(doubleIndirectBlockNumber);
690                                 Block* block = GetBlock(BlockKey(doubleIndirectBlockNumberinode->Key().fsNumber)null);
691                                 block->Clear();
692                                 BlockPutter putter(block);
693                                 WriteBlock(blocknull);
694                             }
695                             else
696                             {
697                                 blockNumber = 0;
698                                 if (Log())
699                                 {
700                                     LogMessage("fs.root.bmgr.getblocknumber.end""blocknumber=" + ToString(blockNumber) + ".blockoffset=" + ToString(blockOffset));
701                                 }
702                                 return;
703                             }
704                         }
705                         Block* block = ReadBlock(BlockKey(doubleIndirectBlockNumberinode->Key().fsNumber)null);
706                         BlockPutter putter(block);
707                         BlockNumberBlock* doubleIndirectBlock = cast<BlockNumberBlock*>(block);
708                         int singleIndirectBlockNumber = doubleIndirectBlock->GetBlockNumber(logicalBlockNumber / numBlockNumbersInBlock);
709                         if (singleIndirectBlockNumber == 0)
710                         {
711                             if (allocate)
712                             {
713                                 FileSystem* fs = GetMountTable().GetFileSystem(inode->Key().fsNumber);
714                                 singleIndirectBlockNumber = fs->AllocateBlockNumber();
715                                 doubleIndirectBlock->SetBlockNumber(logicalBlockNumber / numBlockNumbersInBlocksingleIndirectBlockNumber);
716                                 WriteBlock(doubleIndirectBlocknull);
717                                 Block* block = GetBlock(BlockKey(singleIndirectBlockNumberinode->Key().fsNumber)null);
718                                 block->Clear();
719                                 BlockPutter putter(block);
720                                 WriteBlock(blocknull);
721                             }
722                             else
723                             {
724                                 blockNumber = 0;
725                                 if (Log())
726                                 {
727                                     LogMessage("fs.root.bmgr.getblocknumber.end""blocknumber=" + ToString(blockNumber) + ".blockoffset=" + ToString(blockOffset));
728                                 }
729                                 return;
730                             }
731                         }
732                         {
733                             Block* block = ReadBlock(BlockKey(singleIndirectBlockNumberinode->Key().fsNumber)null);
734                             BlockPutter putter(block);
735                             BlockNumberBlock* singleIndirectBlock = cast<BlockNumberBlock*>(block);
736                             blockNumber = singleIndirectBlock->GetBlockNumber(logicalBlockNumber % numBlockNumbersInBlock);
737                             if (blockNumber == 0)
738                             {
739                                 if (allocate)
740                                 {
741                                     FileSystem* fs = GetMountTable().GetFileSystem(inode->Key().fsNumber);
742                                     blockNumber = fs->AllocateBlockNumber();
743                                     singleIndirectBlock->SetBlockNumber(logicalBlockNumber % numBlockNumbersInBlockblockNumber);
744                                     WriteBlock(singleIndirectBlocknull);
745                                 }
746                                 else
747                                 {
748                                     if (Log())
749                                     {
750                                         LogMessage("fs.root.bmgr.getblocknumber.end""blocknumber=" + ToString(blockNumber) + ".blockoffset=" + ToString(blockOffset));
751                                     }
752                                     return;
753                                 }
754                             }
755                         }
756                     }
757                     else
758                     {
759                         logicalBlockNumber = logicalBlockNumber - numBlockNumbersInBlock * numBlockNumbersInBlock;
760                         if (logicalBlockNumber < numBlockNumbersInBlock * numBlockNumbersInBlock * numBlockNumbersInBlock)
761                         {
762                             int tripleIndirectBlockNumber = inode->GetTripleIndirectBlockNumber();
763                             if (tripleIndirectBlockNumber == 0)
764                             {
765                                 if (allocate)
766                                 {
767                                     FileSystem* fs = GetMountTable().GetFileSystem(inode->Key().fsNumber);
768                                     tripleIndirectBlockNumber = fs->AllocateBlockNumber();
769                                     inode->SetTripleIndirectBlockNumber(tripleIndirectBlockNumber);
770                                     Block* block = GetBlock(BlockKey(tripleIndirectBlockNumberinode->Key().fsNumber)null);
771                                     block->Clear();
772                                     BlockPutter putter(block);
773                                     WriteBlock(blocknull);
774                                 }
775                                 else
776                                 {
777                                     blockNumber = 0;
778                                     if (Log())
779                                     {
780                                         LogMessage("fs.root.bmgr.getblocknumber.end""blocknumber=" + ToString(blockNumber) + ".blockoffset=" + ToString(blockOffset));;
781                                     }
782                                     return;
783                                 }
784                             }
785                             Block* block = ReadBlock(BlockKey(tripleIndirectBlockNumberinode->Key().fsNumber)null);
786                             BlockPutter putter(block);
787                             BlockNumberBlock* tripleIndirectBlock = cast<BlockNumberBlock*>(block);
788                             int doubleIndirectBlockNumber = tripleIndirectBlock->GetBlockNumber(logicalBlockNumber / (numBlockNumbersInBlock * numBlockNumbersInBlock));
789                             if (doubleIndirectBlockNumber == 0)
790                             {
791                                 if (allocate)
792                                 {
793                                     FileSystem* fs = GetMountTable().GetFileSystem(inode->Key().fsNumber);
794                                     doubleIndirectBlockNumber = fs->AllocateBlockNumber();
795                                     tripleIndirectBlock->SetBlockNumber(logicalBlockNumber / (numBlockNumbersInBlock * numBlockNumbersInBlock)doubleIndirectBlockNumber);
796                                     WriteBlock(tripleIndirectBlocknull);
797                                     Block* block = GetBlock(BlockKey(doubleIndirectBlockNumberinode->Key().fsNumber)null);
798                                     block->Clear();
799                                     BlockPutter putter(block);
800                                     WriteBlock(blocknull);
801                                 }
802                                 else
803                                 {
804                                     blockNumber = 0;
805                                     if (Log())
806                                     {
807                                         LogMessage("fs.root.bmgr.getblocknumber.end""blocknumber=" + ToString(blockNumber) + ".blockoffset=" + ToString(blockOffset));
808                                     }
809                                     return;
810                                 }
811                             }
812                             {
813                                 Block* block = ReadBlock(BlockKey(doubleIndirectBlockNumberinode->Key().fsNumber)null);
814                                 BlockPutter putter(block);
815                                 BlockNumberBlock* doubleIndirectBlock = cast<BlockNumberBlock*>(block);
816                                 int singleIndirectBlockNumber = doubleIndirectBlock->GetBlockNumber((logicalBlockNumber % (numBlockNumbersInBlock * numBlockNumbersInBlock)) / numBlockNumbersInBlock);
817                                 if (singleIndirectBlockNumber == 0)
818                                 {
819                                     if (allocate)
820                                     {
821                                         FileSystem* fs = GetMountTable().GetFileSystem(inode->Key().fsNumber);
822                                         singleIndirectBlockNumber = fs->AllocateBlockNumber();
823                                         doubleIndirectBlock->SetBlockNumber((logicalBlockNumber % (numBlockNumbersInBlock * numBlockNumbersInBlock)) / numBlockNumbersInBlocksingleIndirectBlockNumber);
824                                         WriteBlock(doubleIndirectBlocknull);
825                                         Block* block = GetBlock(BlockKey(singleIndirectBlockNumberinode->Key().fsNumber)null);
826                                         block->Clear();
827                                         BlockPutter putter(block);
828                                         WriteBlock(blocknull);
829                                     }
830                                     else
831                                     {
832                                         blockNumber = 0;
833                                         if (Log())
834                                         {
835                                             LogMessage("fs.root.bmgr.getblocknumber.end""blocknumber=" + ToString(blockNumber) + ".blockoffset=" + ToString(blockOffset));
836                                         }
837                                         return;
838                                     }
839                                 }
840                                 {
841                                     Block* block = ReadBlock(BlockKey(singleIndirectBlockNumberinode->Key().fsNumber)null);
842                                     BlockPutter putter(block);
843                                     BlockNumberBlock* singleIndirectBlock = cast<BlockNumberBlock*>(block);
844                                     blockNumber = singleIndirectBlock->GetBlockNumber((logicalBlockNumber % (numBlockNumbersInBlock * numBlockNumbersInBlock)) % numBlockNumbersInBlock);
845                                     if (blockNumber == 0)
846                                     {
847                                         if (allocate)
848                                         {
849                                             FileSystem* fs = GetMountTable().GetFileSystem(inode->Key().fsNumber);
850                                             blockNumber = fs->AllocateBlockNumber();
851                                             singleIndirectBlock->SetBlockNumber((logicalBlockNumber % (numBlockNumbersInBlock * numBlockNumbersInBlock)) % numBlockNumbersInBlockblockNumber);
852                                             WriteBlock(singleIndirectBlocknull);
853                                         }
854                                         else
855                                         {
856                                             if (Log())
857                                             {
858                                                 LogMessage("fs.root.bmgr.getblocknumber.end""blocknumber=" + ToString(blockNumber) + ".blockoffset=" + ToString(blockOffset));
859                                             }
860                                             return;
861                                         }
862                                     }
863                                 }
864                             }
865                         }
866                         else
867                         {
868                             throw SystemError(EINVAL"file offset too big");
869                         }
870                     }
871                 }
872             }
873             if (Log())
874             {
875                 LogMessage("fs.root.bmgr.getblocknumber.end""blocknumber=" + ToString(blockNumber) + ".blockoffset=" + ToString(blockOffset));
876             }
877         }
878         public override void Flush()
879         {
880             if (Log())
881             {
882                 LogMessage("fs.root.bmgr.flush""begin");
883             }
884             cache.Flush();
885             if (Log())
886             {
887                 LogMessage("fs.root.bmgr.flush""end");
888             }
889         }
890         private void RemoveBlockFromFreeList(Block* block)
891         {
892             cache.RemoveBlockFromFreeList(block);
893         }
894         private void PutBlockToFreeList(Block* blockbool tail)
895         {
896             cache.PutBlockToFreeList(blocktail);
897         }
898         private LinkedList<Block*>* GetFreeBlockList()
899         {
900             return cache.GetFreeBlockList();
901         }
902         private void AddWaitingProcess(Process* process)
903         {
904             cache.AddWaitingProcess(process);
905         }
906         private List<Process*> GetWaitingProcesses()
907         {
908             return cache.GetWaitingProcesses();
909         }
910         private HashMap<BlockKeyBlock*BlockKeyHash> blockMap;
911         private BlockCache cache;
912     }
913 }