On 64-bit platforms, the two short fields in struct tmpfs_fid are padded to the 64-bit alignment of the long field. This pushes the offsets of the subsequent fields by 4 bytes and makes struct tmpfs_fid bigger than struct fid. tmpfs_vptofh() casts a struct fid * to struct tmpfs_fid *, causing 4 bytes of adjacent memory to be overwritten when the struct fields are set. Through several layers of indirection and embedded structs, the adjacent memory for one particular call to tmpfs_vptofh() happens to be the stack canary for nfsrvd_compound(). Half of the canary ends up being clobbered, going unnoticed until eventually the stack check fails when nfsrvd_compound() returns and a panic is triggered.
Instead of duplicating fields of struct fid in struct tmpfs_fid, narrow the struct to cover only the unique fields for tmpfs and assert at compile time that the struct fits in the allotted space. This way we don't have to replicate the offsets of struct fid fields, we just use them directly.