Page MenuHomeFreeBSD

D27789.diff
No OneTemporary

D27789.diff

diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -3736,8 +3736,8 @@
#define CACHE_FPL_SUPPORTED_CN_FLAGS \
(NC_NOMAKEENTRY | NC_KEEPPOSENTRY | LOCKLEAF | LOCKPARENT | WANTPARENT | \
- FOLLOW | LOCKSHARED | SAVENAME | SAVESTART | WILLBEDIR | ISOPEN | \
- NOMACCHECK | AUDITVNODE1 | AUDITVNODE2 | NOCAPCHECK)
+ FAILIFEXISTS | FOLLOW | LOCKSHARED | SAVENAME | SAVESTART | WILLBEDIR | \
+ ISOPEN | NOMACCHECK | AUDITVNODE1 | AUDITVNODE2 | NOCAPCHECK)
#define CACHE_FPL_INTERNAL_CN_FLAGS \
(ISDOTDOT | MAKEENTRY | ISLASTCN)
@@ -3990,6 +3990,11 @@
return (cache_fpl_handled(fpl, EROFS));
}
+ if (fpl->tvp != NULL && (cnp->cn_flags & FAILIFEXISTS) != 0) {
+ cache_fpl_smr_exit(fpl);
+ return (cache_fpl_handled(fpl, EEXIST));
+ }
+
/*
* Secure access to dvp; check cache_fplookup_partial_setup for
* reasoning.
@@ -4070,6 +4075,12 @@
return (cache_fpl_aborted(fpl));
}
+ if ((cnp->cn_flags & FAILIFEXISTS) != 0) {
+ vput(dvp);
+ vput(tvp);
+ return (cache_fpl_handled(fpl, EEXIST));
+ }
+
if ((cnp->cn_flags & LOCKLEAF) == 0) {
VOP_UNLOCK(tvp);
}
@@ -4221,6 +4232,7 @@
MPASS(!cache_fpl_isdotdot(cnp));
if (cnp->cn_nameiop != LOOKUP) {
+ fpl->tvp = NULL;
return (cache_fplookup_modifying(fpl));
}
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -545,6 +545,16 @@
ndp->ni_debugflags |= NAMEI_DBG_CALLED;
if (ndp->ni_startdir != NULL)
ndp->ni_debugflags |= NAMEI_DBG_HADSTARTDIR;
+ if (cnp->cn_flags & FAILIFEXISTS) {
+ KASSERT(cnp->cn_nameiop == CREATE,
+ ("%s: FAILIFEXISTS passed for op %d", __func__, cnp->cn_nameiop));
+ /*
+ * The limitation below is to restrict hairy corner cases.
+ */
+ KASSERT((cnp->cn_flags & (LOCKPARENT | LOCKLEAF)) == LOCKPARENT,
+ ("%s: FAILIFEXISTS must be passed with LOCKPARENT and without LOCKLEAF",
+ __func__));
+ }
/*
* For NDVALIDATE.
*
@@ -1295,8 +1305,11 @@
goto bad2;
}
}
- if (ndp->ni_vp != NULL && ndp->ni_vp->v_type == VDIR)
+ if (ndp->ni_vp != NULL) {
nameicap_tracker_add(ndp, ndp->ni_vp);
+ if ((cnp->cn_flags & (FAILIFEXISTS | ISSYMLINK)) == FAILIFEXISTS)
+ goto bad_eexist;
+ }
return (0);
bad2:
@@ -1311,6 +1324,24 @@
vput(dp);
ndp->ni_vp = NULL;
return (error);
+bad_eexist:
+ /*
+ * FAILIFEXISTS handling.
+ *
+ * XXX namei called with LOCKPARENT but not LOCKLEAF has the strange
+ * behaviour of leaving the vnode unlocked if the target is the same
+ * vnode as the parent.
+ */
+ MPASS((cnp->cn_flags & ISSYMLINK) == 0);
+ if (ndp->ni_vp == ndp->ni_dvp)
+ vrele(ndp->ni_dvp);
+ else
+ vput(ndp->ni_dvp);
+ vrele(ndp->ni_vp);
+ ndp->ni_dvp = NULL;
+ ndp->ni_vp = NULL;
+ NDFREE(ndp, NDF_ONLY_PNBUF);
+ return (EEXIST);
}
/*
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -3768,7 +3768,6 @@
int mode)
{
struct mount *mp;
- struct vnode *vp;
struct vattr vattr;
struct nameidata nd;
int error;
@@ -3777,26 +3776,11 @@
restart:
bwillwrite();
NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 |
- NC_NOMAKEENTRY | NC_KEEPPOSENTRY, segflg, path, fd,
+ NC_NOMAKEENTRY | NC_KEEPPOSENTRY | FAILIFEXISTS, segflg, path, fd,
&cap_mkdirat_rights, td);
nd.ni_cnd.cn_flags |= WILLBEDIR;
if ((error = namei(&nd)) != 0)
return (error);
- vp = nd.ni_vp;
- if (vp != NULL) {
- NDFREE(&nd, NDF_ONLY_PNBUF);
- /*
- * XXX namei called with LOCKPARENT but not LOCKLEAF has
- * the strange behaviour of leaving the vnode unlocked
- * if the target is the same vnode as the parent.
- */
- if (vp == nd.ni_dvp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- vrele(vp);
- return (EEXIST);
- }
if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
NDFREE(&nd, NDF_ONLY_PNBUF);
vput(nd.ni_dvp);
diff --git a/sys/sys/namei.h b/sys/sys/namei.h
--- a/sys/sys/namei.h
+++ b/sys/sys/namei.h
@@ -143,7 +143,7 @@
#define LOCKLEAF 0x0004 /* lock vnode on return */
#define LOCKPARENT 0x0008 /* want parent vnode returned locked */
#define WANTPARENT 0x0010 /* want parent vnode returned unlocked */
-/* UNUSED 0x0020 */
+#define FAILIFEXISTS 0x0020 /* return EEXIST if found */
#define FOLLOW 0x0040 /* follow symbolic links */
#define BENEATH 0x0080 /* No escape from the start dir */
#define LOCKSHARED 0x0100 /* Shared lock leaf */

File Metadata

Mime Type
text/plain
Expires
Tue, Oct 13, 2:38 PM (14 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40755632
Default Alt Text
D27789.diff (4 KB)

Event Timeline