PERFORCE change 178836 for review
Efstratios Karatzas
gpf at FreeBSD.org
Wed May 26 21:06:27 UTC 2010
http://p4web.freebsd.org/@@178836?ac=10
Change 178836 by gpf at gpf_desktop on 2010/05/26 21:05:34
- changed how vn_fullpath_nocache(9) works internally.
now the fs specific part whose job is to find a parent directory
for our file has broken off to its own VOP(), VOP_GETPARENT.
VOP_GETPARENT works for UFS & ZFS.
Please refer to the comment headers above the functions in question
for more information on how to use them.
UFS: use directory inode hint or do an exhaustive search.
(exhaustive search still kernel panics)
ZFS: use the directory znode number that is stored inside the physical
part of the znode.
note: there are other ways we could do this such as
zfs_obj_to_path() but there's no documentation to be found and my
zfs magic is limited for the time being.
Still, vn_fullpath_nocache() performs well under UFS & ZFS - any
feedback welcome.
- oh and removed a trailing white space in praudit.c
Affected files ...
.. //depot/projects/soc2010/gpf_audit/freebsd/src/contrib/openbsm/bin/praudit/praudit.c#3 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/kern/vfs_default.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/kern/vnode_if.src#3 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/sys/vnode.h#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/ufs/ffs/ffs_vnops.c#3 edit
.. //depot/projects/soc2010/gpf_audit/vn_fullpath_nocache.c#4 edit
Differences ...
==== //depot/projects/soc2010/gpf_audit/freebsd/src/contrib/openbsm/bin/praudit/praudit.c#3 (text) ====
@@ -152,7 +152,7 @@
case 'x':
xml = 1;
- break;
+ break;
case '?':
default:
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c#2 (text+ko) ====
@@ -40,6 +40,7 @@
#include <sys/uio.h>
#include <sys/atomic.h>
#include <sys/namei.h>
+#include <sys/dirent.h>
#include <sys/mman.h>
#include <sys/cmn_err.h>
#include <sys/errno.h>
@@ -3772,6 +3773,12 @@
ZFS_ENTER(zfsvfs);
ZFS_VERIFY_ZP(zp);
gen = (uint32_t)zp->z_gen;
+
+ printf("EIMAI H VOP_VPTOFH TOU KWLOZFS\n");
+ printf("ID %llu\n", zp->z_id);
+ printf("PARENT ID %llu\n", zp->z_phys->zp_parent);
+ /* gpf shit */
+
size = (zfsvfs->z_parent != zfsvfs) ? LONG_FID_LEN : SHORT_FID_LEN;
fidp->fid_len = size;
@@ -4963,6 +4970,151 @@
return (EOPNOTSUPP);
}
+/*
+ * XXXgpf: should relocate them someplace else
+ * I just dont know where:S
+ */
+#define PARENTHINT 0x0001
+#define EXHAUSTSEARCH 0x0002
+#define WANTNAME 0x0004
+
+/*
+ * VOP_GETPARENT
+ *
+ * int VOP_GETPARENT(struct vnode *vp, struct vnode **dvp, uint64_t hint,
+ * int flags, char *buf, int *buflen);
+ *
+ * Find a parent directory -dvp- with vp as a child. The parent hint is used to
+ * facilitate the search.
+ *
+ * Flags should be set to:
+ * - PARENTHIT: if a hint ino_t of a directory is supplied to facilitate the search
+ * - EXHAUSTSEARCH: if we are willing to search the whole filesystem to find the directory
+ * - WANTNAME: if we want to copy the name used to reference the file inside the dir, to buf
+ *
+ * ZFS note: only WANTNAME is actually checked in ZFS code
+ *
+ * Locks: vp should be locked on entry and will still be locked on exit.
+ * On success, dvp will be locked and have its reference count incremented.
+ *
+ */
+int
+zfs_freebsd_getparent(struct vop_getparent_args *ap)
+/*
+vop_getparent {
+ IN struct vnode *a_vp;
+ OUT struct vnode **a_vpp;
+ IN uint64_t a_hint;
+ IN int a_flags;
+ INOUT char *a_buf;
+ INOUT int *a_buflen;
+};
+*/
+{
+ znode_t *zp;
+ struct mount *mp;
+ struct vnode *dvp;
+ int error;
+
+ zp = VTOZ(ap->a_vp);
+ mp = ap->a_vp->v_mount;
+ dvp = NULL;
+
+ if (zp->z_phys == NULL) {
+ error = ENOENT;
+ goto out;
+ }
+ /* grab directory vnode that should contain this znode */
+ error = VFS_VGET(mp, zp->z_phys->zp_parent, LK_SHARED, &dvp);
+ if (error) {
+ error = ENOENT;
+ goto out;
+ }
+ else if (ap->a_flags & WANTNAME) {
+ struct uio io;
+ struct iovec iov;
+ struct dirent *dp, *edp;
+ struct thread *td;
+ char *dirbuf;
+ u_int64_t dirbuflen;
+ int error, eofflag;
+ char foundit;
+
+ foundit = 0;
+ dirbuflen = ((struct znode *)dvp->v_data)->z_blksz;
+ dirbuf = malloc(dirbuflen, M_TEMP, M_WAITOK);
+ td = curthread;
+
+ /* prep the call to VOP_READDIR() */
+ iov.iov_base = dirbuf;
+ iov.iov_len = dirbuflen;
+ io.uio_iov = &iov;
+ io.uio_iovcnt = 1;
+ io.uio_offset = 0;
+ io.uio_resid = dirbuflen;
+ io.uio_segflg = UIO_SYSSPACE;
+ io.uio_rw = UIO_READ;
+ io.uio_td = td;
+ eofflag = 0;
+
+ error = VOP_READDIR(dvp, &io, td->td_ucred, &eofflag, NULL, NULL);
+ if (error) {
+ error = EIO;
+ goto out;
+ }
+
+ /* search for the correct znode number inside the directory */
+ edp = (struct dirent *)&dirbuf[dirbuflen - io.uio_resid];
+ for (dp = (struct dirent *)dirbuf; dp < edp; ) {
+ if (dp->d_reclen > 0) {
+ /* found it */
+ if (zp->z_id == ((struct dirent *)dp)->d_fileno) {
+ char *pch;
+ int len;
+
+ pch = ((struct dirent *)dp)->d_name;
+ len = strlen(pch);
+
+ if (len >= *(ap->a_buflen)) {
+ error = EOVERFLOW;
+ goto out;
+ }
+
+ strlcpy(ap->a_buf, ((struct dirent *)dp)->d_name, *(ap->a_buflen));
+ *(ap->a_buflen) -= len + 1;
+ foundit = 1;
+ break;
+ }
+ dp = (struct dirent *)((char *)dp + dp->d_reclen);
+ }
+ else {
+ error = EIO;
+ break;
+ }
+ }
+
+ if (dirbuf != NULL) {
+ free(dirbuf, M_TEMP);
+ }
+
+ if (foundit == 0 && error != 0) {
+ error = ENOENT;
+ if (dvp)
+ vput(dvp);
+ }
+ } /* WANTNAME */
+
+out:
+ if (error == 0 && dvp != NULL) {
+ *(ap->a_vpp) = dvp;
+ }
+ else if (error) {
+ *(ap->a_vpp) = NULL;
+ }
+
+ return (error);
+}
+
struct vop_vector zfs_vnodeops;
struct vop_vector zfs_fifoops;
@@ -5005,6 +5157,7 @@
.vop_getacl = zfs_freebsd_getacl,
.vop_setacl = zfs_freebsd_setacl,
.vop_aclcheck = zfs_freebsd_aclcheck,
+ .vop_getparent = zfs_freebsd_getparent,
};
struct vop_vector zfs_fifoops = {
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/kern/vfs_default.c#2 (text+ko) ====
@@ -120,6 +120,7 @@
.vop_unlock = vop_stdunlock,
.vop_vptocnp = vop_stdvptocnp,
.vop_vptofh = vop_stdvptofh,
+ .vop_getparent = vop_stdgetparent,
};
/*
@@ -841,6 +842,12 @@
return (error);
}
+int
+vop_stdgetparent(struct vop_getparent_args *ap)
+{
+ return (EOPNOTSUPP);
+}
+
/*
* vfs default ops
* used to fill the vfs function table to get reasonable default return values.
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/kern/vnode_if.src#3 (text+ko) ====
@@ -612,3 +612,15 @@
INOUT char *buf;
INOUT int *buflen;
};
+
+%% getparent vp L L L
+%% getparent vpp - L -
+
+vop_getparent {
+ IN struct vnode *vp;
+ OUT struct vnode **vpp;
+ IN uint64_t hint;
+ IN int flags;
+ INOUT char *buf;
+ INOUT int *buflen;
+};
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/sys/vnode.h#2 (text+ko) ====
@@ -693,6 +693,7 @@
int vop_stdpoll(struct vop_poll_args *);
int vop_stdvptocnp(struct vop_vptocnp_args *ap);
int vop_stdvptofh(struct vop_vptofh_args *ap);
+int vop_stdgetparent(struct vop_getparent_args *ap);
int vop_eopnotsupp(struct vop_generic_args *ap);
int vop_ebadf(struct vop_generic_args *ap);
int vop_einval(struct vop_generic_args *ap);
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/ufs/ffs/ffs_vnops.c#3 (text+ko) ====
@@ -69,6 +69,7 @@
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/conf.h>
+#include <sys/dirent.h>
#include <sys/extattr.h>
#include <sys/kernel.h>
#include <sys/limits.h>
@@ -119,8 +120,8 @@
static vop_openextattr_t ffs_openextattr;
static vop_setextattr_t ffs_setextattr;
static vop_vptofh_t ffs_vptofh;
+static vop_getparent_t ffs_getparent;
-
/* Global vfs data structures for ufs. */
struct vop_vector ffs_vnodeops1 = {
.vop_default = &ufs_vnodeops,
@@ -131,6 +132,7 @@
.vop_reallocblks = ffs_reallocblks,
.vop_write = ffs_write,
.vop_vptofh = ffs_vptofh,
+ .vop_getparent = ffs_getparent,
};
struct vop_vector ffs_fifoops1 = {
@@ -156,6 +158,7 @@
.vop_openextattr = ffs_openextattr,
.vop_setextattr = ffs_setextattr,
.vop_vptofh = ffs_vptofh,
+ .vop_getparent = ffs_getparent,
};
struct vop_vector ffs_fifoops2 = {
@@ -1789,3 +1792,228 @@
}
return (0);
}
+
+/*
+ * XXXgpf: should relocate them someplace else
+ * I just dont know where:S
+ */
+#define PARENTHINT 0x0001
+#define EXHAUSTSEARCH 0x0002
+#define WANTNAME 0x0004
+
+/*
+ * XXXgpf: used by VOP_GETPARENT
+ *
+ * find the name that is used to reference vp inside the directory vnode dvp.
+ * flags should be set to WANTNAME if the filename should be copied to
+ * the supplied buffer.
+ *
+ * locks: dvp must be locked on entry and will still be locked on exit
+ *
+ * returns:
+ * - ENOENT a file that corresponds to vp was not found inside dvp,
+ * or dvp is not a directory vnode
+ * - EIO error occured while reading the directory
+ * - EOVERFLOW result does not fit in buffer "name"
+ */
+static int
+dir_ilookup(struct vnode *vp, struct vnode *dvp, char *name, int *namelen, int flags)
+{
+ struct uio io;
+ struct iovec iov;
+ struct dirent *dp, *edp;
+ struct thread *td;
+ char *dirbuf;
+ u_int64_t dirbuflen;
+ int error, eofflag;
+ char foundit;
+
+ if (dvp->v_type != VDIR) {
+ return ENOENT;
+ }
+
+ foundit = 0;
+ dirbuflen = ((struct inode *)dvp->v_data)->i_size;
+ dirbuf = malloc(dirbuflen, M_TEMP, M_WAITOK);
+ td = curthread;
+
+ /* prep the call to VOP_READDIR() */
+ iov.iov_base = dirbuf;
+ iov.iov_len = dirbuflen;
+ io.uio_iov = &iov;
+ io.uio_iovcnt = 1;
+ io.uio_offset = 0;
+ io.uio_resid = dirbuflen;
+ io.uio_segflg = UIO_SYSSPACE;
+ io.uio_rw = UIO_READ;
+ io.uio_td = td;
+ eofflag = 0;
+
+ error = VOP_READDIR(dvp, &io, td->td_ucred, &eofflag, NULL, NULL);
+ if (error) {
+ error = EIO;
+ goto out;
+ }
+
+ /* search for the correct inode number inside the directory */
+ edp = (struct dirent *)&dirbuf[dirbuflen - io.uio_resid];
+ for (dp = (struct dirent *)dirbuf; dp < edp; ) {
+ if (dp->d_reclen > 0) {
+ /* found it */
+ if ( ((struct inode *)vp->v_data)->i_number == ((struct dirent *)dp)->d_fileno) {
+ char *pch;
+ int len;
+
+ if (flags & WANTNAME) {
+ pch = ((struct dirent *)dp)->d_name;
+ len = strlen(pch);
+
+ if (len >= *namelen) {
+ error = EOVERFLOW;
+ goto out;
+ }
+
+ strlcpy(name, ((struct dirent *)dp)->d_name, *namelen);
+ *namelen -= len + 1;
+ }
+
+ foundit = 1;
+ break;
+ }
+ dp = (struct dirent *)((char *)dp + dp->d_reclen);
+ }
+ else {
+ error = EIO;
+ break;
+ }
+ }
+
+out:
+ if (dirbuf != NULL) {
+ free(dirbuf, M_TEMP);
+ }
+
+ if (foundit == 0 && error != 0) {
+ error = ENOENT;
+ }
+
+ return error;
+}
+
+/*
+ * VOP_GETPARENT
+ *
+ * int VOP_GETPARENT(struct vnode *vp, struct vnode **dvp, uint64_t hint,
+ * int flags, char *buf, int *buflen);
+ *
+ * Find a parent directory -dvp- with vp as a child. The parent hint is used to
+ * facilitate the search.
+ *
+ * Flags should be set to:
+ * - PARENTHIT: if a hint ino_t of a directory is supplied to facilitate the search
+ * - EXHAUSTSEARCH: if we are willing to search the whole filesystem to find the directory
+ * - WANTNAME: if we want to copy the name used to reference the file inside the dir, to buf
+ *
+ * Locks: vp should be locked on entry and will still be locked on exit.
+ * On success, dvp will be locked and have its reference count incremented.
+ *
+ */
+static int
+ffs_getparent(struct vop_getparent_args *ap)
+/*
+vop_getparent {
+ IN struct vnode *a_vp;
+ OUT struct vnode **a_vpp;
+ IN uint64_t a_hint;
+ IN int a_flags;
+ INOUT char *a_buf;
+ INOUT int *a_buflen;
+};
+*/
+{
+ struct mount *mp;
+ struct vnode *vp, *dvp;
+ int error, flags;
+
+ error = 0;
+ vp = ap->a_vp;
+ mp = vp->v_mount;
+ flags = ap->a_flags;
+
+ /* XXXgpf:is this check necessary? */
+ if (vp->v_type == VBAD) {
+ error = ENOENT;
+ dvp = NULL;
+ goto out;
+ }
+
+ /* grab the parent directory using the directory_hint */
+ if (flags & PARENTHINT) {
+ error = VFS_VGET(mp, ap->a_hint, LK_SHARED, &dvp);
+ /* in case of failure, proceed to exhaustive search */
+ if (error) {
+ dvp = NULL;
+ }
+ else if (flags & WANTNAME) {
+ /* grab the name that is being used to reference vp */
+ error = dir_ilookup(vp, dvp, ap->a_buf, ap->a_buflen, flags);
+ if (error) {
+ vput(dvp);
+ dvp = NULL;
+ }
+ }
+ }
+
+ /*
+ * if our target is not a directory and we haven't found 'a' parent directory,
+ * do an exhaustive search on the filesystem
+ */
+ if ((flags & EXHAUSTSEARCH) && dvp == NULL) {
+ /*
+ * XXXgpf: this actually does not work because when the thread will try to sleep,
+ * e.g. in VOP_READDIR, the kernel will panic because we have ilocked mp >.<
+ *
+ * Not, it also kernel panics because we have locked vp >.<'
+ */
+ MNT_ILOCK(mp);
+ if (!TAILQ_EMPTY(&mp->mnt_nvnodelist)) {
+ struct vnode *tvp;
+
+ TAILQ_FOREACH(tvp, &mp->mnt_nvnodelist, v_nmntvnodes) {
+ if (tvp->v_type == VDIR) {
+ vn_lock(tvp, LK_SHARED);
+ /* grab the name that is being used to reference vp */
+ error = dir_ilookup(vp, tvp, ap->a_buf, ap->a_buflen, flags);
+
+ /* found it */
+ if (error == 0) {
+ dvp = tvp;
+ vref(dvp);
+ break;
+ }
+ VOP_UNLOCK(tvp, 0);
+ }
+ }
+ }
+ MNT_IUNLOCK(mp);
+
+ /* we failed to find a directory that contains the vnode, exit */
+ if (error != 0) {
+ error = ENOENT;
+ }
+ }
+ /* we failed to find a directory that contains the vnode, exit */
+ else if (dvp == NULL) {
+ error = ENOENT;
+ }
+
+out:
+ if (error == 0 && dvp != NULL) {
+ *(ap->a_vpp) = dvp;
+ }
+ else if (error) {
+ *(ap->a_vpp) = NULL;
+ }
+
+ return error;
+}
==== //depot/projects/soc2010/gpf_audit/vn_fullpath_nocache.c#4 (text+ko) ====
@@ -45,108 +45,14 @@
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
-#define PARENT_HINT 0x0001
-#define EXHAUSTIVE_SEARCH 0x0002
-
-/*
- * find the name that is used to reference vp inside the directory vnode dvp
- * locks: dvp must be locked on entry and will still be locked on exit
- *
- * works for UFS
- *
- * returns:
- * - ENOENT a file that corresponds to vp was not found inside dvp
- * - EIO error occured while reading the directory
- * - EOVERFLOW result does not fit in buffer "name"
+/*
+ * XXXgpf: should relocate them someplace else
+ * I just dont know where:S
*/
-static int
-dir_ilookup(struct vnode *vp, struct vnode *dvp, char *name, int *namelen)
-{
- struct uio io;
- struct iovec iov;
- struct dirent *dp, *edp;
- struct thread *td;
- char *dirbuf;
- u_int64_t dirbuflen;
- int error, eofflag;
- char foundit;
-
- KASSERT("vp != NULL", "dir_ilookup: vp == NULL");
- KASSERT("dvp != NULL", "dir_ilookup: dvp == NULL");
- KASSERT("name != NULL", "dir_ilookup: name == NULL");
-
- /* XXXgpf: temporary, must be a better way to check this than f_type or f_fstypename */
- if (strcmp(vp->v_mount->mnt_stat.f_fstypename, "ufs")) {
- uprintf("only ufs supported\n");
- return 1;
- }
-
- foundit = 0;
- dirbuflen = ((struct inode *)dvp->v_data)->i_size;
- dirbuf = malloc(dirbuflen, M_TEMP, M_WAITOK);
- td = curthread;
-
- /* prep the call to VOP_READDIR() */
- iov.iov_base = dirbuf;
- iov.iov_len = dirbuflen;
- io.uio_iov = &iov;
- io.uio_iovcnt = 1;
- io.uio_offset = 0;
- io.uio_resid = dirbuflen;
- io.uio_segflg = UIO_SYSSPACE;
- io.uio_rw = UIO_READ;
- io.uio_td = td;
- eofflag = 0;
-
- error = VOP_READDIR(dvp, &io, td->td_ucred, &eofflag, NULL, NULL);
- if (error) {
- uprintf("VOP_READDIR failure %d\n", error);
- error = EIO;
- goto out;
- }
-
- /* search for the correct inode number inside the directory */
- edp = (struct dirent *)&dirbuf[dirbuflen - io.uio_resid];
- for (dp = (struct dirent *)dirbuf; dp < edp; ) {
- if (dp->d_reclen > 0) {
- /* found it */
- if ( ((struct inode *)vp->v_data)->i_number == ((struct dirent *)dp)->d_fileno) {
- char *pch;
- int len;
-
- pch = ((struct dirent *)dp)->d_name;
- len = strlen(pch);
-
- if (len >= *namelen) {
- error = EOVERFLOW;
- goto out;
- }
-
- strlcpy(name, ((struct dirent *)dp)->d_name, *namelen);
- *namelen -= len + 1;
- foundit = 1;
- break;
- }
- dp = (struct dirent *)((char *)dp + dp->d_reclen);
- }
- else {
- error = EIO;
- break;
- }
- }
+#define PARENTHINT 0x0001
+#define EXHAUSTSEARCH 0x0002
+#define WANTNAME 0x0004
-out:
- if (dirbuf != NULL) {
- free(dirbuf, M_TEMP);
- }
-
- if (foundit == 0 && error != 0) {
- error = ENOENT;
- }
-
- return error;
-}
-
/*
* vn_fullpath_nocache
*
@@ -157,11 +63,13 @@
* - flags should be set to PARENT_HINT, if the directory hint is supplied
* and to EXHAUSTIVE_SEARCH, if we are willing to go intro great trouble to get this path.
*
+ * Locks: no locks required.
+ *
* Author's note: This only works for UFS filesystems (for now).
* Oh, also EXHAUSTIVE_SEARCH will kernel panic :-D
*/
static int
-vn_fullpath_nocache(struct vnode *vp, char **fullpath, char **freepath, ino_t directory_hint, char flags)
+vn_fullpath_nocache(struct vnode *vp, char **fullpath, char **freepath, uint64_t directory_hint, char flags)
{
struct vnode *dvp, *upper_dvp;
struct mount *mp;
@@ -192,68 +100,15 @@
/*
* - If our target is a directory, move on to the part where we traverse the '..' entries.
- * - If not, either use the directory_hint if it's available or do an exhaustive search on the fs (xD) so
- * that we can connect the vp with 'a' parent directory.
+ * - If not, try to find its' parent through VOP_GETPARENT
*/
if (vp->v_type != VDIR) {
- /* grab the parent directory using the directory_hint */
- if ((flags & PARENT_HINT) && vp->v_type != VDIR) {
- error = VFS_VGET(vp->v_mount, directory_hint, LK_SHARED, &dvp);
- /* in case of failure, proceed to exhaustive search */
- if (error) {
- uprintf("VFS_VGET failure %d\n", error);
- dvp = NULL;
- }
- else {
- /* grab the name that is being used to reference vp */
- error = dir_ilookup(vp, dvp, fname, &fnamelen);
- if (error) {
- vput(dvp);
- goto out;
- }
- }
- }
-
- /*
- * if our target is not a directory and we haven't found 'a' parent directory,
- * do an exhaustive search on the filesystem
- */
- if ((flags & EXHAUSTIVE_SEARCH) && dvp == NULL) {
- /*
- * XXXgpf: this actually does not work because when the thread will try to sleep,
- * e.g. in VOP_READDIR, the kernel will panic because we have ilocked mp >.<
- */
- MNT_ILOCK(mp);
- if (!TAILQ_EMPTY(&mp->mnt_nvnodelist)) {
- struct vnode *tvp;
-
- TAILQ_FOREACH(tvp, &mp->mnt_nvnodelist, v_nmntvnodes) {
- if (tvp->v_type == VDIR) {
- vn_lock(tvp, LK_SHARED);
- /* grab the name that is being used to reference vp */
- error = dir_ilookup(vp, tvp, fname, &fnamelen);
-
- /* found it */
- if (error == 0) {
- dvp = tvp;
- vref(dvp);
- break;
- }
- VOP_UNLOCK(tvp, 0);
- }
- }
- }
- MNT_IUNLOCK(mp);
-
- /* we failed to find a directory that contains the vnode, exit */
- if (error != 0) {
- error = ENOENT;
- goto out;
- }
- }
- /* we failed to find a directory that contains the vnode, exit */
- else if (dvp == NULL) {
- error = ENOENT;
+ /* XXXgpf: perhaps locking vp is redundant */
+ vn_lock(vp, LK_SHARED);
+ error = VOP_GETPARENT(vp, &dvp, directory_hint, flags, fname, &fnamelen);
+ VOP_UNLOCK(vp, 0);
+ if (error) {
+ dvp = NULL;
goto out;
}
@@ -268,7 +123,7 @@
strcpy(pch, fname);
buflen -= strlen(fname);
buf[--buflen] = '/';
- } /* if not VDIR */
+ }
/* if our target is a dir, do the initial preparation */
else {
dvp = vp;
@@ -355,11 +210,13 @@
struct nameidata nd;
struct vnode *vp, *dvp;
char *freepath, *fullpath;
- char *path = "/usr/home/gpf/Desktop/gsoc/example";
- //char *path = "/usr/home/gpf/Desktop/usb/abc/file";
+ //char *path = "/usr/home/gpf/Desktop/gsoc/example";
+ //char *path = "/usr/home/gpf/Desktop/";
+ char *path = "/example/test/test.sh";
ino_t directory_hint;
int vfslocked;
int error;
+ int flags;
/* use the namei interface to get something that we can work on */
NDINIT(&nd, LOOKUP, FOLLOW | WANTPARENT, UIO_SYSSPACE, path, curthread);
@@ -372,11 +229,6 @@
vp = nd.ni_vp;
dvp = nd.ni_dvp;
-
- #if defined DEBUG
- uprintf("inode number of the file %u\n", ((struct inode *)vp->v_data)->i_number);
- uprintf("inode number of the dir that contains the file %u\n", ((struct inode *)dvp->v_data)->i_number);
- #endif
vrele(vp);
vrele(dvp);
@@ -384,14 +236,19 @@
/* preping the call to vn_fullpath_nocache() */
freepath = NULL;
- /* careful, should not reference the i_number like that when vp is the root of a fs */
- if (dvp != NULL && dvp->v_data != NULL)
- directory_hint = ((struct inode *)dvp->v_data)->i_number;
-
- error = vn_fullpath_nocache(vp, &fullpath, &freepath, directory_hint, PARENT_HINT);
+ if (!strcmp(vp->v_mount->mnt_stat.f_fstypename, "ufs")) {
+ flags = PARENTHINT | WANTNAME;
+ /* careful, should not reference the i_number like that when vp is the root of a fs */
+ if (dvp != NULL && dvp->v_data != NULL)
+ directory_hint = ((struct inode *)dvp->v_data)->i_number;
+ }
+ else if (!strcmp(vp->v_mount->mnt_stat.f_fstypename, "zfs")) {
+ flags = WANTNAME;
+ }
+ error = vn_fullpath_nocache(vp, &fullpath, &freepath, directory_hint, flags);
uprintf("vn_fullpath_nocache() returned %d\n", error);
- if (freepath != NULL) {
+ if (freepath != NULL) {
uprintf("path: %s\n", fullpath);
free(freepath, M_TEMP);
}
More information about the p4-projects
mailing list