Add dircachesize option for afpd.conf.
Add dircache dumping with a -SIGHUP handler.
/*
- * $Id: afp_dsi.c,v 1.49.2.1 2010-02-01 10:56:08 franklahm Exp $
+ * $Id: afp_dsi.c,v 1.49.2.2 2010-02-04 14:34:31 franklahm Exp $
*
* Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
* Copyright (c) 1990,1993 Regents of The University of Michigan.
}
#endif /* DEBUGGING */
- if (dircache_init(0) != 0)
+ if (dircache_init(obj->options.dircachesize) != 0)
afp_dsi_die(EXITERR_SYS);
/* get stuck here until the end */
if (reload_request) {
reload_request = 0;
load_volumes(child.obj);
+ dircache_dump();
}
if (cmd == DSIFUNC_TICKLE) {
/*
- * $Id: afp_options.c,v 1.51 2009-11-24 21:01:45 didg Exp $
+ * $Id: afp_options.c,v 1.51.4.1 2010-02-04 14:34:31 franklahm Exp $
*
* Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
* Copyright (c) 1990,1993 Regents of The University of Michigan.
/* don't advertize slp by default */
options->flags |= OPTION_NOSLP;
#endif
+ options->dircachesize = 8192;
}
/* parse an afpd.conf line. i'm doing it this way because it's
if ((c = getoption(buf, "-ntseparator")) && (opt = strdup(c)))
options->ntseparator = opt;
+
+ if ((c = getoption(buf, "-dircachesize")))
+ options->dircachesize = atoi(c);
return 1;
}
*/
int unlen = strlen(path.u_name);
if (cached)
- path.d_dir = dircache_search_by_name(vol, dstack[cidx].dir->d_did, path.u_name, unlen);
+ path.d_dir = dircache_search_by_name(vol, dstack[cidx].dir, path.u_name, unlen);
else
path.d_dir = NULL;
if (!path.d_dir) {
/*
- $Id: dircache.c,v 1.1.2.2 2010-02-02 14:39:48 franklahm Exp $
+ $Id: dircache.c,v 1.1.2.3 2010-02-04 14:34:31 franklahm Exp $
Copyright (c) 2010 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify
int i = dircache_free_quantum;
struct dir *dir;
+ LOG(log_debug, logtype_afpd, "dircache: {starting cache eviction}");
+
while (i--) {
if ((dir = (struct dir *)dequeue(index_queue)) == NULL) { /* 1 */
dircache_dump();
assert(queue_count == dircache->hash_nodecount);
assert(queue_count + dircache_free_quantum <= dircache_maxsize);
+
+ LOG(log_debug, logtype_afpd, "dircache: {finished cache eviction}");
}
* @brief Search the cache via did/name hashtable
*
* @param vol (r) volume
- * @param did (r) directory CNID
+ * @param dir (r) directory
* @param name (r) name (server side encoding)
* @parma len (r) strlen of name
*
* @returns pointer to struct dir if found in cache, else NULL
*/
-struct dir *dircache_search_by_name(const struct vol *vol, cnid_t did, char *name, int len)
+struct dir *dircache_search_by_name(const struct vol *vol, const struct dir *dir, char *name, int len)
{
struct dir *cdir = NULL;
struct dir key;
hnode_t *hn;
static_bstring uname = {-1, len, (unsigned char *)name};
- assert(vol != NULL && name != NULL && len && len < 256);
+ assert(vol);
+ assert(dir);
+ assert(name);
+ assert(len == strlen(name));
+ assert(len < 256);
- if ((did && did != DIRDID_ROOT_PARENT)) {
+ if (dir->d_did != DIRDID_ROOT_PARENT) {
key.d_vid = vol->v_vid;
- key.d_pdid = did;
+ key.d_pdid = dir->d_did;
key.d_u_name = &uname;
if ((hn = hash_lookup(index_didname, &key)))
}
if (cdir)
- LOG(log_debug, logtype_afpd, "dircache(did:%u,'%s'): {cached: path:'%s'}", ntohl(did), name, cfrombstring(cdir->d_fullpath));
+ LOG(log_debug, logtype_afpd, "dircache(pdid:%u, did:%u, '%s'): {found in cache}",
+ ntohl(dir->d_did), ntohl(cdir->d_did), cfrombstring(cdir->d_fullpath));
else
- LOG(log_debug, logtype_afpd, "dircache(did:%u,'%s'): {not in cache}", ntohl(did), name);
+ LOG(log_debug, logtype_afpd, "dircache(pdid:%u,'%s/%s'): {not in cache}",
+ ntohl(dir->d_did), cfrombstring(dir->d_fullpath), name);
return cdir;
}
*/
int dircache_add(struct dir *dir)
{
- assert(dir != NULL
- && ntohl(dir->d_pdid) >= 2
- && ntohl(dir->d_did) >= CNID_START
- && dir->d_fullpath != NULL
- && dir->d_u_name != NULL
- && dir->d_vid != 0
- && dircache->hash_nodecount <= dircache_maxsize);
+ assert(dir);
+ assert(ntohl(dir->d_pdid) >= 2);
+ assert(ntohl(dir->d_did) >= CNID_START);
+ assert(dir->d_fullpath);
+ assert(dir->d_u_name);
+ assert(dir->d_vid);
+ assert(dircache->hash_nodecount <= dircache_maxsize);
/* Check if cache is full */
if (dircache->hash_nodecount == dircache_maxsize)
queue_count++;
}
+ LOG(log_debug, logtype_afpd, "dircache(did:%u,'%s'): {added}", ntohl(dir->d_did), cfrombstring(dir->d_fullpath));
+
assert(queue_count == index_didname->hash_nodecount
&& queue_count == dircache->hash_nodecount);
hash_delete(dircache, hn);
}
+ LOG(log_debug, logtype_afpd, "dircache(did:%u,'%s'): {removed}", ntohl(dir->d_did), cfrombstring(dir->d_fullpath));
+
assert(queue_count == index_didname->hash_nodecount
&& queue_count == dircache->hash_nodecount);
}
*/
void dircache_dump(void)
{
- LOG(log_error, logtype_afpd, "Fatal directory cache corruption. Dumping...\n");
+ char tmpnam[64];
+ FILE *dump;
+ qnode_t *n = index_queue->next;
+ const struct dir *dir;
+
+ LOG(log_warning, logtype_afpd, "Dumping directory cache...");
+
+ sprintf(tmpnam, "/tmp/dircache.%u", getpid());
+ if ((dump = fopen(tmpnam, "w+")) == NULL) {
+ LOG(log_error, logtype_afpd, "dircache_dump: %s", strerror(errno));
+ return;
+ }
+ setbuf(dump, NULL);
+
+ fprintf(dump, "Number of cache entries: %u\n", queue_count);
+ fprintf(dump, "Configured maximum cache size: %u\n", dircache_maxsize);
+ fprintf(dump, "==================================================\n\n");
+
+ for (int i = 1; i <= queue_count; i++) {
+ if (n == index_queue)
+ break;
+ dir = (struct dir *)n->data;
+ fprintf(dump, "%05u: vid:%u, pdid:%u, did:%u, path:%s\n",
+ i, ntohs(dir->d_vid), ntohl(dir->d_pdid), ntohl(dir->d_did), cfrombstring(dir->d_fullpath));
+ n = n->next;
+ }
+ fprintf(dump, "\n");
return;
}
/*
- $Id: dircache.h,v 1.1.2.1 2010-02-01 10:56:08 franklahm Exp $
+ $Id: dircache.h,v 1.1.2.2 2010-02-04 14:34:31 franklahm Exp $
Copyright (c) 2010 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify
extern int dircache_add(struct dir *);
extern void dircache_remove(const struct vol *, struct dir *, int flag);
extern struct dir *dircache_search_by_did(const struct vol *vol, cnid_t did);
-extern struct dir *dircache_search_by_name(const struct vol *, cnid_t did, char *name, int len);
+extern struct dir *dircache_search_by_name(const struct vol *, const struct dir *dir, char *name, int len);
extern void dircache_dump(void);
#endif /* DIRCACHE_H */
/*
- * $Id: directory.c,v 1.131.2.8 2010-02-02 14:39:48 franklahm Exp $
+ * $Id: directory.c,v 1.131.2.9 2010-02-04 14:34:31 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
/*
* FIXMEs, loose ends after the dircache rewrite:
- * o case-insensitivity is gone
+ * o dircache aging, place dirlookup'ed dirs on front of queue ??
+ * o merge dircache_search_by_name and dir_add ??
+ * o case-insensitivity is gone from cname
* o catsearch doesn't work, see FIXMEs in catsearch.c
* o curdir per volume caching is gone
* o directory offspring count calculation probably broken
- * o doesn't work with CNID backend last and the like.
+ * o doesn't work with CNID backend last and the like,
* CNID backend must support persistent CNIDs.
*/
assert(path);
assert(len > 0);
- if ((cdir = dircache_search_by_name(vol, dir->d_did, path->u_name, strlen(path->u_name))) != NULL) {
+ if ((cdir = dircache_search_by_name(vol, dir, path->u_name, strlen(path->u_name))) != NULL) {
/* there's a stray entry in the dircache */
LOG(log_debug, logtype_afpd, "dir_add(did:%u,'%s/%s'): {stray cache entry: did:%u,'%s', removing}",
ntohl(dir->d_did), cfrombstring(dir->d_fullpath), path->u_name,
int size = 0;
int toUTF8 = 0;
- LOG(log_debug, logtype_afpd, "came('%s'): {start}", cfrombstring(dir->d_fullpath));
+ LOG(log_maxdebug, logtype_afpd, "came('%s'): {start}", cfrombstring(dir->d_fullpath));
data = *cpath;
afp_errno = AFPERR_NOOBJ;
/* Search the cache */
int unamelen = strlen(ret.u_name);
- cdir = dircache_search_by_name(vol, dir->d_did, ret.u_name, unamelen);
+ cdir = dircache_search_by_name(vol, dir, ret.u_name, unamelen);
if (cdir == NULL) {
/* Not in cache, create one */
if ((cdir = dir_add(vol, dir, &ret, unamelen)) == NULL) {
case DIRPBIT_PDID :
memcpy( data, &pdid, sizeof( pdid ));
data += sizeof( pdid );
+ LOG(log_debug, logtype_afpd, "metadata('%s'): Parent DID: %u",
+ s_path->u_name, ntohl(pdid));
break;
case DIRPBIT_CDATE :
case DIRPBIT_DID :
memcpy( data, &dir->d_did, sizeof( aint ));
data += sizeof( aint );
+ LOG(log_debug, logtype_afpd, "metadata('%s'): DID: %u",
+ s_path->u_name, ntohl(dir->d_did));
break;
case DIRPBIT_OFFCNT :
/*
- * $Id: enumerate.c,v 1.48.2.1 2010-02-01 10:56:08 franklahm Exp $
+ * $Id: enumerate.c,v 1.48.2.2 2010-02-04 14:34:31 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
continue;
}
int len = strlen(s_path.u_name);
- if ((dir = dircache_search_by_name(vol, curdir->d_did, s_path.u_name, len)) == NULL) {
+ if ((dir = dircache_search_by_name(vol, curdir, s_path.u_name, len)) == NULL) {
if ((dir = dir_add(vol, curdir, &s_path, len)) == NULL) {
LOG(log_error, logtype_afpd, "enumerate(vid:%u, did:%u, name:'%s'): error adding dir: '%s'",
ntohs(vid), ntohl(did), o_path->u_name, s_path.u_name);
/*
- * $Id: file.c,v 1.131.2.2 2010-02-02 13:15:30 franklahm Exp $
+ * $Id: file.c,v 1.131.2.3 2010-02-04 14:34:31 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
struct stat *st;
struct maccess ma;
-#ifdef DEBUG
- LOG(log_debug9, logtype_afpd, "begin getmetadata:");
-#endif /* DEBUG */
upath = path->u_name;
st = &path->st;
#endif
memcpy(data, &ashort, sizeof( ashort ));
data += sizeof( ashort );
+ LOG(log_debug, logtype_afpd, "metadata('%s'): AFP Attributes: %04x",
+ path->u_name, ntohs(ashort));
break;
case FILPBIT_PDID :
memcpy(data, &dir->d_did, sizeof( u_int32_t ));
data += sizeof( u_int32_t );
+ LOG(log_debug, logtype_afpd, "metadata('%s'): Parent DID: %u",
+ path->u_name, ntohl(dir->d_did));
break;
case FILPBIT_CDATE :
case FILPBIT_FNUM :
memcpy(data, &id, sizeof( id ));
data += sizeof( id );
+ LOG(log_debug, logtype_afpd, "metadata('%s'): CNID: %u",
+ path->u_name, ntohl(id));
break;
case FILPBIT_DFLEN :
int opened = 0;
int rc;
-#ifdef DEBUG
- LOG(log_debug9, logtype_default, "begin getfilparams:");
-#endif /* DEBUG */
-
opened = PARAM_NEED_ADP(bitmap);
adp = NULL;
if ( adp ) {
ad_close_metadata( adp);
}
-#ifdef DEBUG
- LOG(log_debug9, logtype_afpd, "end getfilparams:");
-#endif /* DEBUG */
return( rc );
}
/*
- * $Id: filedir.c,v 1.69.2.2 2010-02-01 16:13:52 franklahm Exp $
+ * $Id: filedir.c,v 1.69.2.3 2010-02-04 14:34:31 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
st = &s_path->st;
if (!s_path->st_valid) {
- LOG(log_debug, logtype_afpd, "getfildirparams: !s_path->st_valid");
/* it's a dir and it should be there
* because we chdir in it in cname or
* it's curdir (maybe deleted, but then we can't know).
}
if ( s_path->st_errno != 0 ) {
if (afp_errno != AFPERR_ACCESS) {
- LOG(log_debug, logtype_afpd, "getfildirparams: s_path->st_errno != 0");
return( AFPERR_NOOBJ );
}
}
/*
- * $Id: globals.h,v 1.31.2.1 2010-02-01 10:56:08 franklahm Exp $
+ * $Id: globals.h,v 1.31.2.2 2010-02-04 14:34:31 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
};
struct afp_options {
- int connections, transports, tickleval, timeout, server_notif, flags;
+ int connections, transports, tickleval, timeout, server_notif, flags, dircachesize;
unsigned char passwdbits, passwdminlen, loginmaxfail;
u_int32_t server_quantum;
char hostname[MAXHOSTNAMELEN + 1], *server, *ipaddr, *port, *configfile;
/*
- * $Id: ofork.c,v 1.30.4.1 2010-02-01 10:56:08 franklahm Exp $
+ * $Id: ofork.c,v 1.30.4.2 2010-02-04 14:34:31 franklahm Exp $
*
* Copyright (c) 1996 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
{
int ret;
- LOG(log_maxdebug, logtype_afpd, "of_stat: {stat:'%s/%s'}", getcwdpath(), path->u_name);
-
path->st_errno = 0;
path->st_valid = 1;
- if ((ret = stat(path->u_name, &path->st)) < 0)
+ if ((ret = stat(path->u_name, &path->st)) < 0) {
+ LOG(log_debug, logtype_afpd, "of_stat: {'%s/%s': %s}",
+ getcwdpath(), path->u_name, strerror(errno));
path->st_errno = errno;
+ }
return ret;
}
/*
- * $Id: cnid_dbd.c,v 1.16 2010-01-21 14:14:49 didg Exp $
+ * $Id: cnid_dbd.c,v 1.16.2.1 2010-02-04 14:34:31 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* All Rights Reserved. See COPYING.
ssize_t len;
size_t len1;
- LOG(log_maxdebug, logtype_cnid, "write_vec: request to write %d bytes", towrite);
-
len1 = iov[1].iov_len;
while (towrite > 0) {
if (((len = writev(fd, iov, 2)) == -1 && errno == EINTR) || !len)
int len;
struct iovec iov[2];
- LOG(log_debug, logtype_cnid, "init_tsock: BEGIN. Opening volume '%s', CNID Server: %s/%s", db->db_dir, Cnid_srv, Cnid_port);
-
if ((fd = tsock_getfd(Cnid_srv, Cnid_port)) < 0)
return -1;
return -1;
}
- LOG(log_debug, logtype_cnid, "init_tsock: ok");
+ LOG(log_maxdebug, logtype_cnid, "init_tsock: BEGIN. Opening volume '%s', CNID Server: %s/%s",
+ db->db_dir, Cnid_srv, Cnid_port);
return fd;
}
struct iovec iov[2];
size_t towrite;
- LOG(log_maxdebug, logtype_cnid, "send_packet: BEGIN");
-
if (!rqst->namelen) {
if (write(db->fd, rqst, sizeof(struct cnid_dbd_rqst)) != sizeof(struct cnid_dbd_rqst)) {
LOG(log_warning, logtype_cnid, "send_packet: Error/short write rqst (db_dir %s): %s",
return -1;
}
- LOG(log_maxdebug, logtype_cnid, "send_packet: OK");
+ LOG(log_maxdebug, logtype_cnid, "send_packet: {done}");
return 0;
}
char *nametmp;
size_t len;
- LOG(log_maxdebug, logtype_cnid, "dbd_rpc: BEGIN");
-
if (send_packet(db, rqst) < 0) {
return -1;
}
return -1;
}
- LOG(log_maxdebug, logtype_cnid, "dbd_rpc: END");
+ LOG(log_maxdebug, logtype_cnid, "dbd_rpc: {done}");
return 0;
}
time_t orig, t;
int clean = 1; /* no errors so far - to prevent sleep on first try */
- LOG(log_debug7, logtype_cnid, "transmit: BEGIN");
-
if (db->changed) {
/* volume and db don't have the same timestamp
*/
struct cnid_dbd_rply rply_stamp;
char stamp[ADEDLEN_PRIVSYN];
- LOG(log_debug, logtype_cnid, "transmit: connecting to cnid_dbd ...");
+ LOG(log_maxdebug, logtype_cnid, "transmit: connecting to cnid_dbd ...");
if ((db->fd = init_tsock(db)) < 0) {
goto transmit_fail;
}
memcpy(db->client_stamp, stamp, ADEDLEN_PRIVSYN);
memcpy(db->stamp, stamp, ADEDLEN_PRIVSYN);
}
- LOG(log_debug, logtype_cnid, "transmit: succesfully attached to cnid_dbd for volume '%s' with stamp '%08lx'.",
+ LOG(log_debug, logtype_cnid, "transmit: attached to '%s', stamp: '%08lx'.",
db->db_dir, *(uint64_t *)stamp);
}
if (!dbd_rpc(db, rqst, rply)) {
- LOG(log_debug7, logtype_cnid, "transmit: END OK");
+ LOG(log_maxdebug, logtype_cnid, "transmit: {done}");
return 0;
}
transmit_fail: