summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2014-12-13 16:07:01 +0000
committerkib <kib@FreeBSD.org>2014-12-13 16:07:01 +0000
commit07899121cbcd3408ca43bb2f40102fa7e41decae (patch)
tree6c1328cd8a9d3146a168463bd4999b76bef1263d
parentca2d4fd9c1acb3914333668ef0b231d092912fc0 (diff)
downloadFreeBSD-src-07899121cbcd3408ca43bb2f40102fa7e41decae.zip
FreeBSD-src-07899121cbcd3408ca43bb2f40102fa7e41decae.tar.gz
Only sleep interruptible while waiting for suspension end when
filesystem specified VFCF_SBDRY flag, i.e. for NFS. There are two issues with the sleeps. First, applications may get unexpected EINTR from the disk i/o syscalls. Second, interruptible sleep allows the stop of the process, and since mount point is referenced while thread sleeps, unmount cannot free mount point structure' memory, blocking unmount indefinitely. Even for NFS, it is probably only reasonable to enable PCATCH for intr mounts, but this information is currently not available at VFS level. Reported and tested by: pho (previous version) Sponsored by: The FreeBSD Foundation MFC after: 1 week
-rw-r--r--sys/kern/vfs_vnops.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index ee45e01..687269d 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -1600,7 +1600,7 @@ vn_suspendable(struct vnode *vp, struct mount **mpp)
static int
vn_start_write_locked(struct mount *mp, int flags)
{
- int error;
+ int error, mflags;
mtx_assert(MNT_MTX(mp), MA_OWNED);
error = 0;
@@ -1610,13 +1610,15 @@ vn_start_write_locked(struct mount *mp, int flags)
*/
if ((curthread->td_pflags & TDP_IGNSUSP) == 0 ||
mp->mnt_susp_owner != curthread) {
+ mflags = ((mp->mnt_vfc->vfc_flags & VFCF_SBDRY) != 0 ?
+ (flags & PCATCH) : 0) | (PUSER - 1);
while ((mp->mnt_kern_flag & MNTK_SUSPEND) != 0) {
if (flags & V_NOWAIT) {
error = EWOULDBLOCK;
goto unlock;
}
- error = msleep(&mp->mnt_flag, MNT_MTX(mp),
- (PUSER - 1) | (flags & PCATCH), "suspfs", 0);
+ error = msleep(&mp->mnt_flag, MNT_MTX(mp), mflags,
+ "suspfs", 0);
if (error)
goto unlock;
}
@@ -1732,8 +1734,9 @@ vn_start_secondary_write(vp, mpp, flags)
/*
* Wait for the suspension to finish.
*/
- error = msleep(&mp->mnt_flag, MNT_MTX(mp),
- (PUSER - 1) | (flags & PCATCH) | PDROP, "suspfs", 0);
+ error = msleep(&mp->mnt_flag, MNT_MTX(mp), (PUSER - 1) | PDROP |
+ ((mp->mnt_vfc->vfc_flags & VFCF_SBDRY) != 0 ? (flags & PCATCH) : 0),
+ "suspfs", 0);
vfs_rel(mp);
if (error == 0)
goto retry;
OpenPOWER on IntegriCloud