summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/fs/nfsclient/nfs_clnfsiod.c8
-rw-r--r--sys/fs/nfsclient/nfs_clvfsops.c13
-rw-r--r--sys/nfsclient/nfs_nfsiod.c8
-rw-r--r--sys/nfsclient/nfs_vfsops.c10
4 files changed, 37 insertions, 2 deletions
diff --git a/sys/fs/nfsclient/nfs_clnfsiod.c b/sys/fs/nfsclient/nfs_clnfsiod.c
index 0f1810f..25ff694 100644
--- a/sys/fs/nfsclient/nfs_clnfsiod.c
+++ b/sys/fs/nfsclient/nfs_clnfsiod.c
@@ -304,6 +304,14 @@ nfssvc_iod(void *instance)
}
mtx_lock(&ncl_iod_mutex);
/*
+ * Make sure the nmp hasn't been dismounted as soon as
+ * ncl_doio() completes for the last buffer.
+ */
+ nmp = ncl_iodmount[myiod];
+ if (nmp == NULL)
+ break;
+
+ /*
* If there are more than one iod on this mount, then defect
* so that the iods can be shared out fairly between the mounts
*/
diff --git a/sys/fs/nfsclient/nfs_clvfsops.c b/sys/fs/nfsclient/nfs_clvfsops.c
index 281ce44..b717210 100644
--- a/sys/fs/nfsclient/nfs_clvfsops.c
+++ b/sys/fs/nfsclient/nfs_clvfsops.c
@@ -81,6 +81,9 @@ extern struct timeval nfsboottime;
extern struct nfsstats newnfsstats;
extern int nfsrv_useacl;
extern int nfscl_debuglevel;
+extern enum nfsiod_state ncl_iodwant[NFS_MAXASYNCDAEMON];
+extern struct nfsmount *ncl_iodmount[NFS_MAXASYNCDAEMON];
+extern struct mtx ncl_iod_mutex;
NFSCLSTATEMUTEX;
MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "New NFS request header");
@@ -1472,7 +1475,7 @@ nfs_unmount(struct mount *mp, int mntflags)
{
struct thread *td;
struct nfsmount *nmp;
- int error, flags = 0, trycnt = 0;
+ int error, flags = 0, i, trycnt = 0;
struct nfsclds *dsp, *tdsp;
td = curthread;
@@ -1508,6 +1511,14 @@ nfs_unmount(struct mount *mp, int mntflags)
*/
if ((mntflags & MNT_FORCE) == 0)
nfscl_umount(nmp, td);
+ /* Make sure no nfsiods are assigned to this mount. */
+ mtx_lock(&ncl_iod_mutex);
+ for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
+ if (ncl_iodmount[i] == nmp) {
+ ncl_iodwant[i] = NFSIOD_AVAILABLE;
+ ncl_iodmount[i] = NULL;
+ }
+ mtx_unlock(&ncl_iod_mutex);
newnfs_disconnect(&nmp->nm_sockreq);
crfree(nmp->nm_sockreq.nr_cred);
FREE(nmp->nm_nam, M_SONAME);
diff --git a/sys/nfsclient/nfs_nfsiod.c b/sys/nfsclient/nfs_nfsiod.c
index d34c205..2fb2c88 100644
--- a/sys/nfsclient/nfs_nfsiod.c
+++ b/sys/nfsclient/nfs_nfsiod.c
@@ -308,6 +308,14 @@ nfssvc_iod(void *instance)
mtx_unlock(&Giant);
mtx_lock(&nfs_iod_mtx);
/*
+ * Make sure the nmp hasn't been dismounted as soon as
+ * nfs_doio() completes for the last buffer.
+ */
+ nmp = nfs_iodmount[myiod];
+ if (nmp == NULL)
+ break;
+
+ /*
* If there are more than one iod on this mount, then defect
* so that the iods can be shared out fairly between the mounts
*/
diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c
index 6f00cf9..7a26aa2 100644
--- a/sys/nfsclient/nfs_vfsops.c
+++ b/sys/nfsclient/nfs_vfsops.c
@@ -1362,7 +1362,7 @@ static int
nfs_unmount(struct mount *mp, int mntflags)
{
struct nfsmount *nmp;
- int error, flags = 0;
+ int error, flags = 0, i;
if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
@@ -1387,6 +1387,14 @@ nfs_unmount(struct mount *mp, int mntflags)
/*
* We are now committed to the unmount.
*/
+ /* Make sure no nfsiods are assigned to this mount. */
+ mtx_lock(&nfs_iod_mtx);
+ for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
+ if (nfs_iodmount[i] == nmp) {
+ nfs_iodwant[i] = NFSIOD_AVAILABLE;
+ nfs_iodmount[i] = NULL;
+ }
+ mtx_unlock(&nfs_iod_mtx);
nfs_disconnect(nmp);
free(nmp->nm_nam, M_SONAME);
OpenPOWER on IntegriCloud