Inode
An inode is the Unix file system’s per-file metadata structure. It stores everything about a file except two things: the filename (which lives in directory entries) and the file’s data (which lives in disk blocks the inode points to). Every file and directory on every Linux, macOS (HFS+/APFS via translation), and Unix system has an inode containing its permissions, timestamps, owner, size, and pointers to its data blocks. The inode is the file’s true identity at the file system level; the filename is just a human-friendly handle.
Wondershare · USPTO
Classic Unix scheme
ext4-extent era
An inode (index node) is a data structure that stores all metadata about a file or directory on a Unix file system, except for the filename and the file’s actual data. Each inode contains the file’s type, permission bits, owner UID and GID, size, access/modification/change timestamps, hard link count, and pointers to the disk blocks where the file’s data lives. Inodes are identified by inode numbers (i-numbers) that are unique within a single file system. Filenames are stored separately in directory entries that map names to inode numbers; this separation enables hard links, makes renames cheap, and is fundamental to the Unix “everything is a file” philosophy.
What an Inode Is
The Linux Journal documentation captures the inode definition concisely: “An inode (index node) is a data structure that stores information about a file or a directory, excluding its name or its actual data.” This single sentence captures both what the inode is and what it isn’t; it’s metadata, but specifically the metadata that describes a file rather than identifies it by name or contains its content.1
The “everything is a file” Unix principle
The Linux Bash inodes documentation captures the underlying philosophy: “In the world of Linux, everything is considered a file, be it a text file, a directory, a device, or even a socket. This universal approach to system resources simplifies interactions but raises questions about how Linux manages this.” Every entity that the file system tracks (regular files, directories, symbolic links, hard links, named pipes, device nodes, sockets) has an inode. The inode is the unifying abstraction that lets Unix treat radically different things (a 4 GB video file and a /dev/null device entry) with the same metadata structure.2
The inode number
Each inode is identified by an inode number (often abbreviated “i-number” or “ino”) that’s unique within its file system. The inode number is the file’s identity at the file system level; tools like ls -i display it, and the stat command shows complete inode contents. Two different files on the same file system always have different inode numbers; the same inode number can exist on different file systems (each file system has its own inode number space) without ambiguity because the file system identity (combined with the inode number) is what produces unique identification system-wide.
Where inodes live on disk
Inodes are stored in inode tables: contiguous arrays of inode structures at fixed locations on the disk. The placement strategy varies by file system:
- ext2/3/4: the volume is divided into block groups, each containing its own inode table. This locality improves performance because related files (in the same directory) are often allocated near each other.
- XFS: uses dynamically-allocated inode chunks rather than fixed tables, allowing the file system to grow without inode exhaustion concerns.
- ZFS / Btrfs: use object-store-style metadata with inode-equivalent records (dnodes in ZFS) that can be allocated anywhere, with no fixed tables at all.
- UFS / FFS (BSD): uses cylinder groups similar to ext2/3, with fixed inode tables per cylinder group.
Inodes are not directories
One common point of confusion: inodes don’t contain directory listings. An inode for a directory is similar in structure to an inode for a regular file; the difference is what the data blocks contain. For a regular file, the data blocks contain the file’s content; for a directory, the data blocks contain a list of (filename, inode-number) pairs that describe the directory’s children. The directory’s structure (how it organizes children) is defined by the data blocks, not the inode; modern file systems use B-trees or hash tables in directory data blocks for fast lookups in large directories.
The Structure of an Inode
An inode contains several distinct categories of metadata. The exact format varies between file systems, but the conceptual content is consistent across the Unix family.3
Type and permission bits
The mode field is a 16-bit value encoding both the file type and the permission bits. The high 4 bits identify the file type:
- Regular file:
S_IFREG(mode bits indicate regular file) - Directory:
S_IFDIR - Symbolic link:
S_IFLNK - Character device:
S_IFCHR(e.g., terminals, /dev/null) - Block device:
S_IFBLK(e.g., disk devices) - Named pipe (FIFO):
S_IFIFO - Socket:
S_IFSOCK
The low 12 bits encode permissions: 9 bits for user/group/other read/write/execute, plus 3 bits for setuid, setgid, and sticky. These are typically displayed in octal (e.g., 0644 means user read/write, group read, other read).
Ownership
The inode stores the owner’s user ID (UID) and group ID (GID) as 32-bit integers (16-bit on older file systems). These map to user and group names through /etc/passwd and /etc/group. The inode does not store the owner’s username; it stores only the numeric ID, which is why moving files between systems with different user databases can produce unexpected ownership.
Size and link count
The size field stores the file’s logical size in bytes. The link count tracks how many directory entries point to this inode; a freshly-created file has link count 1, and creating a hard link increments it to 2, etc. When the link count drops to 0, the file is deleted; the inode is freed for reuse and the data blocks are returned to the free pool.
Timestamps
Classic Unix inodes have three timestamps:
- atime (access time): updated when the file is read.
- mtime (modification time): updated when the file’s data is changed.
- ctime (change time): updated when the inode itself is changed (including permissions, ownership, link count). Note: not “creation time.”
Modern file systems extend this with creation time (crtime), sometimes called “birth time” or btime, which is the actual creation timestamp. ext4, XFS, and APFS all support crtime; ext2/3 do not. The lack of true creation time on ext2/3 is sometimes a forensic obstacle.
Block pointers (classic scheme)
The most distinctive part of a classic Unix inode is its block pointer scheme. The traditional design used in ext2 and ext3 contains:
- 12 direct block pointers: reference the first 12 data blocks of the file directly. With 4 KB blocks, this covers files up to 48 KB without any indirection.
- 1 single-indirect pointer: references a block that contains 1024 (assuming 4-byte pointers and 4 KB blocks) pointers to data blocks. Adds another 4 MB of file size.
- 1 double-indirect pointer: references a block of pointers to single-indirect blocks. Adds another 4 GB.
- 1 triple-indirect pointer: references a block of pointers to double-indirect blocks. Adds another 4 TB.
This 4-tier scheme produces O(log) access time for any block in the file (the deeper the block, the more indirection); the design is elegant but inefficient for very large files.
Block pointers (extent scheme)
Modern file systems including ext4, XFS, Btrfs, and ZFS use extent trees instead. An extent describes a contiguous run of blocks (start_block + length); a single extent can describe many megabytes of file data with just two integers. The inode contains a small extent tree header and a few inline extent descriptors; for larger files, the inline descriptors point to extent index blocks that themselves contain extent descriptors. Extent-based addressing is more space-efficient and faster than block-pointer arrays for typical files, especially large files; the trade-off is added complexity in the file system code.
Modern extensions
Modern inodes include additional fields beyond the classic structure:
- Inode flags: bits indicating immutable, append-only, no-dump, sync, etc.
- Generation number: incremented on each inode reuse to detect stale references.
- Extended attributes: arbitrary name-value pairs (xattrs) for ACLs, security labels, etc.
- Inode size: ext4 uses 256-byte inodes by default (vs 128 bytes in ext2/3) to accommodate extended fields.
- Project quota ID: for file systems supporting per-project quotas.
Inodes vs Filenames: The Unix Design
The separation between inodes and filenames is one of Unix’s defining architectural choices, with consequences that touch nearly every aspect of file system behavior. Understanding the separation clarifies many otherwise-puzzling Unix idioms.4
Filenames live in directory entries
A directory in Unix is essentially a special file whose contents are a list of (filename, inode-number) pairs. When the file system needs to look up a path like /home/user/file.txt:
- Start with the inode for the root directory (
/) at a well-known inode number (usually 2 in ext file systems). - Read the root directory’s data blocks to find the entry for
home; get the inode number. - Read that inode to find the data blocks of the
homedirectory. - Read those data blocks to find
user; get the inode number. - Read that inode, find data blocks, look up
file.txt, get the inode number. - Read the final inode to access the file’s metadata and data block pointers.
Filenames are not properties of files; they’re just keys in a directory’s lookup table. A file doesn’t “have a name”; it has a list of directory entries that reference it.
Hard links
The separation enables hard links: multiple directory entries (potentially in different directories) all pointing to the same inode. Each directory entry has its own filename, but they all reference the same underlying file. When you create a hard link with ln:
- The file system creates a new directory entry in the target directory with the new filename and the existing inode number.
- The inode’s link count is incremented.
- No data is copied; both names access the same physical file.
Removing one of the names (with rm or unlink) decrements the link count and removes the directory entry, but the file’s data persists as long as any other directory entry still references the inode (or any process has the file open).
Renames are cheap
Because renaming a file just modifies a directory entry (the inode and data blocks aren’t touched), renames are extremely cheap on Unix file systems regardless of file size. Renaming a 100 GB file takes the same time as renaming a 100-byte file: just an update to the directory entry. This is fundamentally different from systems where the filename is part of the file’s metadata.
“Deleted” while open
Unix’s classic surprising behavior: a process can hold a file open while another process deletes it; the open process continues to access the file’s data normally, even though the file no longer appears in any directory listing. This works because the inode’s link count tracks both directory entries and open file descriptors; deleting the directory entry decrements the link count to 0 from the directory’s perspective, but the open process keeps the file alive (effectively a virtual link) until it closes the file. Only then is the inode actually freed and the data blocks reclaimed.
Symbolic links are different
Symbolic links (symlinks) are different from hard links: a symlink is a special kind of file whose data is a path to another file. Resolving a symlink involves reading its data (the target path) and then looking up that path. Unlike hard links, symlinks can point to non-existent targets, can cross file system boundaries, and have their own inode separate from their target’s inode. The inode for a symlink contains the symlink’s own metadata; reading the symlink’s “content” returns the target path string.
Inodes Across File Systems
The inode concept exists across most Unix-derived file systems, but with significant variations in implementation. Understanding the variations helps with cross-platform recovery work.
ext2/3/4: the canonical Linux family
The ext family is the most common Linux file system family and uses the most direct inode implementation:
- Fixed inode allocation: the number of inodes is set at format time and cannot grow.
- Inode tables per block group: each block group has its own inode table at a fixed offset.
- 128-byte inodes (ext2/3) or 256-byte inodes (ext4): ext4’s larger inodes accommodate creation time, nanosecond timestamps, and longer extended attributes.
- Block pointer arrays (ext2/3) or extent trees (ext4): extent trees in ext4 are more efficient but harder to recover from after deletion.
XFS: dynamic allocation
XFS uses dynamic inode allocation: rather than pre-allocating a fixed number of inodes at format time, XFS allocates inodes in chunks of 64 inodes (8 KB total) on demand. This avoids the inode-exhaustion problem that ext file systems can hit, but makes recovery more complex because inodes can be anywhere on the volume rather than at fixed table locations. XFS uses extent-based addressing (similar to ext4) for file data.
ZFS / Btrfs: object stores
ZFS and Btrfs (in different ways) deviate from the traditional inode model. ZFS uses dnodes (data nodes) that play a similar role to inodes but live in the object store rather than fixed inode tables; the dnode contains pointers to indirect blocks that ultimately reference data. Btrfs uses B-tree-based metadata where inode metadata is stored in tree nodes rather than separate inode tables. Both designs are more flexible than classic inodes but require completely different recovery techniques.
APFS: file system records
APFS (Apple File System) doesn’t use inodes in the classic sense; it uses file system records stored in B-trees. Each file is identified by a 64-bit identifier similar to an inode number, and its metadata is stored in records that the B-tree organizes. The conceptual purpose is the same (per-file metadata structure separate from filename), but the implementation is fundamentally different from Unix inodes.
HFS+: catalog file
HFS+ (Apple’s predecessor to APFS) uses a centralized catalog file that’s structurally somewhat similar to NTFS’s MFT: a single B-tree containing records for every file and directory. Each record is the conceptual analogue of an inode, but they’re organized in a tree rather than a flat table.
NTFS comparison
The contrast with NTFS is illuminating: NTFS’s MFT records play the same role as inodes (per-file metadata) but with one major design difference. MFT records contain the filename as one of their attributes ($FILE_NAME), while Unix inodes don’t. This means deleted files on NTFS retain their original filename in the MFT record (until the record is reused), making recovery substantially easier than on ext file systems where the filename lives in the directory entry that gets cleared on deletion.
Inodes and Data Recovery
Inode-based recovery is fundamental to Linux file system recovery. The inode’s central role means that successful recovery typically depends on inode state at the time of the recovery attempt.5
The “shell filename” problem
The Baeldung Linux recovery documentation captures a key inode-related failure mode: “Pointers within inodes refer to what most would call data, e.g., file contents. Losing or damaging an inode can invalidate content block pointers and leave files only as shell filenames. They would contain full metadata but no content.” When the inode’s block pointers are lost or corrupted, the directory entry still names the file but there’s no way to find its data; the file becomes a “shell”: present in directory listings but with no content recoverable through normal means.
debugfs: the canonical tool
The Wondershare debugfs documentation describes its central role: “Debugfs is a powerful debugging utility in the Linux operating system that provides a way to access a file system’s internal data structures and inode information. Kernel developers often use it to perform tasks such as file undeletion and data recovery.”6 The standard debugfs recovery procedure:
- Open the file system in debugfs (read-only mode for safety).
- Use
lsdelto list deleted inodes; identify the target file by size, deletion time, or inode number. - Use
stat <inode>to display the deleted inode’s full contents. - Note the block numbers in the inode’s block pointers.
- Use
dump <inode> /path/to/outputto extract the file’s data based on the inode. - Verify the recovered file’s contents.
The procedure works when the deleted inode is still readable; on ext4, this often requires fast action because extent metadata is cleared more aggressively than block pointer arrays were on ext2/3.
extundelete and ext4magic
Beyond debugfs, two specialized recovery tools handle ext file systems:
- extundelete: reads the file system journal to find inode states from before recent deletions; can recover files whose current inodes are zeroed but whose pre-deletion state survives in the journal.
- ext4magic: ext4-specific tool that handles extent trees better than generic debugfs; can recover from extent-tree-cleared inodes by reconstructing extent state from journal data.
Both tools work above debugfs’s level, providing more automated recovery workflows but with the same fundamental dependency on inode-and-journal state.
Inode exhaustion as a recovery scenario
Inode exhaustion is sometimes confused with disk-full conditions. The Linux Bash documentation mentions the diagnostic command: “df -i: Displays inode usage information and availability, which is quite useful in managing filesystems.” A system reporting “no space left on device” with substantial free disk space (per df) likely has exhausted inodes; this isn’t a recovery scenario per se, but the diagnostic confusion can lead administrators to take inappropriate corrective actions.
When inodes are corrupted
Corrupted inodes (rather than zeroed) present different recovery challenges. The USPTO 11650875 patent on abnormal inode dynamic repair captures the failure mode: “During the operation of a distributed file system, a core data structure ‘inode’ of file metadata may have some missing fields or invalid field values sometimes due to some unknown anomalies, and furthermore, the file system has an error and is unable to keep on operating during request processing and inode checking because the field values are inconsistent with expected values of the file system.” Recovery from corrupted inodes requires either:
- fsck repair: the standard
fscktool can detect and repair some inode inconsistencies, though aggressive repair can lose data. - Manual debugfs repair: for skilled administrators, debugfs can directly modify inode fields to fix specific corruptions.
- Replacement from backup: if the inode is unrecoverable, the file’s data may still be present in blocks that can be carved.
File carving as fallback
When inode recovery fails (zeroed pointers, corrupted inodes, destroyed inode tables), file carving is the fallback: scanning the entire volume looking for file signatures regardless of inode state. Carving recovers file content but loses original filenames, timestamps, ownership, and directory structure; it’s substantially less useful than inode-based recovery but provides a fallback when inodes are gone. Tools like foremost, scalpel, and photorec implement carving for various file types.
The inode is the central data structure of Unix file systems and the central artifact of Unix file system recovery. Understanding inodes is what separates working Linux/macOS recovery from random poking at disk images; nearly every Unix recovery scenario reduces to questions about inode state, inode pointers, journal contents, and file system journals. The conceptual contrast with NTFS’s MFT records is illuminating: NTFS keeps the filename in the MFT record (making deleted-file recovery straightforward), while Unix splits the filename into a separate directory entry (making deletion harder to recover from but providing other architectural benefits like cheap renames and hard links).7
For users facing potential Linux/Unix data loss, the inode-related guidance is consistent. Stop using the file system immediately; modifications to the file system can overwrite the deleted inodes’ block pointers or reuse the inodes for new files. Don’t run fsck on damaged volumes before recovery; fsck can repair inconsistencies in ways that preserve file system integrity but discard recovery context. Use specialized tools (debugfs, extundelete, ext4magic) that handle inode-specific recovery rather than generic file recovery software. The Baeldung guidance bears repeating: “fsck combines both scanning and recovery”, meaning it can write changes that make subsequent recovery harder or impossible.
For users wondering about inode-related design choices, the Unix inode model and NTFS MFT model represent different trade-offs in the same problem space. Unix inodes optimize for things like cheap renames, hard links, and the “everything is a file” abstraction; NTFS MFT records optimize for forensic context preservation and recovery friendliness. Recovery software for Unix file systems typically operates at a different level than for NTFS precisely because of these design differences. Cleanroom recovery doesn’t depend on file system; physical data on platters or NAND can be recovered regardless of inode state. The fundamental principle remains the same across file systems: comprehensive backups are the primary protection, and understanding the file system’s design helps set realistic recovery expectations and choose appropriate tools when something goes wrong.
Inode FAQ
An inode (index node) is a Unix file system data structure that stores metadata about a file or directory, excluding the filename and the file’s actual data contents. Each inode contains the file’s type (regular file, directory, symbolic link, etc.), permissions (mode), owner UID and GID, size, timestamps (atime/mtime/ctime), hard link count, and pointers to the disk blocks where the file’s data lives. Inodes are identified by inode numbers that are unique within a single file system. The Linux Journal documentation captures the definition concisely: an inode is a data structure that stores information about a file or a directory, excluding its name or its actual data.
An inode contains comprehensive file metadata. The standard fields include: file mode (type bits identifying file/directory/symlink/device/etc., plus the 9 permission bits for user/group/other read/write/execute), link count (how many directory entries point to this inode), owner UID and group GID, file size in bytes, timestamps for last access (atime), last modification (mtime), and last status change (ctime), plus block pointers identifying where the file’s data is stored. Modern file systems extend this with additional fields like creation time (crtime in ext4), file flags (immutable, append-only, etc.), and extended attributes. The structure does not contain the filename; filenames live in directory entries that map names to inode numbers.
Filenames and inodes are stored separately in Unix file systems, with directory entries providing the mapping between them. A directory is essentially a special file containing a list of (filename, inode-number) pairs; when you reference a file by name, the file system looks up the directory entry to find the inode number, then reads the inode to access the file’s metadata and locate its data blocks. This design has important consequences: a single inode can have multiple filenames (hard links), all pointing to the same underlying file; renaming a file doesn’t change its inode (only the directory entry changes); and a file’s data is preserved as long as any directory entry still references its inode, even after the original name is deleted. The inode is the file’s true identity; the filename is just a human-friendly handle in a directory.
Classic Unix inodes (used in ext2 and ext3) handle large files through a hierarchy of block pointers. Each inode contains 12 direct block pointers that reference the first 12 data blocks directly, plus one single-indirect pointer (referencing a block that contains pointers to data blocks), one double-indirect pointer (referencing a block of pointers to single-indirect blocks), and one triple-indirect pointer (referencing a block of pointers to double-indirect blocks). With 4 KB blocks and 4-byte pointers (allowing 1024 pointers per indirect block), this scheme supports files up to approximately 4 TB. Modern file systems like ext4 use extent trees instead: a small number of extent descriptors in the inode (each describing a contiguous run of blocks) point to extent index blocks for larger files. Extent-based addressing is more space-efficient and faster than block-pointer arrays for typical files.
Inode-based recovery typically uses tools like debugfs, extundelete, or ext4magic to read inodes from a damaged or post-deletion file system. The Wondershare debugfs documentation describes the process: debugfs allows users to access the file system’s inode information and data structures, and the standard recovery procedure involves identifying the target file’s inode, noting the block pointers within the inode, and reading those blocks to reconstruct the file. The challenge for ext file systems is that deletion typically zeroes the block pointers in the inode (different from NTFS, where the MFT record’s data attribute is preserved); without the block pointers, recovery has to fall back to journal entries (extundelete reads the file system journal to find pointers from before deletion) or signature-based file carving. ext4 with extent trees is harder to recover from than ext2/ext3 with block pointer arrays because extent metadata is more aggressively cleared on deletion.
Inode exhaustion occurs when a file system runs out of inodes despite having free disk space. Each inode in an ext file system is allocated at format time; the file system has a fixed number of inodes determined by the inodes-per-bytes ratio specified during mkfs. If a file system has many tiny files (where each file consumes one inode but very little disk space), the inode table can fill up before the data blocks do. The result is that the file system reports ‘no space left on device’ for new file creation even though df shows substantial free space. The df -i command displays inode usage explicitly; system administrators use it to diagnose inode-exhaustion situations. Recovery from inode exhaustion typically requires deleting files (freeing inodes) or in extreme cases reformatting with a higher inode allocation. ZFS, Btrfs, and XFS allocate inodes dynamically and don’t have this exhaustion problem.
Related glossary entries
- ext4: the most common Linux file system; uses extent-tree-based inodes.
- $MFT: NTFS’s per-file metadata structure; comparable role to inodes but different design.
- APFS: Apple’s modern file system; uses B-tree records as the inode equivalent.
- Journaling File System: ext3+ uses a journal that supports inode-state recovery.
- File Carving: fallback recovery technique when inodes are unrecoverable.
- Deleted File: deletion clears inode block pointers, making ext recovery time-critical.
- Forensic Recovery: inode timestamps are key forensic timeline artifacts.
Sources
- Linux Journal: Understanding Linux Filesystems: Inodes, Block Sizes, and Data Structures (accessed May 2026)
- Linux Bash: Inodes and Their Role in the Filesystem
- Baeldung Linux: Recover Lost and Deleted Data in Linux
- USPTO patent 9047299: Reclaiming blocks from a directory
- USPTO patent 12229009: Techniques for duplicating inode state to prevent loss of inode metadata
- Wondershare Recoverit: Recover Deleted Files in Linux With debugfs
- USPTO patent 11650875: Abnormal inode dynamic repair method and system
About the Authors
Data Recovery Fix earns revenue through affiliate links on some product recommendations. This does not influence our reference content. Glossary entries are written and reviewed independently based on documented research, vendor documentation, independent testing, and recovery-engineer review. If anything on this page looks inaccurate, outdated, or worth revisiting, please reach out at contact@datarecoveryfix.com and we’ll review it promptly.
