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(0, fsNumber), 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 + i, fsNumber), superBlock);
31 block->Clear();
32 }
33 else
34 {
35 block = fs->GetBlockManager()->ReadBlock(BlockKey(firstNumber + i, fsNumber), 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(block, superBlock);
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(0, fsNumber), 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 + bitmapBlockIndex, superBlock->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(block, superBlock);
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(), manager, this);
88 blocks.Add(UniquePtr<Block>(block));
89 freeBlockList.Add(block);
90 block->SetIterator(LinkedList<Block*>.Iterator(&freeBlockList, freeBlockList.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* block, bool tail)
103 {
104 if (tail)
105 {
106 freeBlockList.Add(block);
107 block->SetIterator(LinkedList<Block*>.Iterator(&freeBlockList, freeBlockList.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(processes, waitingProcesses);
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(block, null);
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(this, maxCachedBlocks)
153 {
154 }
155 public override nothrow string Name() const
156 {
157 return "fs.root.bmgr";
158 }
159 public override Block* GetBlock(const BlockKey& key, SuperBlock* sb, bool sleep, bool setOwner)
160 {
161 if (Log())
162 {
163 LogMessage("fs.root.bmgr.getblock.begin", key.ToString());
164 }
165 while (true)
166 {
167 HashMap<BlockKey, Block*, 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(process, blockUnlockedEvent, cast<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(process, anyBlockFreeEvent, 0u, 0u);
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(block, sb);
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(block, true);
273 }
274 else
275 {
276 PutBlockToFreeList(block, false);
277 }
278 List<Process*> anyProcesses = GetWaitingProcesses();
279 Kernel& kernel = GetKernel();
280 ProcessTable& processTable = kernel.GetProcessTable();
281 for (Process* process : anyProcesses)
282 {
283 WakeUpProcess(processTable, process);
284 }
285 List<Process*> blockProcesses = block->GetWaitingProcesses();
286 for (Process* process : blockProcesses)
287 {
288 WakeUpProcess(processTable, process);
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& key, SuperBlock* sb)
298 {
299 if (Log())
300 {
301 LogMessage("fs.root.bmgr.readblock.begin", key.ToString());
302 }
303 Block* block = GetBlock(key, sb);
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* block, SuperBlock* 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(blockNumber, superBlock);
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(blockNumber, inode->Key().fsNumber), null);
353 block->Clear();
354 BlockPutter putter(block);
355 WriteBlock(block, null);
356 fs->SetBlockFree(blockNumber);
357 inode->SetDirectBlockNumber(i, 0);
358 }
359 }
360 int singleIndirectBlockNumber = inode->GetSingleIndirectBlockNumber();
361 if (singleIndirectBlockNumber != 0)
362 {
363 Block* block = ReadBlock(BlockKey(singleIndirectBlockNumber, inode->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(blockNumber, inode->Key().fsNumber), null);
372 block->Clear();
373 BlockPutter putter(block);
374 WriteBlock(block, null);
375 fs->SetBlockFree(blockNumber);
376 }
377 }
378 singleIndirectBlock->Clear();
379 WriteBlock(singleIndirectBlock, null);
380 fs->SetBlockFree(singleIndirectBlockNumber);
381 inode->SetSingleIndirectBlockNumber(0);
382 }
383 int doubleIndirectBlockNumber = inode->GetDoubleIndirectBlockNumber();
384 if (doubleIndirectBlockNumber != 0)
385 {
386 Block* block = ReadBlock(BlockKey(doubleIndirectBlockNumber, inode->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(singleIndirectBlockNumber, inode->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(blockNumber, inode->Key().fsNumber), null);
403 block->Clear();
404 BlockPutter putter(block);
405 WriteBlock(block, null);
406 fs->SetBlockFree(blockNumber);
407 }
408 }
409 singleIndirectBlock->Clear();
410 WriteBlock(singleIndirectBlock, null);
411 fs->SetBlockFree(singleIndirectBlockNumber);
412 }
413 }
414 doubleIndirectBlock->Clear();
415 WriteBlock(doubleIndirectBlock, null);
416 fs->SetBlockFree(doubleIndirectBlockNumber);
417 inode->SetDoubleIndirectBlockNumber(0);
418 }
419 int tripleIndirectBlockNumber = inode->GetTripleIndirectBlockNumber();
420 if (tripleIndirectBlockNumber != 0)
421 {
422 Block* block = ReadBlock(BlockKey(tripleIndirectBlockNumber, inode->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(doubleIndirectBlockNumber, inode->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(singleIndirectBlockNumber, inode->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(blockNumber, inode->Key().fsNumber), null);
447 block->Clear();
448 BlockPutter putter(block);
449 WriteBlock(block, null);
450 fs->SetBlockFree(blockNumber);
451 }
452 }
453 singleIndirectBlock->Clear();
454 WriteBlock(singleIndirectBlock, null);
455 fs->SetBlockFree(singleIndirectBlockNumber);
456 }
457 }
458 doubleIndirectBlock->Clear();
459 WriteBlock(doubleIndirectBlock, null);
460 fs->SetBlockFree(doubleIndirectBlockNumber);
461 }
462 }
463 tripleIndirectBlock->Clear();
464 WriteBlock(tripleIndirectBlock, null);
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* inode, int 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(singleIndirectBlockNumber, inode->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(doubleIndirectBlockNumber, inode->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(singleIndirectBlockNumber, inode->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(tripleIndirectBlockNumber, inode->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(doubleIndirectBlockNumber, inode->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(singleIndirectBlockNumber, inode->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* inode, long offset, int& blockNumber, int& blockOffset, bool 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(logicalBlockNumber, blockNumber);
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(singleIndirectBlockNumber, inode->Key().fsNumber), null);
640 block->Clear();
641 BlockPutter putter(block);
642 WriteBlock(block, null);
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(singleIndirectBlockNumber, inode->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(logicalBlockNumber, blockNumber);
665 WriteBlock(singleIndirectBlock, null);
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(doubleIndirectBlockNumber, inode->Key().fsNumber), null);
691 block->Clear();
692 BlockPutter putter(block);
693 WriteBlock(block, null);
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(doubleIndirectBlockNumber, inode->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 / numBlockNumbersInBlock, singleIndirectBlockNumber);
716 WriteBlock(doubleIndirectBlock, null);
717 Block* block = GetBlock(BlockKey(singleIndirectBlockNumber, inode->Key().fsNumber), null);
718 block->Clear();
719 BlockPutter putter(block);
720 WriteBlock(block, null);
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(singleIndirectBlockNumber, inode->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 % numBlockNumbersInBlock, blockNumber);
744 WriteBlock(singleIndirectBlock, null);
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(tripleIndirectBlockNumber, inode->Key().fsNumber), null);
771 block->Clear();
772 BlockPutter putter(block);
773 WriteBlock(block, null);
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(tripleIndirectBlockNumber, inode->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(tripleIndirectBlock, null);
797 Block* block = GetBlock(BlockKey(doubleIndirectBlockNumber, inode->Key().fsNumber), null);
798 block->Clear();
799 BlockPutter putter(block);
800 WriteBlock(block, null);
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(doubleIndirectBlockNumber, inode->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)) / numBlockNumbersInBlock, singleIndirectBlockNumber);
824 WriteBlock(doubleIndirectBlock, null);
825 Block* block = GetBlock(BlockKey(singleIndirectBlockNumber, inode->Key().fsNumber), null);
826 block->Clear();
827 BlockPutter putter(block);
828 WriteBlock(block, null);
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(singleIndirectBlockNumber, inode->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)) % numBlockNumbersInBlock, blockNumber);
852 WriteBlock(singleIndirectBlock, null);
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* block, bool tail)
895 {
896 cache.PutBlockToFreeList(block, tail);
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<BlockKey, Block*, BlockKeyHash> blockMap;
911 private BlockCache cache;
912 }
913 }