Date: Sun, 1 Sep 2013 23:02:59 +0000 (UTC) From: Rick Macklem <rmacklem@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r255136 - in head/sys: fs/nfsclient kern sys Message-ID: <201309012302.r81N2xwG055662@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: rmacklem Date: Sun Sep 1 23:02:59 2013 New Revision: 255136 URL: http://svnweb.freebsd.org/changeset/base/255136 Log: Forced dismounts of NFS mounts can fail when thread(s) are stuck waiting for an RPC reply from the server while holding the mount point busy (mnt_lockref incremented). This happens because dounmount() msleep()s waiting for mnt_lockref to become 0, before calling VFS_UNMOUNT(). This patch adds a new VFS operation called VFS_PURGE(), which the NFS client implements as purging RPCs in progress. Making this call before checking mnt_lockref fixes the problem, by ensuring that the VOP_xxx() calls will fail and unbusy the mount point. Reported by: sbruno Reviewed by: kib MFC after: 2 weeks Modified: head/sys/fs/nfsclient/nfs_clvfsops.c head/sys/kern/vfs_mount.c head/sys/sys/mount.h Modified: head/sys/fs/nfsclient/nfs_clvfsops.c ============================================================================== --- head/sys/fs/nfsclient/nfs_clvfsops.c Sun Sep 1 22:30:24 2013 (r255135) +++ head/sys/fs/nfsclient/nfs_clvfsops.c Sun Sep 1 23:02:59 2013 (r255136) @@ -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_purge_t nfs_purge; /* * 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_purge = nfs_purge, }; VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY); @@ -1676,6 +1678,19 @@ nfs_sysctl(struct mount *mp, fsctlop_t o } /* + * Purge 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_purge(struct mount *mp) +{ + struct nfsmount *nmp = VFSTONFS(mp); + + newnfs_nmcancelreqs(nmp); +} + +/* * Extract the information needed by the nlm from the nfs vnode. */ static void Modified: head/sys/kern/vfs_mount.c ============================================================================== --- head/sys/kern/vfs_mount.c Sun Sep 1 22:30:24 2013 (r255135) +++ head/sys/kern/vfs_mount.c Sun Sep 1 23:02:59 2013 (r255136) @@ -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_PURGE(mp); + MNT_ILOCK(mp); + } error = 0; if (mp->mnt_lockref) { mp->mnt_kern_flag |= MNTK_DRAINING; Modified: head/sys/sys/mount.h ============================================================================== --- head/sys/sys/mount.h Sun Sep 1 22:30:24 2013 (r255135) +++ head/sys/sys/mount.h Sun Sep 1 23:02:59 2013 (r255136) @@ -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_purge_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_purge_t *vfs_purge; vfs_mount_t *vfs_spare[6]; /* spares for ABI compat */ }; @@ -757,6 +759,14 @@ vfs_statfs_t __vfs_statfs; } \ } while (0) +#define VFS_PURGE(MP) do { \ + if (*(MP)->mnt_op->vfs_purge != NULL) { \ + VFS_PROLOGUE(MP); \ + (*(MP)->mnt_op->vfs_purge)(MP); \ + VFS_EPILOGUE(MP); \ + } \ +} while (0) + #define VFS_KNOTE_LOCKED(vp, hint) do \ { \ if (((vp)->v_vflag & VV_NOKNOTE) == 0) \
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201309012302.r81N2xwG055662>