Introduction

A disk is an array of fixed-size blocks, and a file is a sequence of logical blocks 0, 1, 2 and so on. The allocation method decides which disk blocks hold a file and how the file system finds logical block ii. The choice fixes three quantities: how many disk accesses a read of block ii costs, how large a file can be, and how much space is wasted.

There are three classical methods: contiguous, linked (with its table form, the FAT) and indexed (with the UNIX inode as its multilevel form). The file system must also remember which blocks are free, using a bit vector, a free list, grouping or counting. Each method is given with the arithmetic that goes with it.

Prerequisites

Core concepts

Conventions. Logical blocks are numbered from 0. "Accesses" counts disk-block reads needed to fetch one data block, with the directory entry or inode already in memory unless stated otherwise. Block numbers (disk addresses) are 4 bytes.

MethodDirectory or inode holdsRead logical block iiExternal fragmentationGrowth
ContiguousStart block, length1 access: block start +i+ iYesHard: the next blocks may be in use
LinkedFirst (and last) block; each block holds a pointer to the nexti+1i + 1 accesses (follow the chain)NoEasy
FATFirst block; a table in memory holds the next-block pointers1 disk access once the FAT is cachedNoEasy
IndexedAddress of an index block listing all data blocks2 accesses (index block, data)NoEasy, up to the index size

How each method works

Contiguous, linked and indexed allocation
Figure 1. One 32-block disk shown three times. Contiguous: file a starts at block 14 with length 6. Linked: file b occupies blocks 7, 21, 3, 12 and 28, each pointing to the next. Indexed: file c has the same five data blocks listed in index block 9.

Contiguous allocation

The file occupies blocks start, start +1+ 1, ..., start ++ length −1- 1. File a in Figure 1 has start 14 and length 6: blocks 14 to 19, and logical block 4 is disk block 18. Both sequential and direct access are fast, and sequential reads need almost no seeking. The costs are those of Contiguous Memory Allocation and Fragmentation: choosing a hole by first fit or best fit, external fragmentation, and the need to know the final size in advance. Some systems allocate a contiguous extent and link further extents when the file grows.

Linked allocation

Each block stores the address of the next block of the file; the directory holds the first block (and often the last, for appending). File b has the chain 7, 21, 3, 12, 28, and the last block holds a null pointer. To read logical block 3, the system reads blocks 7, 21 and 3 for their pointers and then block 12: 4 accesses, and in general i+1i + 1 for logical block ii.

  • No external fragmentation, and a file can grow while free blocks exist.
  • Only sequential access is efficient.
  • Each block loses space to the pointer: with 512-byte blocks and 4-byte pointers, 508 bytes hold data, a loss of 0.78%. Grouping blocks into clusters reduces the loss and the number of seeks, at the price of internal fragmentation.
  • One damaged pointer loses the rest of the file.

File-allocation table (FAT)

The FAT moves all the next-block pointers into one table with an entry per disk block, kept at the start of the volume and cached in memory. Entry kk holds the number of the block that follows block kk in its file, an end-of-file mark, or 0 for a free block. For file b:

Block37122128
FAT entry1221283EOF

The directory entry holds 7. Finding logical block ii means following ii entries in memory, then one disk access. The table is large, though: a 2 GB volume with 4 KB blocks has 231/212=2192^{31}/2^{12} = 2^{19} blocks, and with 4-byte entries the FAT occupies 2 MB. The FAT width limits the volume: FAT-16 addresses at most 2162^{16} blocks, so with 32 KB blocks the largest volume is 2 GB (Tanenbaum 4.5.1).

Indexed allocation

Each file has an index block: an array of disk-block addresses, entry ii giving logical block ii. File c's index block is block 9 and holds 7, 21, 3, 12, 28 and then null entries. Reading any block takes 2 accesses (index block, then data); with the index block cached, 1. Direct access is fast and there is no external fragmentation, but every file, however small, costs a whole index block.

When one index block is not enough:

  • Linked scheme: the last entry of an index block points to the next index block.
  • Multilevel index: a first-level block points to second-level index blocks, which point to data. With 4 KB blocks and 4-byte addresses, an index block holds 1,024 addresses, and two levels address 102421024^2 blocks, a 4 GB file.
  • Combined scheme (UNIX inode): a few direct pointers for small files plus single, double and triple indirect pointers.

The UNIX inode and maximum file size

Inode with direct and indirect pointers
Figure 2. An inode with 12 direct pointers and one single, one double and one triple indirect pointer, for 4 KB blocks and 4-byte addresses (1,024 addresses per index block). The highlighted path finds logical block 5,000: double indirect pointer, entry 3 of the first-level block, entry 892 of the second-level block.

Let the block size be BB bytes and the address size aa bytes, so an index block holds N=B/aN = B/a addresses. With dd direct pointers and one each of single, double and triple indirect:

max file size=(d+N+N2+N3)×B.\text{max file size} = \left(d + N + N^2 + N^3\right) \times B .

For d=12d = 12, B=4B = 4 KB and a=4a = 4 bytes, N=1024N = 1024:

PartBlocksBytes
Direct1248 KB
Single indirect1,0244 MB
Double indirect1,048,5764 GB
Triple indirect1,073,741,8244 TB
Total1,074,791,4364,402,345,721,856 bytes, a little over 4 TB

Check the address width too. A 4-byte block address can name 2322^{32} blocks, so with 4 KB blocks the whole file system is limited to 16 TB. In this example the pointers, not the address width, limit the file size; with larger blocks or more indirection the address width can become the binding limit.

Second example. An inode with 10 direct pointers, one single and one double indirect pointer, 1 KB blocks and 4-byte addresses: N=256N = 256, so the largest file is (10+256+65,536)×1(10 + 256 + 65{,}536) \times 1 KB =65,802= 65{,}802 KB.

Which pointer serves block ii?

With d=12d = 12 and N=1024N = 1024: logical blocks 0 to 11 are direct; 12 to 1,035 go through the single indirect block; 1,036 to 1,049,611 through the double indirect block; the rest through the triple indirect block.

  • Logical block 5,000: 5000−1036=3964=3×1024+8925000 - 1036 = 3964 = 3 \times 1024 + 892, so it is entry 892 of the second-level block found at entry 3 of the double indirect block. With the inode in memory, reading it costs 3 accesses (double indirect block, second-level block, data).
  • Byte offset 20,000,000: ⌊20,000,000/4096⌋=4882\lfloor 20{,}000{,}000 / 4096 \rfloor = 4882 with remainder 3,328, so the byte is at offset 3,328 of logical block 4,882, which is also in the double indirect range (entry 3, then entry 774).

The cost of reading block ii, with the inode cached, is 1 access for a direct block, 2 for single indirect, 3 for double and 4 for triple. If the inode must be read first, add 1.

When the address width binds, and the cost of the index blocks

Address width binding. 8 KB blocks, 4-byte block addresses, 12 direct pointers and one each of single, double and triple indirect. An index block holds N=8192/4=2048N = 8192/4 = 2048 addresses, so the pointers reach

12+211+222+233 blocks≈233×213 bytes=246 bytes=64 TB.12 + 2^{11} + 2^{22} + 2^{33} \text{ blocks} \approx 2^{33} \times 2^{13} \text{ bytes} = 2^{46} \text{ bytes} = 64 \text{ TB}.

But a 4-byte address names only 2322^{32} blocks, 232×82^{32} \times 8 KB =245= 2^{45} bytes =32= 32 TB. A file cannot use more blocks than the volume can number, so the largest file is limited to 32 TB by the address width, not by the pointers.

Wider addresses. With 8-byte addresses and the same 8 KB blocks, N=1024N = 1024 and the pointers reach 12+210+220+23012 + 2^{10} + 2^{20} + 2^{30} blocks, a little over 230×82^{30} \times 8 KB =8= 8 TB. A 64-bit address no longer limits anything, so now the pointers bind. Doubling the address size halves NN and cuts the triple-indirect reach by a factor of 8.

Index blocks used by one file. With d=12d = 12 and N=1024N = 1024 (4 KB blocks, 4-byte addresses), a file of 5,000 blocks uses the 12 direct pointers, the single indirect block for blocks 12 to 1,035, and the double indirect block for the remaining 5000−1036=39645000 - 1036 = 3964 blocks. Those need ⌈3964/1024⌉=4\lceil 3964 / 1024 \rceil = 4 second-level blocks. Index blocks in all: 1+1+4=61 + 1 + 4 = 6, so the file occupies 5,006 blocks on disk.

Free-space management

Bit vector (bitmap)

One bit per block. Convention: as in Silberschatz 14.5, bit 1 means the block is free and 0 that it is allocated; some texts use the opposite, so check the question. To find the first free block, skip words that are all 0, then find the first 1 bit:

block=(bits per word)×(number of all-zero words)+(offset of the first 1 bit).\text{block} = (\text{bits per word}) \times (\text{number of all-zero words}) + (\text{offset of the first 1 bit}).

Example. With 8-bit words, bitmap 00000000 00000000 00101100 ... (bits numbered from the left within a word): two all-zero words, then the first 1 is at offset 2, so the first free block is 8×2+2=188 \times 2 + 2 = 18. The free blocks in the third word are 18, 20 and 21.

Size. The bitmap for a 2 GB volume with 4 KB blocks has 2192^{19} bits = 64 KB. For 1 TB with 4 KB blocks: 2282^{28} bits = 32 MB. A bitmap is fast only if it is cached in memory, so its size matters.

Free list, grouping and counting

  • Linked free list: each free block points to the next free one; allocating one block is O(1)O(1), but traversing the list needs a read per block (rarely needed).
  • Grouping: the first free block holds the addresses of nn free blocks; the last of these holds the next nn, so many free addresses come from one read.
  • Counting: store (first block, count) pairs for runs of consecutive free blocks. The free blocks 2, 3, 4, 5, 8, 9, 10, 17, 18, 25, 26 and 27 become (2, 4), (8, 3), (17, 2), (25, 3).

Bitmap or free list? A disk of 2202^{20} blocks of 1 KB needs a 128 KB bitmap (128 blocks) whatever its state. A free list stored as blocks of free addresses (255 four-byte addresses per 1 KB block, plus a pointer to the next such block) needs 40 blocks when 10,000 blocks are free, but 4,113 blocks when all 2202^{20} are free. The list is smaller on a nearly full disk; the bitmap is smaller on an empty one (Tanenbaum 4.4.1).

Important properties and observations

  • Only contiguous allocation has external fragmentation; it also gives the fastest sequential and direct access.
  • Linked allocation supports only sequential access efficiently; the FAT removes the per-block disk reads by caching the pointers.
  • Indexed allocation supports direct access; small files waste most of their index block, which the inode's direct pointers avoid.
  • Maximum file size grows with block size twice: bigger blocks hold more data and more addresses per index block.
  • A bitmap's size depends only on the disk size; a free list's size depends on how much is free.

Common misconceptions.

  • "Linked allocation has no overhead." Each block loses the pointer space, and a lost pointer loses the rest of the file.
  • "Indexed allocation needs one access per block." It needs the index block too, unless that is cached.
  • "The triple indirect pointer adds three levels of blocks." It adds three levels of index blocks above the data, so a triple-indirect block costs 4 reads with the inode cached.

GATE examination perspective

  • Maximum file size. Compute N=B/aN = B/a, add the direct, single, double and triple contributions, and check the address-width limit.
  • Which pointer, how many accesses. Subtract the direct and single ranges, then divide by NN for the indices; count accesses and say whether the inode is cached.
  • Linked versus indexed access counts. Linked: i+1i + 1 reads; indexed: 2 (1 with the index cached); contiguous: 1.
  • FAT and bitmap sizes. Number of blocks times the entry width; one bit per block for the bitmap.
  • Bitmap search. Know the convention (1 free or 0 free) and the bit order within a word.
  • Counting and grouping. Turn a free-block list into runs, or follow a grouping chain.

Summary

Sources

  1. A. Silberschatz, P. B. Galvin, G. Gagne, Operating System Concepts, 10th ed., Wiley: Chapter 14 (14.4 Allocation Methods, 14.5 Free-Space Management).
  2. A. S. Tanenbaum, H. Bos, Modern Operating Systems, 4th ed., Pearson: Chapter 4 (4.3.2 Implementing Files, 4.4.1 Disk-Space Management, 4.5.1 The MS-DOS File System, 4.5.2 The UNIX V7 File System).

Next steps