--- sys/mount.h.sav 2013-08-29 15:19:40.000000000 -0400 +++ sys/mount.h 2013-08-29 15:23:59.000000000 -0400 @@ -609,6 +609,7 @@ typedef int vfs_sysctl_t(struct mount *m struct sysctl_req *req); typedef void vfs_susp_clean_t(struct mount *mp); typedef void vfs_notify_lowervp_t(struct mount *mp, struct vnode *lowervp); +typedef void vfs_killio_t(struct mount *mp); struct vfsops { vfs_mount_t *vfs_mount; @@ -628,6 +629,7 @@ struct vfsops { vfs_susp_clean_t *vfs_susp_clean; vfs_notify_lowervp_t *vfs_reclaim_lowervp; vfs_notify_lowervp_t *vfs_unlink_lowervp; + vfs_killio_t *vfs_killio; }; vfs_statfs_t __vfs_statfs; @@ -756,6 +758,14 @@ vfs_statfs_t __vfs_statfs; } \ } while (0) +#define VFS_KILLIO(MP) do { \ + if (*(MP)->mnt_op->vfs_killio != NULL) { \ + VFS_PROLOGUE(MP); \ + (*(MP)->mnt_op->vfs_killio)(MP); \ + VFS_EPILOGUE(MP); \ + } \ +} while (0) + #define VFS_KNOTE_LOCKED(vp, hint) do \ { \ if (((vp)->v_vflag & VV_NOKNOTE) == 0) \ --- kern/vfs_mount.c.sav 2013-08-29 15:24:36.000000000 -0400 +++ kern/vfs_mount.c 2013-08-29 17:22:51.000000000 -0400 @@ -1269,8 +1269,16 @@ dounmount(mp, flags, td) } mp->mnt_kern_flag |= MNTK_UNMOUNT | MNTK_NOINSMNTQ; /* Allow filesystems to detect that a forced unmount is in progress. */ - if (flags & MNT_FORCE) + if (flags & MNT_FORCE) { mp->mnt_kern_flag |= MNTK_UNMOUNTF; + MNT_IUNLOCK(mp); + /* + * Must be done after setting MNTK_UNMOUNTF and before + * waiting for mnt_lockref to become 0. + */ + VFS_KILLIO(mp); + MNT_ILOCK(mp); + } error = 0; if (mp->mnt_lockref) { mp->mnt_kern_flag |= MNTK_DRAINING; --- fs/nfsclient/nfs_clvfsops.c.sav 2013-08-29 15:30:50.000000000 -0400 +++ fs/nfsclient/nfs_clvfsops.c 2013-08-29 16:52:54.000000000 -0400 @@ -120,6 +120,7 @@ static vfs_root_t nfs_root; static vfs_statfs_t nfs_statfs; static vfs_sync_t nfs_sync; static vfs_sysctl_t nfs_sysctl; +static vfs_killio_t nfs_killio; /* * nfs vfs operations. @@ -134,6 +135,7 @@ static struct vfsops nfs_vfsops = { .vfs_uninit = ncl_uninit, .vfs_unmount = nfs_unmount, .vfs_sysctl = nfs_sysctl, + .vfs_killio = nfs_killio, }; VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY); @@ -1676,6 +1678,19 @@ nfs_sysctl(struct mount *mp, fsctlop_t o } /* + * Kill off any RPCs in progress, so that they will all return errors. + * This allows dounmount() to continue as far as VFS_UNMOUNT() for a + * forced dismount. + */ +static void +nfs_killio(struct mount *mp) +{ + struct nfsmount *nmp = VFSTONFS(mp); + + newnfs_nmcancelreqs(nmp); +} + +/* * Extract the information needed by the nlm from the nfs vnode. */ static void