zfs_dirlook: bailout early if directory is unlinked

Otherwise we could fail with an incorrect error if e.g. parent
object id is removed too or we can even return a wrong vnode if
parent object has been already re-used.

Discussed with:	pjd
Also see:	http://article.gmane.org/gmane.os.freebsd.devel.file-systems/13863
MFC after:	26 days
This commit is contained in:
Andriy Gapon 2012-11-04 14:50:08 +00:00
parent 5c997cc429
commit 2c6024ec1b

View file

@ -374,8 +374,15 @@ zfs_dirlook(znode_t *dzp, char *name, vnode_t **vpp, int flags,
znode_t *zp;
int error = 0;
uint64_t parent;
int unlinked;
if (name[0] == 0 || (name[0] == '.' && name[1] == 0)) {
mutex_enter(&dzp->z_lock);
unlinked = dzp->z_unlinked;
mutex_exit(&dzp->z_lock);
if (unlinked)
return (ENOENT);
*vpp = ZTOV(dzp);
VN_HOLD(*vpp);
} else if (name[0] == '.' && name[1] == '.' && name[2] == 0) {
@ -394,6 +401,13 @@ zfs_dirlook(znode_t *dzp, char *name, vnode_t **vpp, int flags,
NULL, NULL, NULL);
return (error);
}
mutex_enter(&dzp->z_lock);
unlinked = dzp->z_unlinked;
mutex_exit(&dzp->z_lock);
if (unlinked)
return (ENOENT);
rw_enter(&dzp->z_parent_lock, RW_READER);
error = zfs_zget(zfsvfs, parent, &zp);
if (error == 0)