2005-01-05 23:35:00 +00:00
|
|
|
/*-
|
1998-09-02 19:09:53 +00:00
|
|
|
* Coda: an Experimental Distributed File System
|
|
|
|
* Release 3.1
|
2008-02-10 11:18:12 +00:00
|
|
|
*
|
1998-09-02 19:09:53 +00:00
|
|
|
* Copyright (c) 1987-1998 Carnegie Mellon University
|
|
|
|
* All Rights Reserved
|
2008-02-10 11:18:12 +00:00
|
|
|
*
|
1998-09-02 19:09:53 +00:00
|
|
|
* Permission to use, copy, modify and distribute this software and its
|
|
|
|
* documentation is hereby granted, provided that both the copyright
|
|
|
|
* notice and this permission notice appear in all copies of the
|
|
|
|
* software, derivative works or modified versions, and any portions
|
|
|
|
* thereof, and that both notices appear in supporting documentation, and
|
|
|
|
* that credit is given to Carnegie Mellon University in all documents
|
|
|
|
* and publicity pertaining to direct or indirect use of this code or its
|
|
|
|
* derivatives.
|
2008-02-10 11:18:12 +00:00
|
|
|
*
|
1998-09-02 19:09:53 +00:00
|
|
|
* CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
|
|
|
|
* SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
|
|
|
|
* FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
|
|
|
|
* DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
|
|
|
|
* RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
|
|
|
|
* ANY DERIVATIVE WORK.
|
2008-02-10 11:18:12 +00:00
|
|
|
*
|
1998-09-02 19:09:53 +00:00
|
|
|
* Carnegie Mellon encourages users of this software to return any
|
|
|
|
* improvements or extensions that they make, and to grant Carnegie
|
|
|
|
* Mellon the rights to redistribute these changes without encumbrance.
|
2008-02-10 11:18:12 +00:00
|
|
|
*
|
1998-09-13 13:57:59 +00:00
|
|
|
* @(#) src/sys/coda/coda_subr.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
|
2003-06-10 21:29:12 +00:00
|
|
|
*/
|
2008-02-10 11:18:12 +00:00
|
|
|
|
2005-01-05 23:35:00 +00:00
|
|
|
/*-
|
1998-08-29 21:14:52 +00:00
|
|
|
* Mach Operating System
|
|
|
|
* Copyright (c) 1989 Carnegie-Mellon University
|
|
|
|
* All rights reserved. The CMU software License Agreement specifies
|
|
|
|
* the terms and conditions for use and redistribution.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2002-05-16 21:28:32 +00:00
|
|
|
* This code was written for the Coda filesystem at Carnegie Mellon
|
1998-08-29 21:14:52 +00:00
|
|
|
* University. Contributers include David Steere, James Kistler, and
|
1999-07-21 12:51:36 +00:00
|
|
|
* M. Satyanarayanan.
|
|
|
|
*/
|
1998-08-29 21:14:52 +00:00
|
|
|
|
2008-02-10 11:18:12 +00:00
|
|
|
/*-
|
|
|
|
* NOTES: rvb
|
|
|
|
* 1. Added coda_unmounting to mark all cnodes as being UNMOUNTING. This
|
|
|
|
* has to be done before dounmount is called. Because some of the
|
|
|
|
* routines that dounmount calls before coda_unmounted might try to
|
|
|
|
* force flushes to venus. The vnode pager does this.
|
1998-09-11 18:50:17 +00:00
|
|
|
* 2. coda_unmounting marks all cnodes scanning coda_cache.
|
2008-02-10 11:18:12 +00:00
|
|
|
* 3. cfs_checkunmounting (under DEBUG) checks all cnodes by chasing the
|
|
|
|
* vnodes under the /coda mount point.
|
|
|
|
* 4. coda_cacheprint (under DEBUG) prints names with vnode/cnode address.
|
1998-08-29 21:14:52 +00:00
|
|
|
*/
|
|
|
|
|
2003-06-10 21:29:12 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
1998-08-29 21:14:52 +00:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
2001-05-01 08:13:21 +00:00
|
|
|
#include <sys/lock.h>
|
1998-09-02 19:09:53 +00:00
|
|
|
#include <sys/malloc.h>
|
2003-10-05 07:44:45 +00:00
|
|
|
#include <sys/mutex.h>
|
1998-08-29 21:14:52 +00:00
|
|
|
#include <sys/mount.h>
|
|
|
|
|
2007-07-12 21:04:58 +00:00
|
|
|
#include <fs/coda/coda.h>
|
|
|
|
#include <fs/coda/cnode.h>
|
|
|
|
#include <fs/coda/coda_subr.h>
|
1998-08-29 21:14:52 +00:00
|
|
|
|
2008-02-10 11:18:12 +00:00
|
|
|
static int coda_active = 0;
|
|
|
|
static int coda_reuse = 0;
|
|
|
|
static int coda_new = 0;
|
1998-08-29 21:14:52 +00:00
|
|
|
|
2008-02-10 11:18:12 +00:00
|
|
|
static struct cnode *coda_freelist = NULL;
|
|
|
|
static struct cnode *coda_cache[CODA_CACHESIZE];
|
1998-08-29 21:14:52 +00:00
|
|
|
|
|
|
|
#define CNODE_NEXT(cp) ((cp)->c_next)
|
2003-09-07 07:43:10 +00:00
|
|
|
|
|
|
|
#ifdef CODA_COMPAT_5
|
2008-02-10 11:18:12 +00:00
|
|
|
#define coda_hash(fid) (((fid)->Volume + (fid)->Vnode) & (CODA_CACHESIZE-1))
|
|
|
|
#define IS_DIR(cnode) (cnode.Vnode & 0x1)
|
2003-09-07 07:43:10 +00:00
|
|
|
#else
|
2008-02-10 11:18:12 +00:00
|
|
|
#define coda_hash(fid) (coda_f2i(fid) & (CODA_CACHESIZE-1))
|
|
|
|
#define IS_DIR(cnode) (cnode.opaque[2] & 0x1)
|
2003-09-07 07:43:10 +00:00
|
|
|
#endif
|
1998-08-29 21:14:52 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Allocate a cnode.
|
|
|
|
*/
|
|
|
|
struct cnode *
|
1998-09-11 18:50:17 +00:00
|
|
|
coda_alloc(void)
|
1998-08-29 21:14:52 +00:00
|
|
|
{
|
2008-02-10 11:18:12 +00:00
|
|
|
struct cnode *cp;
|
|
|
|
|
|
|
|
if (coda_freelist != NULL) {
|
|
|
|
cp = coda_freelist;
|
|
|
|
coda_freelist = CNODE_NEXT(cp);
|
|
|
|
coda_reuse++;
|
|
|
|
} else {
|
|
|
|
CODA_ALLOC(cp, struct cnode *, sizeof(struct cnode));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FreeBSD vnodes don't have any Pager info in them ('cause
|
|
|
|
* there are no external pagers, duh!).
|
|
|
|
*/
|
|
|
|
#define VNODE_VM_INFO_INIT(vp) /* MT */
|
|
|
|
VNODE_VM_INFO_INIT(CTOV(cp));
|
|
|
|
coda_new++;
|
|
|
|
}
|
|
|
|
bzero(cp, sizeof (struct cnode));
|
|
|
|
return (cp);
|
1998-08-29 21:14:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Deallocate a cnode.
|
|
|
|
*/
|
|
|
|
void
|
2008-02-10 11:18:12 +00:00
|
|
|
coda_free(struct cnode *cp)
|
1998-08-29 21:14:52 +00:00
|
|
|
{
|
|
|
|
|
2008-02-10 11:18:12 +00:00
|
|
|
CNODE_NEXT(cp) = coda_freelist;
|
|
|
|
coda_freelist = cp;
|
1998-08-29 21:14:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2008-02-10 11:18:12 +00:00
|
|
|
* Put a cnode in the hash table.
|
1998-08-29 21:14:52 +00:00
|
|
|
*/
|
|
|
|
void
|
2008-02-10 11:18:12 +00:00
|
|
|
coda_save(struct cnode *cp)
|
1998-08-29 21:14:52 +00:00
|
|
|
{
|
2008-02-10 11:18:12 +00:00
|
|
|
|
1998-09-11 18:50:17 +00:00
|
|
|
CNODE_NEXT(cp) = coda_cache[coda_hash(&cp->c_fid)];
|
|
|
|
coda_cache[coda_hash(&cp->c_fid)] = cp;
|
1998-08-29 21:14:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2008-02-10 11:18:12 +00:00
|
|
|
* Remove a cnode from the hash table.
|
1998-08-29 21:14:52 +00:00
|
|
|
*/
|
|
|
|
void
|
2008-02-10 11:18:12 +00:00
|
|
|
coda_unsave(struct cnode *cp)
|
1998-08-29 21:14:52 +00:00
|
|
|
{
|
2008-02-10 11:18:12 +00:00
|
|
|
struct cnode *ptr;
|
|
|
|
struct cnode *ptrprev = NULL;
|
|
|
|
|
|
|
|
ptr = coda_cache[coda_hash(&cp->c_fid)];
|
|
|
|
while (ptr != NULL) {
|
|
|
|
if (ptr == cp) {
|
|
|
|
if (ptrprev == NULL)
|
|
|
|
coda_cache[coda_hash(&cp->c_fid)] =
|
|
|
|
CNODE_NEXT(ptr);
|
|
|
|
else
|
|
|
|
CNODE_NEXT(ptrprev) = CNODE_NEXT(ptr);
|
|
|
|
CNODE_NEXT(cp) = (struct cnode *)NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ptrprev = ptr;
|
|
|
|
ptr = CNODE_NEXT(ptr);
|
|
|
|
}
|
1998-08-29 21:14:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lookup a cnode by fid. If the cnode is dying, it is bogus so skip it.
|
2008-02-10 11:18:12 +00:00
|
|
|
*
|
1998-08-29 21:14:52 +00:00
|
|
|
* NOTE: this allows multiple cnodes with same fid -- dcs 1/25/95
|
|
|
|
*/
|
|
|
|
struct cnode *
|
2010-04-05 20:12:54 +00:00
|
|
|
coda_find(struct CodaFid *fid)
|
1998-08-29 21:14:52 +00:00
|
|
|
{
|
2008-02-10 11:18:12 +00:00
|
|
|
struct cnode *cp;
|
|
|
|
|
|
|
|
cp = coda_cache[coda_hash(fid)];
|
|
|
|
while (cp) {
|
|
|
|
if (coda_fid_eq(&(cp->c_fid), fid) && (!IS_UNMOUNTING(cp))) {
|
|
|
|
coda_active++;
|
|
|
|
return (cp);
|
|
|
|
}
|
|
|
|
cp = CNODE_NEXT(cp);
|
|
|
|
}
|
|
|
|
return (NULL);
|
1998-08-29 21:14:52 +00:00
|
|
|
}
|
|
|
|
|
Implement a rudimentary access cache for the Coda kernel module,
modeled on the access cache found in NFS, smbfs, and the Linux coda
module. This is a positive access cache of a single entry per file,
tracking recently granted rights, but unlike NFS and smbfs,
supporting explicit invalidation by the distributed file system.
For each cnode, maintain a C_ACCCACHE flag indicating the validity
of the cache, and a cached uid and mode tracking recently granted
positive access control decisions.
Prefer the cache to venus_access() in VOP_ACCESS() if it is valid,
and when we must fall back to venus_access(), update the cache.
Allow Venus to clear the access cache, either the whole cache on
CODA_FLUSH, or just entries for a specific uid on CODA_PURGEUSER.
Unlike the Coda module on Linux, we don't flush all entries on a
user purge using a generation number, we instead walk present
cnodes and clear only entries for the specific user, meaning it is
somewhat more expensive but won't hit all users.
Since the Coda module is agressive about not keeping around
unopened cnodes, the utility of the cache is somewhat limited for
files, but works will for directories. We should make Coda less
agressive about GCing cnodes in VOP_INACTIVE() in order to improve
the effectiveness of in-kernel caching of attributes and access
rights.
MFC after: 1 month
2008-02-13 15:45:12 +00:00
|
|
|
/*
|
|
|
|
* Clear all cached access control decisions from Coda.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
coda_acccache_purge(struct mount *mnt)
|
|
|
|
{
|
|
|
|
struct cnode *cp;
|
|
|
|
int hash;
|
|
|
|
|
|
|
|
for (hash = 0; hash < CODA_CACHESIZE; hash++) {
|
|
|
|
for (cp = coda_cache[hash]; cp != NULL;
|
|
|
|
cp = CNODE_NEXT(cp)) {
|
|
|
|
if (CTOV(cp)->v_mount == mnt && VALID_ACCCACHE(cp)) {
|
|
|
|
CODADEBUG(CODA_FLUSH, myprintf(("acccache "
|
|
|
|
"purge fid %s uid %d mode 0x%x\n",
|
|
|
|
coda_f2s(&cp->c_fid), cp->c_cached_uid,
|
2008-11-03 16:36:23 +00:00
|
|
|
(int)cp->c_cached_mode)););
|
Implement a rudimentary access cache for the Coda kernel module,
modeled on the access cache found in NFS, smbfs, and the Linux coda
module. This is a positive access cache of a single entry per file,
tracking recently granted rights, but unlike NFS and smbfs,
supporting explicit invalidation by the distributed file system.
For each cnode, maintain a C_ACCCACHE flag indicating the validity
of the cache, and a cached uid and mode tracking recently granted
positive access control decisions.
Prefer the cache to venus_access() in VOP_ACCESS() if it is valid,
and when we must fall back to venus_access(), update the cache.
Allow Venus to clear the access cache, either the whole cache on
CODA_FLUSH, or just entries for a specific uid on CODA_PURGEUSER.
Unlike the Coda module on Linux, we don't flush all entries on a
user purge using a generation number, we instead walk present
cnodes and clear only entries for the specific user, meaning it is
somewhat more expensive but won't hit all users.
Since the Coda module is agressive about not keeping around
unopened cnodes, the utility of the cache is somewhat limited for
files, but works will for directories. We should make Coda less
agressive about GCing cnodes in VOP_INACTIVE() in order to improve
the effectiveness of in-kernel caching of attributes and access
rights.
MFC after: 1 month
2008-02-13 15:45:12 +00:00
|
|
|
cp->c_flags &= ~C_ACCCACHE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* When a user loses their tokens (or other related events), we invalidate
|
|
|
|
* any cached access rights in the access cache. In the Linux version of
|
|
|
|
* Coda, we maintain a global epoch and simply bump it to invalidate all
|
|
|
|
* cached results generated in the epoch. For now, we walk all cnodes and
|
|
|
|
* manually invalidate just that uid in FreeBSD.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
coda_acccache_purgeuser(struct mount *mnt, uid_t uid)
|
|
|
|
{
|
|
|
|
struct cnode *cp;
|
|
|
|
int hash;
|
|
|
|
|
|
|
|
for (hash = 0; hash < CODA_CACHESIZE; hash++) {
|
|
|
|
for (cp = coda_cache[hash]; cp != NULL;
|
|
|
|
cp = CNODE_NEXT(cp)) {
|
|
|
|
if (CTOV(cp)->v_mount == mnt &&
|
|
|
|
VALID_ACCCACHE(cp) && (cp->c_cached_uid == uid)) {
|
|
|
|
CODADEBUG(CODA_PURGEUSER, myprintf((
|
|
|
|
"acccache purgeuser fid %s uid %d mode "
|
|
|
|
"0x%x\n", coda_f2s(&cp->c_fid),
|
2008-11-03 16:36:23 +00:00
|
|
|
cp->c_cached_uid, (int)cp->c_cached_mode)););
|
Implement a rudimentary access cache for the Coda kernel module,
modeled on the access cache found in NFS, smbfs, and the Linux coda
module. This is a positive access cache of a single entry per file,
tracking recently granted rights, but unlike NFS and smbfs,
supporting explicit invalidation by the distributed file system.
For each cnode, maintain a C_ACCCACHE flag indicating the validity
of the cache, and a cached uid and mode tracking recently granted
positive access control decisions.
Prefer the cache to venus_access() in VOP_ACCESS() if it is valid,
and when we must fall back to venus_access(), update the cache.
Allow Venus to clear the access cache, either the whole cache on
CODA_FLUSH, or just entries for a specific uid on CODA_PURGEUSER.
Unlike the Coda module on Linux, we don't flush all entries on a
user purge using a generation number, we instead walk present
cnodes and clear only entries for the specific user, meaning it is
somewhat more expensive but won't hit all users.
Since the Coda module is agressive about not keeping around
unopened cnodes, the utility of the cache is somewhat limited for
files, but works will for directories. We should make Coda less
agressive about GCing cnodes in VOP_INACTIVE() in order to improve
the effectiveness of in-kernel caching of attributes and access
rights.
MFC after: 1 month
2008-02-13 15:45:12 +00:00
|
|
|
cp->c_flags &= ~C_ACCCACHE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-08-29 21:14:52 +00:00
|
|
|
/*
|
2008-02-10 11:18:12 +00:00
|
|
|
* coda_kill is called as a side effect to vcopen. To prevent any cnodes
|
|
|
|
* left around from an earlier run of a venus or warden from causing problems
|
|
|
|
* with the new instance, mark any outstanding cnodes as dying. Future
|
|
|
|
* 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
|
Rather than having the Coda module use its own namecache, use the global
VFS namecache, as is done by the Coda module on Linux. Unlike the Coda
namecache, the global VFS namecache isn't tagged by credential, so use
ore conservative flushing behavior (for now) when CODA_PURGEUSER is
issued by Venus.
This improves overall integration with the FreeBSD VFS, including
allowing __getcwd() to work better, procfs/procstat monitoring, and so
on. This improves shell behavior in many cases, and improves ".."
handling. It may lead to some slowdown until we've implemented a
specific access cache, which should net improve performance, but in the
mean time, lookup access control now always goes to Venus, whereas
previously it didn't.
MFC after: 1 month
2008-02-13 13:06:22 +00:00
|
|
|
*
|
|
|
|
* 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...?
|
2008-02-10 11:18:12 +00:00
|
|
|
*/
|
1998-08-29 21:14:52 +00:00
|
|
|
int
|
2008-02-10 11:18:12 +00:00
|
|
|
coda_kill(struct mount *whoIam, enum dc_status dcstat)
|
1998-08-29 21:14:52 +00:00
|
|
|
{
|
|
|
|
int hash, count = 0;
|
|
|
|
struct cnode *cp;
|
2008-02-10 11:18:12 +00:00
|
|
|
|
|
|
|
/*-
|
|
|
|
* Algorithm is as follows:
|
1998-08-29 21:14:52 +00:00
|
|
|
* Second, flush whatever vnodes we can from the name cache.
|
2008-02-10 11:18:12 +00:00
|
|
|
*
|
1998-08-29 21:14:52 +00:00
|
|
|
* Finally, step through whatever is left and mark them dying.
|
|
|
|
* This prevents any operation at all.
|
2008-02-10 11:18:12 +00:00
|
|
|
*
|
|
|
|
* 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.
|
Rather than having the Coda module use its own namecache, use the global
VFS namecache, as is done by the Coda module on Linux. Unlike the Coda
namecache, the global VFS namecache isn't tagged by credential, so use
ore conservative flushing behavior (for now) when CODA_PURGEUSER is
issued by Venus.
This improves overall integration with the FreeBSD VFS, including
allowing __getcwd() to work better, procfs/procstat monitoring, and so
on. This improves shell behavior in many cases, and improves ".."
handling. It may lead to some slowdown until we've implemented a
specific access cache, which should net improve performance, but in the
mean time, lookup access control now always goes to Venus, whereas
previously it didn't.
MFC after: 1 month
2008-02-13 13:06:22 +00:00
|
|
|
*
|
|
|
|
* XXXRW: Perhaps we no longer need to purge the name cache when
|
|
|
|
* using the VFS name cache, as unmount will do that.
|
1998-08-29 21:14:52 +00:00
|
|
|
*/
|
Rather than having the Coda module use its own namecache, use the global
VFS namecache, as is done by the Coda module on Linux. Unlike the Coda
namecache, the global VFS namecache isn't tagged by credential, so use
ore conservative flushing behavior (for now) when CODA_PURGEUSER is
issued by Venus.
This improves overall integration with the FreeBSD VFS, including
allowing __getcwd() to work better, procfs/procstat monitoring, and so
on. This improves shell behavior in many cases, and improves ".."
handling. It may lead to some slowdown until we've implemented a
specific access cache, which should net improve performance, but in the
mean time, lookup access control now always goes to Venus, whereas
previously it didn't.
MFC after: 1 month
2008-02-13 13:06:22 +00:00
|
|
|
cache_purgevfs(whoIam);
|
1998-09-11 18:50:17 +00:00
|
|
|
for (hash = 0; hash < CODA_CACHESIZE; hash++) {
|
2008-02-10 11:18:12 +00:00
|
|
|
for (cp = coda_cache[hash];cp != NULL;
|
|
|
|
cp = CNODE_NEXT(cp)) {
|
1998-08-29 21:14:52 +00:00
|
|
|
if (CTOV(cp)->v_mount == whoIam) {
|
2008-02-10 11:18:12 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
printf("coda_kill: vp %p, cp %p\n", CTOV(cp),
|
|
|
|
cp);
|
1998-08-29 21:14:52 +00:00
|
|
|
#endif
|
|
|
|
count++;
|
2008-02-10 11:18:12 +00:00
|
|
|
CODADEBUG(CODA_FLUSH, myprintf(("Live cnode "
|
|
|
|
"fid %s flags %d count %d\n",
|
|
|
|
coda_f2s(&cp->c_fid), cp->c_flags,
|
|
|
|
vrefcnt(CTOV(cp)))););
|
1998-08-29 21:14:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-02-10 11:18:12 +00:00
|
|
|
return (count);
|
1998-08-29 21:14:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2008-02-10 11:18:12 +00:00
|
|
|
* There are two reasons why a cnode may be in use, it may be in the name
|
|
|
|
* cache or it may be executing.
|
1998-08-29 21:14:52 +00:00
|
|
|
*/
|
|
|
|
void
|
Rather than having the Coda module use its own namecache, use the global
VFS namecache, as is done by the Coda module on Linux. Unlike the Coda
namecache, the global VFS namecache isn't tagged by credential, so use
ore conservative flushing behavior (for now) when CODA_PURGEUSER is
issued by Venus.
This improves overall integration with the FreeBSD VFS, including
allowing __getcwd() to work better, procfs/procstat monitoring, and so
on. This improves shell behavior in many cases, and improves ".."
handling. It may lead to some slowdown until we've implemented a
specific access cache, which should net improve performance, but in the
mean time, lookup access control now always goes to Venus, whereas
previously it didn't.
MFC after: 1 month
2008-02-13 13:06:22 +00:00
|
|
|
coda_flush(struct coda_mntinfo *mnt, enum dc_status dcstat)
|
1998-08-29 21:14:52 +00:00
|
|
|
{
|
2008-02-10 11:18:12 +00:00
|
|
|
int hash;
|
|
|
|
struct cnode *cp;
|
|
|
|
|
|
|
|
coda_clstat.ncalls++;
|
|
|
|
coda_clstat.reqs[CODA_FLUSH]++;
|
|
|
|
|
Implement a rudimentary access cache for the Coda kernel module,
modeled on the access cache found in NFS, smbfs, and the Linux coda
module. This is a positive access cache of a single entry per file,
tracking recently granted rights, but unlike NFS and smbfs,
supporting explicit invalidation by the distributed file system.
For each cnode, maintain a C_ACCCACHE flag indicating the validity
of the cache, and a cached uid and mode tracking recently granted
positive access control decisions.
Prefer the cache to venus_access() in VOP_ACCESS() if it is valid,
and when we must fall back to venus_access(), update the cache.
Allow Venus to clear the access cache, either the whole cache on
CODA_FLUSH, or just entries for a specific uid on CODA_PURGEUSER.
Unlike the Coda module on Linux, we don't flush all entries on a
user purge using a generation number, we instead walk present
cnodes and clear only entries for the specific user, meaning it is
somewhat more expensive but won't hit all users.
Since the Coda module is agressive about not keeping around
unopened cnodes, the utility of the cache is somewhat limited for
files, but works will for directories. We should make Coda less
agressive about GCing cnodes in VOP_INACTIVE() in order to improve
the effectiveness of in-kernel caching of attributes and access
rights.
MFC after: 1 month
2008-02-13 15:45:12 +00:00
|
|
|
coda_acccache_purge(mnt->mi_vfsp);
|
Rather than having the Coda module use its own namecache, use the global
VFS namecache, as is done by the Coda module on Linux. Unlike the Coda
namecache, the global VFS namecache isn't tagged by credential, so use
ore conservative flushing behavior (for now) when CODA_PURGEUSER is
issued by Venus.
This improves overall integration with the FreeBSD VFS, including
allowing __getcwd() to work better, procfs/procstat monitoring, and so
on. This improves shell behavior in many cases, and improves ".."
handling. It may lead to some slowdown until we've implemented a
specific access cache, which should net improve performance, but in the
mean time, lookup access control now always goes to Venus, whereas
previously it didn't.
MFC after: 1 month
2008-02-13 13:06:22 +00:00
|
|
|
cache_purgevfs(mnt->mi_vfsp);
|
2008-02-10 11:18:12 +00:00
|
|
|
for (hash = 0; hash < CODA_CACHESIZE; hash++) {
|
|
|
|
for (cp = coda_cache[hash]; cp != NULL;
|
|
|
|
cp = CNODE_NEXT(cp)) {
|
|
|
|
/*
|
|
|
|
* Only files that can be executed need to be flushed
|
|
|
|
* from the VM.
|
|
|
|
*
|
|
|
|
* NOTE: Currently this doesn't do anything, but
|
|
|
|
* perhaps it should?
|
|
|
|
*/
|
|
|
|
if (!IS_DIR(cp->c_fid))
|
|
|
|
coda_vmflush(cp);
|
|
|
|
}
|
1998-08-29 21:14:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2008-02-10 11:18:12 +00:00
|
|
|
* As a debugging measure, print out any cnodes that lived through a name
|
|
|
|
* cache flush.
|
1998-08-29 21:14:52 +00:00
|
|
|
*/
|
|
|
|
void
|
1998-09-11 18:50:17 +00:00
|
|
|
coda_testflush(void)
|
1998-08-29 21:14:52 +00:00
|
|
|
{
|
2008-02-10 11:18:12 +00:00
|
|
|
int hash;
|
|
|
|
struct cnode *cp;
|
|
|
|
|
|
|
|
for (hash = 0; hash < CODA_CACHESIZE; hash++) {
|
|
|
|
for (cp = coda_cache[hash]; cp != NULL;
|
|
|
|
cp = CNODE_NEXT(cp))
|
|
|
|
myprintf(("Live cnode fid %s count %d\n",
|
|
|
|
coda_f2s(&cp->c_fid), CTOV(cp)->v_usecount));
|
1998-08-29 21:14:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2008-02-10 11:18:12 +00:00
|
|
|
* First, step through all cnodes and mark them unmounting. FreeBSD kernels
|
|
|
|
* may try to fsync them now that venus is dead, which would be a bad thing.
|
1998-08-29 21:14:52 +00:00
|
|
|
*/
|
|
|
|
void
|
2008-02-10 11:18:12 +00:00
|
|
|
coda_unmounting(struct mount *whoIam)
|
|
|
|
{
|
1998-08-29 21:14:52 +00:00
|
|
|
int hash;
|
|
|
|
struct cnode *cp;
|
|
|
|
|
1998-09-11 18:50:17 +00:00
|
|
|
for (hash = 0; hash < CODA_CACHESIZE; hash++) {
|
2008-02-10 11:18:12 +00:00
|
|
|
for (cp = coda_cache[hash]; cp != NULL;
|
|
|
|
cp = CNODE_NEXT(cp)) {
|
1998-08-29 21:14:52 +00:00
|
|
|
if (CTOV(cp)->v_mount == whoIam) {
|
|
|
|
if (cp->c_flags & (C_LOCKED|C_WANTED)) {
|
2008-02-10 11:18:12 +00:00
|
|
|
printf("coda_unmounting: Unlocking "
|
|
|
|
"%p\n", cp);
|
1998-08-29 21:14:52 +00:00
|
|
|
cp->c_flags &= ~(C_LOCKED|C_WANTED);
|
|
|
|
wakeup((caddr_t) cp);
|
|
|
|
}
|
|
|
|
cp->c_flags |= C_UNMOUNTING;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-10 11:18:12 +00:00
|
|
|
#ifdef DEBUG
|
1998-09-25 17:38:32 +00:00
|
|
|
void
|
2008-02-10 11:18:12 +00:00
|
|
|
coda_checkunmounting(struct mount *mp)
|
2003-11-05 04:30:08 +00:00
|
|
|
{
|
2004-07-04 08:52:35 +00:00
|
|
|
struct vnode *vp, *nvp;
|
1998-08-29 21:14:52 +00:00
|
|
|
struct cnode *cp;
|
|
|
|
int count = 0, bad = 0;
|
2003-10-04 13:16:54 +00:00
|
|
|
|
2003-11-05 04:30:08 +00:00
|
|
|
MNT_ILOCK(mp);
|
2004-07-04 08:52:35 +00:00
|
|
|
MNT_VNODE_FOREACH(vp, mp, nvp) {
|
2003-10-05 06:43:30 +00:00
|
|
|
VI_LOCK(vp);
|
2005-03-13 12:14:56 +00:00
|
|
|
if (vp->v_iflag & VI_DOOMED) {
|
2003-10-05 06:43:30 +00:00
|
|
|
VI_UNLOCK(vp);
|
|
|
|
continue;
|
|
|
|
}
|
1998-08-29 21:14:52 +00:00
|
|
|
cp = VTOC(vp);
|
|
|
|
count++;
|
|
|
|
if (!(cp->c_flags & C_UNMOUNTING)) {
|
|
|
|
bad++;
|
|
|
|
printf("vp %p, cp %p missed\n", vp, cp);
|
|
|
|
cp->c_flags |= C_UNMOUNTING;
|
|
|
|
}
|
2003-10-05 06:43:30 +00:00
|
|
|
VI_UNLOCK(vp);
|
1998-08-29 21:14:52 +00:00
|
|
|
}
|
2003-11-05 04:30:08 +00:00
|
|
|
MNT_IUNLOCK(mp);
|
1998-08-29 21:14:52 +00:00
|
|
|
}
|
|
|
|
|
1998-09-25 17:38:32 +00:00
|
|
|
void
|
2008-02-10 11:18:12 +00:00
|
|
|
coda_cacheprint(struct mount *whoIam)
|
|
|
|
{
|
1998-08-29 21:14:52 +00:00
|
|
|
int hash;
|
|
|
|
struct cnode *cp;
|
|
|
|
int count = 0;
|
|
|
|
|
2008-02-10 11:18:12 +00:00
|
|
|
printf("coda_cacheprint: coda_ctlvp %p, cp %p", coda_ctlvp,
|
|
|
|
VTOC(coda_ctlvp));
|
Rather than having the Coda module use its own namecache, use the global
VFS namecache, as is done by the Coda module on Linux. Unlike the Coda
namecache, the global VFS namecache isn't tagged by credential, so use
ore conservative flushing behavior (for now) when CODA_PURGEUSER is
issued by Venus.
This improves overall integration with the FreeBSD VFS, including
allowing __getcwd() to work better, procfs/procstat monitoring, and so
on. This improves shell behavior in many cases, and improves ".."
handling. It may lead to some slowdown until we've implemented a
specific access cache, which should net improve performance, but in the
mean time, lookup access control now always goes to Venus, whereas
previously it didn't.
MFC after: 1 month
2008-02-13 13:06:22 +00:00
|
|
|
|
|
|
|
#if 0
|
1998-09-25 17:38:32 +00:00
|
|
|
coda_nc_name(VTOC(coda_ctlvp));
|
Rather than having the Coda module use its own namecache, use the global
VFS namecache, as is done by the Coda module on Linux. Unlike the Coda
namecache, the global VFS namecache isn't tagged by credential, so use
ore conservative flushing behavior (for now) when CODA_PURGEUSER is
issued by Venus.
This improves overall integration with the FreeBSD VFS, including
allowing __getcwd() to work better, procfs/procstat monitoring, and so
on. This improves shell behavior in many cases, and improves ".."
handling. It may lead to some slowdown until we've implemented a
specific access cache, which should net improve performance, but in the
mean time, lookup access control now always goes to Venus, whereas
previously it didn't.
MFC after: 1 month
2008-02-13 13:06:22 +00:00
|
|
|
#endif
|
1998-08-29 21:14:52 +00:00
|
|
|
printf("\n");
|
1998-09-11 18:50:17 +00:00
|
|
|
for (hash = 0; hash < CODA_CACHESIZE; hash++) {
|
2008-02-10 11:18:12 +00:00
|
|
|
for (cp = coda_cache[hash]; cp != NULL;
|
|
|
|
cp = CNODE_NEXT(cp)) {
|
1998-08-29 21:14:52 +00:00
|
|
|
if (CTOV(cp)->v_mount == whoIam) {
|
2008-02-10 11:18:12 +00:00
|
|
|
printf("coda_cacheprint: vp %p, cp %p",
|
|
|
|
CTOV(cp), cp);
|
Rather than having the Coda module use its own namecache, use the global
VFS namecache, as is done by the Coda module on Linux. Unlike the Coda
namecache, the global VFS namecache isn't tagged by credential, so use
ore conservative flushing behavior (for now) when CODA_PURGEUSER is
issued by Venus.
This improves overall integration with the FreeBSD VFS, including
allowing __getcwd() to work better, procfs/procstat monitoring, and so
on. This improves shell behavior in many cases, and improves ".."
handling. It may lead to some slowdown until we've implemented a
specific access cache, which should net improve performance, but in the
mean time, lookup access control now always goes to Venus, whereas
previously it didn't.
MFC after: 1 month
2008-02-13 13:06:22 +00:00
|
|
|
#if 0
|
1998-09-11 18:50:17 +00:00
|
|
|
coda_nc_name(cp);
|
Rather than having the Coda module use its own namecache, use the global
VFS namecache, as is done by the Coda module on Linux. Unlike the Coda
namecache, the global VFS namecache isn't tagged by credential, so use
ore conservative flushing behavior (for now) when CODA_PURGEUSER is
issued by Venus.
This improves overall integration with the FreeBSD VFS, including
allowing __getcwd() to work better, procfs/procstat monitoring, and so
on. This improves shell behavior in many cases, and improves ".."
handling. It may lead to some slowdown until we've implemented a
specific access cache, which should net improve performance, but in the
mean time, lookup access control now always goes to Venus, whereas
previously it didn't.
MFC after: 1 month
2008-02-13 13:06:22 +00:00
|
|
|
#endif
|
1998-08-29 21:14:52 +00:00
|
|
|
printf("\n");
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-09-11 18:50:17 +00:00
|
|
|
printf("coda_cacheprint: count %d\n", count);
|
1998-08-29 21:14:52 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2008-02-10 11:18:12 +00:00
|
|
|
/*-
|
|
|
|
* There are 6 cases where invalidations occur. The semantics of each is
|
|
|
|
* listed here:
|
|
|
|
*
|
|
|
|
* CODA_FLUSH -- Flush all entries from the name cache and the cnode
|
|
|
|
* cache.
|
|
|
|
*
|
|
|
|
* CODA_PURGEUSER -- Flush all entries from the name cache for a specific
|
|
|
|
* user. This call is a result of token expiration.
|
1998-08-29 21:14:52 +00:00
|
|
|
*
|
2008-02-10 11:18:12 +00:00
|
|
|
* The next two are the result of callbacks on a file or directory:
|
1998-08-29 21:14:52 +00:00
|
|
|
*
|
2008-02-10 11:18:12 +00:00
|
|
|
* CODA_ZAPDIR -- Flush the attributes for the dir from its cnode. Zap
|
|
|
|
* all children of this directory from the namecache.
|
1998-08-29 21:14:52 +00:00
|
|
|
*
|
2008-02-10 11:18:12 +00:00
|
|
|
* CODA_ZAPFILE -- Flush the attributes for a file.
|
1998-08-29 21:14:52 +00:00
|
|
|
*
|
2008-02-10 11:18:12 +00:00
|
|
|
* The fifth is a result of Venus detecting an inconsistent file:
|
1998-08-29 21:14:52 +00:00
|
|
|
*
|
2008-02-10 11:18:12 +00:00
|
|
|
* CODA_PURGEFID -- Flush the attribute for the file; if it is a dir (odd
|
|
|
|
* vnode), purge its children from the namecache; remove
|
|
|
|
* the file from the namecache.
|
|
|
|
*
|
|
|
|
* The sixth allows Venus to replace local fids with global ones during
|
|
|
|
* reintegration.
|
|
|
|
*
|
|
|
|
* CODA_REPLACE -- Replace one CodaFid with another throughout the name
|
|
|
|
* cache.
|
1998-08-29 21:14:52 +00:00
|
|
|
*/
|
Rather than having the Coda module use its own namecache, use the global
VFS namecache, as is done by the Coda module on Linux. Unlike the Coda
namecache, the global VFS namecache isn't tagged by credential, so use
ore conservative flushing behavior (for now) when CODA_PURGEUSER is
issued by Venus.
This improves overall integration with the FreeBSD VFS, including
allowing __getcwd() to work better, procfs/procstat monitoring, and so
on. This improves shell behavior in many cases, and improves ".."
handling. It may lead to some slowdown until we've implemented a
specific access cache, which should net improve performance, but in the
mean time, lookup access control now always goes to Venus, whereas
previously it didn't.
MFC after: 1 month
2008-02-13 13:06:22 +00:00
|
|
|
int
|
|
|
|
handleDownCall(struct coda_mntinfo *mnt, int opcode, union outputArgs *out)
|
1998-08-29 21:14:52 +00:00
|
|
|
{
|
2008-02-10 11:18:12 +00:00
|
|
|
int error;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Handle invalidate requests.
|
|
|
|
*/
|
|
|
|
switch (opcode) {
|
|
|
|
case CODA_FLUSH: {
|
Rather than having the Coda module use its own namecache, use the global
VFS namecache, as is done by the Coda module on Linux. Unlike the Coda
namecache, the global VFS namecache isn't tagged by credential, so use
ore conservative flushing behavior (for now) when CODA_PURGEUSER is
issued by Venus.
This improves overall integration with the FreeBSD VFS, including
allowing __getcwd() to work better, procfs/procstat monitoring, and so
on. This improves shell behavior in many cases, and improves ".."
handling. It may lead to some slowdown until we've implemented a
specific access cache, which should net improve performance, but in the
mean time, lookup access control now always goes to Venus, whereas
previously it didn't.
MFC after: 1 month
2008-02-13 13:06:22 +00:00
|
|
|
coda_flush(mnt, IS_DOWNCALL);
|
1998-08-29 21:14:52 +00:00
|
|
|
|
2008-02-10 11:18:12 +00:00
|
|
|
/* Print any remaining cnodes. */
|
|
|
|
CODADEBUG(CODA_FLUSH, coda_testflush(););
|
|
|
|
return (0);
|
|
|
|
}
|
1998-08-29 21:14:52 +00:00
|
|
|
|
2008-02-10 11:18:12 +00:00
|
|
|
case CODA_PURGEUSER: {
|
|
|
|
coda_clstat.ncalls++;
|
|
|
|
coda_clstat.reqs[CODA_PURGEUSER]++;
|
|
|
|
|
|
|
|
/* XXX - need to prevent fsync's. */
|
Implement a rudimentary access cache for the Coda kernel module,
modeled on the access cache found in NFS, smbfs, and the Linux coda
module. This is a positive access cache of a single entry per file,
tracking recently granted rights, but unlike NFS and smbfs,
supporting explicit invalidation by the distributed file system.
For each cnode, maintain a C_ACCCACHE flag indicating the validity
of the cache, and a cached uid and mode tracking recently granted
positive access control decisions.
Prefer the cache to venus_access() in VOP_ACCESS() if it is valid,
and when we must fall back to venus_access(), update the cache.
Allow Venus to clear the access cache, either the whole cache on
CODA_FLUSH, or just entries for a specific uid on CODA_PURGEUSER.
Unlike the Coda module on Linux, we don't flush all entries on a
user purge using a generation number, we instead walk present
cnodes and clear only entries for the specific user, meaning it is
somewhat more expensive but won't hit all users.
Since the Coda module is agressive about not keeping around
unopened cnodes, the utility of the cache is somewhat limited for
files, but works will for directories. We should make Coda less
agressive about GCing cnodes in VOP_INACTIVE() in order to improve
the effectiveness of in-kernel caching of attributes and access
rights.
MFC after: 1 month
2008-02-13 15:45:12 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Purge any access cache entries for the uid.
|
|
|
|
*/
|
2003-09-07 07:43:10 +00:00
|
|
|
#ifdef CODA_COMPAT_5
|
Implement a rudimentary access cache for the Coda kernel module,
modeled on the access cache found in NFS, smbfs, and the Linux coda
module. This is a positive access cache of a single entry per file,
tracking recently granted rights, but unlike NFS and smbfs,
supporting explicit invalidation by the distributed file system.
For each cnode, maintain a C_ACCCACHE flag indicating the validity
of the cache, and a cached uid and mode tracking recently granted
positive access control decisions.
Prefer the cache to venus_access() in VOP_ACCESS() if it is valid,
and when we must fall back to venus_access(), update the cache.
Allow Venus to clear the access cache, either the whole cache on
CODA_FLUSH, or just entries for a specific uid on CODA_PURGEUSER.
Unlike the Coda module on Linux, we don't flush all entries on a
user purge using a generation number, we instead walk present
cnodes and clear only entries for the specific user, meaning it is
somewhat more expensive but won't hit all users.
Since the Coda module is agressive about not keeping around
unopened cnodes, the utility of the cache is somewhat limited for
files, but works will for directories. We should make Coda less
agressive about GCing cnodes in VOP_INACTIVE() in order to improve
the effectiveness of in-kernel caching of attributes and access
rights.
MFC after: 1 month
2008-02-13 15:45:12 +00:00
|
|
|
coda_acccache_purgeuser(mnt->mi_vfsp,
|
|
|
|
out->coda_purgeuser.cred.cr_uid);
|
2003-09-07 07:43:10 +00:00
|
|
|
#else
|
Implement a rudimentary access cache for the Coda kernel module,
modeled on the access cache found in NFS, smbfs, and the Linux coda
module. This is a positive access cache of a single entry per file,
tracking recently granted rights, but unlike NFS and smbfs,
supporting explicit invalidation by the distributed file system.
For each cnode, maintain a C_ACCCACHE flag indicating the validity
of the cache, and a cached uid and mode tracking recently granted
positive access control decisions.
Prefer the cache to venus_access() in VOP_ACCESS() if it is valid,
and when we must fall back to venus_access(), update the cache.
Allow Venus to clear the access cache, either the whole cache on
CODA_FLUSH, or just entries for a specific uid on CODA_PURGEUSER.
Unlike the Coda module on Linux, we don't flush all entries on a
user purge using a generation number, we instead walk present
cnodes and clear only entries for the specific user, meaning it is
somewhat more expensive but won't hit all users.
Since the Coda module is agressive about not keeping around
unopened cnodes, the utility of the cache is somewhat limited for
files, but works will for directories. We should make Coda less
agressive about GCing cnodes in VOP_INACTIVE() in order to improve
the effectiveness of in-kernel caching of attributes and access
rights.
MFC after: 1 month
2008-02-13 15:45:12 +00:00
|
|
|
coda_acccache_purgeuser(mnt->mi_vfsp,
|
|
|
|
out->coda_purgeuser.uid);
|
Rather than having the Coda module use its own namecache, use the global
VFS namecache, as is done by the Coda module on Linux. Unlike the Coda
namecache, the global VFS namecache isn't tagged by credential, so use
ore conservative flushing behavior (for now) when CODA_PURGEUSER is
issued by Venus.
This improves overall integration with the FreeBSD VFS, including
allowing __getcwd() to work better, procfs/procstat monitoring, and so
on. This improves shell behavior in many cases, and improves ".."
handling. It may lead to some slowdown until we've implemented a
specific access cache, which should net improve performance, but in the
mean time, lookup access control now always goes to Venus, whereas
previously it didn't.
MFC after: 1 month
2008-02-13 13:06:22 +00:00
|
|
|
#endif
|
2008-02-10 11:18:12 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
case CODA_ZAPFILE: {
|
|
|
|
struct cnode *cp;
|
|
|
|
|
|
|
|
error = 0;
|
|
|
|
coda_clstat.ncalls++;
|
|
|
|
coda_clstat.reqs[CODA_ZAPFILE]++;
|
|
|
|
cp = coda_find(&out->coda_zapfile.Fid);
|
|
|
|
if (cp != NULL) {
|
|
|
|
vref(CTOV(cp));
|
Rather than having the Coda module use its own namecache, use the global
VFS namecache, as is done by the Coda module on Linux. Unlike the Coda
namecache, the global VFS namecache isn't tagged by credential, so use
ore conservative flushing behavior (for now) when CODA_PURGEUSER is
issued by Venus.
This improves overall integration with the FreeBSD VFS, including
allowing __getcwd() to work better, procfs/procstat monitoring, and so
on. This improves shell behavior in many cases, and improves ".."
handling. It may lead to some slowdown until we've implemented a
specific access cache, which should net improve performance, but in the
mean time, lookup access control now always goes to Venus, whereas
previously it didn't.
MFC after: 1 month
2008-02-13 13:06:22 +00:00
|
|
|
cache_purge(CTOV(cp));
|
Implement a rudimentary access cache for the Coda kernel module,
modeled on the access cache found in NFS, smbfs, and the Linux coda
module. This is a positive access cache of a single entry per file,
tracking recently granted rights, but unlike NFS and smbfs,
supporting explicit invalidation by the distributed file system.
For each cnode, maintain a C_ACCCACHE flag indicating the validity
of the cache, and a cached uid and mode tracking recently granted
positive access control decisions.
Prefer the cache to venus_access() in VOP_ACCESS() if it is valid,
and when we must fall back to venus_access(), update the cache.
Allow Venus to clear the access cache, either the whole cache on
CODA_FLUSH, or just entries for a specific uid on CODA_PURGEUSER.
Unlike the Coda module on Linux, we don't flush all entries on a
user purge using a generation number, we instead walk present
cnodes and clear only entries for the specific user, meaning it is
somewhat more expensive but won't hit all users.
Since the Coda module is agressive about not keeping around
unopened cnodes, the utility of the cache is somewhat limited for
files, but works will for directories. We should make Coda less
agressive about GCing cnodes in VOP_INACTIVE() in order to improve
the effectiveness of in-kernel caching of attributes and access
rights.
MFC after: 1 month
2008-02-13 15:45:12 +00:00
|
|
|
cp->c_flags &= ~(C_VATTR | C_ACCCACHE);
|
2008-02-10 11:18:12 +00:00
|
|
|
ASSERT_VOP_LOCKED(CTOV(cp), "coda HandleDownCall");
|
|
|
|
if (CTOV(cp)->v_vflag & VV_TEXT)
|
|
|
|
error = coda_vmflush(cp);
|
|
|
|
CODADEBUG(CODA_ZAPFILE,
|
|
|
|
myprintf(("zapfile: fid = %s, refcnt = %d, error = "
|
|
|
|
"%d\n", coda_f2s(&cp->c_fid),
|
|
|
|
CTOV(cp)->v_usecount - 1, error)););
|
|
|
|
if (vrefcnt(CTOV(cp)) == 1)
|
|
|
|
cp->c_flags |= C_PURGING;
|
|
|
|
vrele(CTOV(cp));
|
|
|
|
}
|
|
|
|
return (error);
|
1998-08-29 21:14:52 +00:00
|
|
|
}
|
|
|
|
|
2008-02-10 11:18:12 +00:00
|
|
|
case CODA_ZAPDIR: {
|
|
|
|
struct cnode *cp;
|
|
|
|
|
|
|
|
coda_clstat.ncalls++;
|
|
|
|
coda_clstat.reqs[CODA_ZAPDIR]++;
|
|
|
|
cp = coda_find(&out->coda_zapdir.Fid);
|
|
|
|
if (cp != NULL) {
|
|
|
|
vref(CTOV(cp));
|
Rather than having the Coda module use its own namecache, use the global
VFS namecache, as is done by the Coda module on Linux. Unlike the Coda
namecache, the global VFS namecache isn't tagged by credential, so use
ore conservative flushing behavior (for now) when CODA_PURGEUSER is
issued by Venus.
This improves overall integration with the FreeBSD VFS, including
allowing __getcwd() to work better, procfs/procstat monitoring, and so
on. This improves shell behavior in many cases, and improves ".."
handling. It may lead to some slowdown until we've implemented a
specific access cache, which should net improve performance, but in the
mean time, lookup access control now always goes to Venus, whereas
previously it didn't.
MFC after: 1 month
2008-02-13 13:06:22 +00:00
|
|
|
cache_purge(CTOV(cp));
|
Implement a rudimentary access cache for the Coda kernel module,
modeled on the access cache found in NFS, smbfs, and the Linux coda
module. This is a positive access cache of a single entry per file,
tracking recently granted rights, but unlike NFS and smbfs,
supporting explicit invalidation by the distributed file system.
For each cnode, maintain a C_ACCCACHE flag indicating the validity
of the cache, and a cached uid and mode tracking recently granted
positive access control decisions.
Prefer the cache to venus_access() in VOP_ACCESS() if it is valid,
and when we must fall back to venus_access(), update the cache.
Allow Venus to clear the access cache, either the whole cache on
CODA_FLUSH, or just entries for a specific uid on CODA_PURGEUSER.
Unlike the Coda module on Linux, we don't flush all entries on a
user purge using a generation number, we instead walk present
cnodes and clear only entries for the specific user, meaning it is
somewhat more expensive but won't hit all users.
Since the Coda module is agressive about not keeping around
unopened cnodes, the utility of the cache is somewhat limited for
files, but works will for directories. We should make Coda less
agressive about GCing cnodes in VOP_INACTIVE() in order to improve
the effectiveness of in-kernel caching of attributes and access
rights.
MFC after: 1 month
2008-02-13 15:45:12 +00:00
|
|
|
cp->c_flags &= ~(C_VATTR | C_ACCCACHE);
|
2008-02-10 11:18:12 +00:00
|
|
|
CODADEBUG(CODA_ZAPDIR, myprintf(("zapdir: fid = %s, "
|
|
|
|
"refcnt = %d\n", coda_f2s(&cp->c_fid),
|
|
|
|
CTOV(cp)->v_usecount - 1)););
|
|
|
|
if (vrefcnt(CTOV(cp)) == 1)
|
|
|
|
cp->c_flags |= C_PURGING;
|
|
|
|
vrele(CTOV(cp));
|
|
|
|
}
|
|
|
|
return (0);
|
1998-08-29 21:14:52 +00:00
|
|
|
}
|
|
|
|
|
2008-02-10 11:18:12 +00:00
|
|
|
case CODA_PURGEFID: {
|
|
|
|
struct cnode *cp;
|
|
|
|
|
|
|
|
error = 0;
|
|
|
|
coda_clstat.ncalls++;
|
|
|
|
coda_clstat.reqs[CODA_PURGEFID]++;
|
|
|
|
cp = coda_find(&out->coda_purgefid.Fid);
|
|
|
|
if (cp != NULL) {
|
|
|
|
vref(CTOV(cp));
|
Rather than having the Coda module use its own namecache, use the global
VFS namecache, as is done by the Coda module on Linux. Unlike the Coda
namecache, the global VFS namecache isn't tagged by credential, so use
ore conservative flushing behavior (for now) when CODA_PURGEUSER is
issued by Venus.
This improves overall integration with the FreeBSD VFS, including
allowing __getcwd() to work better, procfs/procstat monitoring, and so
on. This improves shell behavior in many cases, and improves ".."
handling. It may lead to some slowdown until we've implemented a
specific access cache, which should net improve performance, but in the
mean time, lookup access control now always goes to Venus, whereas
previously it didn't.
MFC after: 1 month
2008-02-13 13:06:22 +00:00
|
|
|
cache_purge(CTOV(cp));
|
Implement a rudimentary access cache for the Coda kernel module,
modeled on the access cache found in NFS, smbfs, and the Linux coda
module. This is a positive access cache of a single entry per file,
tracking recently granted rights, but unlike NFS and smbfs,
supporting explicit invalidation by the distributed file system.
For each cnode, maintain a C_ACCCACHE flag indicating the validity
of the cache, and a cached uid and mode tracking recently granted
positive access control decisions.
Prefer the cache to venus_access() in VOP_ACCESS() if it is valid,
and when we must fall back to venus_access(), update the cache.
Allow Venus to clear the access cache, either the whole cache on
CODA_FLUSH, or just entries for a specific uid on CODA_PURGEUSER.
Unlike the Coda module on Linux, we don't flush all entries on a
user purge using a generation number, we instead walk present
cnodes and clear only entries for the specific user, meaning it is
somewhat more expensive but won't hit all users.
Since the Coda module is agressive about not keeping around
unopened cnodes, the utility of the cache is somewhat limited for
files, but works will for directories. We should make Coda less
agressive about GCing cnodes in VOP_INACTIVE() in order to improve
the effectiveness of in-kernel caching of attributes and access
rights.
MFC after: 1 month
2008-02-13 15:45:12 +00:00
|
|
|
cp->c_flags &= ~(C_VATTR | C_ACCCACHE);
|
2008-02-10 11:18:12 +00:00
|
|
|
ASSERT_VOP_LOCKED(CTOV(cp), "coda HandleDownCall");
|
|
|
|
if (!(IS_DIR(out->coda_purgefid.Fid))
|
|
|
|
&& (CTOV(cp)->v_vflag & VV_TEXT))
|
|
|
|
error = coda_vmflush(cp);
|
|
|
|
CODADEBUG(CODA_PURGEFID, myprintf(("purgefid: fid "
|
|
|
|
"= %s, refcnt = %d, error = %d\n",
|
|
|
|
coda_f2s(&cp->c_fid),
|
|
|
|
CTOV(cp)->v_usecount - 1, error)););
|
|
|
|
if (vrefcnt(CTOV(cp)) == 1)
|
|
|
|
cp->c_flags |= C_PURGING;
|
|
|
|
vrele(CTOV(cp));
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
case CODA_REPLACE: {
|
|
|
|
struct cnode *cp = NULL;
|
|
|
|
|
|
|
|
coda_clstat.ncalls++;
|
|
|
|
coda_clstat.reqs[CODA_REPLACE]++;
|
|
|
|
cp = coda_find(&out->coda_replace.OldFid);
|
|
|
|
if (cp != NULL) {
|
|
|
|
/*
|
|
|
|
* Remove the cnode from the hash table, replace the
|
2008-02-14 00:30:06 +00:00
|
|
|
* fid, and reinsert. Clear the attribute cache as
|
|
|
|
* the "inode number" may have changed (it's just a
|
|
|
|
* hash of the fid, and the fid is changing).
|
2008-02-10 11:18:12 +00:00
|
|
|
*/
|
|
|
|
vref(CTOV(cp));
|
|
|
|
coda_unsave(cp);
|
|
|
|
cp->c_fid = out->coda_replace.NewFid;
|
2008-02-14 00:30:06 +00:00
|
|
|
cp->c_flags &= ~C_VATTR;
|
2008-02-10 11:18:12 +00:00
|
|
|
coda_save(cp);
|
|
|
|
CODADEBUG(CODA_REPLACE, myprintf(("replace: oldfid "
|
|
|
|
"= %s, newfid = %s, cp = %p\n",
|
|
|
|
coda_f2s(&out->coda_replace.OldFid),
|
|
|
|
coda_f2s(&cp->c_fid), cp)););
|
|
|
|
vrele(CTOV(cp));
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
myprintf(("handleDownCall: unknown opcode %d\n", opcode));
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
}
|
1998-08-29 21:14:52 +00:00
|
|
|
|
|
|
|
int
|
2008-02-10 11:18:12 +00:00
|
|
|
coda_vmflush(struct cnode *cp)
|
1998-08-29 21:14:52 +00:00
|
|
|
{
|
|
|
|
|
2008-02-10 11:18:12 +00:00
|
|
|
return (0);
|
|
|
|
}
|
1998-08-29 21:14:52 +00:00
|
|
|
|
2008-02-10 11:18:12 +00:00
|
|
|
/*
|
|
|
|
* Kernel-internal debugging switches.
|
1998-08-29 21:14:52 +00:00
|
|
|
*/
|
2008-02-10 11:18:12 +00:00
|
|
|
void
|
|
|
|
coda_debugon(void)
|
1998-08-29 21:14:52 +00:00
|
|
|
{
|
2008-02-10 11:18:12 +00:00
|
|
|
|
|
|
|
codadebug = -1;
|
|
|
|
coda_vnop_print_entry = 1;
|
|
|
|
coda_psdev_print_entry = 1;
|
|
|
|
coda_vfsop_print_entry = 1;
|
1998-08-29 21:14:52 +00:00
|
|
|
}
|
|
|
|
|
2008-02-10 11:18:12 +00:00
|
|
|
void
|
|
|
|
coda_debugoff(void)
|
1998-08-29 21:14:52 +00:00
|
|
|
{
|
2008-02-10 11:18:12 +00:00
|
|
|
|
|
|
|
codadebug = 0;
|
|
|
|
coda_vnop_print_entry = 0;
|
|
|
|
coda_psdev_print_entry = 0;
|
|
|
|
coda_vfsop_print_entry = 0;
|
1998-08-29 21:14:52 +00:00
|
|
|
}
|
|
|
|
|
2008-02-10 11:18:12 +00:00
|
|
|
/*-
|
1998-08-29 21:14:52 +00:00
|
|
|
* Utilities used by both client and server
|
|
|
|
* Standard levels:
|
|
|
|
* 0) no debugging
|
|
|
|
* 1) hard failures
|
|
|
|
* 2) soft failures
|
|
|
|
* 3) current test software
|
|
|
|
* 4) main procedure entry points
|
|
|
|
* 5) main procedure exit points
|
|
|
|
* 6) utility procedure entry points
|
|
|
|
* 7) utility procedure exit points
|
|
|
|
* 8) obscure procedure entry points
|
|
|
|
* 9) obscure procedure exit points
|
|
|
|
* 10) random stuff
|
|
|
|
* 11) all <= 1
|
|
|
|
* 12) all <= 2
|
|
|
|
* 13) all <= 3
|
|
|
|
* ...
|
|
|
|
*/
|