NFS: Store the file system "fsid" value in the NFS super block. This should enable us to detect if we are crossing a mountpoint in the case where the server is exporting "nohide" mounts. Signed-off-by: Trond Myklebust --- fs/nfs/idmap.c | 1 - fs/nfs/inode.c | 8 ++++++++ fs/nfs/nfs2xdr.c | 3 ++- fs/nfs/nfs3xdr.c | 3 ++- fs/nfs/nfs4xdr.c | 4 ++-- include/linux/nfs_fs.h | 5 +++-- include/linux/nfs_fs_sb.h | 1 + include/linux/nfs_page.h | 1 - include/linux/nfs_xdr.h | 19 ++++++++++++------- 9 files changed, 30 insertions(+), 15 deletions(-) Index: linux-2.6.11/fs/nfs/inode.c =================================================================== --- linux-2.6.11.orig/fs/nfs/inode.c +++ linux-2.6.11/fs/nfs/inode.c @@ -225,6 +225,7 @@ nfs_get_root(struct super_block *sb, str return ERR_PTR(error); } + server->fsid = fsinfo->fattr->fsid; rooti = nfs_fhget(sb, rootfh, fsinfo->fattr); if (!rooti) return ERR_PTR(-ENOMEM); @@ -1212,6 +1213,7 @@ int nfs_refresh_inode(struct inode *inod */ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsigned long verifier) { + struct nfs_server *server; struct nfs_inode *nfsi = NFS_I(inode); __u64 new_size; loff_t new_isize; @@ -1241,6 +1243,12 @@ static int nfs_update_inode(struct inode if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) goto out_changed; + server = NFS_SERVER(inode); + /* Update the fsid if and only if this is the root directory */ + if (inode == inode->i_sb->s_root->d_inode + && !nfs_fsid_equal(&server->fsid, &fattr->fsid)) + server->fsid = fattr->fsid; + /* * Update the read time so we don't revalidate too often. */ Index: linux-2.6.11/fs/nfs/nfs2xdr.c =================================================================== --- linux-2.6.11.orig/fs/nfs/nfs2xdr.c +++ linux-2.6.11/fs/nfs/nfs2xdr.c @@ -131,7 +131,8 @@ xdr_decode_fattr(u32 *p, struct nfs_fatt fattr->du.nfs2.blocksize = ntohl(*p++); rdev = ntohl(*p++); fattr->du.nfs2.blocks = ntohl(*p++); - fattr->fsid_u.nfs3 = ntohl(*p++); + fattr->fsid.major = ntohl(*p++); + fattr->fsid.minor = 0; fattr->fileid = ntohl(*p++); p = xdr_decode_time(p, &fattr->atime); p = xdr_decode_time(p, &fattr->mtime); Index: linux-2.6.11/fs/nfs/nfs3xdr.c =================================================================== --- linux-2.6.11.orig/fs/nfs/nfs3xdr.c +++ linux-2.6.11/fs/nfs/nfs3xdr.c @@ -160,7 +160,8 @@ xdr_decode_fattr(u32 *p, struct nfs_fatt if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor) fattr->rdev = 0; - p = xdr_decode_hyper(p, &fattr->fsid_u.nfs3); + p = xdr_decode_hyper(p, &fattr->fsid.major); + fattr->fsid.minor = 0; p = xdr_decode_hyper(p, &fattr->fileid); p = xdr_decode_time3(p, &fattr->atime); p = xdr_decode_time3(p, &fattr->mtime); Index: linux-2.6.11/include/linux/nfs_fs_sb.h =================================================================== --- linux-2.6.11.orig/include/linux/nfs_fs_sb.h +++ linux-2.6.11/include/linux/nfs_fs_sb.h @@ -29,6 +29,7 @@ struct nfs_server { char * hostname; /* remote hostname */ struct nfs_fh fh; struct sockaddr_in addr; + struct nfs_fsid fsid; #ifdef CONFIG_NFS_V4 /* Our own IP address, as a null-terminated string. * This is used to generate the clientid, and the callback address. Index: linux-2.6.11/include/linux/nfs_xdr.h =================================================================== --- linux-2.6.11.orig/include/linux/nfs_xdr.h +++ linux-2.6.11/include/linux/nfs_xdr.h @@ -3,11 +3,19 @@ #include -struct nfs4_fsid { - __u64 major; - __u64 minor; +struct nfs_fsid { + uint64_t major; + uint64_t minor; }; +/* + * Helper for checking equality between 2 fsids. + */ +static inline int nfs_fsid_equal(const struct nfs_fsid *a, const struct nfs_fsid *b) +{ + return a->major == b->major && a->minor == b->minor; +} + struct nfs_fattr { unsigned short valid; /* which fields are valid */ __u64 pre_size; /* pre_op_attr.size */ @@ -29,10 +37,7 @@ struct nfs_fattr { } nfs3; } du; dev_t rdev; - union { - __u64 nfs3; /* also nfs2 */ - struct nfs4_fsid nfs4; - } fsid_u; + struct nfs_fsid fsid; __u64 fileid; struct timespec atime; struct timespec mtime; Index: linux-2.6.11/fs/nfs/nfs4xdr.c =================================================================== --- linux-2.6.11.orig/fs/nfs/nfs4xdr.c +++ linux-2.6.11/fs/nfs/nfs4xdr.c @@ -2101,7 +2101,7 @@ static int decode_attr_symlink_support(s return 0; } -static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fsid *fsid) +static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid) { uint32_t *p; @@ -2750,7 +2750,7 @@ static int decode_getfattr(struct xdr_st goto xdr_error; if ((status = decode_attr_size(xdr, bitmap, &fattr->size)) != 0) goto xdr_error; - if ((status = decode_attr_fsid(xdr, bitmap, &fattr->fsid_u.nfs4)) != 0) + if ((status = decode_attr_fsid(xdr, bitmap, &fattr->fsid)) != 0) goto xdr_error; if ((status = decode_attr_fileid(xdr, bitmap, &fattr->fileid)) != 0) goto xdr_error; Index: linux-2.6.11/include/linux/nfs_fs.h =================================================================== --- linux-2.6.11.orig/include/linux/nfs_fs.h +++ linux-2.6.11/include/linux/nfs_fs.h @@ -16,8 +16,6 @@ #include #include -#include - #include #include #include @@ -27,6 +25,9 @@ #include #include #include + +#include + #include #include Index: linux-2.6.11/fs/nfs/idmap.c =================================================================== --- linux-2.6.11.orig/fs/nfs/idmap.c +++ linux-2.6.11/fs/nfs/idmap.c @@ -46,7 +46,6 @@ #include #include -#include #include #include Index: linux-2.6.11/include/linux/nfs_page.h =================================================================== --- linux-2.6.11.orig/include/linux/nfs_page.h +++ linux-2.6.11/include/linux/nfs_page.h @@ -13,7 +13,6 @@ #include #include #include -#include #include #include