From owner-p4-projects@FreeBSD.ORG Thu May 27 14:41:58 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id C515A1065674; Thu, 27 May 2010 14:41:57 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 894321065672 for ; Thu, 27 May 2010 14:41:57 +0000 (UTC) (envelope-from gpf@FreeBSD.org) Received: from repoman.freebsd.org (unknown [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 75C588FC1C for ; Thu, 27 May 2010 14:41:57 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id o4REfuO5058843 for ; Thu, 27 May 2010 14:41:56 GMT (envelope-from gpf@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id o4REfur1058841 for perforce@freebsd.org; Thu, 27 May 2010 14:41:56 GMT (envelope-from gpf@FreeBSD.org) Date: Thu, 27 May 2010 14:41:56 GMT Message-Id: <201005271441.o4REfur1058841@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to gpf@FreeBSD.org using -f From: Efstratios Karatzas To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 178885 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 27 May 2010 14:41:58 -0000 http://p4web.freebsd.org/@@178885?ac=10 Change 178885 by gpf@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 #include +/* + * 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; }