Copy-on-Write principle in ZFS

From Thomas-Krenn-Wiki
Jump to navigation Jump to search

Copy-on-Write is an optimization principle of data processing in which changes are not made directly to the existing data set, but are always written to a new copy. As the cornerstone of the ZFS file system's storage strategy, CoW, in combination with transaction groups, ensures that an interrupted write operation can never result in an inconsistent file system. This is why ZFS stands out from classic file systems that overwrite the data completely.

Copy-on-Write principle

For write operations based on the CoW principle, data blocks are not overwritten when changes are made. Instead, new data blocks are written with the changes, and the old data blocks are simply overwritten. To receive the consistency of the data, CoW works with a reference system that is also known as Hash-Tree (or Merkle-Tree)[1]. With the help of this system it is ensured that errors in data integrity can be noticed all time.

The tree structure

Image 1: A simple Hash-tree.
1st image: A simple hash tree

In the first image, a simplified view of a hash tree is represented:

  • At the endpoints of the trees, that are also called leaves, the data blocks can be found.
  • The nodes above, inner nodes or branches, include block pointers. Every of these pointers includes information on the underlying blocks, for example the physical location of the data, the size of blocks as well as the number of the transaction group (Birth-TXG), in which the block has been written to. The most important information, however, is the check sum.
  • At the top level, the uberblock is located. This value is unique within a zpool and is recalculated after every write operation. It includes the check sum from which can be used to verify all data contained in zpool.

Application in transaction groups

ZFS stores the data in so-called transaction groups (txg) in the RAM of the system. After a determined timeline, the default setting is 5 seconds, or when enough data has been collected, all changes collected in the transaction group are committed simultaneously[2].

With this procedure, it is ensured that an inconsistent data set is excluded by an interrupted writing process.

Either the txg is committed: Then a new "uberblock" was created, and the file system is now consistent.

Or the txg has not been committed: In that case, the old "uberblock" is considered current, and the file system is also consistent (just older).

The writing process

2nd image: After a writing process, the replaced blocks are released. The unchanged blocks remain untouched[2].

In the second image, the condition of the file system can be seen with Copy-on-Write after a writing process. The following steps have contributed to this result:

  1. A change makes it necessary to replace the data in the block D4
  2. A new block D4' is created that includes the new data
  3. The new block should be included into the Hash-tree. For this, it is necessary to form a new inode2, which is described with inode2' here. This step is necessary, as the checksum must be recalculated for all parent nodes
  4. As described in step 3, root and uberblock are also recreated
  5. The inner nodes are reconnected with the unchanged nodes and the check sums are reformed. The new data blocks are now integrated

With the integration of the new data block, the old data block D4 was replaced and released, just like all parent nodes. As long as there is no snapshot that references the old block, it can be reused for future write operations.

Consequences of CoW-strategy

CoW gives rise to some of ZFS's most important features as a logical consequence. However, this also highlights some of ZFS's weaknesses. These are listed as advantages and disadvantages in the following.

Advantages

  • Snapshots – in other words, snapshots of a system's state - can be simply created by CoW. All you need to do is reference and freeze the "uberblock" and its underlying nodes and blocks.
  • Clones can be also simply created, as simple references can be used here as well.
  • Incremental Duplication is exactly, as every block knows, in which transaction group it has been created. This allows ZFS to jump directly to the changed sections when comparing two snapshots, rather than checking each file individually.
  • Data corruption is traceable and often repairable. Damaged blocks can be identified by verifying the check sums. If the file system has been built redundant, no damaged block can be recreated in most cases.
  • fsck is obsolete, as CoW always ensures a consistant pool.

Disadvantages

  • Fragmentation occurs. Every change is written into new blocks. As a result, even files that were originally written sequentially become fragmented. The fuller zpool gets, the more difficult it gets to find sufficiently contiguous blocks for sequential writing processes.
  • Free storage space is required at all times, because even during deletion operations, the blocks that were used are not deleted; instead, new nodes and blocks must be created.
  • If only parts of a data set must be changed, it can be slow independent of the recordsize, as the whole data set must be read. For a data set with recordsize=128k in which 8 KB are to be modified, 128 KB must be read, 8 KB must be modified in memory, and the result must then be written back as a new 128-KB record.

More information

ZFS, Part 1: Concepts and basics from Michael Plura (heise.de, 2017)

The Time Machine in Kernel Space: ZFS-Workflows on Ubuntu 24.04 (linux-magazin.de, 2026)

"ZFS: The last word in file systems." by Jeff Bonwick (web.archive.org, 2026)

Sources

  1. Merkle Tree (en.wikipedia.org, 2026)
  2. 2.0 2.1 Copy-on-Write in the OpenZFS Documentation (openzfs.github.io, 2026)


Author: Stefan Bohn

Stefan Bohn has been employed at Thomas-Krenn.AG since 2020. Originally based in PreSales as a consultant for IT solutions, he moved to Product Management in 2022. There he dedicates himself to knowledge transfer and also drives the Thomas-Krenn Wiki.

Translator: Alina Ranzinger

Alina has been working at Thomas-Krenn.AG since 2024. After her training as multilingual business assistant, she got her job as assistant of the Product Management and is responsible for the translation of texts and for the organisation of the department.


Related articles

ISCSI Multipathing under Linux
Synology UC3400 Metadata-Overflow
ZFS basics