summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrmacklem <rmacklem@FreeBSD.org>2011-01-09 02:10:54 +0000
committerrmacklem <rmacklem@FreeBSD.org>2011-01-09 02:10:54 +0000
commit9a7c4f93a92ca7c680c4af40f9f83e04d20090ea (patch)
tree521628913021edf841e86053b17d873099eadec3
parent3a61afec3c31632aa62686e28a104916e353199d (diff)
downloadFreeBSD-src-9a7c4f93a92ca7c680c4af40f9f83e04d20090ea.zip
FreeBSD-src-9a7c4f93a92ca7c680c4af40f9f83e04d20090ea.tar.gz
Modify readdirplus in the experimental NFS server in a
manner analogous to r216633 for the regular server. This change busies the file system so that VFS_VGET() is guaranteed to be using the correct mount point even during a forced dismount attempt. Since nfsd_fhtovp() is not called immediately before readdirplus, the patch is actually a clone of pjd@'s nfs_serv.c.4.patch instead of the one committed in r216633. Reviewed by: kib MFC after: 10 days
-rw-r--r--sys/fs/nfsserver/nfs_nfsdport.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index 4a03f4b..71d68ea 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -1685,6 +1685,7 @@ nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdgram,
struct iovec iv;
struct componentname cn;
int not_zfs;
+ struct mount *mp;
if (nd->nd_repstat) {
nfsrv_postopattr(nd, getret, &at);
@@ -1854,7 +1855,24 @@ again:
toff = off;
goto again;
}
+
+ /*
+ * Busy the file system so that the mount point won't go away
+ * and, as such, VFS_VGET() can be used safely.
+ */
+ mp = vp->v_mount;
+ vfs_ref(mp);
VOP_UNLOCK(vp, 0);
+ nd->nd_repstat = vfs_busy(mp, 0);
+ vfs_rel(mp);
+ if (nd->nd_repstat != 0) {
+ vrele(vp);
+ free(cookies, M_TEMP);
+ free(rbuf, M_TEMP);
+ if (nd->nd_flag & ND_NFSV3)
+ nfsrv_postopattr(nd, getret, &at);
+ return (0);
+ }
/*
* Save this position, in case there is an error before one entry
@@ -1914,9 +1932,8 @@ again:
vp, dp->d_fileno);
if (refp == NULL) {
if (usevget)
- r = VFS_VGET(vp->v_mount,
- dp->d_fileno, LK_SHARED,
- &nvp);
+ r = VFS_VGET(mp, dp->d_fileno,
+ LK_SHARED, &nvp);
else
r = EOPNOTSUPP;
if (r == EOPNOTSUPP) {
@@ -2035,6 +2052,7 @@ again:
ncookies--;
}
vrele(vp);
+ vfs_unbusy(mp);
/*
* If dirlen > cnt, we must strip off the last entry. If that
OpenPOWER on IntegriCloud