An ext2 file's inode
points to the first 12 blocks of the file directly. But rather
than a linked list, for longer files inodes use an "indirect"
block--they store the block number of a block that contains the numbers
of the other blocks. For files too long to fit the block list in
a single block, they have a "double indirect" block (points to a block
that points to blocks that point to blocks!), and for crazy-long files,
they have a "triple indirect" pointer, something like this:
struct ext2_inode {
...
int data_blocks[12]; /* points to first 12 blocks in file (block *) */
int ind_block; /* block that lists the next 1K blocks (block **) */
int dind_block; /* block -> block -> blocks (block ***) */
int tind_block; /* block -> block -> block -> blocks (block ****) */
};