Translating a NFS file handle to inode the long-ish way

There might be a better tool or easier way to do this, but the method works for me 🙂

I was looking into a large number of getfattr requests on one of our CentOS 6 NFS Servers, and was curious what files all the requests were for and where they were coming from. The where part just requires the always helpful tcpdump…


# tcpdump -i bond0 'tcp port nfs'
....
08:58:18.971667 IP xxxxxx.3434118295 > xxxxx.sdsc.edu.nfs: 128 getattr fh Unknown/0100060188D45B4900CC684F00000000000000000...

This alone gets us most of the information we are looking for with the exception of which file was being acted on. It does give us the NFS file handle though, and that is easy enough to translate. Using the chart on page 5 of the following pdf, we see the file handle has the format…

Length Bytes Field Name Meaning Typical Values
1 1 fb_version NFS version Always 1
1 2 fb_auth_type Authentication method Always 0
1 3 fb_fsid_type File system ID encoding method Always 0
1 4 fb_fileid_type File ID encoding method Always either 0,
1, or 2
4 5-8 xdev Major/Minor number of exported device Major
number 3 (IDE), 8 (SCSI)
4 9-12 xino Export inode number Almost always 2
4 13-16 ino Inode number 2 for /, 19 for
/home/foo
4 17-20 gen_no Generation number 0xFF16DDF1, 0x3F6AE3C0
4 21-24 par_ino_no Parent’s inode number 2 for /, 19
for /home
8 25-32 Padding for NFSv2 Always 0
32 33-64 Unused by Linux

 

…so now we just need to split up our file handle to get the inode.

0 fb_version
1 fb_auth_type
0 fb_fsid_type
0 fb_fileid_type
0601 xdev
88D4 xino
5B49 ino (what we want)
00CC gen_no
684F par_ino_no
00000000 Padding
000000000… ??

 

Then we just need to convert from hex to decimal and pass it to find…


$ echo $((0x5b49))
23369

find /path/to/export -inum 23369

And we get to take a bit of a shortcut here as this system only had a single export, so no need to figure out what filesystem it was coming from.