cachefs_resource.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/pathname.h>
#include <sys/sysmacros.h>
/* forward references */
/*
* This function moves an RL entry from whereever it currently is to
* the back of the requested list.
*/
void
{
}
void
{
enum cachefs_rl_type otype;
int error;
if (error)
return;
if (type == CACHEFS_RL_PACKED_PENDING) {
/* XXX sam: is this the right place to turn this on? */
}
/* remove entry from its previous list */
if (prev != 0) {
if (error)
return;
}
if (next != 0) {
if (error)
return;
}
lhp->rli_itemcnt--;
/* add entry to its new list */
if (error)
return;
rl_ent->rl_bkwd_idx = 0;
if (error)
return;
} else {
}
lhp->rli_itemcnt++;
}
/*
* This function verifies that an rl entry is of the `correct' type.
* it's used for debugging (only?).
*/
/*ARGSUSED*/
void
{
#ifdef CFSDEBUG
int error;
#ifdef CFSRLDEBUG
debug_enter("cachefs_rlent_verify");
#else /* CFSRLDEBUG */
#endif /* CFSRLDEBUG */
}
#endif /* CFSDEBUG */
}
/*
* Returns the rl data of the front of the specified resource list.
* Returns 0 for success, !0 if the list is empty.
*/
int
{
int error = 0;
enum cachefs_rl_type type;
*entnop = 0;
if (*entnop == 0) {
} else {
if (!error)
}
return (error);
}
/*
* This function plucks a slot from the RL free list and creates an RL entry.
*/
int
{
int error = 0;
if (entno == 0) {
goto out;
}
lhp->rli_itemcnt++;
if (error)
goto out;
rl_ent->rl_fwd_idx = 0;
rl_ent->rl_bkwd_idx = 0;
}
if (error)
goto out;
out:
if (error == 0)
return (error);
}
/*
* Call to change a local fileno in an rl entry to a normal fileno.
*/
void
{
int error;
if (!error) {
}
}
/*
* Moves the files on the modified list for this file system to
* the modified fix list.
*/
void
{
int error;
lhp->rli_blkcnt = 0;
/* walk the modified list */
/* get the next element */
if (error) {
return;
}
/* skip if element is not in this file system */
continue;
/* move from modified list to mf list */
}
}
/*
* Moves the contents of the active list to the rl list.
* Leave modified files on the active list, so they are not
* garbage collected.
*/
void
{
int error;
/*
* if fsck ran, then both of these lists should be empty. the
* only time this isn't the case is when we've done a cachefs
* boot with a clean cache. then, the cache may have been
* clean, but files and attrfiles were left dangling.
*
* when this happens, we just fix the linked lists here. this
* means that the attrcache header and cnode metadata might
* have incorrect information about which resource lists an
* entity is currently on. so, we set CACHE_CHECK_RLTYPE,
* which says cache-wide to double-check and go with whatever
* is in the resource list at the time such an object is
* loaded into memory.
*/
if (lhp->rli_itemcnt > 0) {
}
if (error)
return;
}
#if 0
if (lhp->rli_itemcnt > 0) {
}
if (error)
return;
}
#endif
}
int
{
int error = 0;
int collect = 0;
/* if there are no more available inodes */
collect = 1;
}
/* else if there are more available inodes */
else {
collect = 1;
}
if (collect)
return (error);
}
void
{
}
/*ARGSUSED*/
int
enum cachefs_rl_type type)
{
int error = 0;
int collect = 0;
/* if there are no more available blocks */
collect = 1;
}
/* else if there are more available blocks */
else {
collect = 1;
}
if (collect)
return (error);
}
void
enum cachefs_rl_type type)
{
}
int
{
int error = 0;
struct cachefs_metadata md;
int isattrc;
/* get the file and fsid of the first item on the rl list */
/* XXX call rlent_data() instead */
if (entno == 0) {
goto out;
}
if (error) {
goto out;
}
/* get the file system cache object for this fsid */
if (error) {
"cachefs: cache corruption, run fsck\n");
error = 0;
goto out;
}
}
/* get the file group object for this file */
}
if (isattrc == 0) {
"cachefs: cache corruption, run fsck\n");
}
error = 0;
goto out;
}
/* if we are victimizing an attrcache file */
if (isattrc) {
/* if the filegrp is not writable */
goto out;
}
/* if the filegrp did not go active on us */
} else {
#ifdef CFSDEBUG
printf("c_victim: filegrp went active"
" %p %llu %d %d %lld\n",
(void *) fgp,
#endif
}
error = 0;
goto out;
}
/* grab the cnode list lock */
/* see if a cnode exists for this file */
if (cp) {
/* move file from rl to active list */
error = 0;
goto out;
}
/*
* The cnode does not exist and since we hold the hashlock
* it cannot be created until we are done.
*/
/* see if the item is no longer on the rl list, it could happen */
if (entno == 0) {
goto out;
}
if (error) {
goto out;
}
error = 0;
goto out;
}
/* Get the metadata from the attrcache file */
/* md.md_rltype may be incorrect, but we know file isn't active. */
if (error) {
/* XXX this should never happen, fix on panic */
error = 0;
goto out;
}
/* destroy the frontfile */
/* remove the victim from the gc list */
/* destroy the metadata */
error = 0;
out:
if (fgp) {
}
if (fscp) {
}
return (error);
}
static void
{
int error;
cachep->c_gc_count++;
/*
* since we're here, we're running out of blocks or files.
* file and block lowat are what determine how low we garbage
* collect. in order to do any good, we should drop below
* maxblocks, threshblocks, or the current blocks, whichever
* is smaller (same goes for files). however, we won't go
* below an arbitrary (small) minimum for each.
*/
/* move down for maxfiles and maxblocks */
/* move down for threshfiles and threshblocks */
/* move down for current files and blocks */
/* move up for an arbitrary minimum */
#define MIN_FILELO 1000
if (filelowat < MIN_FILELO)
if (blocklowat < MIN_BLKLO)
/* if the thread is to terminate */
break;
if (error)
break;
}
}
/*
* traverse the packed pending list, repacking files when possible.
*/
static void
{
int error = 0; /* not returned -- used as placeholder */
int count = 0;
if (count-- <= 0) {
#ifdef CFSDEBUG
printf("cachefs_ppending: count exceeded\n");
#endif /* CFSDEBUG */
break;
}
#ifdef CFSDEBUG
printf("cachefs_ppending: early exit\n");
#endif /* CFSDEBUG */
break;
}
#ifdef CFSDEBUG
printf("cachefs_ppending: gone from list\n");
#endif /* CFSDEBUG */
break;
}
/* if the fscp we have does not match */
if (fscp) {
}
/* get the file system cache object for this fsid */
/*
* uh oh, the filesystem probably
* isn't mounted. we `move' this
* entry onto the same list that it's
* on, which really just moves it to
* the back of the list. we need not
* worry about an infinite loop, due
* to the counter.
*/
#ifdef CFSDEBUG
printf("cachefs_ppending: "
"fscp find failed\n");
#endif /* CFSDEBUG */
continue;
}
/* get access to the file system */
if ((error) ||
#ifdef CFSDEBUG
printf("cachefs: "
"ppending: err %d con %d\n",
#endif /* CFSDEBUG */
break;
}
}
/* get the cnode for the file */
if (error) {
#ifdef CFSDEBUG
printf("cachefs: "
"ppending: could not find %llu\n",
#endif /* CFSDEBUG */
break;
}
/* back file went away behind our back */
#ifdef CFSDEBUG
printf("cachefs: ppending: stale\n");
#endif /* CFSDEBUG */
continue;
}
if (error != 0) {
#ifdef CFSDEBUG
printf("cachefs: "
"ppending: pack_common: error = %d\n",
error);
#endif /* CFSDEBUG */
break;
}
}
}
if (lhp->rli_itemcnt == 0)
}
/* seconds; interval to do ppend list */
/* main routine for the cachep worker thread */
void
{
int error;
/* lock the lock file for exclusive write access */
if (error) {
"cachefs: Can't lock Cache Lock File(r); Error %d\n",
error);
}
/* loop while the thread is allowed to run */
/* wait for a wakeup call */
/* if the thread is to terminate */
break;
/* thread is running during nofill, but just to hold lock */
continue;
/* if garbage collection is to run */
/*
* Prevent garbage collection from running more
* than once every 30 seconds. This addresses
* those cases which do not allow removing
* an item from the rl by keeping gc from
* being a spin loop.
*/
}
}
/* unlock the lock file */
if (error) {
}
thread_exit();
/*NOTREACHED*/
}
/* queues up a request to run the garbage collection */
void
{
/* quit if there is no garbage collection thread */
return;
}
/* quit if garbage collection is already in progress */
return;
}
/* quit if there is no garbage to collect */
return;
}
/* indicate garbage collecting is in progress */
/* wake up the garbage collection thread */
}
#ifdef CFSRLDEBUG
static int cachefs_rl_debug_maxcount = CACHEFS_RLDB_DEF_MAXCOUNT;
static int cachefs_rl_debug_inuse = 0;
void
cachefs_rl_debug_reclaim(void *cdrarg)
{
extern cachefscache_t *cachefs_cachelist;
int index;
int error;
for (index = 0;
index++) {
if (error)
break;
}
}
}
void
{
int count = 0;
if (cachefs_rl_debug_cache == NULL)
kmem_cache_create("cachefs_rl_debug",
sizeof (rl_debug_t), 0,
} else {
}
if (++count >= cachefs_rl_debug_maxcount) {
} else {
}
}
}
void
{
int i;
printf("cachefs_rldb: rl entry at %lx -- no info!\n",
return;
}
printf("----- cachefs_rldb record start -----\n");
printf("cachefs_rldb: ago = %lds %ldus\n",
switch (rldb->db_current) {
case CACHEFS_RL_NONE:
cname = "CACHEFS_RL_NONE";
break;
case CACHEFS_RL_FREE:
cname = "CACHEFS_RL_FREE";
break;
case CACHEFS_RL_GC:
cname = "CACHEFS_RL_GC";
break;
case CACHEFS_RL_ACTIVE:
cname = "CACHEFS_RL_ACTIVE";
break;
case CACHEFS_RL_ATTRFILE:
cname = "CACHEFS_RL_ATTRFILE";
break;
case CACHEFS_RL_MODIFIED:
cname = "CACHEFS_RL_MODIFIED";
break;
case CACHEFS_RL_PACKED:
cname = "CACHEFS_RL_PACKED";
break;
cname = "CACHEFS_RL_PACKED_PENDING";
break;
case CACHEFS_RL_MF:
cname = "CACHEFS_MF_GC";
break;
}
} else {
printf("cachefs_rldb: undefined state %x\n",
rldb->db_current);
}
printf("cachefs_rldb: stack trace\n");
for (i = 0; i < rldb->db_stackheight; i++) {
char *sym;
printf("cachefs_rldb: %s+%lx\n",
}
printf("----- cachefs_rldb record end -----\n");
}
}
void
{
return;
}
}
}
#endif /* CFSRLDEBUG */
int
{
int error = 0;
#if 0
#endif
if (error)
return (error);
}
else
if (error) {
return (error);
}
}
#ifdef CFSRLDEBUG
#endif /* CFSRLDEBUG */
return (error);
}
static time_t
{
char namebuf[CFS_FRONTFILE_NAME_SIZE];
int error;
int reledir = 0;
int gotfile = 0;
if (entno == 0) {
goto out;
}
if (error) {
goto out;
}
goto out;
}
} else {
reledir++;
} else {
goto out;
}
}
gotfile = 1;
}
if (reledir)
if (gotfile) {
}
out:
return (rc);
}