zfsctl_freebsd_root_lookup: gfs_vop_lookup may return a doomed vnode
gfs code is (almsot) completely agnostic of FreeBSD VFS locking, so it does not handle doomed but not yet dead vnodes and may return them. Check for those vnodes here and retry a lookup. Note that ZFS and gfs have additional protections that ensure that a parent vnode of the current vnode is never doomed. The fixed problem is an occasional failure to lookup a 'snapshot' or 'shares' directories under .zfs. Note that for the above reason all uses of zfsctl_root_lookup() are better be replaced with VOP_LOOKUP. MFC after: 5 weeks
This commit is contained in:
parent
a381878b79
commit
a98987454e
@ -603,19 +603,25 @@ zfsctl_freebsd_root_lookup(ap)
|
||||
|
||||
ASSERT(ap->a_cnp->cn_namelen < sizeof(nm));
|
||||
strlcpy(nm, ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen + 1);
|
||||
relookup:
|
||||
err = zfsctl_root_lookup(dvp, nm, vpp, NULL, 0, NULL, cr, NULL, NULL, NULL);
|
||||
if (err == 0 && (nm[0] != '.' || nm[1] != '\0')) {
|
||||
if (flags & ISDOTDOT)
|
||||
if (flags & ISDOTDOT) {
|
||||
VOP_UNLOCK(dvp, 0);
|
||||
err = vn_lock(*vpp, lkflags);
|
||||
if (err != 0) {
|
||||
vrele(*vpp);
|
||||
*vpp = NULL;
|
||||
}
|
||||
if (flags & ISDOTDOT)
|
||||
err = vn_lock(*vpp, lkflags);
|
||||
if (err != 0) {
|
||||
vrele(*vpp);
|
||||
*vpp = NULL;
|
||||
}
|
||||
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
|
||||
} else {
|
||||
err = vn_lock(*vpp, LK_EXCLUSIVE);
|
||||
if (err != 0) {
|
||||
VERIFY3S(err, ==, ENOENT);
|
||||
goto relookup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user