summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authorrmacklem <rmacklem@FreeBSD.org>2011-04-13 22:16:52 +0000
committerrmacklem <rmacklem@FreeBSD.org>2011-04-13 22:16:52 +0000
commit7e629ce106fd53a906d116de0a7324b0c265f4a6 (patch)
tree6d609ed70a6359fe8f19feed47cfdbc69f7b8956 /sys/fs
parent0b7551a5c94afc2f16e0c6e06bcfe84f5ff45867 (diff)
downloadFreeBSD-src-7e629ce106fd53a906d116de0a7324b0c265f4a6.zip
FreeBSD-src-7e629ce106fd53a906d116de0a7324b0c265f4a6.tar.gz
Fix the experimental NFSv4 client so that it recognizes server
mount point crossings correctly. It was testing the wrong flag. Also, try harder to make sure that the fsid is different than the one assigned to the client mount point, by hashing the server's fsid (just to create a different value deterministically) when it is the same. MFC after: 2 weeks
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/nfsclient/nfs_clport.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c
index 10e1b8e..e9ebbde 100644
--- a/sys/fs/nfsclient/nfs_clport.c
+++ b/sys/fs/nfsclient/nfs_clport.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
* generally, I don't like #includes inside .h files, but it seems to
* be the easiest way to handle the port.
*/
+#include <sys/hash.h>
#include <fs/nfs/nfsport.h>
#include <netinet/if_ether.h>
#include <net/if_types.h>
@@ -377,12 +378,23 @@ nfscl_loadattrcache(struct vnode **vpp, struct nfsvattr *nap, void *nvaper,
* be the same as a local fs, but since this is in an NFS mount
* point, I don't think that will cause any problems?
*/
- if ((nmp->nm_flag & (NFSMNT_NFSV4 | NFSMNT_HASSETFSID)) ==
- (NFSMNT_NFSV4 | NFSMNT_HASSETFSID) &&
+ if (NFSHASNFSV4(nmp) && NFSHASHASSETFSID(nmp) &&
(nmp->nm_fsid[0] != np->n_vattr.na_filesid[0] ||
- nmp->nm_fsid[1] != np->n_vattr.na_filesid[1]))
- vap->va_fsid = np->n_vattr.na_filesid[0];
- else
+ nmp->nm_fsid[1] != np->n_vattr.na_filesid[1])) {
+ /*
+ * va_fsid needs to be set to some value derived from
+ * np->n_vattr.na_filesid that is not equal
+ * vp->v_mount->mnt_stat.f_fsid[0], so that it changes
+ * from the value used for the top level server volume
+ * in the mounted subtree.
+ */
+ if (vp->v_mount->mnt_stat.f_fsid.val[0] !=
+ (uint32_t)np->n_vattr.na_filesid[0])
+ vap->va_fsid = (uint32_t)np->n_vattr.na_filesid[0];
+ else
+ vap->va_fsid = (uint32_t)hash32_buf(
+ np->n_vattr.na_filesid, 2 * sizeof(uint64_t), 0);
+ } else
vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
np->n_attrstamp = time_second;
if (vap->va_size != np->n_size) {
OpenPOWER on IntegriCloud