aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/vfs_default.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/vfs_default.c')
-rw-r--r--sys/kern/vfs_default.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c
index 382fbb2d9ace..3c428d7b7511 100644
--- a/sys/kern/vfs_default.c
+++ b/sys/kern/vfs_default.c
@@ -423,10 +423,25 @@ int
vop_stdadvlock(struct vop_advlock_args *ap)
{
struct vnode *vp;
+ struct mount *mp;
struct vattr vattr;
int error;
vp = ap->a_vp;
+
+ /*
+ * Provide atomicity of open(O_CREAT | O_EXCL | O_EXLOCK) for
+ * local filesystems. See vn_open_cred() for reciprocal part.
+ */
+ mp = vp->v_mount;
+ if (mp != NULL && (mp->mnt_flag & MNT_LOCAL) != 0 &&
+ ap->a_op == F_SETLK && (ap->a_flags & F_FIRSTOPEN) == 0) {
+ VI_LOCK(vp);
+ while ((vp->v_iflag & VI_FOPENING) != 0)
+ msleep(vp, VI_MTX(vp), PLOCK, "lockfo", 0);
+ VI_UNLOCK(vp);
+ }
+
if (ap->a_fl->l_whence == SEEK_END) {
/*
* The NFSv4 server must avoid doing a vn_lock() here, since it