From 9a61514e736de1cc79c31b54c5d1c9e1dbc5ac66 Mon Sep 17 00:00:00 2001 From: jmarcus Date: Fri, 14 Dec 2001 03:10:37 +0000 Subject: [PATCH] Hopefully fix a problem when multiple clients mount and unmount a volume repeatedly. Also, make the cnid.recover file a little more fool-proof. --- libatalk/cnid/cnid_close.c | 43 ++++++++++++++++++++++-------------- libatalk/cnid/cnid_open.c | 18 +++++++++++++-- libatalk/cnid/cnid_private.h | 3 ++- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/libatalk/cnid/cnid_close.c b/libatalk/cnid/cnid_close.c index 232a6cf9..133bf737 100644 --- a/libatalk/cnid/cnid_close.c +++ b/libatalk/cnid/cnid_close.c @@ -1,5 +1,5 @@ /* - * $Id: cnid_close.c,v 1.17 2001-12-13 15:15:05 jmarcus Exp $ + * $Id: cnid_close.c,v 1.18 2001-12-14 03:10:37 jmarcus Exp $ */ #ifdef HAVE_CONFIG_H @@ -40,33 +40,42 @@ void cnid_close(void *CNID) { lock.l_start = lock.l_len = 0; if (fcntl(db->lockfd, F_SETLK, &lock) == 0) { char **list, **first; + int cfd = -1; - /* Checkpoint the databases until we can checkpoint no - * more. */ - rc = txn_checkpoint(db->dbenv, 0, 0, 0); - while (rc == DB_INCOMPLETE) { + if ((cfd = open(db->close_file, O_RDWR | O_CREAT, 0666)) > -1) { + + /* 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); + } #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_LOG | 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_LOG | 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); } - 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)); } } } diff --git a/libatalk/cnid/cnid_open.c b/libatalk/cnid/cnid_open.c index e7086242..520ced1f 100644 --- a/libatalk/cnid/cnid_open.c +++ b/libatalk/cnid/cnid_open.c @@ -1,5 +1,5 @@ /* - * $Id: cnid_open.c,v 1.27 2001-12-13 03:31:34 jmarcus Exp $ + * $Id: cnid_open.c,v 1.28 2001-12-14 03:10:37 jmarcus Exp $ * * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu) * All Rights Reserved. See COPYRIGHT. @@ -72,6 +72,7 @@ #define DBLONGNAME "longname.db" /* did/unicode mapping */ #define DBLOCKFILE "cnid.lock" #define DBRECOVERFILE "cnid.dbrecover" +#define DBCLOSEFILE "cnid.close" #define DBHOMELEN 8 #define DBLEN 10 @@ -187,7 +188,7 @@ static int compare_unicode(const DBT *a, const DBT *b) static int have_lock = 0; void *cnid_open(const char *dir) { - struct stat st, rsb; + struct stat st, rsb, csb; struct flock lock; char path[MAXPATHLEN + 1]; char recover_file[MAXPATHLEN + 1]; @@ -234,6 +235,15 @@ 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, sleep on the close file. */ + while(stat(db->close_file, &csb) == 0) { + sleep(1); + } + strcpy(recover_file, path); strcat(recover_file, DBRECOVERFILE); @@ -555,6 +565,10 @@ fail_lock: if (db->lockfd > -1) { close(db->lockfd); } + if (rfd > -1) { + (void)remove(recover_file); + close(rfd); + } fail_adouble: diff --git a/libatalk/cnid/cnid_private.h b/libatalk/cnid/cnid_private.h index 1f079843..eb104e25 100644 --- a/libatalk/cnid/cnid_private.h +++ b/libatalk/cnid/cnid_private.h @@ -1,5 +1,5 @@ /* - * $Id: cnid_private.h,v 1.4 2001-11-27 23:38:18 jmarcus Exp $ + * $Id: cnid_private.h,v 1.5 2001-12-14 03:10:37 jmarcus Exp $ */ #ifndef LIBATALK_CNID_PRIVATE_H @@ -46,6 +46,7 @@ typedef struct CNID_private { #endif /* EXTENDED_DB */ DB_ENV* dbenv; int lockfd, flags; + char close_file[MAXPATHLEN + 1]; } CNID_private; /* on-disk data format (in network byte order where appropriate) -- -- 2.39.2