No Space Left on Device
carlmastrangelo.com
carlmastrangelo.com
After a few years of this server merrily creating a new file for each user I found that my disk was full, as this poster did. After a lot of hunting around, I found out that I had hit my inode limit, a concept I was completely unaware of.
I know for sure I won't be making THAT mistake again.
It was much easier than coding a database back-end, with no need to run a database server. And, when we needed to scale beyond one machine, it was trivial to use a central NFS server (read-only NFS worked really well for this) and multiple front-end web servers.
Though we did know how many files we'd be hosting, so we sized the number of bytes per inode appropriately.
git is an example of a program that uses this technique (among others) to store blobs. In case of git, the blob names are already SHA-1 hashes.
[1] Exception: I don't know how prone Murmur is to hash collisions, so if collision-based attacks are part of your threat model, a randomly salted cryptographic hash might be appropriate.
What was the number you hit?
I have a flat file system for something I'm prototyping. The files are in a database with a random SHA256 filename associated with them. I was thinking about doing what Git does with creating folders for parts of the string to alleviate the number of files in one single directory. I'm sure that makes file retrieval a prettier process.
Do all the files for have to be in the same directory for the iNode limit to be reached or just there in general?
NOTE: I ask because the prototype isn't ever meant to go into production, but my customer keeps getting confused and I'm concerned this very important system may inherit (or even use) my design.
The thing that git does is for speed.
How is that number calculated? It's less than 2^25 but greater than 2^24, so I imagine it's even awkward to store. I guess that has something to do with the file table size for HDD - you can't have more nodes than you have addressable space for those nodes.
I knew Git did it for speed, but I was wondering whether it was also about the number of files that can exist in a single directory.
EDIT: Corrected percentage.
I wonder how many people understand what the term "news server" of the partition wizard in the Debian installer means.
Hopefully not now, this is why we all appreciate people sharing these sorts of information :)
That lead to the second discussion of why you don't fix it by piping filenames one by one to rm, but either use find's inbuilt unlink/rm if there is one or xargs to rm if not.
That's crazy. Thanks for that information.
That's crazy.
Why? Do you expect to store many files less than 16KiB?
I don't think that amount of information is really suitable for a database? It may be larger in some cases too, so there's not guarantees I can even make about size.
It depends on the filesytem, but it is typically a function of filesystem size (and in ext, the number of block groups and inodes per block group size). To take an example:
sudo tune2fs -l <device> | egrep -i 'group'
Blocks per group: 32768
Fragments per group: 32768
Inodes per group: 8192
So, we have got 1 inode per 4 blocks. This particular filesystem has 79472640 blocks (of 4KiB) and 19873792 inodes. This corresponds to the 4:1 ratio: 79472640 / 19873792 =~ 4.(The exception are empty files, because on most filesystems an empty file does not use any data blocks, but possibly an inode to store file size, permissions, etc.)
https://developer.apple.com/legacy/library/documentation/Dar...
Maybe Linux and the BSDs could adopt that as well.
Btrfs?
Another good one that even less people know about is the sticky bit.
People who have the vague notion of 'an inode stores metadata' will usually answer this incorrectly.
NB: My current working folders are now in Google Drive, but is essentially the same folder structure as I started on our Novell server about 25 years ago...
512?
https://en.wikipedia.org/wiki/File_Allocation_Table#Final_FA... (see the last paragraph.)
At some point there was a bug when sometimes users got "wrong permissions or no space left" errors (sorry don't remember the exact error and IIRC our app just tried to save a file and failed with unspecific error if it couldn't write the new temporary file, so we haven't had the exact system error).
What was weird is - there was still lots of space on that disk, permissions were OK, and I've tried creating new files there, both from our app and by hand and it worked.
It turned out after a few days of frantic debugging, that when there's too many files with similar names in one directory - creating a new file can fail because of hash conflict, depending on the filename only. So,
ls A1234.txt S1234.txt # no results
touch S12345.txt # fails
touch S1234.txt # works
:) It was one of the biggest WTF moments I had while programming. "No one will ever need in 280 trillion files. Ever." ~bbcbasic on Hacker News, September 2016
Found in someone's email .sig in the year 2046..."The lesson here is that even in 2016, filesystems still are finicky with large numbers of files in a single directory."
The linked post mentions dir_index default and tune2fs -l lists the dir_index under Filesystem features only.
Not knowing this default behavior, i was considering enabling dir_index explicitly to aid chocking rsync.
EDIT: I ran the reproduction code with 200K instead of 100K just to be sure. There was no problem creating file as well as copying all the files to a different folder. The disk was formatted about 3 months ago and mounted with default options "ext4 noatime,barrier=0 0 0" . On original as well as copied folder `ls | wc -l` still gives 200000.
It's good RHEL/CentOS 7 defaults to XFS now which doesn't suffer (as much) from this problem.
Statements like this make me trust a developer significantly less. It's our job to care about "technical reasons."
ext4 doesn't care if there's collisions in the dir_index hash - they're entirely expected. The dir_index hashes are just used to look up in a tree, the lowest level of which points you to the directory block that contains all the directory entries for names with hashes in a given range.
However, those hashes do get used for the directory position used by telldir() / seekdir() - and those are only 32 bits on 32 bit architectures. So I suspect that something involving those calls is generating the ENOSPC.
The reason I stay with ext4 is that it has proven amazingly robust in the event of hard reboots.
Some reading if you're not familiar with sysrq: https://en.wikipedia.org/wiki/Magic_SysRq_key Depending on your distro you might have to enable it, I believe ubuntu (for some dumb reason) ships with emergency sync as the only command available.
Enabling it should amount to adding: kernel.sysrq=1 to /etc/sysctl.conf on older machines or editing /etc/sysctl.d/10-magic-sysrq.conf on newer ones.
also if you are running out of ram that often you might want to consider a swap partition. Or if you have one already try setting a more aggressive swapiness value.
Explorer will not be too happy displaying such a folder though!
I was hit by this recently - with our 500ish (!!) entries in /node_modules and their dependencies of dependencies of dependencies, a standard 8GB VM formatted with ext4 just simply didn't have enough inodes for us to have two copies of our app (deployment swapover). Had to increase the size to 20GB, just to get the extra inodes. XFS would have handled it much better (from testing on a parallel machine). It was inode exhaustion, though the 'disk full' error message was the same - confusing at first, as df showed 40% free space...