File allocation methods and inodes
How the blocks of a file are placed on the disk and found again: contiguous, linked, FAT and indexed allocation with their access costs, the Unix inode with direct and indirect pointers, the maximum file size, the number of disk accesses to read a given block, and the size of a FAT.
Why it exists
A disk offers numbered blocks. A file system must decide which blocks hold which file, and keep enough information to find block number of a file quickly. The choice is a trade between three things: fast access (sequential and direct), efficient use of space (no waste, files that can grow), and small bookkeeping. Four classical methods, contiguous, linked (with its table version, the FAT), indexed and the combined Unix inode scheme, embody different trades. GATE asks, over and over, for the maximum file size of an inode scheme and for the number of disk accesses to read a given block, and for the size of a FAT.
Prerequisites
You need files, directories and inodes from file systems.
Precise definitions
Block. The unit of transfer between disk and memory (512 bytes to a few kilobytes). A file occupies a whole number of blocks; its last block is partly empty (internal fragmentation, on average half a block per file).
Contiguous allocation. Each file occupies a set of consecutive blocks. The directory entry holds the start block and the length.
- Direct access to block : start , one disk access; sequential access is fastest (the head moves little).
- Problems: external fragmentation (free space split into runs too small for a new file), the final size must be known when the file is created (or space is over-reserved), and a file that grows may have to be moved. Compaction is expensive.
Linked allocation. Each file is a linked list of blocks that may be anywhere on the disk; each block holds a pointer to the next. The directory entry holds the first (and often the last) block.
- No external fragmentation, files grow freely.
- Block can be reached only by following pointers: disk accesses for logical block (counting from 0), so direct access is slow.
- The pointer takes space (a block of bytes holds bytes of data); a damaged pointer loses the rest of the file.
File allocation table (FAT). Linked allocation with the pointers stored in a table, with one entry per disk block: the entry of block holds the number of the block that follows it in its file (or a special end-of-file value; unused blocks have entry 0). The directory entry holds the first block. The FAT is cached in memory, so following the chain costs no disk accesses: reading logical block is one disk access (to the data block), and direct access is fast. Disadvantages: the table (all its entries) must be in memory and is big for a big disk.
Indexed allocation. Each file has an index block that holds the block numbers of all its data blocks; entry is the block of logical block . The directory entry points to the index block.
- No external fragmentation; direct access is easy: 2 disk accesses for a block (the index block, then the data block), or 1 if the index block is cached.
- The index block is overhead even for a tiny file. A file with more blocks than an index block can hold needs more than one index block: linked index blocks (the last entry points to the next index block), a multilevel index (an index of index blocks), or the combined scheme.
Combined scheme: the Unix inode. The inode, kept in memory when the file is open, holds the attributes and:
- direct pointers (usually 12) to data blocks,
- one single indirect pointer to a block of pointers to data blocks,
- one double indirect pointer to a block of pointers to blocks of pointers to data blocks,
- one triple indirect pointer, one level deeper again.
With block size and pointer size one indirect block holds pointers. The number of data blocks an inode can address is
(drop the terms of the levels that the inode does not have). Small files use only direct pointers (no extra blocks at all); large files pay for indirect blocks. Disk accesses to read logical block (inode in memory, indirect blocks not cached): if ; if in the single range (); in the double range; in the triple range. (Each level of indirection adds one access.)
Comparison.
| Method | Direct access to block | External fragmentation | Growth | Overhead |
|---|---|---|---|---|
| contiguous | 1 access | yes | hard | none |
| linked | accesses | no | easy | pointer in every block |
| FAT | 1 access (table in memory) | no | easy | the table in memory |
| indexed | 2 accesses (1 if cached) | no | easy up to the index size | index block per file |
| inode | 1 to 4 accesses | no | easy | indirect blocks for large files |
How it works
All the animations use a disk of 32 blocks (the inode one uses 64), drawn as a grid; each block shows the file and logical position it holds (A3 is the fourth block of file A), and the blocks read in a step are numbered in reading order. The panel at the right shows the directory entry, FAT, index block or inode.
Contiguous. File C starts at block 12; reading logical block 3 is one access (block 15). The animation also shows the problem: file B cannot grow because C follows it, and the free space (19 blocks) is split into runs of 2, 3 and 14 so a 15-block file does not fit.
Contiguous allocation: start
Layout built by script, not typedContiguous allocation. Disk of 32 blocks.
| start block | 12 |
| length | 6 |
Step 0
Contiguous allocation: each file occupies a run of consecutive blocks, and its directory entry holds just the START block and the LENGTH. Files A, B and C are stored; the free runs are (0, 2), (6, 3), (18, 14) (start, length).
Linked. File A is the chain 3, 7, 4, 12, 9; reading logical block 4 means reading all five blocks in order: 5 accesses.
Linked allocation: start
Layout built by script, not typedLinked allocation. Disk of 32 blocks.
| first block | 3 |
| last block | 9 |
Step 0
Linked allocation: a file is a chain of blocks that can be ANYWHERE on the disk; each block holds a POINTER to the next (shown as an arrow and a number). The directory entry has only the first and last block of file A. There is no external fragmentation and a file can grow by taking any free block.
FAT. The same chain with the pointers in a table in memory: the walk 3, 7, 4, 12, 9 costs nothing, and the single disk read is block 9.
File allocation table: start
Layout built by script, not typedFAT: linked allocation with the pointers in a table in memory. Disk of 32 blocks.
| 3 | 7 |
| 7 | 4 |
| 4 | 12 |
| 12 | 9 |
| 9 | EOF |
Step 0
File allocation table (FAT): the linked chain, but the POINTERS are moved out of the data blocks into one table, the FAT, with one entry per disk block (the entry of block b is the number of the block that follows it, or EOF). The FAT is read into MEMORY, so following the chain costs no disk accesses. The data blocks hold only data. The directory entry holds the first block (3).
Indexed. File A's index block (20) lists its data blocks; reading logical block 3 reads the index block, then block 11: 2 accesses; the next read, with the index in memory, costs 1.
Indexed allocation: start
Layout built by script, not typedIndexed allocation (one index block per file). Disk of 32 blocks.
| entry 0 | 5 |
| entry 1 | 2 |
| entry 2 | 17 |
| entry 3 | 11 |
| entry 4 | 26 |
Step 0
Indexed allocation: ALL the pointers of a file are gathered in one INDEX BLOCK (block 20); entry i is the block number of logical block i. The directory entry points to the index block. Data blocks can be anywhere, there is no external fragmentation, and direct access is easy. The cost is the index block itself (a file of one block still needs an index block).
Unix inode (toy sizes). Blocks of 32 bytes and 4-byte pointers give 8 pointers per indirect block; the inode has 4 direct pointers, a single and a double indirect pointer. Reading logical block 2 costs 1 access, block 7 costs 2, and block 25 costs 3.
Unix inode allocation: start
Layout built by script, not typedCombined (Unix inode) allocation: direct, single and double indirect pointers. Disk of 64 blocks.
| direct[0] | 1 |
| direct[1] | 2 |
| direct[2] | 3 |
| direct[3] | 4 |
| single indirect | 6 |
| double indirect | 17 |
Step 0
Unix inode allocation (toy sizes): a block is 32 bytes and a pointer 4 bytes, so an indirect block holds 8 pointers. The inode, kept in memory while the file is open, has 4 DIRECT pointers, one SINGLE indirect pointer and one DOUBLE indirect pointer. Small files need no index block at all; larger ones add one or two levels. The file F has 30 blocks: logical blocks 0 to 3 are direct, 4 to 11 go through the single indirect block, and the rest through the double indirect block.
Worked examples
EX 1Maximum file size and access counts, by program
EasyBlock size 1 KB, 4-byte pointers (256 pointers per block), an inode with 12 direct pointers and single, double and triple indirect pointers.
#include <stdio.h>
/* blocks addressable by an inode with `direct` direct pointers and one single, double and triple indirect pointer */
static unsigned long long max_blocks(unsigned direct, unsigned per_block) {
unsigned long long n = direct, p = 1;
for (int level = 1; level <= 3; level++) { p *= per_block; n += p; }
return n;
}
/* disk blocks read to fetch logical block k, with the inode in memory */
static int accesses(unsigned long long k, unsigned direct, unsigned per_block) {
if (k < direct) return 1;
k -= direct;
unsigned long long p = 1;
for (int level = 1; level <= 3; level++) {
p *= per_block;
if (k < p) return 1 + level;
k -= p;
}
return -1;
}
int main(void) {
unsigned block = 1024, ptr = 4, per = block / ptr;
unsigned long long n = max_blocks(12, per);
printf("block %u bytes, pointer %u bytes: %u pointers per block\n", block, ptr, per);
printf("12 direct + single + double + triple: %llu blocks, %.2f GB\n", n, (double)n * block / (1024.0 * 1024 * 1024));
printf("direct only: %u KB; with the single indirect block: %u KB\n", 12 * block / 1024, (12 + per) * block / 1024);
unsigned long long ks[7] = {0, 11, 12, 267, 268, 65803, 65804};
printf("disk accesses for logical blocks:");
for (int i = 0; i < 7; i++) printf(" %llu->%d", ks[i], accesses(ks[i], 12, per));
printf("\n");
/* 512-byte blocks, 4-byte pointers, 10 direct, single and double indirect only */
unsigned long long m = 10 + 128 + 128ull * 128;
printf("10 direct + single + double with 512-byte blocks: %llu blocks, %llu KB\n", m, m * 512 / 1024);
/* FAT: a 16 GB disk with 4 KB blocks */
unsigned long long blocks = (16ull << 30) / 4096;
int bits = 0;
while ((1ull << bits) < blocks) bits++;
printf("FAT for a 16 GB disk with 4 KB blocks: %llu entries of %d bits (stored in 4 bytes): %llu MB\n", blocks, bits, blocks * 4 / (1024 * 1024));
printf("linked allocation: %d data bytes in a 512-byte block, %d in a 4096-byte block\n", 512 - 4, 4096 - 4);
return 0;
}block 1024 bytes, pointer 4 bytes: 256 pointers per block
12 direct + single + double + triple: 16843020 blocks, 16.06 GB
direct only: 12 KB; with the single indirect block: 268 KB
disk accesses for logical blocks: 0->1 11->1 12->2 267->2 268->3 65803->3 65804->4
10 direct + single + double with 512-byte blocks: 16522 blocks, 8261 KB
FAT for a 16 GB disk with 4 KB blocks: 4194304 entries of 22 bits (stored in 4 bytes): 16 MB
linked allocation: 508 data bytes in a 512-byte block, 4092 in a 4096-byte blockReading it. The inode addresses blocks, 16.06 GB at 1 KB per block. The ranges of logical blocks and their costs: 0 to 11 direct (1 access), 12 to 267 single indirect (2), 268 to 65803 double (3), 65804 on triple (4). The second case (512-byte blocks, no triple indirect pointer) has 128 pointers per block and blocks, about 8.07 MB. The FAT for the big disk takes 16 MB of memory, which is why a FAT is used on small disks and for removable media.
EX 2Reading the toy inode
MediumBlocks of 32 bytes, pointers of 4 bytes: 8 pointers per indirect block; 4 direct pointers, one single and one double indirect. Logical blocks 0 to 3 are direct. Logical block 7: after the 4 direct blocks, is entry 3 of the single indirect block: read the indirect block, then the data block: 2 accesses. Logical block 25: ; the single indirect range holds 8, so is in the double range; : entry 1 of the double indirect block names an inner indirect block, whose entry 5 names the data block: 3 accesses (double, inner, data). The largest file here has blocks. A search over every logical block of several toy inode shapes confirmed that each maps to a distinct pointer path and that their number equals .
EX 3Which method suits which need?
MediumA file that is written once and read in order (a video, a backup): contiguous allocation (fast sequential reading) if the size is known. A file that grows by appending (a log): linked, FAT, indexed or inode (no relocation). Fast random access to any block of a big file: indexed, FAT or inode, not plain linked (it needs accesses). No external fragmentation: all but contiguous. The disk must be usable by a small system with very little memory: not the FAT (its table must be in memory). Mostly small files: the inode (no index block at all for the first 12 blocks).
EX 4Maximum size with 4 KB blocks
GATE levelBlocks of 4 KB, 4-byte pointers: pointers per block. An inode with 12 direct pointers, one single and one double indirect pointer addresses blocks, which is bytes, a little over 4 GB (4 GB 4 MB 48 KB). With only direct and single indirect pointers the maximum would be KB KB. A change of pointer size changes : with 8-byte pointers and 4 KB blocks, . The disk size can limit it too: a pointer of bytes can number at most blocks, so with 4-byte pointers the disk addressable is at most blocks. Questions often ask the maximum file size and then ask for the number of disk accesses to read the last block of that maximum file: with the triple indirect pointer in use, 4.
EX 5Contiguous against linked
GATE levelA file of 100 blocks. Reading block 60 (counting from 0): contiguous 1 access; linked accesses; FAT 1; indexed 2 (or 1 if the index is cached). Reading the whole file sequentially: contiguous 100 accesses with very short head movements; linked 100 accesses, but the blocks may be scattered, so each access needs a seek. Appending 10 blocks: linked just takes 10 free blocks and fixes pointers; contiguous may need to move the whole file if the next blocks are used. The external fragmentation example in the first animation: 19 free blocks in runs of 2, 3 and 14 cannot hold a file of 15 blocks.
Cheat box
Cheat box
- Contiguous: start and length; 1 access; external fragmentation; hard to grow. Linked: pointer in each block; accesses; no fragmentation; pointer overhead per block.
- FAT: table with one entry per BLOCK in memory; 1 disk access; size blocks entry size, entry bits.
- Indexed: index block; 2 accesses (1 if cached). Pointers per block .
- Inode: direct, single, double, triple. Max blocks ; max size blocks .
- Accesses to block (inode in memory): 1 direct, 2 single, 3 double, 4 triple.
- Internal fragmentation: half a block per file on average.
Traps and GATE patterns
Connections
Unlocks
Across subjects
No cross-subject links yet.
Each method rests on the files and inodes of file systems. Contiguous allocation has the external fragmentation of contiguous memory allocation, and the inode's levels of pointers are the same idea as a multilevel page table: the number of levels adds one access each. Where the blocks lie decides how far the head must move, which is the subject of disk scheduling.
PYQs
8 previous year questions from your book. I re-solved each one myself (6 by running or simulating, 2 by reasoning only); the book's key is shown next to my answer. All PYQs
A disk of size 512M bytes is divided into blocks of 64K bytes. A file is stored in the disk using linked allocation. In linked allocation, each data block reserves 4 bytes to store the pointer to the next data block. The link part of the last data block contains a NULL pointer (also of 4 bytes). Suppose a file of 1M bytes needs to be stored in the disk. Assume, 1K = 210 and 1M = 220. The amount of space in bytes that will be wasted due to internal fragmentation is ______. (Answer in integer)
A disk of size 512 M bytes is divided into blocks of 64 K bytes. A file is stored in the disk using linked allocation. In linked allocation, each data block reserves 4 bytes to store the pointer to the next data block. The link part of the last data block contains a NULL pointer (also of 4 bytes). Suppose a file of 1 M bytes needs to be stored in the disk. Assume, 1 K = 210and 1 M = 220. The amount of space in bytes that will be wasted due to internal fragmentation is ______
Consider two files systems A and B, that use contiguous allocation and linked allocation, respectively. A file of size 100 blocks is already stored in A and also in B. Now, consider inserting a new block in the middle of the file (between 50th and 51st block), whose data is already available in the memory. Assume that there are enough free blocks at the end of the file and that the file control blocks are already in memory. Let the number of disk accesses required to insert a block in the middle of the file in A and B are nA and nB, respectively, then the value of nA+nB is__________________.
The index node (inode) of a Unix-like file system has 12 direct, one single-indirect and one double-indirect pointers. The disk block size is 4 kB, and the disk block address is 32-bits long. The maximum possible file size is (rounded off to 1 decimal place) ______ GB.
In a file allocation system, which of the following allocation scheme(s) can be used if no external fragmentation is allowed? 1. Contiguous 2. Linked 3. Indexed
- (a)1 and 3 only
- (b)2 only
- (c)3 only
- (d)2 and 3 only
A FAT (file allocation table) based file system is being used and the total overhead of each entry in the FAT is 4 bytes in size. Given a 100 × 106 bytes disk on which the file system is stored and data block size is 103 bytes, the maximum size of a file that can be stored on this disk in units of 106 bytes is ____________. OPERATING SYSTEMS
A file system with 300 Gbyte disk uses a file descriptor with 8 direct block addresses, 1 indirect block address and 1 doubly indirect block address. The size of each disk block is 128 Bytes and the size of each disk block address is 8 Bytes. The maximum possible file size in this file system is
- (a)3 KBytes
- (b)35 KBytes
- (c)280 Kbytes
- (d)dependent on the size of the disk
The data blocks of a very large file in the Unix file system are allocated using
- (a)contiguous allocation
- (b)linked allocation
- (c)indexed allocation
- (d)an extension of indexed allocation
Self-check
Question 1
Blocks of 512 bytes, 4-byte pointers, an inode with 10 direct pointers and one single indirect pointer. Maximum file size?
Show answerHide
. Blocks ; size bytes (69 KB).
Question 2
Same inode (with also a double indirect pointer). How many disk accesses to read logical block 200 (counting from 0)?
Show answerHide
Direct 0 to 9, single 10 to 137; , so it is in the double range: 3 accesses.
Question 3
A FAT disk has 2 million blocks. How many bits must each entry have at least, and how big is the table with 4-byte entries?
Show answerHide
bits (since ). With 4-byte entries: bytes, about 7.6 MB.
Question 4
Which allocation method needs no extra disk access to find block of a file once the file is open, and does not suffer external fragmentation?
Show answerHide
The FAT (the chain is followed in memory, one access reads the data); an inode with only direct pointers also qualifies for small files.
Revision card
One-screen revision
- Contiguous: start, length, 1 access, external fragmentation. Linked: . FAT: table of blocks in memory, 1 access. Indexed: index block, 2 accesses.
- Inode: ; blocks ; accesses 1, 2, 3, 4 by range.
- FAT size blocks entry size; entry bits.
References
- ·Silberschatz, Galvin, Gagne, Operating System Concepts, Chapter 14 File-System Implementation (allocation methods)
- ·Tanenbaum and Bos, Modern Operating Systems, Chapter 4 File Systems (implementing files, i-nodes)
- ·Stallings, Operating Systems: Internals and Design Principles, Chapter 12 File Management (file allocation)
Verification
Each layout is built by a script (scripts/gen-os-fs-traces.py) and the blocks read for a logical block are computed by following the on-disk structure (the chain, the FAT, the index block, the inode pointers); tests/os-fs-traces.test.ts rebuilds each path from the cells' own labels and notes and rechecks the read order and the access counts, and scripts/enum-checks/os_fs.py checks by brute force that a toy inode (several sizes) maps every logical block to a distinct pointer path and that their number equals the formula. The size and access-count figures (16843020 blocks = 16.06 GB for 12 direct + 256 + 256^2 + 256^3 blocks of 1 KB; 16522 blocks for the 512-byte-block case; a 16 MB FAT for a 16 GB disk with 4 KB blocks) are exact arithmetic checked in Python and by the C program on this page (npm run verify:c). Conventions that change answers: the inode is in memory when the file is open; the index or indirect blocks are not cached; a pointer is 4 bytes unless stated; the FAT is in memory. Textbook chapter titles are from memory. SECOND PASS (2026-11-02, done by the assistant, not a human check): every Self-check question was solved before the printed answer was read and all agreed; the definitions, worked examples, cheat box and traps were read claim by claim and the numbers re-derived by hand. No defect found. Status raised to self-checked; verified needs a textbook or human check.
last verified: never
My notes (saved in this browser)