What is the meaning of "ext[3/4]_dx_add_entry: Directory index full!"?
Environment
- Red Hat Enterprise Linux (all versions)
- ext3 or ext4
Issue
-
System log file contains the following messages (dependent on filesystem type ext3 or ext4):
kernel: EXT3-fs warning (device sdb1): ext3_dx_add_entry: Directory index full!
or
kernel: EXT4-fs warning (device dm-2): ext4_dx_add_entry: Directory index full!
- What does
ext[3/4]_dx_add_entry: Directory index full
mean?
Resolution
There are a number of possible resolutions:
- Determine if a process is creating unexpected or unwanted files or directories.
- Remove unnecessary or unwanted files or directories.
- Reorganize files and directories within the filesystem to reduce the number of entries in each individual directory.
- Use shorter filenames.
-
Change the block size of the filesystem. This option requires a re-format of the filesystem, since the block size cannot be changed once it is set.
CAUTION: Before re-formatting the filesystem backup any important files to another device as reformatting will recreate the filesystem metadata and not retain information about existing files. By default the ext3 block size for small volumes is 1024. If possible format the disk with 4096 bytes (4k) block size as follows:# mkfs -t ext3 -b 4096 /dev/device
-
Disable
dir_index
option of the filesystem.
Note: There is no need to unmount the file system.
CAUTION: Disabling this option may impact performance on lookups in large directories.# tune2fs -O ^dir_index /dev/device
To recreate the
dir_index
:# umount /dev/device # tune2fs -O dir_index /dev/device # e2fsck -D /dev/device
-
Optimize directories in filesystem.
$ MANWIDTH=80 man e2fsck -D Optimize directories in filesystem. This option causes e2fsck to try to optimize all directories, either by reindexing them if the filesystem supports directory indexing, or by sorting and compressing directories for smaller directories, or for filesys‐ tems using traditional linear directories. Even without the -D option, e2fsck may sometimes optimize a few directories --- for example, if directory indexing is enabled and a directory is not indexed and would benefit from being indexed, or if the index structures are corrupted and need to be rebuilt. The -D option forces all directories in the filesystem to be optimized. This can sometimes make them a little smaller and slightly faster to search, but in practice, you should rarely need to use this option. The -D option will detect directory entries with duplicate names in a single directory, which e2fsck normally does not enforce for performance reasons.
-
To identify the directory, use the following
auditd
rule. You can get the audit log of the rule withausearch -m syscall -k for_ext3_dx_add_entry_warning
.-a exit,always -F arch=b64 -S open -S openat -S creat -S link -S symlink -S mkdir -F exit=-ENOSPC -k for_ext3_dx_add_entry_warning
Root Cause
-
The 'directory index full' error will be seen if there are lots of files/directories in a specific directory so that it reaches its indexing limits and cannot keep track further.
-
The directory index is an additional tree structure which helps directory lookups, improving performance for huge directories.
-
There is a limit in ext3 and ext4 of the directory structure.
- A directory on ext3 can have at most 31998 sub directories, because an inode can have at most 32000 links. This is one cause of the warning.
- A directory on ext4 can have at most 64000 sub directories.
-
The size of each section of a directory index is limited by the filesystem's block size. If very long filenames are used, fewer entries will fit in the block, leading to 'directory index full' errors earlier than they would occur with shorter filenames. This can become a bigger problem when the filesystem's block size is small (1024-byte or 2048-byte blocks), but will occur with 4096-byte blocks as well.
-
For further information about directory indexing, you may refer to the following page :
State of the Art: Where we are with the Ext3 filesystem
Diagnostic Steps
Example repoducer
This reproducer illustrates the problem on a filesystem with a blocksize of 1024.
[root@rhel8 ~]# uname -r
4.18.0-425.3.1.el8.x86_64
[root@rhel8 ~]# rpm -q e2fsprogs
e2fsprogs-1.45.6-5.el8.x86_64
[root@rhel8 ~]#
[root@rhel8 ~]# truncate -s5G /tmp/ext.image
[root@rhel8 ~]# mkfs.ext4 -b 1024 /tmp/ext.image
mke2fs 1.45.6 (20-Mar-2020)
Discarding device blocks: done
Creating filesystem with 5242880 1k blocks and 327680 inodes
Filesystem UUID: 526bff79-f5ae-47c1-af13-4694e0341b8b
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409, 663553,
1024001, 1990657, 2809857, 5120001
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done
[root@rhel8 ~]# mount /tmp/ext.image /mnt
[root@rhel8 ~]# for I in $(seq 0 300000); do touch /mnt/file_$I; done
touch: cannot touch '/mnt/file_161845': No space left on device
touch: cannot touch '/mnt/file_164116': No space left on device
touch: cannot touch '/mnt/file_164819': No space left on device
touch: cannot touch '/mnt/file_175308': No space left on device
...
[root@rhel8 ~]# df -i /mnt
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/loop0 327680 299358 28322 92% /mnt
[root@rhel8 ~]#
[root@rhel8 ~]# dmesg | tail
EXT4-fs warning (device loop0): ext4_dx_add_entry:2281: Directory (ino: 2) index full, reach max htree level :2
EXT4-fs warning (device loop0): ext4_dx_add_entry:2285: Large directory feature is not enabled on this filesystem
EXT4-fs warning (device loop0): ext4_dx_add_entry:2281: Directory (ino: 2) index full, reach max htree level :2
EXT4-fs warning (device loop0): ext4_dx_add_entry:2285: Large directory feature is not enabled on this filesystem
Note: Files can still be successfully created if the hash of their filename does not fall into an already full hash bucket.
[root@rhel8 ~]# touch /mnt/newfile1
[root@rhel8 ~]# touch /mnt/newfile2
[root@rhel8 ~]# touch /mnt/newfile3
[root@rhel8 ~]# touch /mnt/file_161845
touch: cannot touch '/mnt/file_161845': No space left on device
[root@rhel8 ~]# touch /mnt/newfile4
[root@rhel8 ~]# touch /mnt/newfile5
[root@rhel8 ~]#
The htree structure can be inspected using debugfs.
[root@rhel8 ~]# umount /mnt
[root@rhel8 ~]# debugfs /tmp/ext.image
debugfs 1.45.6 (20-Mar-2020)
debugfs: htree /
Root node dump:
Reserved zero: 0
Hash Version: 1
Info length: 8
Indirect levels: 1
Flags: 0
Number of entries (count): 123
Number of entries (limit): 123
Checksum: 0x1eb549c9
Entry #0: Hash 0x00000000, block 124
Entry #1: Hash 0x020818ba, block 8347
Entry #2: Hash 0x03fef34c, block 4238
Entry #3: Hash 0x05f14b4a, block 8032
...
Entry #122: Hash 0xfe0b5880, block 8484
Entry #0: Hash 0x00000000, block 124
Number of entries (count): 126
Number of entries (limit): 126
Checksum: 0x7d289d82
Entry #0: Hash 0x00000000, block 1
Entry #1: Hash 0x0002deec, block 14606
Entry #2: Hash 0x000545f4, block 5833
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.
Comments