mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-18 15:30:21 +00:00
Fix autofs triggering problem. Assume you have an NFS server,
192.168.1.1, with share "share". This commit fixes a problem where "mkdir /net/192.168.1.1/share/meh" would return spurious error instead of creating the directory if the target filesystem wasn't mounted yet; subsequent attempts would work correctly. The failure scenario is kind of complicated to explain, but it all boils down to calling VOP_MKDIR() for the target filesystem (NFS) with wrong dvp - the autofs vnode instead of the filesystem root mounted over it. Reviewed by: kib@ MFC after: 1 month Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D5442
This commit is contained in:
parent
6d3eca246c
commit
213ed83855
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=296715
@ -214,7 +214,7 @@ autofs_lookup(struct vop_lookup_args *ap)
|
|||||||
struct autofs_mount *amp;
|
struct autofs_mount *amp;
|
||||||
struct autofs_node *anp, *child;
|
struct autofs_node *anp, *child;
|
||||||
struct componentname *cnp;
|
struct componentname *cnp;
|
||||||
int error, lock_flags;
|
int error;
|
||||||
|
|
||||||
dvp = ap->a_dvp;
|
dvp = ap->a_dvp;
|
||||||
vpp = ap->a_vpp;
|
vpp = ap->a_vpp;
|
||||||
@ -257,23 +257,13 @@ autofs_lookup(struct vop_lookup_args *ap)
|
|||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
if (newvp != NULL) {
|
if (newvp != NULL) {
|
||||||
error = VOP_LOOKUP(newvp, ap->a_vpp, ap->a_cnp);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Instead of figuring out whether our vnode should
|
* The target filesystem got automounted.
|
||||||
* be locked or not given the error and cnp flags,
|
* Let the lookup(9) go around with the same
|
||||||
* just "copy" the lock status from vnode returned
|
* path component.
|
||||||
* by mounted filesystem's VOP_LOOKUP(). Get rid
|
|
||||||
* of that new vnode afterwards.
|
|
||||||
*/
|
*/
|
||||||
lock_flags = VOP_ISLOCKED(newvp);
|
vput(newvp);
|
||||||
if (lock_flags == 0) {
|
return (ERELOOKUP);
|
||||||
VOP_UNLOCK(dvp, 0);
|
|
||||||
vrele(newvp);
|
|
||||||
} else {
|
|
||||||
vput(newvp);
|
|
||||||
}
|
|
||||||
return (error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,6 +495,7 @@ lookup(struct nameidata *ndp)
|
|||||||
int rdonly; /* lookup read-only flag bit */
|
int rdonly; /* lookup read-only flag bit */
|
||||||
int error = 0;
|
int error = 0;
|
||||||
int dpunlocked = 0; /* dp has already been unlocked */
|
int dpunlocked = 0; /* dp has already been unlocked */
|
||||||
|
int relookup = 0; /* do not consume the path component */
|
||||||
struct componentname *cnp = &ndp->ni_cnd;
|
struct componentname *cnp = &ndp->ni_cnd;
|
||||||
int lkflags_save;
|
int lkflags_save;
|
||||||
int ni_dvp_unlocked;
|
int ni_dvp_unlocked;
|
||||||
@ -745,6 +746,14 @@ lookup(struct nameidata *ndp)
|
|||||||
goto unionlookup;
|
goto unionlookup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (error == ERELOOKUP) {
|
||||||
|
vref(dp);
|
||||||
|
ndp->ni_vp = dp;
|
||||||
|
error = 0;
|
||||||
|
relookup = 1;
|
||||||
|
goto good;
|
||||||
|
}
|
||||||
|
|
||||||
if (error != EJUSTRETURN)
|
if (error != EJUSTRETURN)
|
||||||
goto bad;
|
goto bad;
|
||||||
/*
|
/*
|
||||||
@ -777,6 +786,8 @@ lookup(struct nameidata *ndp)
|
|||||||
goto success;
|
goto success;
|
||||||
} else
|
} else
|
||||||
cnp->cn_lkflags = lkflags_save;
|
cnp->cn_lkflags = lkflags_save;
|
||||||
|
|
||||||
|
good:
|
||||||
#ifdef NAMEI_DIAGNOSTIC
|
#ifdef NAMEI_DIAGNOSTIC
|
||||||
printf("found\n");
|
printf("found\n");
|
||||||
#endif
|
#endif
|
||||||
@ -856,6 +867,14 @@ lookup(struct nameidata *ndp)
|
|||||||
*/
|
*/
|
||||||
KASSERT((cnp->cn_flags & ISLASTCN) || *ndp->ni_next == '/',
|
KASSERT((cnp->cn_flags & ISLASTCN) || *ndp->ni_next == '/',
|
||||||
("lookup: invalid path state."));
|
("lookup: invalid path state."));
|
||||||
|
if (relookup) {
|
||||||
|
relookup = 0;
|
||||||
|
if (ndp->ni_dvp != dp)
|
||||||
|
vput(ndp->ni_dvp);
|
||||||
|
else
|
||||||
|
vrele(ndp->ni_dvp);
|
||||||
|
goto dirloop;
|
||||||
|
}
|
||||||
if (*ndp->ni_next == '/') {
|
if (*ndp->ni_next == '/') {
|
||||||
cnp->cn_nameptr = ndp->ni_next;
|
cnp->cn_nameptr = ndp->ni_next;
|
||||||
while (*cnp->cn_nameptr == '/') {
|
while (*cnp->cn_nameptr == '/') {
|
||||||
|
@ -190,6 +190,7 @@ __END_DECLS
|
|||||||
#define EJUSTRETURN (-2) /* don't modify regs, just return */
|
#define EJUSTRETURN (-2) /* don't modify regs, just return */
|
||||||
#define ENOIOCTL (-3) /* ioctl not handled by this layer */
|
#define ENOIOCTL (-3) /* ioctl not handled by this layer */
|
||||||
#define EDIRIOCTL (-4) /* do direct ioctl in GEOM */
|
#define EDIRIOCTL (-4) /* do direct ioctl in GEOM */
|
||||||
|
#define ERELOOKUP (-5) /* retry the directory lookup */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user