From 4aa533548cd9b128da0b844e907033ebf1d2c05a Mon Sep 17 00:00:00 2001 From: jmarcus Date: Sat, 9 Feb 2002 20:29:02 +0000 Subject: [PATCH] Merge latest CNID DB code from HEAD. --- etc/afpd/enumerate.c | 14 ++- etc/afpd/file.c | 17 +++- etc/afpd/fork.c | 14 ++- include/atalk/cnid.h | 7 ++ libatalk/cnid/cnid_add.c | 172 ++++++++++++++--------------------- libatalk/cnid/cnid_close.c | 40 ++++---- libatalk/cnid/cnid_delete.c | 20 ++-- libatalk/cnid/cnid_get.c | 6 +- libatalk/cnid/cnid_lookup.c | 10 +- libatalk/cnid/cnid_nextid.c | 2 +- libatalk/cnid/cnid_open.c | 137 +++++++++------------------- libatalk/cnid/cnid_private.h | 6 +- libatalk/cnid/cnid_resolve.c | 6 +- libatalk/cnid/cnid_update.c | 7 +- macros/db3-check.m4 | 4 +- 15 files changed, 205 insertions(+), 257 deletions(-) diff --git a/etc/afpd/enumerate.c b/etc/afpd/enumerate.c index 90de28f5..1888d369 100644 --- a/etc/afpd/enumerate.c +++ b/etc/afpd/enumerate.c @@ -1,5 +1,5 @@ /* - * $Id: enumerate.c,v 1.9.2.3 2002-02-07 23:56:04 srittau Exp $ + * $Id: enumerate.c,v 1.9.2.4 2002-02-09 20:29:02 jmarcus Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -81,6 +81,18 @@ struct stat *st; /* add to cnid db */ cdir->d_did = cnid_add(vol->v_db, st, dir->d_did, upath, upathlen, cdir->d_did); + /* Fail out if things go bad with CNID. */ + if (cdir->d_did == CNID_INVALID) { + switch (errno) { + case CNID_ERR_PARAM: + syslog(LOG_ERR, "adddir: Incorrect parameters passed to cnid_add"); + return NULL; + case CNID_ERR_PATH: + case CNID_ERR_DB: + case CNID_ERR_MAX: + return NULL; + } + } #endif /* CNID_DB */ if (cdir->d_did == 0) { diff --git a/etc/afpd/file.c b/etc/afpd/file.c index a7b2933b..cfa3545e 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -1,5 +1,5 @@ /* - * $Id: file.c,v 1.29.2.4 2002-02-07 23:56:33 srittau Exp $ + * $Id: file.c,v 1.29.2.5 2002-02-09 20:29:02 jmarcus Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -224,6 +224,19 @@ int getfilparams(struct vol *vol, #ifdef CNID_DB aint = cnid_add(vol->v_db, st, dir->d_did, upath, strlen(upath), aint); + /* Throw errors if cnid_add fails. */ + if (aint == CNID_INVALID) { + switch (errno) { + case CNID_ERR_PARAM: + syslog(LOG_ERR, "getfilparams: Incorrect parameters passed to cnid_add"); + return(AFPERR_PARAM); + case CNID_ERR_PATH: + return(AFPERR_PARAM); + case CNID_ERR_DB: + case CNID_ERR_MAX: + return(AFPERR_MISC); + } + } #endif /* CNID_DB */ if (aint == 0) { @@ -1354,7 +1367,7 @@ int ibuflen, *rbuflen; } #endif /* AD_VERSION > AD_VERSION1 */ - if (id = cnid_add(vol->v_db, &st, did, upath, len, id)) { + if (id = cnid_add(vol->v_db, &st, did, upath, len, id) != CNID_INVALID) { memcpy(rbuf, &id, sizeof(id)); *rbuflen = sizeof(id); return AFP_OK; diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c index c18c0063..e4881d43 100644 --- a/etc/afpd/fork.c +++ b/etc/afpd/fork.c @@ -1,5 +1,5 @@ /* - * $Id: fork.c,v 1.11.2.3 2002-02-07 23:56:58 srittau Exp $ + * $Id: fork.c,v 1.11.2.4 2002-02-09 20:29:02 jmarcus Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -191,6 +191,18 @@ const u_int16_t attrbits; aint = cnid_add(ofork->of_vol->v_db, &st, ofork->of_dir->d_did, upath, strlen(upath), aint); + if (aint == CNID_INVALID) { + switch (errno) { + case CNID_ERR_PARAM: + syslog(LOG_ERR, "getforkparams: Incorrect parameters passed to cnid_add"); + return(AFPERR_PARAM); + case CNID_ERR_PATH: + return(AFPERR_PARAM); + case CNID_ERR_DB: + case CNID_ERR_MAX: + return(AFPERR_MISC); + } + } #endif /* CNID_DB */ if (aint == 0) { diff --git a/include/atalk/cnid.h b/include/atalk/cnid.h index 19c84171..43ac5006 100644 --- a/include/atalk/cnid.h +++ b/include/atalk/cnid.h @@ -13,6 +13,13 @@ #include +#define CNID_INVALID 0 + +#define CNID_ERR_PARAM 0x80000001 +#define CNID_ERR_PATH 0x80000002 +#define CNID_ERR_DB 0x80000003 +#define CNID_ERR_MAX 0x80000004 + typedef u_int32_t cnid_t; /* cnid_open.c */ diff --git a/libatalk/cnid/cnid_add.c b/libatalk/cnid/cnid_add.c index 6591088a..e6a72554 100644 --- a/libatalk/cnid/cnid_add.c +++ b/libatalk/cnid/cnid_add.c @@ -1,5 +1,5 @@ /* - * $Id: cnid_add.c,v 1.14.2.3 2001-12-15 06:35:28 jmarcus Exp $ + * $Id: cnid_add.c,v 1.14.2.4 2002-02-09 20:29:02 jmarcus Exp $ * * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu) * All Rights Reserved. See COPYRIGHT. @@ -39,45 +39,32 @@ #include "cnid_private.h" -#define MAX_ABORTS 255 - /* add an entry to the CNID databases. we do this as a transaction * to prevent messiness. */ -static int add_cnid(CNID_private *db, DB_TXN *ptid, DBT *key, DBT *data) { +static int add_cnid(CNID_private *db, DBT *key, DBT *data) { DBT altkey, altdata; DB_TXN *tid; - /* We create rc here because using errno is bad. Why? Well, if you - * use errno once, then call another function which resets it, you're - * screwed. */ - int rc, ret, aborts = 0; + int rc, ret; memset(&altkey, 0, sizeof(altkey)); memset(&altdata, 0, sizeof(altdata)); - if (0) { retry: - if ((rc = txn_abort(tid)) != 0) { - return rc; - } - if (++aborts > MAX_ABORTS) { - return DB_LOCK_DEADLOCK; - } - } - - if ((rc = txn_begin(db->dbenv, ptid, &tid, 0)) != 0) { + if ((rc = txn_begin(db->dbenv, NULL, &tid, 0)) != 0) { return rc; } /* main database */ if ((rc = db->db_cnid->put(db->db_cnid, tid, key, data, DB_NOOVERWRITE))) { if (rc == DB_LOCK_DEADLOCK) { + if ((ret = txn_abort(tid)) != 0) { + return ret; + } goto retry; } - goto abort; } - /* dev/ino database */ altkey.data = data->data; altkey.size = CNID_DEVINO_LEN; @@ -85,29 +72,32 @@ retry: altdata.size = key->size; if ((rc = db->db_devino->put(db->db_devino, tid, &altkey, &altdata, 0))) { if (rc == DB_LOCK_DEADLOCK) { + if ((ret = txn_abort(tid)) != 0) { + return ret; + } goto retry; } - goto abort; } - /* did/name database */ altkey.data = (char *) data->data + CNID_DEVINO_LEN; altkey.size = data->size - CNID_DEVINO_LEN; if ((rc = db->db_didname->put(db->db_didname, tid, &altkey, &altdata, 0))) { if (rc == DB_LOCK_DEADLOCK) { + if ((ret = txn_abort(tid)) != 0) { + return ret; + } goto retry; } - goto abort; } if ((rc = txn_commit(tid, 0)) != 0) { - syslog(LOG_ERR, "add_cnid: Failed to commit transaction: %s", - db_strerror(rc)); + syslog(LOG_ERR, "add_cnid: Failed to commit transaction: %s", db_strerror(rc)); return rc; } + return 0; abort: @@ -115,7 +105,6 @@ abort: return ret; } return rc; - } cnid_t cnid_add(void *CNID, const struct stat *st, @@ -130,7 +119,8 @@ cnid_t cnid_add(void *CNID, const struct stat *st, int rc; if (!(db = CNID) || !st || !name) { - return 0; + errno = CNID_ERR_PARAM; + return CNID_INVALID; } /* Do a lookup. */ @@ -138,8 +128,7 @@ cnid_t cnid_add(void *CNID, const struct stat *st, /* ... Return id if it is valid, or if Rootinfo is read-only. */ if (id || (db->flags & CNIDFLAG_DB_RO)) { #ifdef DEBUG - syslog(LOG_INFO, "cnid_add: Looked up did %u, name %s as %u", - ntohl(did), name, ntohl(id)); + syslog(LOG_INFO, "cnid_add: Looked up did %u, name %s as %u", ntohl(did), name, ntohl(id)); #endif return id; } @@ -154,7 +143,8 @@ cnid_t cnid_add(void *CNID, const struct stat *st, if ((data.data = make_cnid_data(st, did, name, len)) == NULL) { syslog(LOG_ERR, "cnid_add: Path name is too long"); - goto cleanup_err; + errno = CNID_ERR_PATH; + return CNID_INVALID; } data.size = CNID_HEADER_LEN + len + 1; @@ -164,44 +154,56 @@ cnid_t cnid_add(void *CNID, const struct stat *st, * cnid's to the database. */ if (ntohl(hint) >= CNID_START) { /* If the key doesn't exist, add it in. Don't fiddle with nextID. */ - rc = add_cnid(db, NULL, &key, &data); + rc = add_cnid(db, &key, &data); switch (rc) { case DB_KEYEXIST: /* Need to use RootInfo after all. */ break; default: - syslog(LOG_ERR, "cnid_add: Unable to add CNID %u: %s", - ntohl(hint), db_strerror(rc)); - goto cleanup_err; + syslog(LOG_ERR, "cnid_add: Unable to add CNID %u: %s", ntohl(hint), db_strerror(rc)); + errno = CNID_ERR_DB; + return CNID_INVALID; case 0: #ifdef DEBUG - syslog(LOG_INFO, "cnid_add: Used hint for did %u, name %s as %u", - ntohl(did), name, ntohl(hint)); + syslog(LOG_INFO, "cnid_add: Used hint for did %u, name %s as %u", ntohl(did), name, ntohl(hint)); #endif return hint; } } - /* We need to create a random sleep interval to prevent deadlocks. */ - (void)srand(getpid() ^ time(NULL)); - t.tv_sec = 0; - memset(&rootinfo_key, 0, sizeof(rootinfo_key)); memset(&rootinfo_data, 0, sizeof(rootinfo_data)); rootinfo_key.data = ROOTINFO_KEY; rootinfo_key.size = ROOTINFO_KEYLEN; +retry: + if ((rc = txn_begin(db->dbenv, NULL, &tid, 0)) != 0) { + syslog(LOG_ERR, "cnid_add: Failed to begin transaction: %s", db_strerror(rc)); + errno = CNID_ERR_DB; + return CNID_INVALID; + } + /* Get the key. */ -retry_get: - switch (rc = db->db_didname->get(db->db_didname, NULL, &rootinfo_key, - &rootinfo_data, 0)) { + switch (rc = db->db_didname->get(db->db_didname, tid, &rootinfo_key, + &rootinfo_data, DB_RMW)) { case DB_LOCK_DEADLOCK: if ((rc = txn_abort(tid)) != 0) { syslog(LOG_ERR, "cnid_add: txn_abort: %s", db_strerror(rc)); - goto cleanup_err; + errno = CNID_ERR_DB; + return CNID_INVALID; } - goto retry_get; + goto retry; case 0: memcpy(&hint, rootinfo_data.data, sizeof(hint)); + id = ntohl(hint); + /* If we've hit the max CNID allowed, we return a fatal error. CNID + * needs to be recycled before proceding. */ + if (++id == CNID_INVALID) { + txn_abort(tid); + syslog(LOG_ERR, "cnid_add: FATAL: Cannot add CNID for %s. CNID database has reached its limit.", name); + errno = CNID_ERR_MAX; + return CNID_INVALID; + } + hint = htonl(id); #ifdef DEBUG syslog(LOG_INFO, "cnid_add: Found rootinfo for did %u, name %s as %u", ntohl(did), name, ntohl(hint)); #endif @@ -209,54 +211,12 @@ retry_get: case DB_NOTFOUND: hint = htonl(CNID_START); #ifdef DEBUG - syslog(LOG_INFO, "cnid_add: Using CNID_START for did %u, name %s", - ntohl(did), name); + syslog(LOG_INFO, "cnid_add: Using CNID_START for did %u, name %s", ntohl(did), name); #endif break; default: - syslog(LOG_ERR, "cnid_add: Unable to lookup rootinfo: %s", - db_strerror(rc)); - goto cleanup_err; - } - - - if (0) { -retry: - t.tv_usec = rand() % 1000000; -#ifdef DEBUG - syslog(LOG_INFO, "cnid_add: Hitting MAX_ABORTS, sleeping"); -#endif - (void)select(0, NULL, NULL, NULL, &t); - } - if ((rc = txn_begin(db->dbenv, NULL, &tid, 0)) != 0) { - syslog(LOG_ERR, "cnid_add: Failed to begin transaction: %s", - db_strerror(rc)); - goto cleanup_err; - } - - /* Search for a new id. We keep the first id around to check for - * wrap-around. NOTE: I do it this way so that we can go back and - * fill in holes. */ - save = id = ntohl(hint); - while ((rc = add_cnid(db, tid, &key, &data)) != 0) { - /* Don't use any special CNIDs. */ - if (++id < CNID_START) { - id = CNID_START; - } - if (rc == DB_LOCK_DEADLOCK) { - if ((rc = txn_abort(tid)) != 0) { - syslog(LOG_ERR, "cnid_add: txn_abort: %s", db_strerror(rc)); - goto cleanup_err; - } - goto retry; - } - - if ((rc != DB_KEYEXIST) || (save == id)) { - syslog(LOG_ERR, "cnid_add: Unable to add CNID %u: %s", - ntohl(hint), db_strerror(rc)); - goto cleanup_abort; - } - hint = htonl(id); + syslog(LOG_ERR, "cnid_add: Unable to lookup rootinfo: %s", db_strerror(rc)); + goto cleanup_abort; } rootinfo_data.data = &hint; @@ -266,36 +226,42 @@ retry: case DB_LOCK_DEADLOCK: if ((rc = txn_abort(tid)) != 0) { syslog(LOG_ERR, "cnid_add: txn_abort: %s", db_strerror(rc)); - goto cleanup_err; + errno = CNID_ERR_DB; + return CNID_INVALID; } goto retry; case 0: + /* The transaction finished, commit it. */ + if ((rc = txn_commit(tid, 0)) != 0) { + syslog(LOG_ERR, "cnid_add: Unable to commit transaction: %s", db_strerror(rc)); + errno = CNID_ERR_DB; + return CNID_INVALID; + } break; default: - syslog(LOG_ERR, "cnid_add: Unable to update rootinfo: %s", - db_strerror(rc)); + syslog(LOG_ERR, "cnid_add: Unable to update rootinfo: %s", db_strerror(rc)); goto cleanup_abort; } -cleanup_commit: - /* The transaction finished, commit it. */ - if ((rc = txn_commit(tid, 0)) != 0) { - syslog(LOG_ERR, "cnid_add: Unable to commit transaction: %s", - db_strerror(rc)); - goto cleanup_err; + /* Now we need to add the CNID data to the databases. */ + rc = add_cnid(db, &key, &data); + if (rc) { + syslog(LOG_ERR, "cnid_add: Failed to add CNID for %s to database using hint %u: %s", name, ntohl(hint), db_strerror(rc)); + errno = CNID_ERR_DB; + return CNID_INVALID; } #ifdef DEBUG - syslog(LOG_INFO, "cnid_add: Returned CNID for did %u, name %s as %u", - ntohl(did), name, ntohl(hint)); + syslog(LOG_INFO, "cnid_add: Returned CNID for did %u, name %s as %u", ntohl(did), name, ntohl(hint)); #endif + return hint; cleanup_abort: txn_abort(tid); -cleanup_err: - return 0; + errno = CNID_ERR_DB; + return CNID_INVALID; } #endif /* CNID_DB */ diff --git a/libatalk/cnid/cnid_close.c b/libatalk/cnid/cnid_close.c index ecef6c4e..de35433f 100644 --- a/libatalk/cnid/cnid_close.c +++ b/libatalk/cnid/cnid_close.c @@ -1,5 +1,5 @@ /* - * $Id: cnid_close.c,v 1.12.2.3 2001-12-15 06:35:28 jmarcus Exp $ + * $Id: cnid_close.c,v 1.12.2.4 2002-02-09 20:29:02 jmarcus Exp $ */ #ifdef HAVE_CONFIG_H @@ -42,42 +42,34 @@ void cnid_close(void *CNID) { char **list, **first; int cfd = -1; - if ((cfd = open(db->close_file, O_RDWR | O_CREAT, 0666)) > -1) { - /* Checkpoint the databases until we can checkpoint no - * more. */ + /* Checkpoint the databases until we can checkpoint no + * more. */ + rc = txn_checkpoint(db->dbenv, 0, 0, 0); + while (rc == DB_INCOMPLETE) { rc = txn_checkpoint(db->dbenv, 0, 0, 0); - while (rc == DB_INCOMPLETE) { - rc = txn_checkpoint(db->dbenv, 0, 0, 0); - } + } #if DB_VERSION_MINOR > 2 - if ((rc = log_archive(db->dbenv, &list, DB_ARCH_LOG | DB_ARCH_ABS)) != 0) { + if ((rc = log_archive(db->dbenv, &list, DB_ARCH_ABS)) != 0) { #else /* DB_VERSION_MINOR < 2 */ - if ((rc = log_archive(db->dbenv, &list, DB_ARCH_LOG | DB_ARCH_ABS, NULL)) != 0) { + if ((rc = log_archive(db->dbenv, &list, DB_ARCH_ABS, NULL)) != 0) { #endif /* DB_VERSION_MINOR */ - syslog(LOG_ERR, "cnid_close: Unable to archive logfiles: %s", - db_strerror(rc)); - } + syslog(LOG_ERR, "cnid_close: Unable to archive logfiles: %s", db_strerror(rc)); + } - if (list != NULL) { - for (first = list; *list != NULL; ++list) { - if ((rc = remove(*list)) != 0) { + if (list != NULL) { + for (first = list; *list != NULL; ++list) { + if ((rc = remove(*list)) != 0) { #ifdef DEBUG - syslog(LOG_INFO, "cnid_close: failed to remove %s: %s", - *list, strerror(rc)); + syslog(LOG_INFO, "cnid_close: failed to remove %s: %s", *list, strerror(rc)); #endif - } } - free(first); } - (void)remove(db->close_file); - close(cfd); - } - else { - syslog(LOG_ERR, "cnid_close: Failed to open database closing lock file: %s", strerror(errno)); + free(first); } } + (void)remove(db->lock_file); } db->db_didname->close(db->db_didname, 0); diff --git a/libatalk/cnid/cnid_delete.c b/libatalk/cnid/cnid_delete.c index a151f7b4..acd7b955 100644 --- a/libatalk/cnid/cnid_delete.c +++ b/libatalk/cnid/cnid_delete.c @@ -1,5 +1,5 @@ /* - * $Id: cnid_delete.c,v 1.9.2.3 2001-12-15 06:35:28 jmarcus Exp $ + * $Id: cnid_delete.c,v 1.9.2.4 2002-02-09 20:29:02 jmarcus Exp $ * * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu) * All Rights Reserved. See COPYRIGHT. @@ -51,12 +51,12 @@ int cnid_delete(void *CNID, const cnid_t id) { case DB_NOTFOUND: #ifdef DEBUG syslog(LOG_INFO, "cnid_delete: CNID %u not in database", - ntohl(id)); + ntohl(id)); #endif return 0; default: syslog(LOG_ERR, "cnid_delete: Unable to delete entry: %s", - db_strerror(rc)); + db_strerror(rc)); return rc; } } @@ -64,7 +64,7 @@ int cnid_delete(void *CNID, const cnid_t id) { retry: if ((rc = txn_begin(db->dbenv, NULL, &tid, 0)) != 0) { syslog(LOG_ERR, "cnid_delete: Failed to begin transaction: %s", - db_strerror(rc)); + db_strerror(rc)); return rc; } @@ -93,7 +93,7 @@ retry: case DB_LOCK_DEADLOCK: if ((rc = txn_abort(tid)) != 0) { syslog(LOG_ERR, "cnid_delete: txn_abort: %s", - db_strerror(rc)); + db_strerror(rc)); return rc; } goto retry; @@ -103,7 +103,7 @@ retry: default: if ((rc = txn_abort(tid)) != 0) { syslog(LOG_ERR, "cnid_delete: txn_abort: %s", - db_strerror(rc)); + db_strerror(rc)); return rc; } goto abort_err; @@ -119,7 +119,7 @@ retry: case DB_LOCK_DEADLOCK: if ((rc = txn_abort(tid)) != 0) { syslog(LOG_ERR, "cnid_delete: txn_abort: %s", - db_strerror(rc)); + db_strerror(rc)); return rc; } goto retry; @@ -128,7 +128,7 @@ retry: default: if ((rc = txn_abort(tid)) != 0) { syslog(LOG_ERR, "cnid_delete: txn_abort: %s", - db_strerror(rc)); + db_strerror(rc)); return rc; } goto abort_err; @@ -140,14 +140,14 @@ retry: #endif if ((rc = txn_commit(tid, 0)) != 0) { syslog(LOG_ERR, "cnid_delete: Failed to commit transaction: %s", - db_strerror(rc)); + db_strerror(rc)); return rc; } return 0; abort_err: syslog(LOG_ERR, "cnid_delete: Unable to delete CNID %u: %s", - ntohl(id), db_strerror(rc)); + ntohl(id), db_strerror(rc)); return rc; } #endif /*CNID_DB */ diff --git a/libatalk/cnid/cnid_get.c b/libatalk/cnid/cnid_get.c index 53ca2212..3ff1423b 100644 --- a/libatalk/cnid/cnid_get.c +++ b/libatalk/cnid/cnid_get.c @@ -1,5 +1,5 @@ /* - * $Id: cnid_get.c,v 1.9.2.3 2001-12-15 06:35:28 jmarcus Exp $ + * $Id: cnid_get.c,v 1.9.2.4 2002-02-09 20:29:02 jmarcus Exp $ */ #ifdef HAVE_CONFIG_H @@ -53,7 +53,7 @@ cnid_t cnid_get(void *CNID, const cnid_t did, const char *name, if (rc != DB_NOTFOUND) { syslog(LOG_ERR, "cnid_get: Unable to get CNID %u, name %s: %s", - ntohl(did), name, db_strerror(rc)); + ntohl(did), name, db_strerror(rc)); } return 0; @@ -62,7 +62,7 @@ cnid_t cnid_get(void *CNID, const cnid_t did, const char *name, memcpy(&id, data.data, sizeof(id)); #ifdef DEBUG syslog(LOG_INFO, "cnid_get: Returning CNID for %u, name %s as %u", - ntohl(did), name, ntohl(id)); + ntohl(did), name, ntohl(id)); #endif return id; } diff --git a/libatalk/cnid/cnid_lookup.c b/libatalk/cnid/cnid_lookup.c index 01acaff3..039bcc77 100644 --- a/libatalk/cnid/cnid_lookup.c +++ b/libatalk/cnid/cnid_lookup.c @@ -1,5 +1,5 @@ /* - * $Id: cnid_lookup.c,v 1.9.2.3 2001-12-15 06:35:28 jmarcus Exp $ + * $Id: cnid_lookup.c,v 1.9.2.4 2002-02-09 20:29:02 jmarcus Exp $ */ #ifdef HAVE_CONFIG_H @@ -53,7 +53,7 @@ cnid_t cnid_lookup(void *CNID, const struct stat *st, const cnid_t did, break; default: syslog(LOG_ERR, "cnid_lookup: txn_checkpoint: %s", - db_strerror(rc)); + db_strerror(rc)); return 0; } } @@ -82,7 +82,7 @@ cnid_t cnid_lookup(void *CNID, const struct stat *st, const cnid_t did, } syslog(LOG_ERR, "cnid_lookup: Unable to get CNID dev %u, ino %u: %s", - st->st_dev, st->st_ino, db_strerror(rc)); + st->st_dev, st->st_ino, db_strerror(rc)); return 0; } @@ -100,7 +100,7 @@ cnid_t cnid_lookup(void *CNID, const struct stat *st, const cnid_t did, } syslog(LOG_ERR, "cnid_lookup: Unable to get CNID %u, name %s: %s", - ntohl(did), name, db_strerror(rc)); + ntohl(did), name, db_strerror(rc)); return 0; } @@ -117,7 +117,7 @@ cnid_t cnid_lookup(void *CNID, const struct stat *st, const cnid_t did, if ((devino && didname) || !(devino || didname)) { #ifdef DEBUG syslog(LOG_INFO, "cnid_lookup: Looked up did %u, name %s, as %u", - ntohl(did), name, ntohl(id)); + ntohl(did), name, ntohl(id)); #endif return id; } diff --git a/libatalk/cnid/cnid_nextid.c b/libatalk/cnid/cnid_nextid.c index 3742fbbe..fc917d7e 100644 --- a/libatalk/cnid/cnid_nextid.c +++ b/libatalk/cnid/cnid_nextid.c @@ -1,5 +1,5 @@ /* - * $Id: cnid_nextid.c,v 1.6.2.3 2001-12-15 06:35:28 jmarcus Exp $ + * $Id: cnid_nextid.c,v 1.6.2.4 2002-02-09 20:29:02 jmarcus Exp $ */ #ifdef unused diff --git a/libatalk/cnid/cnid_open.c b/libatalk/cnid/cnid_open.c index 02c07ee0..e356013a 100644 --- a/libatalk/cnid/cnid_open.c +++ b/libatalk/cnid/cnid_open.c @@ -1,5 +1,5 @@ /* - * $Id: cnid_open.c,v 1.19.2.3 2001-12-15 06:35:28 jmarcus Exp $ + * $Id: cnid_open.c,v 1.19.2.4 2002-02-09 20:29:02 jmarcus Exp $ * * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu) * All Rights Reserved. See COPYRIGHT. @@ -30,7 +30,8 @@ * 1 -- parent of root directory (handled by afpd) * 2 -- root directory (handled by afpd) * - * so, CNID_START begins at 3. + * CNIDs 4-16 are reserved according to page 31 of the AFP 3.0 spec so, + * CNID_START begins at 17. */ #ifdef HAVE_CONFIG_H @@ -92,23 +93,19 @@ #define DBOPTIONS (DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | \ DB_INIT_LOG | DB_INIT_TXN) #else /* DB_VERSION_MINOR < 1 */ -#define DBOPTIONS (DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | \ -DB_INIT_LOG | DB_INIT_TXN | DB_TXN_NOSYNC) /*#define DBOPTIONS (DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | \ -DB_INIT_LOG | DB_INIT_TXN)*/ +DB_INIT_LOG | DB_INIT_TXN | DB_TXN_NOSYNC)*/ +#define DBOPTIONS (DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | \ +DB_INIT_LOG | DB_INIT_TXN) #endif /* DB_VERSION_MINOR */ -/* Let's try and use the random deadlock decider if available. This adds - * a bit of entropy to the mix that might be beneficial. If random isn't - * available, we'll decide deadlocks by kicking off the youngest process. +/* Let's try and use the youngest lock detector if present. * If we can't do that, then let DB3 use its default deadlock detector. */ -#ifdef DB_LOCK_RANDOM -#define DEAD_LOCK_DETECT DB_LOCK_RANDOM -#elif defined DB_LOCK_YOUNGEST +#if defined DB_LOCK_YOUNGEST #define DEAD_LOCK_DETECT DB_LOCK_YOUNGEST -#else /* DB_LOCK_RANDOM */ +#else /* DB_LOCK_YOUNGEST */ #define DEAD_LOCK_DETECT DB_LOCK_DEFAULT -#endif /* DB_LOCK_RANDOM */ +#endif /* DB_LOCK_YOUNGEST */ #define MAXITER 0xFFFF /* maximum number of simultaneously open CNID * databases. */ @@ -188,19 +185,15 @@ static int compare_unicode(const DBT *a, const DBT *b) #endif /* DB_VERSION_MINOR */ } -static int have_lock = 0; - void *cnid_open(const char *dir) { - struct stat st, rsb, csb; + struct stat st, rsb, lsb, csb; struct flock lock; char path[MAXPATHLEN + 1]; - char recover_file[MAXPATHLEN + 1]; CNID_private *db; DBT key, data; DB_TXN *tid; - u_int32_t DBEXTRAS = 0; int open_flag, len; - int rc, rfd = -1; + int rc; if (!dir) { return NULL; @@ -238,27 +231,13 @@ void *cnid_open(const char *dir) { strcat(path, "/"); len++; - strcpy(db->close_file, path); - strcat(db->close_file, DBCLOSEFILE); - - /* Check to make sure that a client isn't in the process of closing - * the database environment. To do this, select on the close file. */ - while(stat(db->close_file, &csb) == 0) { - struct timeval ct; - ct.tv_sec = 1; - ct.tv_usec = 0; - (void)select(0, NULL, NULL, NULL, &ct); - } - - strcpy(recover_file, path); - strcat(recover_file, DBRECOVERFILE); - /* Search for a byte lock. This allows us to cleanup the log files * at cnid_close() in a clean fashion. * * NOTE: This won't work if multiple volumes for the same user refer * to the sahe directory. */ strcat(path, DBLOCKFILE); + strcpy(db->lock_file, path); if ((db->lockfd = open(path, O_RDWR | O_CREAT, 0666)) > -1) { lock.l_start = 0; lock.l_len = 1; @@ -275,27 +254,6 @@ void *cnid_open(const char *dir) { syslog(LOG_ERR, "cnid_open: Cannot establish logfile cleanup lock for database environment %s (open() failed)", path); } - /* Create a file to represent database recovery. While this file - * exists, the database is being recovered, and all other clients will - * select until recovery is complete, and this file goes away. */ - if (!have_lock && db->lockfd > -1 && lock.l_start == 0) { - if (stat(recover_file, &rsb) == 0) { - (void)remove(recover_file); - } - if ((rfd = open(recover_file, O_RDWR | O_CREAT, 0666)) > -1) { - DBEXTRAS |= DB_RECOVER; - have_lock = 1; - } - } - else if (!have_lock) { - while (stat(recover_file, &rsb) == 0) { - struct timeval rt; - rt.tv_sec = 1; - rt.tv_usec = 0; - (void)select(0, NULL, NULL, NULL, &rt); - } - } - path[len + DBHOMELEN] = '\0'; open_flag = DB_CREATE; @@ -314,15 +272,17 @@ void *cnid_open(const char *dir) { } #if DB_VERSION_MINOR > 1 +#if 0 /* Take care of setting the DB_TXN_NOSYNC flag in db3 > 3.1.x. */ if ((rc = db->dbenv->set_flags(db->dbenv, DB_TXN_NOSYNC, 1)) != 0) { syslog(LOG_ERR, "cnid_open: set_flags: %s", db_strerror(rc)); goto fail_lock; } +#endif #endif /* DB_VERSION_MINOR > 1 */ /* Open the database environment. */ - if ((rc = db->dbenv->open(db->dbenv, path, DBOPTIONS | DBEXTRAS, 0666)) != 0) { + if ((rc = db->dbenv->open(db->dbenv, path, DBOPTIONS, 0666)) != 0) { if (rc == DB_RUNRECOVERY) { /* This is the mother of all errors. We _must_ fail here. */ syslog(LOG_ERR, "cnid_open: CATASTROPHIC ERROR opening database environment %s. Run db_recovery -c immediately", path); @@ -337,7 +297,7 @@ void *cnid_open(const char *dir) { * open the environment with no flags. */ if ((rc = db->dbenv->open(db->dbenv, path, 0, 0666)) != 0) { syslog(LOG_ERR, "cnid_open: dbenv->open of %s failed: %s", - path, db_strerror(rc)); + path, db_strerror(rc)); goto fail_lock; } } @@ -346,34 +306,18 @@ void *cnid_open(const char *dir) { syslog(LOG_INFO, "cnid_open: Obtained read-only database environment %s", path); } - /* If we have the recovery lock, close the file, remove it, so other - * clients can proceed opening the DB environment. */ - if (rfd > -1) { - (void)remove(recover_file); - switch(errno) { - case 0: - case ENOENT: - break; - default: - syslog(LOG_ERR, "cnid_open: Unable to remove %s: %s", - recover_file, strerror(errno)); - } - close(rfd); - rfd = -1; - } - /* did/name reverse mapping. We use a BTree for this one. */ if ((rc = db_create(&db->db_didname, db->dbenv, 0)) != 0) { syslog(LOG_ERR, "cnid_open: Failed to create did/name database: %s", - db_strerror(rc)); + db_strerror(rc)); goto fail_appinit; } - db->db_didname->set_bt_compare(db->db_didname, &compare_unix); + /*db->db_didname->set_bt_compare(db->db_didname, &compare_unix);*/ if ((rc = db->db_didname->open(db->db_didname, DBDIDNAME, NULL, - DB_BTREE, open_flag, 0666))) { + DB_HASH, open_flag, 0666))) { syslog(LOG_ERR, "cnid_open: Failed to open did/name database: %s", - db_strerror(rc)); + db_strerror(rc)); goto fail_appinit; } @@ -387,7 +331,7 @@ void *cnid_open(const char *dir) { dbversion_retry: if ((rc = txn_begin(db->dbenv, NULL, &tid, 0)) != 0) { syslog(LOG_ERR, "cnid_open: txn_begin: failed to check db version: %s", - db_strerror(rc)); + db_strerror(rc)); db->db_didname->close(db->db_didname, 0); goto fail_appinit; } @@ -415,7 +359,7 @@ dbversion_retry: if (ret == DB_LOCK_DEADLOCK) { if ((ret = txn_abort(tid)) != 0) { syslog(LOG_ERR, "cnid_open: txn_abort: %s", - db_strerror(ret)); + db_strerror(ret)); db->db_didname->close(db->db_didname, 0); goto fail_appinit; } @@ -426,7 +370,7 @@ dbversion_retry: * successfully or not. */ txn_abort(tid); syslog(LOG_ERR, "cnid_open: Error putting new version: %s", - db_strerror(ret)); + db_strerror(ret)); db->db_didname->close(db->db_didname, 0); goto fail_appinit; } @@ -435,7 +379,7 @@ dbversion_retry: default: txn_abort(tid); syslog(LOG_ERR, "cnid_open: Failed to check db version: %s", - db_strerror(rc)); + db_strerror(rc)); db->db_didname->close(db->db_didname, 0); goto fail_appinit; } @@ -443,7 +387,7 @@ dbversion_retry: if ((rc = txn_commit(tid, 0)) != 0) { syslog(LOG_ERR, "cnid_open: Failed to commit db version: %s", - db_strerror(rc)); + db_strerror(rc)); db->db_didname->close(db->db_didname, 0); goto fail_appinit; } @@ -460,7 +404,7 @@ dbversion_retry: /* did/macname (31 character) mapping. Use a BTree for this one. */ if ((rc = db_create(&db->db_macname, db->dbenv, 0)) != 0) { syslog(LOG_ERR, "cnid_open: Failed to create did/macname database: %s", - db_strerror(rc)); + db_strerror(rc)); db->db_didname->close(db->db_didname, 0); goto fail_appinit; } @@ -468,7 +412,7 @@ dbversion_retry: db->db_macname->set_bt_compare(db->db_macname, &compare_mac); if ((rc = db->db_macname->open(db->db_macname, DBMACNAME, NULL, DB_BTREE, open_flag, 0666)) != 0) { syslog(LOG_ERR, "cnid_open: Failed to open did/macname database: %s", - db_strerror(rc)); + db_strerror(rc)); db->db_didname->close(db->db_didname, 0); goto fail_appinit; } @@ -476,7 +420,7 @@ dbversion_retry: /* did/shortname (DOS 8.3) mapping. Use a BTree for this one. */ if ((rc = db_create(&db->db_shortname, db->dbenv, 0)) != 0) { syslog(LOG_ERR, "cnid_open: Failed to create did/shortname database: %s", - db_strerror(rc)); + db_strerror(rc)); db->db_didname->close(db->db_didname, 0); db->db_macname->close(db->db_macname, 0); goto fail_appinit; @@ -485,7 +429,7 @@ dbversion_retry: db->db_shortname->set_bt_compare(db->db_shortname, &compare_mac); if ((rc = db->db_shortname->open(db->db_shortname, DBSHORTNAME, NULL, DB_BTREE, open_flag, 0666)) != 0) { syslog(LOG_ERR, "cnid_open: Failed to open did/shortname database: %s", - db_strerror(rc)); + db_strerror(rc)); db->db_didname->close(db->db_didname, 0); db->db_macname->close(db->db_macname, 0); goto fail_appinit; @@ -494,7 +438,7 @@ dbversion_retry: /* did/longname (Unicode) mapping. Use a BTree for this one. */ if ((rc = db_create(&db->db_longname, db->dbenv, 0)) != 0) { syslog(LOG_ERR, "cnid_open: Failed to create did/longname database: %s", - db_strerror(rc)); + db_strerror(rc)); db->db_didname->close(db->db_didname, 0); db->db_macname->close(db->db_macname, 0); db->db_shortname->close(db->db_shortname, 0); @@ -504,7 +448,7 @@ dbversion_retry: db->db_longname->set_bt_compare(db->db_longname, &compare_unicode); if ((rc = db->db_longname->open(db->db_longname, DBLONGNAME, NULL, DB_BTREE, open_flag, 0666)) != 0) { syslog(LOG_ERR, "cnid_open: Failed to open did/longname database: %s", - db_strerror(rc)); + db_strerror(rc)); db->db_didname->close(db->db_didname, 0); db->db_macname->close(db->db_macname, 0); db->db_shortname->close(db->db_shortname, 0); @@ -515,7 +459,7 @@ dbversion_retry: /* dev/ino reverse mapping. Use a hash for this one. */ if ((rc = db_create(&db->db_devino, db->dbenv, 0)) != 0) { syslog(LOG_ERR, "cnid_open: Failed to create dev/ino database: %s", - db_strerror(rc)); + db_strerror(rc)); db->db_didname->close(db->db_didname, 0); #ifdef EXTENDED_DB db->db_macname->close(db->db_macname, 0); @@ -527,7 +471,7 @@ dbversion_retry: if ((rc = db->db_devino->open(db->db_devino, DBDEVINO, NULL, DB_HASH, open_flag, 0666)) != 0) { syslog(LOG_ERR, "cnid_open: Failed to open devino database: %s", - db_strerror(rc)); + db_strerror(rc)); db->db_didname->close(db->db_didname, 0); #ifdef EXTENDED_DB db->db_macname->close(db->db_macname, 0); @@ -540,7 +484,7 @@ dbversion_retry: /* Main CNID database. Use a hash for this one. */ if ((rc = db_create(&db->db_cnid, db->dbenv, 0)) != 0) { syslog(LOG_ERR, "cnid_open: Failed to create cnid database: %s", - db_strerror(rc)); + db_strerror(rc)); db->db_didname->close(db->db_didname, 0); #ifdef EXTENDED_DB db->db_macname->close(db->db_macname, 0); @@ -554,7 +498,7 @@ dbversion_retry: if ((rc = db->db_cnid->open(db->db_cnid, DBCNID, NULL, DB_HASH, open_flag, 0666)) != 0) { syslog(LOG_ERR, "cnid_open: Failed to open dev/ino database: %s", - db_strerror(rc)); + db_strerror(rc)); db->db_didname->close(db->db_didname, 0); #ifdef EXTENDED_DB db->db_macname->close(db->db_macname, 0); @@ -564,6 +508,10 @@ dbversion_retry: goto fail_appinit; } + /* Print out the version of DB3 we're linked against. */ + syslog(LOG_INFO, "CNID DB initialized using %s", + db_version(NULL, NULL, NULL)); + return db; fail_appinit: @@ -573,10 +521,7 @@ fail_appinit: fail_lock: if (db->lockfd > -1) { close(db->lockfd); - } - if (rfd > -1) { - (void)remove(recover_file); - close(rfd); + (void)remove(db->lock_file); } fail_adouble: diff --git a/libatalk/cnid/cnid_private.h b/libatalk/cnid/cnid_private.h index a315dfb5..97b33ab8 100644 --- a/libatalk/cnid/cnid_private.h +++ b/libatalk/cnid/cnid_private.h @@ -1,5 +1,5 @@ /* - * $Id: cnid_private.h,v 1.3.2.3 2001-12-15 06:35:28 jmarcus Exp $ + * $Id: cnid_private.h,v 1.3.2.4 2002-02-09 20:29:02 jmarcus Exp $ */ #ifndef LIBATALK_CNID_PRIVATE_H @@ -24,7 +24,7 @@ #define CNID_DID_LEN 4 #define CNID_HEADER_LEN (CNID_DEVINO_LEN + CNID_DID_LEN) -#define CNID_START 3 +#define CNID_START 17 #define CNIDFLAG_ROOTINFO_RO (1 << 0) #define CNIDFLAG_DB_RO (1 << 1) @@ -46,7 +46,7 @@ typedef struct CNID_private { #endif /* EXTENDED_DB */ DB_ENV* dbenv; int lockfd, flags; - char close_file[MAXPATHLEN + 1]; + char lock_file[MAXPATHLEN + 1]; } CNID_private; /* on-disk data format (in network byte order where appropriate) -- diff --git a/libatalk/cnid/cnid_resolve.c b/libatalk/cnid/cnid_resolve.c index 023a8f60..78e6fedb 100644 --- a/libatalk/cnid/cnid_resolve.c +++ b/libatalk/cnid/cnid_resolve.c @@ -1,5 +1,5 @@ /* - * $Id: cnid_resolve.c,v 1.8.2.3 2001-12-15 06:35:28 jmarcus Exp $ + * $Id: cnid_resolve.c,v 1.8.2.4 2002-02-09 20:29:02 jmarcus Exp $ */ #ifdef HAVE_CONFIG_H @@ -43,7 +43,7 @@ char *cnid_resolve(void *CNID, cnid_t *id) { if (rc != DB_NOTFOUND) { syslog(LOG_ERR, "cnid_resolve: Unable to get did/name: %s", - db_strerror(rc)); + db_strerror(rc)); } *id = 0; @@ -53,7 +53,7 @@ char *cnid_resolve(void *CNID, cnid_t *id) { memcpy(id, (char *)data.data + CNID_DEVINO_LEN, sizeof(cnid_t)); #ifdef DEBUG syslog(LOG_INFO, "cnid_resolve: Returning id = %u, did/name = %s", - ntohl(*id), (char *)data.data + CNID_HEADER_LEN); + ntohl(*id), (char *)data.data + CNID_HEADER_LEN); #endif return (char *)data.data + CNID_HEADER_LEN; } diff --git a/libatalk/cnid/cnid_update.c b/libatalk/cnid/cnid_update.c index c8d6b52d..b851a02c 100644 --- a/libatalk/cnid/cnid_update.c +++ b/libatalk/cnid/cnid_update.c @@ -1,5 +1,5 @@ /* - * $Id: cnid_update.c,v 1.12.2.3 2001-12-15 06:35:28 jmarcus Exp $ + * $Id: cnid_update.c,v 1.12.2.4 2002-02-09 20:29:02 jmarcus Exp $ */ #ifdef HAVE_CONFIG_H @@ -42,8 +42,7 @@ int cnid_update(void *CNID, const cnid_t id, const struct stat *st, retry: if ((rc = txn_begin(db->dbenv, NULL, &tid, 0))) { - syslog(LOG_ERR, "cnid_update: Failed to begin transaction: %s", - db_strerror(rc)); + syslog(LOG_ERR, "cnid_update: Failed to begin transaction: %s", db_strerror(rc)); return rc; } @@ -148,7 +147,7 @@ retry: update_err: syslog(LOG_ERR, "cnid_update: Unable to update CNID %u: %s", - ntohl(id), db_strerror(rc)); + ntohl(id), db_strerror(rc)); return -1; } #endif /* CNID_DB */ diff --git a/macros/db3-check.m4 b/macros/db3-check.m4 index d2b4778c..8f831426 100644 --- a/macros/db3-check.m4 +++ b/macros/db3-check.m4 @@ -1,4 +1,4 @@ -dnl $Id: db3-check.m4,v 1.6 2001-11-16 21:51:05 jnewman Exp $ +dnl $Id: db3-check.m4,v 1.6.2.1 2002-02-09 20:29:02 jmarcus Exp $ dnl Autoconf macro to check for the Berkeley DB3 library AC_DEFUN([AC_PATH_DB3], [ @@ -24,6 +24,7 @@ AC_DEFUN([AC_PATH_DB3], [ db3found=yes DB3_CFLAGS="-I$db3dir" DB3_LIBS="-L$db3libdir -ldb" + DB3_PATH="`echo $db3dir | sed 's,include/db3$,,'`" ]) CFLAGS="$savedcflags" LDFLAGS="$savedldflags" @@ -39,4 +40,5 @@ AC_DEFUN([AC_PATH_DB3], [ AC_SUBST(DB3_CFLAGS) AC_SUBST(DB3_LIBS) + AC_SUBST(DB3_PATH) ]) -- 2.39.2