PERFORCE change 178885 for review
Efstratios Karatzas
gpf at FreeBSD.org
Thu May 27 14:41:58 UTC 2010
http://p4web.freebsd.org/@@178885?ac=10
Change 178885 by gpf at gpf_desktop on 2010/05/27 14:41:11
- removed some debuging printf()s
- moved vn_fullpath_nocache(9) to sys/kern/vfs_cache.c.
This is the temporary home, till and if I find a more suitable one.
From now on, this file should be looked up for the latest version
of the KPI, not the LKM that I uploaded a few weeks ago.
- What is stored inside the filehandle is fs specific. Therefore, I
thought a VFS op would be the best way to extract the parent "hint".
Introduced VFS_FHHINT() that does this job for us. I made sure that
a default implementation for this vfs op is available, and that every
filesystem that uses VFS_FHTOVP() would also have this new VFS op mapped
to the default implementation in sys/kern/vfs_default.c so that we won't
kernel-panic when some fs other than UFS tries to dereference the mp
for that operation. For now, only UFS really needs it.
- A problem of old got solved. In my NFS test, during the first few operations
after a new file was created, vn_fullpath(9) was unable to acquire a
path. This problem was with both UFS & ZFS.
Now, I've added a call to vn_fullpath_nocache() inside nfs server code for the
write operation and it works just fine; we are able to acquire paths when we
do something like "echo message > new_file".
In the next few hours, I'll alter all
all of nfs server code so that every time that the cache fails us, this
KPI will be used instead as a last resort.
- fixed/added some KASSERTS here and there.
Affected files ...
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c#3 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/cd9660/cd9660_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/ext2fs/ext2_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/hpfs/hpfs_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/msdosfs/msdosfs_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/ntfs/ntfs_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/nullfs/null_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/tmpfs/tmpfs_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/udf/udf_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/unionfs/union_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/gnu/fs/reiserfs/reiserfs_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/gnu/fs/xfs/FreeBSD/xfs_mountops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/kern/vfs_cache.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/kern/vfs_default.c#3 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/nfsserver/nfs_serv.c#9 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/sys/mount.h#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/sys/vnode.h#3 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/ufs/ffs/ffs_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/ufs/ffs/ffs_vnops.c#4 edit
Differences ...
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c#2 (text+ko) ====
@@ -112,6 +112,7 @@
.vfs_sync = zfs_sync,
.vfs_checkexp = zfs_checkexp,
.vfs_fhtovp = zfs_fhtovp,
+ .vfs_fhhint = vfs_stdfhhint,
};
VFS_SET(zfs_vfsops, zfs, VFCF_JAIL | VFCF_DELEGADMIN);
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c#3 (text+ko) ====
@@ -3772,13 +3772,7 @@
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 */
-
+ gen = (uint32_t)zp->z_gen;
size = (zfsvfs->z_parent != zfsvfs) ? LONG_FID_LEN : SHORT_FID_LEN;
fidp->fid_len = size;
@@ -5016,6 +5010,10 @@
struct vnode *dvp;
int error;
+ KASSERT(ap->a_vp != NULL, ("VOP_GEPARENT: null vp"));
+ if (ap->a_flags & WANTPARENT)
+ KASSERT(ap->a_buf != NULL, ("VOP_GEPARENT: null buffer"));
+
zp = VTOZ(ap->a_vp);
mp = ap->a_vp->v_mount;
dvp = NULL;
@@ -5030,6 +5028,7 @@
error = ENOENT;
goto out;
}
+ /* scan the directory for a matching dirent */
else if (ap->a_flags & WANTNAME) {
struct uio io;
struct iovec iov;
@@ -5108,7 +5107,7 @@
if (error == 0 && dvp != NULL) {
*(ap->a_vpp) = dvp;
}
- else if (error) {
+ else {
*(ap->a_vpp) = NULL;
}
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/cd9660/cd9660_vfsops.c#2 (text+ko) ====
@@ -84,6 +84,7 @@
.vfs_statfs = cd9660_statfs,
.vfs_unmount = cd9660_unmount,
.vfs_vget = cd9660_vget,
+ .vfs_fhhint = vfs_stdfhhint,
};
VFS_SET(cd9660_vfsops, cd9660, VFCF_READONLY);
MODULE_VERSION(cd9660, 1);
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/ext2fs/ext2_vfsops.c#2 (text+ko) ====
@@ -86,6 +86,7 @@
.vfs_sync = ext2_sync,
.vfs_unmount = ext2_unmount,
.vfs_vget = ext2_vget,
+ .vfs_fhhint = vfs_stdfhhint,
};
VFS_SET(ext2fs_vfsops, ext2fs, 0);
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/hpfs/hpfs_vfsops.c#2 (text+ko) ====
@@ -538,5 +538,6 @@
.vfs_statfs = hpfs_statfs,
.vfs_unmount = hpfs_unmount,
.vfs_vget = hpfs_vget,
+ .vfs_fhhint = vfs_stdfhhint,
};
VFS_SET(hpfs_vfsops, hpfs, 0);
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/msdosfs/msdosfs_vfsops.c#2 (text+ko) ====
@@ -986,6 +986,7 @@
.vfs_statfs = msdosfs_statfs,
.vfs_sync = msdosfs_sync,
.vfs_unmount = msdosfs_unmount,
+ .vfs_fhhint = vfs_stdfhhint,
};
VFS_SET(msdosfs_vfsops, msdosfs, 0);
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/ntfs/ntfs_vfsops.c#2 (text+ko) ====
@@ -787,6 +787,7 @@
.vfs_uninit = ntfs_uninit,
.vfs_unmount = ntfs_unmount,
.vfs_vget = ntfs_vget,
+ .vfs_fhhint = vfs_stdfhhint,
};
VFS_SET(ntfs_vfsops, ntfs, 0);
MODULE_VERSION(ntfs, 1);
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/nullfs/null_vfsops.c#2 (text+ko) ====
@@ -359,6 +359,7 @@
.vfs_uninit = nullfs_uninit,
.vfs_unmount = nullfs_unmount,
.vfs_vget = nullfs_vget,
+ .vfs_fhhint = vfs_stdfhhint,
};
VFS_SET(null_vfsops, nullfs, VFCF_LOOPBACK);
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/tmpfs/tmpfs_vfsops.c#2 (text+ko) ====
@@ -414,5 +414,6 @@
.vfs_root = tmpfs_root,
.vfs_statfs = tmpfs_statfs,
.vfs_fhtovp = tmpfs_fhtovp,
+ .vfs_fhhint = vfs_stdfhhint,
};
VFS_SET(tmpfs_vfsops, tmpfs, 0);
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/udf/udf_vfsops.c#2 (text+ko) ====
@@ -129,6 +129,7 @@
.vfs_uninit = udf_uninit,
.vfs_unmount = udf_unmount,
.vfs_vget = udf_vget,
+ .vfs_fhhint = vfs_stdfhhint,
};
VFS_SET(udf_vfsops, udf, VFCF_READONLY);
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/unionfs/union_vfsops.c#2 (text+ko) ====
@@ -519,6 +519,7 @@
.vfs_uninit = unionfs_uninit,
.vfs_unmount = unionfs_unmount,
.vfs_vget = unionfs_vget,
+ .vfs_fhhint = vfs_stdfhhint,
};
VFS_SET(unionfs_vfsops, unionfs, VFCF_LOOPBACK);
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/gnu/fs/reiserfs/reiserfs_vfsops.c#2 (text+ko) ====
@@ -1114,6 +1114,7 @@
//.vfs_checkexp = reiserfs_checkexp,
//.vfs_extattrctl = reiserfs_extattrctl,
.vfs_fhtovp = reiserfs_fhtovp,
+ .vfs_fhhint = vfs_stdfhhint,
//.vfs_quotactl = reiserfs_quotactl,
.vfs_root = reiserfs_root,
//.vfs_start = reiserfs_start,
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/gnu/fs/xfs/FreeBSD/xfs_mountops.c#2 (text+ko) ====
@@ -419,6 +419,7 @@
.vfs_init = _xfs_init,
.vfs_uninit = _xfs_uninit,
.vfs_extattrctl = _xfs_extattrctl,
+ .vfs_fhhint = vfs_stdfhhint,
};
VFS_SET(xfs_fsops, xfs, 0);
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/kern/vfs_cache.c#2 (text+ko) ====
@@ -1226,3 +1226,151 @@
buf[l] = '\0';
return (0);
}
+
+/*
+ * vn_fullpath_nocache
+ *
+ * Retrieve the full filesystem path that corresponds to a vnode without use of the
+ * name cache.
+ * - A directory hint (UFS file_id of the directory that contains the vnode) may be
+ * supplied to facilitate the search if our target is not a directory itself.
+ * - 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
+ */
+int
+vn_fullpath_nocache(struct vnode *vp, char **fullpath, char **freepath, uint64_t directory_hint, char flags)
+{
+ struct vnode *dvp, *upper_dvp;
+ struct mount *mp;
+ struct thread * td;
+ char *buf, *pch;
+ char fname[MNAMELEN];
+ int error, buflen, vfslocked, fnamelen;
+
+ KASSERT(vp != NULL, ("vn_fullpath_nocache: null vp"));
+
+ dvp = NULL;
+ buf = NULL;
+ *freepath = NULL;
+
+ if (vp->v_type == VBAD) {
+ error = ENOENT;
+ goto out;
+ }
+
+ vref(vp);
+ error = 0;
+ td = curthread;
+ mp = vp->v_mount;
+ fnamelen = sizeof(fname);
+ buf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ buflen = MAXPATHLEN - 1;
+ buf[MAXPATHLEN-1] = '\0';
+
+ /*
+ * - If our target is a directory, move on to the part where we traverse the '..' entries.
+ * - If not, try to find its' parent through VOP_GETPARENT
+ */
+ if (vp->v_type != VDIR) {
+ /* 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;
+ }
+
+ /* we have found a parent directory and a name for our vnode, save the name */
+ pch = buf + buflen - strlen(fname);
+ if (pch < buf) {
+ error = EOVERFLOW;
+ if (dvp != NULL)
+ vput(dvp);
+ goto out;
+ }
+ strcpy(pch, fname);
+ buflen -= strlen(fname);
+ buf[--buflen] = '/';
+ }
+ /* if our target is a dir, do the initial preparation */
+ else {
+ dvp = vp;
+ vref(dvp);
+ vn_lock(dvp, LK_SHARED);
+ }
+
+ /*
+ * We have found 'a' directory that contains our target or our target is a directory.
+ * In any case, just traverse the '..' nodes and construct a path via VOP_VPTOCNP(9)
+ */
+ while (dvp != rootvnode) {
+ /*
+ * If we've found a vnode that is the root of a filesystem
+ * Use the path that the filesystem was mounted on to complete our fullpath
+ *
+ * XXXgpf: how safe is it to use the path from the statistics of a mounted fs?
+ * the size of the f_mntonname field seems kinda small :-S
+ */
+ if ((dvp->v_vflag & VV_ROOT) != 0) {
+ char *pch, *fs_path;
+ int fs_path_len;
+
+ vfslocked = VFS_LOCK_GIANT(dvp->v_mount);
+
+ *fullpath = buf + buflen;
+
+ fs_path = dvp->v_mount->mnt_stat.f_mntonname;
+ fs_path_len = strlen(fs_path);
+
+ if (buflen - fs_path_len - 1 < 0) {
+ vput(dvp);
+ error = EOVERFLOW;
+ VFS_UNLOCK_GIANT(vfslocked);
+ goto out;
+ }
+
+ pch = buf + buflen - fs_path_len;
+ memcpy(pch, fs_path, fs_path_len);
+ buflen -= fs_path_len;
+
+ VFS_UNLOCK_GIANT(vfslocked);
+
+ break;
+ }
+
+ error = VOP_VPTOCNP(dvp, &upper_dvp, td->td_ucred, buf, &buflen);
+ if (error) {
+ uprintf("VOP_VPTOCNP failure %d\n", error);
+ break;
+ }
+
+ buf[--buflen] = '/';
+ if (dvp != NULL)
+ vput(dvp);
+
+ vdrop(upper_dvp);
+ dvp = upper_dvp;
+ vn_lock(dvp, LK_SHARED);
+ vref(dvp);
+ } /* while */
+
+ vput(dvp);
+ *fullpath = buf + buflen;
+ *freepath = buf;
+
+out:
+ if (error != 0) {
+ *freepath = NULL;
+ if (buf != NULL)
+ free(buf, M_TEMP);
+ }
+ vrele(vp);
+
+ return error;
+}
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/kern/vfs_default.c#3 (text+ko) ====
@@ -955,6 +955,12 @@
}
int
+vfs_stdfhhint (struct mount *mp, struct fid *fhp, uint64_t *hint)
+{
+ return (EOPNOTSUPP);
+}
+
+int
vfs_stdinit (vfsp)
struct vfsconf *vfsp;
{
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/nfsserver/nfs_serv.c#9 (text+ko) ====
@@ -101,6 +101,14 @@
#include <nfs/xdr_subs.h>
#include <nfsserver/nfsm_subs.h>
+/*
+ * XXXgpf: should relocate them someplace else
+ * I just dont know where:S
+ */
+#define PARENTHINT 0x0001
+#define EXHAUSTSEARCH 0x0002
+#define WANTNAME 0x0004
+
#ifdef NFSRV_DEBUG
#define nfsdbprintf(info) printf info
#else
@@ -1390,6 +1398,22 @@
AUDIT_ARG_UPATH1(td, fullpath);
free(freepath, M_TEMP);
}
+ /* if our cache fails us */
+ else if (fhp != NULL) {
+ uint64_t parent_hint;
+ printf("going for hint\n");
+ /* get the hint stored inside the file handle */
+ VFS_FHHINT(mntp, &(fhp->fh_fid), &parent_hint);
+ printf("got hint, going to cache\n");
+ vn_fullpath_nocache(new_vp, &fullpath, &freepath,
+ parent_hint, PARENTHINT | WANTNAME);
+ printf("got cache %p\n", freepath);
+ if (freepath != NULL) {
+ AUDIT_ARG_UPATH1(td, fullpath);
+ free(freepath, M_TEMP);
+ }
+ printf("all done!\n");
+ }
}
}
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/sys/mount.h#2 (text+ko) ====
@@ -567,6 +567,7 @@
typedef int vfs_vget_t(struct mount *mp, ino_t ino, int flags,
struct vnode **vpp);
typedef int vfs_fhtovp_t(struct mount *mp, struct fid *fhp, struct vnode **vpp);
+typedef int vfs_fhhint_t(struct mount *mp, struct fid *fhp, uint64_t *hint);
typedef int vfs_checkexp_t(struct mount *mp, struct sockaddr *nam,
int *extflagsp, struct ucred **credanonp,
int *numsecflavors, int **secflavors);
@@ -590,6 +591,7 @@
vfs_sync_t *vfs_sync;
vfs_vget_t *vfs_vget;
vfs_fhtovp_t *vfs_fhtovp;
+ vfs_fhhint_t *vfs_fhhint;
vfs_checkexp_t *vfs_checkexp;
vfs_init_t *vfs_init;
vfs_uninit_t *vfs_uninit;
@@ -612,6 +614,8 @@
(*(MP)->mnt_op->vfs_vget)(MP, INO, FLAGS, VPP)
#define VFS_FHTOVP(MP, FIDP, VPP) \
(*(MP)->mnt_op->vfs_fhtovp)(MP, FIDP, VPP)
+#define VFS_FHHINT(MP, FIDP, HINT) \
+ (*(MP)->mnt_op->vfs_fhhint)(MP, FIDP, HINT)
#define VFS_CHECKEXP(MP, NAM, EXFLG, CRED, NUMSEC, SEC) \
(*(MP)->mnt_op->vfs_checkexp)(MP, NAM, EXFLG, CRED, NUMSEC, SEC)
#define VFS_EXTATTRCTL(MP, C, FN, NS, N) \
@@ -763,6 +767,7 @@
vfs_sync_t vfs_stdnosync;
vfs_vget_t vfs_stdvget;
vfs_fhtovp_t vfs_stdfhtovp;
+vfs_fhhint_t vfs_stdfhhint;
vfs_checkexp_t vfs_stdcheckexp;
vfs_init_t vfs_stdinit;
vfs_uninit_t vfs_stduninit;
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/sys/vnode.h#3 (text+ko) ====
@@ -609,6 +609,8 @@
char **retbuf, char **freebuf);
int vn_fullpath_global(struct thread *td, struct vnode *vn,
char **retbuf, char **freebuf);
+int vn_fullpath_nocache(struct vnode *vp, char **fullpath,
+ char **freepath, uint64_t directory_hint, char flags);
int vn_commname(struct vnode *vn, char *buf, u_int buflen);
int vaccess(enum vtype type, mode_t file_mode, uid_t file_uid,
gid_t file_gid, accmode_t accmode, struct ucred *cred,
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/ufs/ffs/ffs_vfsops.c#2 (text+ko) ====
@@ -88,11 +88,13 @@
static vfs_mount_t ffs_mount;
static vfs_statfs_t ffs_statfs;
static vfs_fhtovp_t ffs_fhtovp;
+static vfs_fhhint_t ffs_fhhint;
static vfs_sync_t ffs_sync;
static struct vfsops ufs_vfsops = {
.vfs_extattrctl = ffs_extattrctl,
.vfs_fhtovp = ffs_fhtovp,
+ .vfs_fhhint = ffs_fhhint,
.vfs_init = ffs_init,
.vfs_mount = ffs_mount,
.vfs_cmount = ffs_cmount,
@@ -1631,6 +1633,19 @@
}
/*
+ * Get Parent Directory Hint from the File Handle
+ */
+static int
+ffs_fhhint(struct mount *mp, struct fid *fhp, uint64_t *hint)
+{
+ struct ufid *ufhp;
+
+ ufhp = (struct ufid *)fhp;
+ *hint = ufhp->ufid_dino;
+ return (0);
+}
+
+/*
* Initialize the filesystem.
*/
static int
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/ufs/ffs/ffs_vnops.c#4 (text+ko) ====
@@ -1933,13 +1933,16 @@
{
struct mount *mp;
struct vnode *vp, *dvp;
- int error, flags;
+ int error, flags;
error = 0;
vp = ap->a_vp;
mp = vp->v_mount;
flags = ap->a_flags;
+ KASSERT(vp != NULL, ("VOP_GEPARENT: null vp"));
+ if (flags & WANTNAME)
+ KASSERT(ap->a_buf != NULL, ("VOP_GEPARENT: null buffer"));
/* XXXgpf:is this check necessary? */
if (vp->v_type == VBAD) {
error = ENOENT;
@@ -2011,7 +2014,7 @@
if (error == 0 && dvp != NULL) {
*(ap->a_vpp) = dvp;
}
- else if (error) {
+ else {
*(ap->a_vpp) = NULL;
}
More information about the p4-projects
mailing list