Page MenuHomeFreeBSD

D58178.diff
No OneTemporary

D58178.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
@@ -3292,32 +3292,9 @@
if ((error = namei(&nd)) != 0)
return (error);
- if (nd.ni_vp->v_type == VREG && nd.ni_dvp->v_type != VDIR &&
- (nd.ni_vp->v_vflag & VV_ROOT) != 0) {
- struct vnode *covered_vp;
-
- /*
- * This happens if vp is a file mount. The call to
- * vn_fullpath_hardlink can panic if path resolution can't be
- * handled without the directory.
- *
- * To resolve this, we find the vnode which was mounted on -
- * this should have a unique global path since we disallow
- * mounting on linked files.
- */
- error = vn_lock(nd.ni_vp, LK_SHARED);
- if (error != 0)
- goto out;
- covered_vp = nd.ni_vp->v_mount->mnt_vnodecovered;
- vref(covered_vp);
- VOP_UNLOCK(nd.ni_vp);
- error = vn_fullpath(covered_vp, &retbuf, &freebuf);
- vrele(covered_vp);
- } else {
- error = vn_fullpath_hardlink(nd.ni_vp, nd.ni_dvp,
- nd.ni_cnd.cn_nameptr, nd.ni_cnd.cn_namelen, &retbuf,
- &freebuf, &size);
- }
+ error = vn_fullpath_hardlink(nd.ni_vp, nd.ni_dvp,
+ nd.ni_cnd.cn_nameptr, nd.ni_cnd.cn_namelen, &retbuf,
+ &freebuf, &size);
if (error == 0) {
size_t len;
@@ -3330,7 +3307,6 @@
memcpy(buf, retbuf, len);
free(freebuf, M_TEMP);
}
-out:
vrele(nd.ni_vp);
vrele(nd.ni_dvp);
NDFREE_PNBUF(&nd);
@@ -3839,15 +3815,6 @@
int error;
__enum_uint8(vtype) type;
- if (*buflen < 2)
- return (EINVAL);
- if (*buflen > MAXPATHLEN)
- *buflen = MAXPATHLEN;
-
- buf = malloc(*buflen, M_TEMP, M_WAITOK);
-
- addend = 0;
-
/*
* Check for VBAD to work around the vp_crossmp bug in lookup().
*
@@ -3861,10 +3828,50 @@
* vp == vp_crossmp. Prevent the problem by checking for VBAD.
*/
type = atomic_load_8(&vp->v_type);
- if (type == VBAD) {
- error = ENOENT;
- goto out_bad;
+ if (type == VBAD)
+ return (ENOENT);
+
+ /*
+ * For file mounts dvp is vp_crossmp and unusable; resolve via the
+ * covered vnode instead, whose path is unique since file mounts
+ * require nlink == 1.
+ */
+ if (type != VDIR && (vp->v_vflag & VV_ROOT) != 0) {
+ struct vnode *covered_vp;
+ size_t len;
+
+ error = vn_lock(vp, LK_SHARED);
+ if (error != 0)
+ return (error);
+ /* Recheck under the lock, the unlocked test is racy. */
+ if ((vp->v_vflag & VV_ROOT) == 0) {
+ VOP_UNLOCK(vp);
+ return (ENOENT);
+ }
+ covered_vp = vp->v_mount->mnt_vnodecovered;
+ vref(covered_vp);
+ VOP_UNLOCK(vp);
+ error = vn_fullpath(covered_vp, retbuf, freebuf);
+ vrele(covered_vp);
+ if (error != 0)
+ return (error);
+ len = strlen(*retbuf) + 1;
+ if (len > *buflen) {
+ free(*freebuf, M_TEMP);
+ return (ENAMETOOLONG);
+ }
+ *buflen = len;
+ return (0);
}
+
+ if (*buflen < 2)
+ return (EINVAL);
+ if (*buflen > MAXPATHLEN)
+ *buflen = MAXPATHLEN;
+
+ buf = malloc(*buflen, M_TEMP, M_WAITOK);
+
+ addend = 0;
if (type != VDIR) {
addend = hrdl_name_length + 2;
if (*buflen < addend) {

File Metadata

Mime Type
text/plain
Expires
Thu, Jul 16, 11:07 PM (10 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35038364
Default Alt Text
D58178.diff (2 KB)

Event Timeline