diff options
author | rmacklem <rmacklem@FreeBSD.org> | 2013-09-01 23:02:59 +0000 |
---|---|---|
committer | rmacklem <rmacklem@FreeBSD.org> | 2013-09-01 23:02:59 +0000 |
commit | 8d06f831a7fd6d823c0aff22030a780f8b8fd05e (patch) | |
tree | d7581118dafcc5b29d5d01d4bb41cb2114a97168 /sys/sys/mount.h | |
parent | 09ec5c277c487bd53321f3f207be7a596ea08f65 (diff) | |
download | FreeBSD-src-8d06f831a7fd6d823c0aff22030a780f8b8fd05e.zip FreeBSD-src-8d06f831a7fd6d823c0aff22030a780f8b8fd05e.tar.gz |
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
Diffstat (limited to 'sys/sys/mount.h')
-rw-r--r-- | sys/sys/mount.h | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/sys/sys/mount.h b/sys/sys/mount.h index 1a835b7..8f94451 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -609,6 +609,7 @@ typedef int vfs_sysctl_t(struct mount *mp, fsctlop_t op, 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) \ |