nfs: Fetch MOUNTED_ON_FILEID when updating an inode
Subsystems (2)
PATCH 1/1 nfs: Fetch MOUNTED_ON_FILEID when updating an inode
2ef47eb1 (NFS: Fix use of nfs_attr_use_mounted_on_fileid()) was a good start to fixing a circular directory structure warning for NFS v4 "junctioned" mountpoints. Unfortunately, further testing continued to generate this error.
My server is configured like this:
anna@nfsd ~ % df
Filesystem Size Used Avail Use% Mounted on /dev/vda1 9.1G 2.0G 6.5G 24% / /dev/vdc1 1014M 33M 982M 4% /exports /dev/vdc2 1014M 33M 982M 4% /exports/vol1 /dev/vdc3 1014M 33M 982M 4% /exports/vol1/vol2
anna@nfsd ~ % cat /etc/exports
/exports/ *(rw,async,no_subtree_check,no_root_squash)
/exports/vol1/ *(rw,async,no_subtree_check,no_root_squash)
/exports/vol1/vol2 *(rw,async,no_subtree_check,no_root_squash)
I've been running chown across the entire mountpoint twice in a row to hit this problem. The first run succeeds, but the second one fails with the circular directory warning along with:
anna@client ~ % dmesg
[Apr 3 14:28] NFS: server 192.168.100.204 error: fileid changed
fsid 0:39: expected fileid 0x100080, got 0x80
WHere 0x80 is the mountpoint's fileid and 0x100080 is the mounted-on fileid.
This patch fixes the issue by requesting an updated mounted-on fileid from the server during nfs_update_inode(), and then checking that the fileid stored in the nfs_inode matches either the fileid or mounted-on fileid returned by the server.
--- fs/nfs/inode.c | 15 ++++++++++++++- fs/nfs/nfs4proc.c | 3 ++- 2 files changed, 16 insertions(+), 2 deletions(-)
fs/nfs/inode.c +14 -1
@@ -1588,6 +1588,19 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa }EXPORT_SYMBOL_GPL (nfs_post_op_update_inode_force_wcc); + +static inline bool nfs_fileid_valid (struct nfs_inode *nfsi, +struct nfs_fattr *fattr) +{ +bool ret1 = true, ret2 = true; + +if (fattr->valid &NFS_ATTR_FATTR_FILEID ) + ret1 = (nfsi->fileid == fattr->fileid); +if (fattr->valid &NFS_ATTR_FATTR_MOUNTED_ON_FILEID ) + ret2 = (nfsi->fileid == fattr->mounted_on_fileid); +return ret1 || ret2; +} +/* * Many nfs protocol calls return the new file attributes after * an operation. Here we update the inode to reflect the state
@@ -1614,7 +1627,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)nfs_display_fhandle_hash (NFS_FH (inode)), atomic_read(&inode->i_count), fattr->valid); -if ((fattr->valid &NFS_ATTR_FATTR_FILEID ) && nfsi->fileid != fattr->fileid) { +if (!nfs_fileid_valid (nfsi, fattr)) { printk(KERN_ERR "NFS: server %s error: fileid changed\n" "fsid %s: expected fileid 0x%Lx, got 0x%Lx\n", NFS_SERVER(inode)->nfs_client->cl_hostname,
fs/nfs/nfs4proc.c +2 -1
@@ -185,7 +185,8 @@ const u32 nfs4_fattr_bitmap[3] = { | FATTR4_WORD1_SPACE_USED | FATTR4_WORD1_TIME_ACCESS | FATTR4_WORD1_TIME_METADATA - | FATTR4_WORD1_TIME_MODIFY, + | FATTR4_WORD1_TIME_MODIFY + | FATTR4_WORD1_MOUNTED_ON_FILEID,#ifdef CONFIG_NFS_V4_SECURITY_LABEL FATTR4_WORD2_SECURITY_LABEL#endif
Signature · 1 line
2.3.5