diff --git a/sys/fs/coda/cnode.h b/sys/fs/coda/cnode.h index c1c544166a5b..33524962375c 100644 --- a/sys/fs/coda/cnode.h +++ b/sys/fs/coda/cnode.h @@ -190,7 +190,8 @@ int coda_call(struct coda_mntinfo *mntinfo, int inSize, int *outSize, extern int coda_kernel_version; /* cfs_subr.h */ -int handleDownCall(int opcode, union outputArgs *out); +int handleDownCall(struct coda_mntinfo *mnt, int opcode, + union outputArgs *out); void coda_unmounting(struct mount *whoIam); int coda_vmflush(struct cnode *cp); diff --git a/sys/fs/coda/coda_psdev.c b/sys/fs/coda/coda_psdev.c index 0cf856a54ff9..27ef7396dc98 100644 --- a/sys/fs/coda/coda_psdev.c +++ b/sys/fs/coda/coda_psdev.c @@ -69,7 +69,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -118,8 +117,6 @@ vc_open(struct cdev *dev, int flag, int mode, struct thread *td) struct coda_mntinfo *mnt; ENTRY; - if (!coda_nc_initialized) - coda_nc_init(); mnt = dev2coda_mntinfo(dev); KASSERT(mnt, ("Coda: tried to open uninitialized cfs device")); vcp = &mnt->mi_vcomm; @@ -306,7 +303,7 @@ vc_write(struct cdev *dev, struct uio *uiop, int flag) "seq %ld)\n", error, opcode, seq)); return (EINVAL); } - return (handleDownCall(opcode, &pbuf)); + return (handleDownCall(dev2coda_mntinfo(dev), opcode, &pbuf)); } /* @@ -409,26 +406,14 @@ vc_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, ENTRY; switch(cmd) { - case CODARESIZE: { - struct coda_resize *data = (struct coda_resize *)addr; - - return (coda_nc_resize(data->hashsize, data->heapsize, - IS_DOWNCALL)); - } + case CODARESIZE: + return (ENODEV); case CODASTATS: - if (coda_nc_use) { - coda_nc_gather_stats(); - return (0); - } else - return (ENODEV); + return (ENODEV); case CODAPRINT: - if (coda_nc_use) { - print_coda_nc(); - return (0); - } else - return (ENODEV); + return (ENODEV); case CIOC_KERNEL_VERSION: switch (*(u_int *)addr) { diff --git a/sys/fs/coda/coda_subr.c b/sys/fs/coda/coda_subr.c index 9183bf0a329f..ed081c22096d 100644 --- a/sys/fs/coda/coda_subr.c +++ b/sys/fs/coda/coda_subr.c @@ -66,7 +66,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include static int coda_active = 0; static int coda_reuse = 0; @@ -187,6 +186,10 @@ coda_find(CodaFid *fid) * operations on these cnodes should fail (excepting coda_inactive of * course!). Since multiple venii/wardens can be running, only kill the * cnodes for a particular entry in the coda_mnttbl. -- DCS 12/1/94 + * + * XXX: I don't believe any special behavior is required with respect to the + * global namecache here, as /coda will have unmounted and hence cache_flush + * will have run...? */ int coda_kill(struct mount *whoIam, enum dc_status dcstat) @@ -204,8 +207,11 @@ coda_kill(struct mount *whoIam, enum dc_status dcstat) * This is slightly overkill, but should work. Eventually it'd be * nice to only flush those entries from the namecache that reference * a vnode in this vfs. + * + * XXXRW: Perhaps we no longer need to purge the name cache when + * using the VFS name cache, as unmount will do that. */ - coda_nc_flush(dcstat); + cache_purgevfs(whoIam); for (hash = 0; hash < CODA_CACHESIZE; hash++) { for (cp = coda_cache[hash];cp != NULL; cp = CNODE_NEXT(cp)) { @@ -230,7 +236,7 @@ coda_kill(struct mount *whoIam, enum dc_status dcstat) * cache or it may be executing. */ void -coda_flush(enum dc_status dcstat) +coda_flush(struct coda_mntinfo *mnt, enum dc_status dcstat) { int hash; struct cnode *cp; @@ -238,10 +244,7 @@ coda_flush(enum dc_status dcstat) coda_clstat.ncalls++; coda_clstat.reqs[CODA_FLUSH]++; - /* - * Flush files from the name cache. - */ - coda_nc_flush(dcstat); + cache_purgevfs(mnt->mi_vfsp); for (hash = 0; hash < CODA_CACHESIZE; hash++) { for (cp = coda_cache[hash]; cp != NULL; cp = CNODE_NEXT(cp)) { @@ -338,7 +341,10 @@ coda_cacheprint(struct mount *whoIam) printf("coda_cacheprint: coda_ctlvp %p, cp %p", coda_ctlvp, VTOC(coda_ctlvp)); + +#if 0 coda_nc_name(VTOC(coda_ctlvp)); +#endif printf("\n"); for (hash = 0; hash < CODA_CACHESIZE; hash++) { for (cp = coda_cache[hash]; cp != NULL; @@ -346,7 +352,9 @@ coda_cacheprint(struct mount *whoIam) if (CTOV(cp)->v_mount == whoIam) { printf("coda_cacheprint: vp %p, cp %p", CTOV(cp), cp); +#if 0 coda_nc_name(cp); +#endif printf("\n"); count++; } @@ -385,7 +393,8 @@ coda_cacheprint(struct mount *whoIam) * CODA_REPLACE -- Replace one CodaFid with another throughout the name * cache. */ -int handleDownCall(int opcode, union outputArgs *out) +int +handleDownCall(struct coda_mntinfo *mnt, int opcode, union outputArgs *out) { int error; @@ -394,7 +403,7 @@ int handleDownCall(int opcode, union outputArgs *out) */ switch (opcode) { case CODA_FLUSH: { - coda_flush(IS_DOWNCALL); + coda_flush(mnt, IS_DOWNCALL); /* Print any remaining cnodes. */ CODADEBUG(CODA_FLUSH, coda_testflush();); @@ -406,12 +415,20 @@ int handleDownCall(int opcode, union outputArgs *out) coda_clstat.reqs[CODA_PURGEUSER]++; /* XXX - need to prevent fsync's. */ +#if 0 #ifdef CODA_COMPAT_5 coda_nc_purge_user(out->coda_purgeuser.cred.cr_uid, IS_DOWNCALL); #else coda_nc_purge_user(out->coda_purgeuser.uid, IS_DOWNCALL); #endif +#endif + /* + * For now, we flush the entire namecache, but this is + * undesirable. Once we have an access control cache, we + * should just flush that instead. + */ + cache_purgevfs(mnt->mi_vfsp); return (0); } @@ -424,6 +441,7 @@ int handleDownCall(int opcode, union outputArgs *out) cp = coda_find(&out->coda_zapfile.Fid); if (cp != NULL) { vref(CTOV(cp)); + cache_purge(CTOV(cp)); cp->c_flags &= ~C_VATTR; ASSERT_VOP_LOCKED(CTOV(cp), "coda HandleDownCall"); if (CTOV(cp)->v_vflag & VV_TEXT) @@ -447,9 +465,8 @@ int handleDownCall(int opcode, union outputArgs *out) cp = coda_find(&out->coda_zapdir.Fid); if (cp != NULL) { vref(CTOV(cp)); + cache_purge(CTOV(cp)); cp->c_flags &= ~C_VATTR; - coda_nc_zapParentfid(&out->coda_zapdir.Fid, - IS_DOWNCALL); CODADEBUG(CODA_ZAPDIR, myprintf(("zapdir: fid = %s, " "refcnt = %d\n", coda_f2s(&cp->c_fid), CTOV(cp)->v_usecount - 1));); @@ -469,11 +486,8 @@ int handleDownCall(int opcode, union outputArgs *out) cp = coda_find(&out->coda_purgefid.Fid); if (cp != NULL) { vref(CTOV(cp)); - if (IS_DIR(out->coda_purgefid.Fid)) - coda_nc_zapParentfid(&out->coda_purgefid.Fid, - IS_DOWNCALL); + cache_purge(CTOV(cp)); cp->c_flags &= ~C_VATTR; - coda_nc_zapfid(&out->coda_purgefid.Fid, IS_DOWNCALL); ASSERT_VOP_LOCKED(CTOV(cp), "coda HandleDownCall"); if (!(IS_DIR(out->coda_purgefid.Fid)) && (CTOV(cp)->v_vflag & VV_TEXT)) @@ -501,6 +515,7 @@ int handleDownCall(int opcode, union outputArgs *out) * fid, and reinsert. */ vref(CTOV(cp)); + cache_purge(CTOV(cp)); coda_unsave(cp); cp->c_fid = out->coda_replace.NewFid; coda_save(cp); @@ -533,7 +548,6 @@ coda_debugon(void) { codadebug = -1; - coda_nc_debug = -1; coda_vnop_print_entry = 1; coda_psdev_print_entry = 1; coda_vfsop_print_entry = 1; @@ -544,7 +558,6 @@ coda_debugoff(void) { codadebug = 0; - coda_nc_debug = 0; coda_vnop_print_entry = 0; coda_psdev_print_entry = 0; coda_vfsop_print_entry = 0; diff --git a/sys/fs/coda/coda_subr.h b/sys/fs/coda/coda_subr.h index 2b307cb65fbd..0efc08169eb8 100644 --- a/sys/fs/coda/coda_subr.h +++ b/sys/fs/coda/coda_subr.h @@ -36,7 +36,7 @@ struct cnode *coda_alloc(void); void coda_free(struct cnode *cp); struct cnode *coda_find(CodaFid *fid); -void coda_flush(enum dc_status dcstat); +void coda_flush(struct coda_mntinfo *mnt, enum dc_status dcstat); void coda_testflush(void); void coda_checkunmounting(struct mount *mp); void coda_cacheprint(struct mount *whoIam); diff --git a/sys/fs/coda/coda_vnops.c b/sys/fs/coda/coda_vnops.c index de765f899ec1..b5724126b385 100644 --- a/sys/fs/coda/coda_vnops.c +++ b/sys/fs/coda/coda_vnops.c @@ -70,7 +70,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include /* @@ -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. - */ - 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); + 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)); - } + /* + * 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! + */ + 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,39 +1087,14 @@ 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 - */ - 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); - } - - /* - * Invalidate the parent's attr cache, the modification time has - * changed. - */ - VTOC(dvp)->c_flags &= ~C_VATTR; - /* * Check for remove of control object. */ @@ -1140,8 +1102,18 @@ coda_remove(struct vop_remove_args *ap) MARK_INT_FAIL(CODA_REMOVE_STATS); return (ENOENT); } + + /* + * Invalidate the parent's attr cache, the modification time has + * 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; + 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 "..". + * Possibly somewhat conservative purging, perhaps we just need to + * purge vp? */ - 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. - */ - coda_nc_zapfile(dcp, nm, len); + cache_purge(dvp); + cache_purge(vp); /* * Invalidate the parent's attr cache, the modification time has diff --git a/sys/fs/coda/coda_vnops.h b/sys/fs/coda/coda_vnops.h index 386dd07d1e1a..e43b09fb9b97 100644 --- a/sys/fs/coda/coda_vnops.h +++ b/sys/fs/coda/coda_vnops.h @@ -61,7 +61,7 @@ vop_access_t coda_access; vop_readlink_t coda_readlink; vop_fsync_t coda_fsync; vop_inactive_t coda_inactive; -vop_lookup_t coda_lookup; +vop_cachedlookup_t coda_lookup; vop_create_t coda_create; vop_remove_t coda_remove; vop_link_t coda_link; diff --git a/sys/modules/coda/Makefile b/sys/modules/coda/Makefile index 8e008121bbf2..ebcb39c2055e 100644 --- a/sys/modules/coda/Makefile +++ b/sys/modules/coda/Makefile @@ -4,8 +4,7 @@ KMOD= coda SRCS= vnode_if.h \ - coda_fbsd.c coda_namecache.c coda_psdev.c coda_subr.c \ - coda_venus.c coda_vfsops.c coda_vnops.c \ - opt_coda.h + coda_fbsd.c coda_psdev.c coda_subr.c coda_venus.c coda_vfsops.c \ + coda_vnops.c opt_coda.h .include