Doom moved to vectors (arrays) because linked lists are slow, and because there wasn't enough other slow parts that needed attention.
There is a time and a place for them, but if you need speed I agree... there are better solutions
File systems are usually part of the kernel.
We can evaluate the Linux kernel developers' priorities by benchmarking[1] and assuming they aren't stupid, because if they are stupid, then their opinion doesn't matter, and if they're not and they're not making things faster, then it's because they have other priorities.
That being said, there are a few[2] notable[3] moves away from linked lists that were ostensibly for performance reasons.
[1]: Even crap benchmarks: http://www.phoronix.com/scan.php?page=article&item=linux-44-...
One list is traversed when committing blocks, so a linked list was never necessary - just a commit-list (vector of pointers).
Another list is traversed when dequeueing the next lock, so again: a linked list isn't necessary, just a dequeue (which might not have to be serialised).
Another list is traversed when finding the next blocked reader, but again serialisation wasn't required here.
And so on.
However when you have the right data structure, you'll find you won't need it.
Benchmarking is important because searching for the right data structure is time consuming (expensive for the programmer) and it's usually not necessary.
I built something once that used intrusive skiplists because it needed to expire elements using one ordering and search them by another. It would have been much less efficient if I'd have broken it up into multiple flat representations.
(Actually, it was flat, but explaining that aspect of it is quite difficult).
I can't speak for the kernel developers, but for the same line of reasoning it may be more significant that there is the lack of error paths.
When you allocate an 'object', further changes of state (eg. added or removal to other lists) in its lifetime can be done without the possibility of running out of memory or address space. This can be a huge benefit to overall program structure in certain types of application.
In contrast, addition or removal to a vector or flat list can ultimately require various actions to happen.
I am not sure if anyone has evaluated using alternatives, but my understanding of why has generally been memory efficiency. If you allocate a Foo, you also allocate everything you need for Foo to be on all of the lists it may appear on. I couldn't find any confirmation (with actual numbers) for this intuition, but this is what I could find:
A 2005 explanation of how intrusive lists work in the Linux kernel: "Linux Kernel Linked List Explained", https://isis.poly.edu/kulesh/stuff/src/klist/
HN submission on intrusive lists in Doom 3: https://news.ycombinator.com/item?id=8795745
And that points to technical note on the optimizations to Doom 3's BFG Edition to get it to perform well on PS3, XBox 360 and PC: http://fabiensanglard.net/doom3_documentation/DOOM-3-BFG-Tec... One of the optimizations was moving from intrusive lists.
I'm quite aware of how inappropriate linked lists are for most applications because of their poor cache locality. I thought the Linux kernel may be a case where linked lists are actually better, but I can't find any numbers or even arguments why they would be.