]> arthur.barton.de Git - netatalk.git/commitdiff
Restructure opening and deleting the CNID dbs and CNID wraparound support
authorRalph Boehme <sloowfranklin@gmail.com>
Mon, 10 Dec 2012 17:38:07 +0000 (18:38 +0100)
committerRalph Boehme <sloowfranklin@gmail.com>
Mon, 17 Dec 2012 18:04:58 +0000 (19:04 +0100)
If opening the db fails, delete it and recreate a new empty one.

Add handling of CNID overflow, ie when the last used CNID reaches
its maximum (UINT32_MAX), wrap around to CNID_START. This then neccesites
a modification to get_id() where we used to just increment the last
used CNID counter and use that as next CNID.
Now we need to ensure that it isn't already used in the db and keep
searching for an used in case it is in a loop.

Move locking function back to main.c, as it's only used by cnid_dbd.

Modify dbd_add() such that it can add an entry with the CNID passed
in from the client, the CNID hint read from the adouble file.

Invalidate CNID hint in case lookup detected a problem

etc/cnid_dbd/dbd_add.c
etc/cnid_dbd/dbd_lookup.c
etc/cnid_dbd/dbif.c
etc/cnid_dbd/dbif.h
etc/cnid_dbd/main.c

index e6e5e50127624561cd7a9762bddb504fd719dbd2..db9c6cc29d23f5c3ba023032e97cd7e325b8ea54 100644 (file)
@@ -74,7 +74,7 @@ int get_cnid(DBD *dbd, struct cnid_dbd_rply *rply)
 {
     static cnid_t id;
     static char buf[ROOTINFO_DATALEN];
-    DBT rootinfo_key, rootinfo_data;
+    DBT rootinfo_key, rootinfo_data, key, data;
     int rc;
     cnid_t hint;
 
@@ -83,41 +83,57 @@ int get_cnid(DBD *dbd, struct cnid_dbd_rply *rply)
     rootinfo_key.data = ROOTINFO_KEY;
     rootinfo_key.size = ROOTINFO_KEYLEN;
 
+    memset(&key, 0, sizeof(key));
+    memset(&data, 0, sizeof(data));
+
     if (id == 0) {
-        if ((rc = dbif_get(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0)) < 0) {
+        if ((rc = dbif_get(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0)) != 1) {
             rply->result = CNID_DBD_RES_ERR_DB;
             return -1;
         }
-        if (rc == 0) {
-            /* no rootinfo key yet */
-            memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN);
+        memcpy(buf, (char *)rootinfo_data.data, ROOTINFO_DATALEN);
+        memcpy(&hint, buf + CNID_TYPE_OFS, sizeof(hint));
+        id = ntohl(hint);
+        if (id < CNID_START - 1)
             id = CNID_START - 1;
-        } else {
-            memcpy(buf, (char *)rootinfo_data.data, ROOTINFO_DATALEN);
-            memcpy(&hint, buf + CNID_TYPE_OFS, sizeof(hint));
-            id = ntohl(hint);
-            if (id < CNID_START - 1)
-                id = CNID_START - 1;
-        }
     }
 
-    /* If we've hit the max CNID allowed, we return an error. CNID
-     * needs to be recycled before proceding. */
-    if (++id == CNID_INVALID) {
-        rply->result = CNID_DBD_RES_ERR_MAX;
-        return -1;
+    cnid_t trycnid, tmp;
+
+    while (true) {
+        if (rply->cnid != CNID_INVALID) {
+            trycnid = ntohl(rply->cnid);
+            rply->cnid = CNID_INVALID;
+        } else {
+            if (++id == CNID_INVALID)
+                id = CNID_START;
+            trycnid = id;
+        }
+        tmp = htonl(trycnid);
+        key.data = &tmp;
+        key.size = sizeof(cnid_t);
+        rc = dbif_get(dbd, DBIF_CNID, &key, &data, 0);
+        if (rc == 0) {
+            break;
+        } else if (rc == -1) {
+            rply->result = CNID_DBD_RES_ERR_DB;
+            return -1;
+        }
     }
 
-    rootinfo_data.data = buf;
-    rootinfo_data.size = ROOTINFO_DATALEN;
-    hint = htonl(id);
-    memcpy(buf + CNID_TYPE_OFS, &hint, sizeof(hint));
+    if (trycnid == id) {
+        rootinfo_data.data = buf;
+        rootinfo_data.size = ROOTINFO_DATALEN;
+        hint = htonl(id);
+        memcpy(buf + CNID_TYPE_OFS, &hint, sizeof(hint));
 
-    if (dbif_put(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0) < 0) {
-        rply->result = CNID_DBD_RES_ERR_DB;
-        return -1;
+        if (dbif_put(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0) < 0) {
+            rply->result = CNID_DBD_RES_ERR_DB;
+            return -1;
+        }
     }
-    rply->cnid = hint;
+
+    rply->cnid = htonl(trycnid);
     return 0;
 }
 
@@ -146,7 +162,10 @@ int dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
     LOG(log_debug, logtype_cnid, "dbd_add(did:%u, '%s', dev/ino:0x%llx/0x%llx): {adding to database ...}",
         ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
 
-
+    if (rqst->cnid) {
+        /* rqst->cnid is the cnid "hint"/backup from the adouble file */
+        rply->cnid = rqst->cnid;
+    }
     if (get_cnid(dbd, rply) < 0) {
         if (rply->result == CNID_DBD_RES_ERR_MAX) {
             LOG(log_error, logtype_cnid, "dbd_add: FATAL: CNID database has reached its limit.");
index 0ab85f9944904d2fbadab36155042398b55a97cc..44e46620adab03e1bbc88c88b2f31375a78c974a 100644 (file)
@@ -120,6 +120,7 @@ to be safe we must assign new CNIDs to both files.
 
 #include <atalk/logger.h>
 #include <atalk/cnid_dbd_private.h>
+#include <atalk/cnid.h>
 
 #include "pack.h"
 #include "dbif.h"
@@ -281,6 +282,7 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
             if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
                 return -1;
             rply->result = CNID_DBD_RES_NOTFOUND;
+            rqst->cnid = CNID_INVALID; /* invalidate CNID hint */
             return 1;
         }
     }
@@ -292,6 +294,7 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
         if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
             return -1;
         rply->result = CNID_DBD_RES_NOTFOUND;
+        rqst->cnid = CNID_INVALID; /* invalidate CNID hint */
         return 1;
     }
 
index b21f259b860f40e12c71167d27c4695a9bc1bda9..3dae61cdad2f6ba5561f14708d4c37f39dc5f27c 100644 (file)
@@ -22,6 +22,7 @@
 #include <atalk/logger.h>
 #include <atalk/util.h>
 #include <atalk/errchk.h>
+#include <atalk/cnid.h>
 
 #include "db_param.h"
 #include "dbif.h"
@@ -88,13 +89,11 @@ EC_CLEANUP:
 static int dbif_init_rootinfo(DBD *dbd, int version)
 {
     DBT key, data;
-    uint32_t v;
+    uint32_t uint32;
     char buf[ROOTINFO_DATALEN];
 
     LOG(log_debug, logtype_cnid, "Setting CNID database version to %u", version);
 
-    v = version;
-    v = htonl(v);
 
     memset(&key, 0, sizeof(key));
     memset(&data, 0, sizeof(data));
@@ -104,7 +103,13 @@ static int dbif_init_rootinfo(DBD *dbd, int version)
     data.size = ROOTINFO_DATALEN;
 
     memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN);
-    memcpy(buf + CNID_DID_OFS, &v, sizeof(v));
+
+    uint32 = htonl(CNID_START - 1);
+    memcpy(buf + CNID_TYPE_OFS, &uint32, sizeof(uint32));
+
+    uint32 = htonl(version);
+    memcpy(buf + CNID_DID_OFS, &uint32, sizeof(uint32));
+
     if (dbif_stamp(dbd, buf + CNID_DEV_OFS, CNID_DEV_LEN) < 0)
         return -1;
 
@@ -326,97 +331,6 @@ exit:
     return ret;
 }
 
-/*!
- * Get lock on db lock file
- *
- * @args cmd       (r) lock command:
- *                     LOCK_FREE:   close lockfd
- *                     LOCK_UNLOCK: unlock lockm keep lockfd open
- *                     LOCK_EXCL:   F_WRLCK on lockfd
- *                     LOCK_SHRD:   F_RDLCK on lockfd
- * @args dbpath    (r) path to lockfile, only used on first call,
- *                     later the stored fd is used
- * @returns            LOCK_FREE/LOCK_UNLOCK return 0 on success, -1 on error
- *                     LOCK_EXCL/LOCK_SHRD return LOCK_EXCL or LOCK_SHRD respectively on
- *                     success, 0 if the lock couldn't be acquired, -1 on other errors
- */
-int get_lock(int cmd, const char *dbpath)
-{
-    static int lockfd = -1;
-    int ret;
-    char lockpath[PATH_MAX];
-    struct stat st;
-
-    LOG(log_debug, logtype_cnid, "get_lock(%s, \"%s\")",
-        cmd == LOCK_EXCL ? "LOCK_EXCL" :
-        cmd == LOCK_SHRD ? "LOCK_SHRD" :
-        cmd == LOCK_FREE ? "LOCK_FREE" :
-        cmd == LOCK_UNLOCK ? "LOCK_UNLOCK" : "UNKNOWN" , dbpath ? dbpath : "");
-
-    switch (cmd) {
-    case LOCK_FREE:
-        if (lockfd == -1)
-            return -1;
-        close(lockfd);
-        lockfd = -1;
-        return 0;
-
-    case LOCK_UNLOCK:
-        if (lockfd == -1)
-            return -1;
-        return unlock(lockfd, 0, SEEK_SET, 0);
-
-    case LOCK_EXCL:
-    case LOCK_SHRD:
-        if (lockfd == -1) {
-            if ( (strlen(dbpath) + strlen(LOCKFILENAME+1)) > (PATH_MAX - 1) ) {
-                LOG(log_error, logtype_cnid, ".AppleDB pathname too long");
-                return -1;
-            }
-            strncpy(lockpath, dbpath, PATH_MAX - 1);
-            strcat(lockpath, "/");
-            strcat(lockpath, LOCKFILENAME);
-
-            if ((lockfd = open(lockpath, O_RDWR | O_CREAT, 0644)) < 0) {
-                LOG(log_error, logtype_cnid, "Error opening lockfile: %s", strerror(errno));
-                return -1;
-            }
-
-            if ((stat(dbpath, &st)) != 0) {
-                LOG(log_error, logtype_cnid, "Error statting lockfile: %s", strerror(errno));
-                return -1;
-            }
-
-            if ((chown(lockpath, st.st_uid, st.st_gid)) != 0) {
-                LOG(log_error, logtype_cnid, "Error inheriting lockfile permissions: %s",
-                         strerror(errno));
-                return -1;
-            }
-        }
-    
-        if (cmd == LOCK_EXCL)
-            ret = write_lock(lockfd, 0, SEEK_SET, 0);
-        else
-            ret = read_lock(lockfd, 0, SEEK_SET, 0);
-
-        if (ret != 0) {
-            if (cmd == LOCK_SHRD)
-                LOG(log_error, logtype_cnid, "Volume CNID db is locked, try again...");
-            return 0; 
-        }
-
-        LOG(log_debug, logtype_cnid, "get_lock: got %s lock",
-            cmd == LOCK_EXCL ? "LOCK_EXCL" : "LOCK_SHRD");    
-        return cmd;
-
-    default:
-        return -1;
-    } /* switch(cmd) */
-
-    /* deadc0de, never get here */
-    return -1;
-}
-
 /* --------------- */
 DBD *dbif_init(const char *envhome, const char *filename)
 {
@@ -813,11 +727,6 @@ int dbif_env_remove(const char *path)
 
     LOG(log_debug, logtype_cnid, "Trying to remove BerkeleyDB environment");
 
-    if (get_lock(LOCK_EXCL, path) != LOCK_EXCL) {
-        LOG(log_debug, logtype_cnid, "CNID db \"%s\" in use, not removing BerkeleyDB environment", path);
-        return 0;
-    }
-    
     if (NULL == (dbd = dbif_init(path, "cnid2.db")))
         return -1;
 
index 8c71de36b96221f598f64f4943b0878e7906f444..a6c88a98068ad30f9535e03d6cb694c12e17e7dd 100644 (file)
@@ -64,7 +64,6 @@
 #define DBIF_IDX_DIDNAME   2
 #define DBIF_IDX_NAME      3
 
-/* get_lock cmd and return value */
 #define LOCKFILENAME  "lock"
 #define LOCK_FREE          0
 #define LOCK_UNLOCK        1
@@ -91,9 +90,6 @@ typedef struct {
     db_table db_table[DBIF_DB_CNT];
 } DBD;
 
-/* Functions */
-extern int get_lock(int cmd, const char *dbpath);
-
 extern DBD *dbif_init(const char *envhome, const char *dbname);
 extern int dbif_env_open(DBD *dbd, struct db_param *dbp, uint32_t dbenv_oflags);
 extern int dbif_open(DBD *dbd, struct db_param *dbp, int reindex);
index e2a24d488c7e6ffb6769850c6c60e3f7378456c9..72df407860cf7ffda77ec8c43a9f4a4a58a366c2 100644 (file)
@@ -27,6 +27,7 @@
 #include <atalk/errchk.h>
 #include <atalk/bstrlib.h>
 #include <atalk/netatalk_conf.h>
+#include <atalk/util.h>
 
 #include "db_param.h"
 #include "dbif.h"
@@ -45,6 +46,7 @@ static int exit_sig = 0;
 static int db_locked;
 static bstring dbpath;
 static struct db_param *dbp;
+static struct vol *vol;
 
 static void sig_exit(int signo)
 {
@@ -79,72 +81,198 @@ static void block_sigs_onoff(int block)
   of the cnid_dbd_rply structure contains further details.
 
 */
-#ifndef min
-#define min(a,b)        ((a)<(b)?(a):(b))
-#endif
+
+/*!
+ * Get lock on db lock file
+ *
+ * @args cmd       (r) lock command:
+ *                     LOCK_FREE:   close lockfd
+ *                     LOCK_UNLOCK: unlock lockm keep lockfd open
+ *                     LOCK_EXCL:   F_WRLCK on lockfd
+ *                     LOCK_SHRD:   F_RDLCK on lockfd
+ * @args dbpath    (r) path to lockfile, only used on first call,
+ *                     later the stored fd is used
+ * @returns            LOCK_FREE/LOCK_UNLOCK return 0 on success, -1 on error
+ *                     LOCK_EXCL/LOCK_SHRD return LOCK_EXCL or LOCK_SHRD respectively on
+ *                     success, 0 if the lock couldn't be acquired, -1 on other errors
+ */
+static int get_lock(int cmd, const char *dbpath)
+{
+    static int lockfd = -1;
+    int ret;
+    char lockpath[PATH_MAX];
+    struct stat st;
+
+    LOG(log_debug, logtype_cnid, "get_lock(%s, \"%s\")",
+        cmd == LOCK_EXCL ? "LOCK_EXCL" :
+        cmd == LOCK_SHRD ? "LOCK_SHRD" :
+        cmd == LOCK_FREE ? "LOCK_FREE" :
+        cmd == LOCK_UNLOCK ? "LOCK_UNLOCK" : "UNKNOWN",
+        dbpath ? dbpath : "");
+
+    switch (cmd) {
+    case LOCK_FREE:
+        if (lockfd == -1)
+            return -1;
+        close(lockfd);
+        lockfd = -1;
+        return 0;
+
+    case LOCK_UNLOCK:
+        if (lockfd == -1)
+            return -1;
+        return unlock(lockfd, 0, SEEK_SET, 0);
+
+    case LOCK_EXCL:
+    case LOCK_SHRD:
+        if (lockfd == -1) {
+            if ( (strlen(dbpath) + strlen(LOCKFILENAME+1)) > (PATH_MAX - 1) ) {
+                LOG(log_error, logtype_cnid, ".AppleDB pathname too long");
+                return -1;
+            }
+            strncpy(lockpath, dbpath, PATH_MAX - 1);
+            strcat(lockpath, "/");
+            strcat(lockpath, LOCKFILENAME);
+
+            if ((lockfd = open(lockpath, O_RDWR | O_CREAT, 0644)) < 0) {
+                LOG(log_error, logtype_cnid, "Error opening lockfile: %s", strerror(errno));
+                return -1;
+            }
+
+            if ((stat(dbpath, &st)) != 0) {
+                LOG(log_error, logtype_cnid, "Error statting lockfile: %s", strerror(errno));
+                return -1;
+            }
+
+            if ((chown(lockpath, st.st_uid, st.st_gid)) != 0) {
+                LOG(log_error, logtype_cnid, "Error inheriting lockfile permissions: %s",
+                         strerror(errno));
+                return -1;
+            }
+        }
+    
+        if (cmd == LOCK_EXCL)
+            ret = write_lock(lockfd, 0, SEEK_SET, 0);
+        else
+            ret = read_lock(lockfd, 0, SEEK_SET, 0);
+
+        if (ret != 0) {
+            if (cmd == LOCK_SHRD)
+                LOG(log_error, logtype_cnid, "Volume CNID db is locked, try again...");
+            return 0; 
+        }
+
+        LOG(log_debug, logtype_cnid, "get_lock: got %s lock",
+            cmd == LOCK_EXCL ? "LOCK_EXCL" : "LOCK_SHRD");    
+        return cmd;
+
+    default:
+        return -1;
+    } /* switch(cmd) */
+
+    /* deadc0de, never get here */
+    return -1;
+}
+
+static int open_db(void)
+{
+    EC_INIT;
+
+    /* Get db lock */
+    if ((db_locked = get_lock(LOCK_EXCL, bdata(dbpath))) != LOCK_EXCL) {
+        LOG(log_error, logtype_cnid, "main: fatal db lock error");
+        EC_FAIL;
+    }
+
+    if (NULL == (dbd = dbif_init(bdata(dbpath), "cnid2.db")))
+        EC_FAIL;
+
+    /* Only recover if we got the lock */
+    if (dbif_env_open(dbd, dbp, DBOPTIONS | DB_RECOVER) < 0)
+        EC_FAIL;
+
+    LOG(log_debug, logtype_cnid, "Finished initializing BerkeleyDB environment");
+
+    if (dbif_open(dbd, dbp, 0) < 0)
+        EC_FAIL;
+
+    LOG(log_debug, logtype_cnid, "Finished opening BerkeleyDB databases");
+
+EC_CLEANUP:
+    if (ret != 0) {
+        if (dbd) {
+            (void)dbif_close(dbd);
+            dbd = NULL;
+        }
+    }
+
+    EC_EXIT;
+}
 
 static int delete_db(void)
 {
     EC_INIT;
     int cwd = -1;
 
+    EC_ZERO( get_lock(LOCK_FREE, bdata(dbpath)) );
     EC_NEG1( cwd = open(".", O_RDONLY) );
-
     chdir(bdata(dbpath));
     system("rm -f cnid2.db lock log.* __db.*");
+
     if ((db_locked = get_lock(LOCK_EXCL, bdata(dbpath))) != LOCK_EXCL) {
         LOG(log_error, logtype_cnid, "main: fatal db lock error");
         EC_FAIL;
     }
 
+    LOG(log_warning, logtype_cnid, "Recreated CNID BerkeleyDB databases of volume \"%s\"", vol->v_localname);
+
 EC_CLEANUP:
     if (cwd != -1)
         fchdir(cwd);
     EC_EXIT;
 }
 
-static int wipe_db(void)
+
+/**
+ * Close dbd if open, delete it, reopen
+ *
+ * Also tries to copy the rootinfo key, that would allow for keeping the db stamp
+ * and last used CNID
+ **/
+static int reinit_db(void)
 {
     EC_INIT;
     DBT key, data;
+    bool copyRootInfo;
 
-    memset(&key, 0, sizeof(key));
-    memset(&data, 0, sizeof(data));
+    if (dbd) {
+        memset(&key, 0, sizeof(key));
+        memset(&data, 0, sizeof(data));
 
-    key.data = ROOTINFO_KEY;
-    key.size = ROOTINFO_KEYLEN;
+        key.data = ROOTINFO_KEY;
+        key.size = ROOTINFO_KEYLEN;
 
-    if (dbif_get(dbd, DBIF_CNID, &key, &data, 0) <= 0) {
-        LOG(log_error, logtype_cnid, "dbif_copy_rootinfokey: Error getting rootinfo record");
-        EC_FAIL;
+        if (dbif_get(dbd, DBIF_CNID, &key, &data, 0) <= 0) {
+            LOG(log_error, logtype_cnid, "dbif_copy_rootinfokey: Error getting rootinfo record");
+            copyRootInfo = false;
+        } else {
+            copyRootInfo = true;
+        }
+        (void)dbif_close(dbd);
     }
 
-    EC_NEG1_LOG( dbif_close(dbd) );
-    EC_NEG1_LOG( dbif_env_remove(bdata(dbpath)) );
     EC_ZERO_LOG( delete_db() );
+    EC_ZERO_LOG( open_db() );
 
-    /* Get db lock */
-    if ((db_locked = get_lock(LOCK_EXCL, bdata(dbpath))) != LOCK_EXCL) {
-        LOG(log_error, logtype_cnid, "main: fatal db lock error");
-        EC_FAIL;
-    }
-
-    EC_NULL_LOG( dbd = dbif_init(bdata(dbpath), "cnid2.db") );
-
-    /* Only recover if we got the lock */
-    EC_NEG1_LOG( dbif_env_open(dbd, dbp, DBOPTIONS | DB_RECOVER) );
+    if (copyRootInfo == true) {
+        memset(&key, 0, sizeof(key));
+        key.data = ROOTINFO_KEY;
+        key.size = ROOTINFO_KEYLEN;
 
-    LOG(log_debug, logtype_cnid, "Finished initializing BerkeleyDB environment");
-
-    EC_NEG1_LOG( dbif_open(dbd, dbp, 0) );
-
-    memset(&key, 0, sizeof(key));
-    key.data = ROOTINFO_KEY;
-    key.size = ROOTINFO_KEYLEN;
-
-    if (dbif_put(dbd, DBIF_CNID, &key, &data, 0) != 0) {
-        LOG(log_error, logtype_cnid, "dbif_copy_rootinfokey: Error writing rootinfo key");
-        EC_FAIL;
+        if (dbif_put(dbd, DBIF_CNID, &key, &data, 0) != 0) {
+            LOG(log_error, logtype_cnid, "dbif_copy_rootinfokey: Error writing rootinfo key");
+            EC_FAIL;
+        }
     }
 
 EC_CLEANUP:
@@ -180,7 +308,7 @@ static int loop(struct db_param *dbp)
         dbp->flush_interval, timebuf);
 
     while (1) {
-        timeout = min(time_next_flush, time_last_rqst +dbp->idle_timeout);
+        timeout = MIN(time_next_flush, time_last_rqst + dbp->idle_timeout);
         if (timeout > now)
             timeout -= now;
         else
@@ -242,7 +370,7 @@ static int loop(struct db_param *dbp)
                 ret = dbd_search(dbd, &rqst, &rply);
                 break;
             case CNID_DBD_OP_WIPE:
-                ret = wipe_db();
+                ret = reinit_db();
                 break;
             default:
                 LOG(log_error, logtype_cnid, "loop: unknown op %d", rqst.op);
@@ -351,12 +479,12 @@ int main(int argc, char *argv[])
     int ctrlfd = -1, clntfd = -1;
     char *logconfig;
     AFPObj obj = { 0 };
-    struct vol *vol;
     char *volpath = NULL;
 
     while (( ret = getopt( argc, argv, "dF:l:p:t:vV")) != -1 ) {
         switch (ret) {
         case 'd':
+            /* this is now just ignored, as we do it automatically anyway */
             delete_bdb = 1;
             break;
         case 'F':
@@ -397,17 +525,6 @@ int main(int argc, char *argv[])
 
     switch_to_user(bdata(dbpath));
 
-    /* Get db lock */
-    if ((db_locked = get_lock(LOCK_EXCL, bdata(dbpath))) != LOCK_EXCL) {
-        LOG(log_error, logtype_cnid, "main: fatal db lock error");
-        EC_FAIL;
-    }
-
-    if (delete_bdb) {
-        LOG(log_warning, logtype_cnid, "main: too many CNID db opening attempts, wiping the slate clean");
-        EC_ZERO( delete_db() );
-    }
-
     set_signal();
 
     /* SIGINT and SIGTERM are always off, unless we are in pselect */
@@ -417,37 +534,11 @@ int main(int argc, char *argv[])
         EC_FAIL;
     LOG(log_maxdebug, logtype_cnid, "Finished parsing db_param config file");
 
-    if (NULL == (dbd = dbif_init(bdata(dbpath), "cnid2.db")))
-        EC_FAIL;
-
-    /* Only recover if we got the lock */
-    if (dbif_env_open(dbd,
-                      dbp,
-                      (db_locked == LOCK_EXCL) ? DBOPTIONS | DB_RECOVER : DBOPTIONS) < 0)
-        EC_FAIL;
-    LOG(log_debug, logtype_cnid, "Finished initializing BerkeleyDB environment");
-
-    if (dbif_open(dbd, dbp, 0) < 0) {
-        ret = -1;
-        goto close_db;
-    }
-
-    LOG(log_debug, logtype_cnid, "Finished opening BerkeleyDB databases");
-
-    /* Downgrade db lock  */
-    if (db_locked == LOCK_EXCL) {
-        if (get_lock(LOCK_UNLOCK, NULL) != 0) {
-            ret = -1;
-            goto close_db;
-        }
-
-        if (get_lock(LOCK_SHRD, NULL) != LOCK_SHRD) {
-            ret = -1;
-            goto close_db;
-        }
+    if (open_db() != 0) {
+        LOG(log_error, logtype_cnid, "Failed to open CNID database for volume \"%s\"", vol->v_localname);
+        EC_ZERO_LOG( reinit_db() );
     }
 
-
     if (comm_init(dbp, ctrlfd, clntfd) < 0) {
         ret = -1;
         goto close_db;