I was looking around to see how Linux handles directories with a
high link count (ie. when they have many subdirectories) and I think
I have stumbled across a bug in the Linux xfs glue.
It seems that internally xfs uses a 32 bit field for the link count,
and the stat64 syscalls use a 32 bit field. These fields are copied
via the vattr structure in xfs_vnode.h, which uses a nlink_t for
the link count. However, in the kernel, I think this field is
actually of type __kernel_nlink_t which seems to be 16 bits on many
I've tested this on an i386 2.6.11 kernel and it seems that the
link count presented to userland wraps after 65536 subdirectories.
This naturally doesn't let you screw up the filesystem or anything,
but it does let you can hide files from find/fts, as demonstrated
I guess to fix it you'd change the type of nlink in struct vattr
so that it is the same type (unsigned int) as the type in struct
kstat. I've included the obvious patch, but I don't have a machine
that I can test it on right now.
turing 2% mkdir testdir
turing 3% cd testdir
turing 4% ls -ld .
drwxr-xr-x 2 dwmalone dwmalone 6 Mar 30 12:18 .
turing 5% perl ../mk65536dirs.pl
turing 6% ls -ld .
drwxr-xr-x 2 dwmalone dwmalone 1056768 Mar 30 12:19 .
turing 7% mkdir .hidden
turing 8% touch .hidden/secret
turing 9% find . -name secret -print
--- /usr/src/linux-2.6.11/fs/xfs/linux-2.6/xfs_vnode.h 2005-03-02
+++ /tmp/xfs_vnode.h 2005-03-30 18:49:22.000000000 +0100
@@ -409,7 +409,7 @@
int va_mask; /* bit-mask of attributes present */
enum vtype va_type; /* vnode type (for create) */
mode_t va_mode; /* file access mode and type */
- nlink_t va_nlink; /* number of references to file */
+ unsigned int va_nlink; /* number of references to file */
uid_t va_uid; /* owner user id */
gid_t va_gid; /* owner group id */
xfs_ino_t va_nodeid; /* file id */