diff options
Diffstat (limited to 'sys/fs/coda/coda_vnops.c')
-rw-r--r-- | sys/fs/coda/coda_vnops.c | 198 |
1 files changed, 73 insertions, 125 deletions
diff --git a/sys/fs/coda/coda_vnops.c b/sys/fs/coda/coda_vnops.c index de765f8..b572412 100644 --- a/sys/fs/coda/coda_vnops.c +++ b/sys/fs/coda/coda_vnops.c @@ -70,7 +70,6 @@ __FBSDID("$FreeBSD$"); #include <fs/coda/coda_venus.h> #include <fs/coda/coda_opstats.h> #include <fs/coda/coda_subr.h> -#include <fs/coda/coda_namecache.h> #include <fs/coda/coda_pioctl.h> /* @@ -78,7 +77,9 @@ __FBSDID("$FreeBSD$"); */ static int coda_attr_cache = 1; /* Set to cache attributes. */ static int coda_symlink_cache = 1; /* Set to cache symbolic links. */ +#if 0 static int coda_access_cache = 1; /* Set to cache some access checks. */ +#endif /* * Structure to keep track of vfs calls. @@ -112,7 +113,8 @@ static int coda_lockdebug = 0; */ struct vop_vector coda_vnodeops = { .vop_default = &default_vnodeops, - .vop_lookup = coda_lookup, /* lookup */ + .vop_cachedlookup = coda_lookup, /* uncached lookup */ + .vop_lookup = vfs_cache_lookup, /* namecache lookup */ .vop_create = coda_create, /* create */ .vop_open = coda_open, /* open */ .vop_close = coda_close, /* close */ @@ -613,7 +615,6 @@ coda_access(struct vop_access_args *ap) struct ucred *cred = ap->a_cred; struct thread *td = ap->a_td; /* locals */ - int error; MARK_ENTRY(CODA_ACCESS_STATS); @@ -631,20 +632,16 @@ coda_access(struct vop_access_args *ap) } /* - * if the file is a directory, and we are checking exec (eg lookup) - * access, and the file is in the namecache, then the user must have - * lookup access to it. + * XXXRW: We should add an actual access cache here, similar to the + * one found in NFS, the Linux Coda module, etc. + * + * In principle it could be as simple as caching the uid and granted + * access mode (as in NFS), but we also need invalidation. The Coda + * module on Linux does this using a global generation number which + * is bumped on an access control cache flush, whereas NFS does it + * with a timeout. */ - if (coda_access_cache) { - if ((vp->v_type == VDIR) && (mode & VEXEC)) { - if (coda_nc_lookup(cp, ".", 1, cred)) { - MARK_INT_SAT(CODA_ACCESS_STATS); - return (0); - } - } - } - error = venus_access(vtomi(vp), &cp->c_fid, mode, cred, td->td_proc); - return (error); + return (venus_access(vtomi(vp), &cp->c_fid, mode, cred, td->td_proc)); } int @@ -841,7 +838,7 @@ coda_inactive(struct vop_inactive_args *ap) * In FreeBSD, lookup returns the vnode locked. */ int -coda_lookup(struct vop_lookup_args *ap) +coda_lookup(struct vop_cachedlookup_args *ap) { /* true args */ struct vnode *dvp = ap->a_dvp; @@ -886,46 +883,28 @@ coda_lookup(struct vop_lookup_args *ap) goto exit; } - /* - * First try to look the file up in the cfs name cache. - * - * XXX: lock the parent vnode? - */ - cp = coda_nc_lookup(dcp, nm, len, cred); - if (cp) { - *vpp = CTOV(cp); - vref(*vpp); - CODADEBUG(CODA_LOOKUP, myprintf(("lookup result %d vpp %p\n", - error,*vpp));); + error = venus_lookup(vtomi(dvp), &dcp->c_fid, nm, len, cred, + td->td_proc, &VFid, &vtype); + if (error) { + MARK_INT_FAIL(CODA_LOOKUP_STATS); + CODADEBUG(CODA_LOOKUP, myprintf(("lookup error on %s " + "(%s)%d\n", coda_f2s(&dcp->c_fid), nm, error));); + *vpp = NULL; } else { - /* - * The name wasn't cached, so we need to contact Venus. + MARK_INT_SAT(CODA_LOOKUP_STATS); + CODADEBUG(CODA_LOOKUP, myprintf(("lookup: %s type %o " + "result %d\n", coda_f2s(&VFid), vtype, error));); + cp = make_coda_node(&VFid, dvp->v_mount, vtype); + *vpp = CTOV(cp); + + /* + * Enter the new vnode in the namecache only if the top bit + * isn't set. + * + * And don't enter a new vnode for an invalid one! */ - error = venus_lookup(vtomi(dvp), &dcp->c_fid, nm, len, cred, - td->td_proc, &VFid, &vtype); - if (error) { - MARK_INT_FAIL(CODA_LOOKUP_STATS); - CODADEBUG(CODA_LOOKUP, myprintf(("lookup error on " - "%s (%s)%d\n", coda_f2s(&dcp->c_fid), nm, - error));); - *vpp = NULL; - } else { - MARK_INT_SAT(CODA_LOOKUP_STATS); - CODADEBUG(CODA_LOOKUP, myprintf(("lookup: %s type %o " - "result %d\n", coda_f2s(&VFid), vtype, error));); - cp = make_coda_node(&VFid, dvp->v_mount, vtype); - *vpp = CTOV(cp); - - /* - * Enter the new vnode in the Name Cache only if the - * top bit isn't set. - * - * And don't enter a new vnode for an invalid one! - */ - if (!(vtype & CODA_NOCACHE)) - coda_nc_enter(VTOC(dvp), nm, len, cred, - VTOC(*vpp)); - } + if (!(vtype & CODA_NOCACHE) && (cnp->cn_flags & MAKEENTRY)) + cache_enter(dvp, *vpp, cnp); } exit: /* @@ -1064,11 +1043,7 @@ coda_create(struct vop_create_args *ap) * has changed. */ VTOC(dvp)->c_flags &= ~C_VATTR; - - /* - * Enter the new vnode in the Name Cache. - */ - coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp)); + cache_enter(dvp, *vpp, cnp); CODADEBUG(CODA_CREATE, myprintf(("create: %s, result %d\n", coda_f2s(&VFid), error));); } else { @@ -1077,12 +1052,23 @@ coda_create(struct vop_create_args *ap) error));); } if (!error) { + if (cnp->cn_flags & MAKEENTRY) + cache_enter(dvp, *vpp, cnp); if (cnp->cn_flags & LOCKLEAF) vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY); #ifdef OLD_DIAGNOSTIC else printf("coda_create: LOCKLEAF not set!\n"); #endif + } else if (error == ENOENT) { + /* + * XXXRW: We only enter a negative entry if ENOENT is + * returned, not other errors. But will Venus invalidate dvp + * properly in all cases when new files appear via the + * network rather than a local operation? + */ + if (cnp->cn_flags & MAKEENTRY) + cache_enter(dvp, NULL, cnp); } return (error); } @@ -1091,6 +1077,7 @@ int coda_remove(struct vop_remove_args *ap) { /* true args */ + struct vnode *vp = ap->a_vp; struct vnode *dvp = ap->a_dvp; struct cnode *cp = VTOC(dvp); struct componentname *cnp = ap->a_cnp; @@ -1100,48 +1087,33 @@ coda_remove(struct vop_remove_args *ap) int error; const char *nm = cnp->cn_nameptr; int len = cnp->cn_namelen; +#if 0 struct cnode *tp; +#endif MARK_ENTRY(CODA_REMOVE_STATS); CODADEBUG(CODA_REMOVE, myprintf(("remove: %s in %s\n", nm, coda_f2s(&cp->c_fid)));); /* - * Remove the file's entry from the CODA Name Cache. - * - * We're being conservative here, it might be that this person - * doesn't really have sufficient access to delete the file but we - * feel zapping the entry won't really hurt anyone -- dcs. - * - * I'm gonna go out on a limb here. If a file and a hardlink to it - * exist, and one is removed, the link count on the other will be off - * by 1. We could either invalidate the attrs if cached, orfix them. - * I'll try to fix them. DCS 11/8/94 + * Check for remove of control object. */ - tp = coda_nc_lookup(VTOC(dvp), nm, len, cred); - if (tp!= NULL) { - if (VALID_VATTR(tp)) { - if (tp->c_vattr.va_nlink > 1) - tp->c_vattr.va_nlink--; - } - coda_nc_zapfile(VTOC(dvp), nm, len); + if (IS_CTL_NAME(dvp, nm, len)) { + MARK_INT_FAIL(CODA_REMOVE_STATS); + return (ENOENT); } /* * Invalidate the parent's attr cache, the modification time has - * changed. + * changed. We don't yet know if the last reference to the file is + * being removed, but we do know the reference count on the child has + * changed, so invalidate its attr cache also. */ VTOC(dvp)->c_flags &= ~C_VATTR; - - /* - * Check for remove of control object. - */ - if (IS_CTL_NAME(dvp, nm, len)) { - MARK_INT_FAIL(CODA_REMOVE_STATS); - return (ENOENT); - } + VTOC(vp)->c_flags &= ~C_VATTR; error = venus_remove(vtomi(dvp), &cp->c_fid, nm, len, cred, td->td_proc); + cache_purge(vp); CODADEBUG(CODA_REMOVE, myprintf(("in remove result %d\n",error));); return (error); } @@ -1234,25 +1206,12 @@ coda_rename(struct vop_rename_args *ap) } /* - * Problem with moving directories -- need to flush entry for .. + * Remove the entries for both source and target directories, which + * should catch references to the children. Perhaps we could purge + * less? */ - if (odvp != ndvp) { - struct cnode *ovcp = coda_nc_lookup(VTOC(odvp), fnm, flen, - cred); - - if (ovcp) { - struct vnode *ovp = CTOV(ovcp); - - if ((ovp) && (ovp->v_type == VDIR)) - coda_nc_zapfile(VTOC(ovp),"..", 2); - } - } - - /* - * Remove the entries for both source and target files. - */ - coda_nc_zapfile(VTOC(odvp), fnm, flen); - coda_nc_zapfile(VTOC(ndvp), tnm, tlen); + cache_purge(odvp); + cache_purge(ndvp); /* * Invalidate the parent's attr cache, the modification time has @@ -1341,17 +1300,13 @@ coda_mkdir(struct vop_mkdir_args *ap) /* * Enter the new vnode in the Name Cache. */ - coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp)); + if (cnp->cn_flags & MAKEENTRY) + cache_enter(dvp, *vpp, cnp); /* - * As a side effect, enter "." and ".." for the directory. + * Update the attr cache and mark as valid. */ - coda_nc_enter(VTOC(*vpp), ".", 1, cred, VTOC(*vpp)); - coda_nc_enter(VTOC(*vpp), "..", 2, cred, VTOC(dvp)); if (coda_attr_cache) { - /* - * Update the attr cache and mark as valid. - */ VTOC(*vpp)->c_vattr = ova; VTOC(*vpp)->c_flags |= C_VATTR; } @@ -1375,6 +1330,7 @@ int coda_rmdir(struct vop_rmdir_args *ap) { /* true args */ + struct vnode *vp = ap->a_vp; struct vnode *dvp = ap->a_dvp; struct cnode *dcp = VTOC(dvp); struct componentname *cnp = ap->a_cnp; @@ -1384,7 +1340,9 @@ coda_rmdir(struct vop_rmdir_args *ap) int error; const char *nm = cnp->cn_nameptr; int len = cnp->cn_namelen; +#if 0 struct cnode *cp; +#endif MARK_ENTRY(CODA_RMDIR_STATS); @@ -1397,21 +1355,11 @@ coda_rmdir(struct vop_rmdir_args *ap) } /* - * We're being conservative here, it might be that this person - * doesn't really have sufficient access to delete the file but we - * feel zapping the entry won't really hurt anyone -- dcs - * - * As a side effect of the rmdir, remove any entries for children of - * the directory, especially "." and "..". - */ - cp = coda_nc_lookup(dcp, nm, len, cred); - if (cp) - coda_nc_zapParentfid(&(cp->c_fid), NOT_DOWNCALL); - - /* - * Remove the file's entry from the CODA Name Cache. + * Possibly somewhat conservative purging, perhaps we just need to + * purge vp? */ - coda_nc_zapfile(dcp, nm, len); + cache_purge(dvp); + cache_purge(vp); /* * Invalidate the parent's attr cache, the modification time has |