Skip to content

Commit

Permalink
zfs: port vop_lookup
Browse files Browse the repository at this point in the history
The way lookups work in OSv are very different from Solaris and FreeBSD
as we already get a preallocated vnode passed in.  Thus the code also
is very different and basically the vnode operation is an entirely
different implementation.  We thus don't even try to keep the code,
and also leave out support for things like case insenstive lookups
or extended attributes which might never be supported or at least
will look very different.
  • Loading branch information
Christoph Hellwig committed Jun 26, 2013
1 parent 3651135 commit b7ee91e
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 179 deletions.
18 changes: 14 additions & 4 deletions bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
#include <sys/policy.h>
#include <sys/kcondvar.h>
#include <sys/callb.h>
#include <sys/smp.h>
#include <sys/zfs_dir.h>
#include <sys/zfs_acl.h>
#include <sys/fs/zfs.h>
Expand All @@ -53,7 +52,6 @@
#include <sys/zfs_fuid.h>
#include <sys/sa.h>
#include <sys/zfs_sa.h>
#include <sys/dnlc.h>
#include <sys/extdirent.h>

/*
Expand Down Expand Up @@ -91,8 +89,10 @@ zfs_match_find(zfsvfs_t *zfsvfs, znode_t *dzp, char *name, boolean_t exact,
}
*zoid = ZFS_DIRENT_OBJ(*zoid);

#ifndef __OSV__
if (error == ENOENT && update)
dnlc_update(ZTOV(dzp), name, DNLC_NO_VNODE);
#endif

return (error);
}
Expand Down Expand Up @@ -141,7 +141,9 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp,
boolean_t update;
boolean_t exact;
uint64_t zoid;
#ifndef __OSV__
vnode_t *vp = NULL;
#endif
int error = 0;
int cmpflags;

Expand Down Expand Up @@ -285,6 +287,7 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp,
if (error == 0)
error = (zoid == 0 ? ENOENT : 0);
} else {
#ifndef __OSV__
if (update)
vp = dnlc_lookup(ZTOV(dzp), name);
if (vp == DNLC_NO_VNODE) {
Expand All @@ -299,7 +302,9 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp,
*dlpp = dl;
*zpp = VTOZ(vp);
return (0);
} else {
} else
#endif
{
error = zfs_match_find(zfsvfs, dzp, name, exact,
update, direntflags, realpnp, &zoid);
}
Expand All @@ -319,8 +324,10 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp,
zfs_dirent_unlock(dl);
return (error);
}
#ifndef __OSV__
if (!(flag & ZXATTR) && update)
dnlc_update(ZTOV(dzp), name, ZTOV(*zpp));
#endif
}

*dlpp = dl;
Expand All @@ -339,8 +346,9 @@ zfs_dirent_unlock(zfs_dirlock_t *dl)

mutex_enter(&dzp->z_lock);

if (!dl->dl_namelock)
if (!dl->dl_namelock) {
rw_exit(&dzp->z_name_lock);
}

if (dl->dl_sharecnt > 1) {
dl->dl_sharecnt--;
Expand All @@ -358,6 +366,7 @@ zfs_dirent_unlock(zfs_dirlock_t *dl)
kmem_free(dl, sizeof (*dl) + dl->dl_namesize);
}

#ifdef NOTYET
/*
* Look up an entry in a directory.
*
Expand Down Expand Up @@ -1103,3 +1112,4 @@ zfs_sticky_remove_access(znode_t *zdp, znode_t *zp, cred_t *cr)
else
return (secpolicy_vnode_remove(ZTOV(zp), cr));
}
#endif /* NOTYET */
206 changes: 32 additions & 174 deletions bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
Original file line number Diff line number Diff line change
Expand Up @@ -1205,205 +1205,63 @@ specvp_check(vnode_t **vpp, cred_t *cr)
}
return (error);
}
#endif /* NOTYET */


/*
* Lookup an entry in a directory, or an extended attribute directory.
* If it exists, return a held vnode reference for it.
*
* IN: dvp - vnode of directory to search.
* nm - name of entry to lookup.
* pnp - full pathname to lookup [UNUSED].
* flags - LOOKUP_XATTR set if looking for an attribute.
* rdir - root directory vnode [UNUSED].
* cr - credentials of caller.
* ct - caller context
* direntflags - directory lookup flags
* realpnp - returned pathname.
*
* OUT: vpp - vnode of located entry, NULL if not found.
*
* RETURN: 0 if success
* error code if failure
*
* Timestamps:
* NA
*/
/* ARGSUSED */
static int
zfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct componentname *cnp,
int nameiop, cred_t *cr, kthread_t *td, int flags)
zfs_lookup(struct vnode *dvp, char *nm, struct vnode *vp)
{
znode_t *zdp = VTOZ(dvp);
zfsvfs_t *zfsvfs = zdp->z_zfsvfs;
int error = 0;
int *direntflags = NULL;
void *realpnp = NULL;

/* fast path */
if (!(flags & (LOOKUP_XATTR | FIGNORECASE))) {

if (dvp->v_type != VDIR) {
return (ENOTDIR);
} else if (zdp->z_sa_hdl == NULL) {
return (EIO);
}

if (nm[0] == 0 || (nm[0] == '.' && nm[1] == '\0')) {
error = zfs_fastaccesschk_execute(zdp, cr);
if (!error) {
*vpp = dvp;
VN_HOLD(*vpp);
return (0);
}
return (error);
} else {
vnode_t *tvp = dnlc_lookup(dvp, nm);

if (tvp) {
error = zfs_fastaccesschk_execute(zdp, cr);
if (error) {
VN_RELE(tvp);
return (error);
}
if (tvp == DNLC_NO_VNODE) {
VN_RELE(tvp);
return (ENOENT);
} else {
*vpp = tvp;
return (specvp_check(vpp, cr));
}
}
}
}
znode_t *dzp = VTOZ(dvp);
zfsvfs_t *zfsvfs = dzp->z_zfsvfs;
znode_t *zp;
zfs_dirlock_t *dl;
int error = 0;

DTRACE_PROBE2(zfs__fastpath__lookup__miss, vnode_t *, dvp, char *, nm);
if (*nm == '\0')
return ENOENT;
if (dvp->v_type != VDIR)
return ENOTDIR;

ASSERT0(!(nm[0] == '.' && nm[1] == '\0'));
ASSERT0(!(nm[0] == '.' && nm[1] == '.' && nm[2] == '\0'));

ZFS_ENTER(zfsvfs);
ZFS_VERIFY_ZP(zdp);

*vpp = NULL;

if (flags & LOOKUP_XATTR) {
#ifdef TODO
/*
* If the xattr property is off, refuse the lookup request.
*/
if (!(zfsvfs->z_vfs->vfs_flag & VFS_XATTR)) {
ZFS_EXIT(zfsvfs);
return (EINVAL);
}
#endif

/*
* We don't allow recursive attributes..
* Maybe someday we will.
*/
if (zdp->z_pflags & ZFS_XATTR) {
ZFS_EXIT(zfsvfs);
return (EINVAL);
}

if (error = zfs_get_xattrdir(VTOZ(dvp), vpp, cr, flags)) {
ZFS_EXIT(zfsvfs);
return (error);
}

/*
* Do we have permission to get into attribute directory?
*/

if (error = zfs_zaccess(VTOZ(*vpp), ACE_EXECUTE, 0,
B_FALSE, cr)) {
VN_RELE(*vpp);
*vpp = NULL;
}

ZFS_EXIT(zfsvfs);
return (error);
}

if (dvp->v_type != VDIR) {
ZFS_EXIT(zfsvfs);
return (ENOTDIR);
}
ZFS_VERIFY_ZP(dzp);

#ifdef ACL_TODO
/*
* Check accessibility of directory.
*/

if (error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr)) {
if (error = zfs_zaccess(dzp, ACE_EXECUTE, 0, B_FALSE, cr)) {
ZFS_EXIT(zfsvfs);
return (error);
}
#endif

if (zfsvfs->z_utf8 && u8_validate(nm, strlen(nm),
NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
ZFS_EXIT(zfsvfs);
return (EILSEQ);
}

error = zfs_dirlook(zdp, nm, vpp, flags, direntflags, realpnp);
if (error == 0)
error = specvp_check(vpp, cr);

/* Translate errors and add SAVENAME when needed. */
if (cnp->cn_flags & ISLASTCN) {
switch (nameiop) {
case CREATE:
case RENAME:
if (error == ENOENT) {
error = EJUSTRETURN;
cnp->cn_flags |= SAVENAME;
break;
}
/* FALLTHROUGH */
case DELETE:
if (error == 0)
cnp->cn_flags |= SAVENAME;
break;
}
}
if (error == 0 && (nm[0] != '.' || nm[1] != '\0')) {
int ltype = 0;
error = zfs_dirent_lock(&dl, dzp, nm, &zp, ZEXISTS | ZSHARED, NULL, NULL);
if (error)
return error;
zfs_dirent_unlock(dl);
dzp->z_zn_prefetch = B_TRUE; /* enable prefetching */

if (cnp->cn_flags & ISDOTDOT) {
ltype = VOP_ISLOCKED(dvp);
VOP_UNLOCK(dvp, 0);
}
ZFS_EXIT(zfsvfs);
error = zfs_vnode_lock(*vpp, cnp->cn_lkflags);
if (cnp->cn_flags & ISDOTDOT)
vn_lock(dvp, ltype | LK_RETRY);
if (error != 0) {
VN_RELE(*vpp);
*vpp = NULL;
return (error);
}
} else {
ZFS_EXIT(zfsvfs);
}
zp->z_vnode = vp;
vp->v_data = zp;

#ifdef FREEBSD_NAMECACHE
/*
* Insert name into cache (as non-existent) if appropriate.
*/
if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
cache_enter(dvp, *vpp, cnp);
/*
* Insert name into cache if appropriate.
*/
if (error == 0 && (cnp->cn_flags & MAKEENTRY)) {
if (!(cnp->cn_flags & ISLASTCN) ||
(nameiop != DELETE && nameiop != RENAME)) {
cache_enter(dvp, *vpp, cnp);
}
}
#endif
vp->v_mode = zp->z_mode;
vp->v_type = IFTOVT(vp->v_mode);
vp->v_size = zp->z_size;

return (error);
ZFS_EXIT(zfsvfs);
return error;
}

#ifdef NOTYET
/*
* Attempt to create a new entry in a directory. If the entry
* already exists, truncate the file if permissible, else return
Expand Down Expand Up @@ -5983,7 +5841,7 @@ struct vnops zfs_vnops = {
(vnop_ioctl_t)vop_einval, /* ioctl */
zfs_fsync, /* fsync */
zfs_readdir, /* readdir */
NULL, /* lookup */
zfs_lookup, /* lookup */
NULL, /* create */
NULL, /* remove */
NULL, /* rename */
Expand Down
2 changes: 1 addition & 1 deletion build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ zfs += bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.o
zfs += bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_byteswap.o
#zfs += bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.o
zfs += bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_debug.o
#zfs += bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.o
zfs += bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.o
zfs += bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_fm.o
#zfs += bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_fuid.o
#zfs += bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.o
Expand Down

0 comments on commit b7ee91e

Please sign in to comment.