diff options
author | Rick Macklem <rmacklem@FreeBSD.org> | 2017-07-29 19:52:47 +0000 |
---|---|---|
committer | Rick Macklem <rmacklem@FreeBSD.org> | 2017-07-29 19:52:47 +0000 |
commit | 47cbff34fa9a88fc8c12c4de15882a0563a33055 (patch) | |
tree | aa3367f7e70e9c66d04fd0ade1463d1b6ee266a1 /sys/fs/nfsclient/nfs_clport.c | |
parent | d35f6548e63e5deb4e9a7ac40f517fc10b1dc7b9 (diff) | |
download | src-47cbff34fa9a88fc8c12c4de15882a0563a33055.tar.gz src-47cbff34fa9a88fc8c12c4de15882a0563a33055.zip |
Notes
Diffstat (limited to 'sys/fs/nfsclient/nfs_clport.c')
-rw-r--r-- | sys/fs/nfsclient/nfs_clport.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c index e49382ea6783..c22d87227b2f 100644 --- a/sys/fs/nfsclient/nfs_clport.c +++ b/sys/fs/nfsclient/nfs_clport.c @@ -1311,6 +1311,8 @@ nfssvc_nfscl(struct thread *td, struct nfssvc_args *uap) cap_rights_t rights; char *buf; int error; + struct mount *mp; + struct nfsmount *nmp; if (uap->flag & NFSSVC_CBADDSOCK) { error = copyin(uap->argp, (caddr_t)&nfscbdarg, sizeof(nfscbdarg)); @@ -1365,6 +1367,56 @@ nfssvc_nfscl(struct thread *td, struct nfssvc_args *uap) dumpmntopts.ndmnt_blen); free(buf, M_TEMP); } + } else if (uap->flag & NFSSVC_FORCEDISM) { + buf = malloc(MNAMELEN + 1, M_TEMP, M_WAITOK); + error = copyinstr(uap->argp, buf, MNAMELEN + 1, NULL); + if (error == 0) { + nmp = NULL; + mtx_lock(&mountlist_mtx); + TAILQ_FOREACH(mp, &mountlist, mnt_list) { + if (strcmp(mp->mnt_stat.f_mntonname, buf) == + 0 && strcmp(mp->mnt_stat.f_fstypename, + "nfs") == 0 && mp->mnt_data != NULL) { + nmp = VFSTONFS(mp); + mtx_lock(&nmp->nm_mtx); + if ((nmp->nm_privflag & + NFSMNTP_FORCEDISM) == 0) { + nmp->nm_privflag |= + (NFSMNTP_FORCEDISM | + NFSMNTP_CANCELRPCS); + mtx_unlock(&nmp->nm_mtx); + } else { + nmp = NULL; + mtx_unlock(&nmp->nm_mtx); + } + break; + } + } + mtx_unlock(&mountlist_mtx); + + if (nmp != NULL) { + /* + * Call newnfs_nmcancelreqs() to cause + * any RPCs in progress on the mount point to + * fail. + * This will cause any process waiting for an + * RPC to complete while holding a vnode lock + * on the mounted-on vnode (such as "df" or + * a non-forced "umount") to fail. + * This will unlock the mounted-on vnode so + * a forced dismount can succeed. + * Then clear NFSMNTP_CANCELRPCS and wakeup(), + * so that nfs_unmount() can complete. + */ + newnfs_nmcancelreqs(nmp); + mtx_lock(&nmp->nm_mtx); + nmp->nm_privflag &= ~NFSMNTP_CANCELRPCS; + wakeup(nmp); + mtx_unlock(&nmp->nm_mtx); + } else + error = EINVAL; + } + free(buf, M_TEMP); } else { error = EINVAL; } |