if (offset > file[0]) { flag error }
The next 13 words are pointers to the first thirteen blocks of the file:
if (bn < 13) {
get_block(buf, file[bn+1]);
return buf[bo];
}
The 14th word is a pointer to a block of cached block pointers.
It contains pairs of file block numbers and
disk pointers. So if a block number is thirteen or greater, before
we try to find it elsewhere, we check the cache:
get_block(buf,file[14]);
ip = (int *) buf;
for (i = 0; i < ibs; i += 2) {
if (ip[i] == bn) {
get_block(buf, ip[i+1]);
return buf[bo];
}
}
Finally, the last block is a pointer to a triple indirect block,
as described in section 11.2.3 of the book (indexed allocation).
That block contains pointers to blocks (level 1).
The blocks pointed to by level 1 pointers contain pointers to blocks
(level 2).
And the
The blocks pointed to by level 2 pointers contain pointers to blocks
(level 3).
These pointers point to file blocks.
bn -= 13; ib1n = bn / ibs; ib1o = bn % ibs; ib2n = ib1n / ibs; ib2o = ib1n % ibs; get_block(buf, file[15]); get_block(buf, buf[ib2n]); get_block(buf, buf[ib2o]); get_block(buf, buf[ib1o]); return buf[bo];So, for example, to get block 13, you have get the block in file[15] to get the first level 1 pointer. Use that to get the level 1 block, and the first level 2 pointer. Use that to get the level 2 block, and the first level 3 pointer. Use that to get the level 3 block, and the pointer to file block 13.Now, motivationally, this structure works well for small files, but holds arbitrarily big files too. If we cache recently-used blocks (or perhaps cache based on lookahead) in our disk-reading routines, then we can use the cache block to improve performance when getting blocks greater than number 12.
Part 2
The first 13 pointers are responsible for 128 bytes each, and the last pointer is responsible for 32*32*32*128 = 2^22 bytes (roughly 4 megabytes). The whole expression is:
(13 * 128) + (32 * 32 * 32 * 128) = 4,195,968 bytes
Grading
Only one student got the fact that file[14] was meant to be a cache -- well done!