cnid_metad_SOURCES = cnid_metad.c usockfd.c db_param.c
cnid_metad_LDADD = $(top_builddir)/libatalk/libatalk.la
-dbd_SOURCES = cmd_dbd.c cmd_dbd_scanvol.c cmd_dbd_lookup.c \
+dbd_SOURCES = cmd_dbd.c cmd_dbd_scanvol.c \
dbif.c pack.c \
dbd_delete.c dbd_update.c dbd_add.c dbd_lookup.c \
dbd_rebuild_add.c dbd_getstamp.c
with SIGTERM, it will be restarted automatically by cnid_metad as soon
as the volume is accessed again.
-cnid_metad needs one command line argument, the name of the cnid_dbd
-executeable. You can either specify "cnid_dbd" if it is in the path
-for cnid_metad or otherwise use the fully qualified pathname to
-cnid_dbd, e.g. /usr/local/netatalk/sbin/cnid_dbd. cnid_metad listens
-on TCP port 4700 by default for request from afpd processes.
-
cnid_dbd changes to the Berkeley DB directory on startup and sets
effective UID and GID to owner and group of that directory. Database and
-supporting files should therefore be writeable by that user/group. cnid_dbd
-reads configuration information from the file db_param in the database
-directory on startup. If the file does not exist, suitable default
-values for all parameters are used. The format for a single parameter
-is the parameter name, followed by one or more spaces, followed by the
-parameter value, followed by a newline. The following parameters are
-currently recognized:
-
-Name Default
-==== =======
-cachesize 8192
-flush_frequency 100
-flush_interval 1800
-usock_file <databasedirectory>/usock
-fd_table_size 128
-idle_timeout 600
-
-"cachesize" determines the size of the Berkeley DB cache in
-kilobytes. Each cnid_dbd process grabs that much memory on top of its
-normal memory footprint. It can be used to tune database
-performance. The db_stat utility with the "-m" option that comes with
-Berkely DB can help you determine wether you need to change this
-value. The default is pretty conservative so that a large percentage
-of requests should be satisfied from the cache directly. If memory is
-not a bottleneck on your system you might want to leave it at that
-value. The Berkeley DB Tutorial and Reference Guide has a section
-"Selecting a cache size" that gives more detailed information.
-
-"flush_frequency" and "flush_interval" control how often changes to
-the database are written to the underlying database files if no
-transactions are used or how often the transaction system is
-checkpointed for transactions. Both of these operations are
-performed if either i) more than flush_frequency requests have been
-received or ii) more than flush_interval seconds have elapsed since
-the last save/checkpoint.
-Be careful to check your harddisk configuration for on disk cache
-settings. Many IDE disks just cache writes as the default behaviour,
-so even flushing database files to disk will not have the desired effect.
-
-"usock_file" gives the pathname of the unix domain socket file that
-that instance of cnid_dbd will use for receiving requests. You might
-have to use another value if the total length of the default pathname
-exceeds the limits for unix domain socket files on your system,
-usually this is something like 100 bytes.
-
-"fd_table_size" is the maximum number of connections (filedescriptors)
-that can be open for afpd client processes in cnid_dbd. If this number
-is exceeded, one of the existing connections is closed and reused. The
-affected afpd process will transparently reconnect later, which causes
-slight overhead. On the other hand, setting this parameter too high
-could affect performance in cnid_dbd since all descriptors have to be
-checked in a select() system call, or worse, you might exceed the per
-process limit of open file descriptors on your system. It is safe to
-set the value to 1 on volumes where only one afpd client process
-is expected to run, e.g. home directories.
-
-"idle_timeout" is the number of seconds of inactivity before an idle
-cnid_dbd exits. Set this to 0 to disable the timeout.
+supporting files should therefore be writeable by that user/group.
Current shortcomings:
-- The implementation for cnid_dbd doubles code from libatalk/cnid,
-making it more difficult to keep changes to the library interface and
-the semantics of database requests in sync. If cnid_dbd takes over
-the world, this problem will eventually disappear, otherwise it should
-be possible to merge things again, if transactional support is
-eliminated from libatalk/cnid. I do not think it can work relieably in
-the current form anyway.
-
-- mmap for IPC would be nice as an alternative.
-
- The parameter file parsing of db_param is very simpleminded. It is
easy to cause buffer overruns and the like.
Also, there is no support for blanks (or weird characters) in
/*
- $Id: cmd_dbd.c,v 1.14 2009-11-24 14:48:07 franklahm Exp $
+ $Id: cmd_dbd.c,v 1.15 2009-11-25 14:59:15 franklahm Exp $
Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
" -x rebuild indexes (just for completeness, mostly useless!)\n"
" -v verbose\n\n"
"WARNING:\n"
- "If you want/need to run an -r -f rebuild after adding 'cachecnid' to a volume configuration,\n"
- "you must run a rebuild with -r alone at first in order to sync all existing CNIDs from the db\n"
- "to the AppleDouble files!\n"
+ "For -r -f restore of the CNID database from the adouble files, the CNID must of course\n"
+ "be synched to them files first with a plain -r rebuild !\n"
);
}
Functions for querying the database which couldn't be reused from the existing
funcs pool of dbd_* for one reason or another
*/
-extern int cmd_dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int roflag);
extern int cmd_dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply);
#endif /* CMD_DBD_H */
+++ /dev/null
-/*
- * $Id: cmd_dbd_lookup.c,v 1.3 2009-10-14 01:38:28 didg Exp $
- *
- * Copyright (C) Frank Lahm 2009
- * All Rights Reserved. See COPYING.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/param.h>
-#include <errno.h>
-#include <netatalk/endian.h>
-#include <atalk/logger.h>
-#include <atalk/cnid_dbd_private.h>
-
-#include "pack.h"
-#include "dbif.h"
-#include "dbd.h"
-#include "cmd_dbd.h"
-
-/*
- ATTENTION:
- whatever you change here, also change cmd_dbd_lookup.c !
- cmd_dbd_lookup has an read-only mode, but besides that it's the same.
- */
-
-
-/*
- * This returns the CNID corresponding to a particular file and logs any inconsitencies.
- * If roflags == 1 we only scan, if roflag == 0, we modify i.e. call dbd_update
- * FIXME: realign this wih dbd_lookup.
- */
-
-int cmd_dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int roflag)
-{
- unsigned char *buf;
- DBT key, devdata, diddata;
- uint64_t dev = 0;
- int devino = 1, didname = 1;
- int rc;
- cnid_t id_devino, id_didname;
- u_int32_t type_devino = (unsigned)-1;
- u_int32_t type_didname = (unsigned)-1;
- int update = 0;
-
- memset(&key, 0, sizeof(key));
- memset(&diddata, 0, sizeof(diddata));
- memset(&devdata, 0, sizeof(devdata));
-
- rply->namelen = 0;
- rply->cnid = 0;
-
- buf = pack_cnid_data(rqst);
-
- /* Look for a CNID. We have two options: dev/ino or did/name. If we
- only get a match in one of them, that means a file has moved. */
- key.data = buf + CNID_DEVINO_OFS;
- key.size = CNID_DEVINO_LEN;
-
- if ((rc = dbif_get(dbd, DBIF_IDX_DEVINO, &key, &devdata, 0)) < 0) {
- dbd_log( LOGSTD, "dbd_search: Unable to get CNID %u, name %s",
- ntohl(rqst->did), rqst->name);
- rply->result = CNID_DBD_RES_ERR_DB;
- return -1;
- }
- if (rc == 0) {
- devino = 0;
- }
- else {
- memcpy(&id_devino, devdata.data, sizeof(rply->cnid));
- memcpy(&type_devino, (char *)devdata.data +CNID_TYPE_OFS, sizeof(type_devino));
- type_devino = ntohl(type_devino);
- }
-
- key.data = buf + CNID_DID_OFS;
- key.size = CNID_DID_LEN + rqst->namelen + 1;
-
- if ((rc = dbif_get(dbd, DBIF_IDX_DIDNAME, &key, &diddata, 0)) < 0) {
- dbd_log( LOGSTD, "dbd_search: Unable to get CNID %u, name %s",
- ntohl(rqst->did), rqst->name);
- rply->result = CNID_DBD_RES_ERR_DB;
- return -1;
- }
- if (rc == 0) {
- didname = 0;
- }
- else {
- memcpy(&id_didname, diddata.data, sizeof(rply->cnid));
- memcpy(&type_didname, (char *)diddata.data +CNID_TYPE_OFS, sizeof(type_didname));
- type_didname = ntohl(type_didname);
- }
-
- if (!devino && !didname) {
- /* not found */
- dbd_log( LOGDEBUG, "name: '%s/%s', did: %u, dev/ino: 0x%llx/0x%llx is not in the CNID database",
- cwdbuf, rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
- rply->result = CNID_DBD_RES_NOTFOUND;
- return 1;
- }
-
- if (devino && didname && id_devino == id_didname && type_devino == rqst->type) {
- /* the same */
- rply->cnid = id_didname;
- rply->result = CNID_DBD_RES_OK;
- return 1;
- }
-
- /*
- Order matters for the next 2 ifs because both found a CNID but they didn't match.
- So in order to pick the CNID from "didname" it must come after devino.
- See test cases laid out in dbd_lookup.c.
- */
- if (devino) {
- dbd_log( LOGSTD, "CNID resolve problem: server side rename oder reused inode for '%s/%s'", cwdbuf, rqst->name);
- rqst->cnid = id_devino;
- if (type_devino != rqst->type) {
- /* same dev/inode but not same type: it's an inode reused, delete the record */
- if (! roflag)
- if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
- return -1;
- }
- else {
- update = 1;
- }
- }
- if (didname) {
- dbd_log( LOGSTD, "CNID resolve problem: changed dev/ino for '%s/%s'", cwdbuf, rqst->name);
- rqst->cnid = id_didname;
- /* we have a did/name.
- If it's the same dev or not the same type, e.g. a remove followed by a new file
- with the same name */
- if (!memcmp(&dev, (char *)diddata.data + CNID_DEV_OFS, CNID_DEV_LEN) ||
- type_didname != rqst->type) {
- if (! roflag)
- if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
- return -1;
- }
- else {
- update = 1;
- }
- }
-
- if (!update || roflag) {
- rply->result = CNID_DBD_RES_NOTFOUND;
- return 1;
- }
- /* Fix up the database. assume it was a file move and rename */
- rc = dbd_update(dbd, rqst, rply);
- if (rc >0) {
- rply->cnid = rqst->cnid;
- }
-
- dbd_log( LOGSTD, "CNID database needed update: dev/ino: 0x%llx/0x%llx, did: %u, name: '%s/%s' --> CNID: %u",
- (unsigned long long)rqst->dev, (unsigned long long)rqst->ino,
- ntohl(rqst->did), cwdbuf, rqst->name, ntohl(rply->cnid));
-
- return rc;
-}
-
-/*
- This is taken from dbd_add.c, but this func really is only "add", dbd_add calls dbd_lookup
- before adding.
- FIXME: realign with dbd_add using e.g. using a new arg like "int lookup".
-*/
-int cmd_dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
-{
- if (get_cnid(dbd, rply) < 0) {
- if (rply->result == CNID_DBD_RES_ERR_MAX) {
- dbd_log( LOGSTD, "FATAL: CNID database has reached its limit.");
- /* This will cause an abort/rollback if transactions are used */
- return 0;
- } else {
- dbd_log( LOGSTD, "Failed to compute CNID for %s, error reading/updating Rootkey", rqst->name);
- return -1;
- }
- }
-
- if (add_cnid(dbd, rqst, rply) < 0) {
- if (rply->result == CNID_DBD_RES_ERR_DUPLCNID) {
- dbd_log( LOGSTD, "Cannot add CNID %u. Corrupt/invalid Rootkey?.", ntohl(rply->cnid));
- /* abort/rollback, see above */
- return 0;
- } else {
- dbd_log( LOGSTD, "Failed to add CNID for %s to database", rqst->name);
- return -1;
- }
- }
- dbd_log( LOGDEBUG, "Add to CNID database: did: %u, cnid: %u, name: '%s', dev/ino: 0x%llx/0x%llx",
- ntohl(rqst->did), ntohl(rply->cnid), rqst->name,
- (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
-
- rply->result = CNID_DBD_RES_OK;
- return 1;
-}
/*
- $Id: cmd_dbd_scanvol.c,v 1.10 2009-10-14 01:38:28 didg Exp $
+ $Id: cmd_dbd_scanvol.c,v 1.11 2009-11-25 14:59:15 franklahm Exp $
Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
rqst.namelen = strlen(name);
/* Query the database */
- ret = cmd_dbd_lookup(dbd, &rqst, &rply, (dbd_flags & DBD_FLAGS_SCAN) ? 1 : 0);
+ ret = dbd_lookup(dbd, &rqst, &rply, (dbd_flags & DBD_FLAGS_SCAN) ? 1 : 0);
dbif_txn_close(dbd, ret);
if (rply.result == CNID_DBD_RES_OK) {
db_cnid = rply.cnid;
/* Note: the next test will use this new CNID too! */
if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
/* add to db */
- ret = cmd_dbd_add(dbd, &rqst, &rply);
+ ret = dbd_add(dbd, &rqst, &rply, 1);
dbif_txn_close(dbd, ret);
db_cnid = rply.cnid;
dbd_log( LOGSTD, "New CNID for '%s/%s': %u", cwdbuf, name, ntohl(db_cnid));
/*
- * $Id: dbd.h,v 1.6 2009-10-14 01:38:28 didg Exp $
+ * $Id: dbd.h,v 1.7 2009-11-25 14:59:15 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* Copyright (C) Frank Lahm 2009
extern int get_cnid(DBD *dbd, struct cnid_dbd_rply *rply);
extern int dbd_stamp(DBD *dbd);
-extern int dbd_add(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
+extern int dbd_add(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *, int nolookup);
+extern int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *, int roflag);
extern int dbd_get(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
extern int dbd_resolve(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
-extern int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
extern int dbd_update(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
extern int dbd_delete(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *, int idx);
extern int dbd_getstamp(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
/*
- * $Id: dbd_add.c,v 1.6 2009-05-14 13:46:08 franklahm Exp $
+ * $Id: dbd_add.c,v 1.7 2009-11-25 14:59:15 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* All Rights Reserved. See COPYING.
}
/* ------------------------ */
-int dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
+/* We need a nolookup version for `dbd` */
+int dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int nolookup)
{
rply->namelen = 0;
/* See if we have an entry already and return it if yes */
- if (dbd_lookup(dbd, rqst, rply) < 0)
- return -1;
+ if (! nolookup) {
+ if (dbd_lookup(dbd, rqst, rply, 0) < 0)
+ return -1;
- if (rply->result == CNID_DBD_RES_OK) {
- /* Found it. rply->cnid is the correct CNID now. */
- LOG(log_debug, logtype_cnid, "dbd_add: dbd_lookup success, cnid %u", ntohl(rply->cnid));
- return 1;
+ if (rply->result == CNID_DBD_RES_OK) {
+ /* Found it. rply->cnid is the correct CNID now. */
+ LOG(log_debug, logtype_cnid, "dbd_add: dbd_lookup success --> CNID: %u", ntohl(rply->cnid));
+ return 1;
+ }
}
if (get_cnid(dbd, rply) < 0) {
if (add_cnid(dbd, rqst, rply) < 0) {
if (rply->result == CNID_DBD_RES_ERR_DUPLCNID) {
- LOG(log_error, logtype_cnid, "dbd_add: Cannot add CNID %u. Corrupt/invalid Rootkey?.", ntohl(rply->cnid));
+ LOG(log_error, logtype_cnid, "dbd_add(DID: %u/\"%s\", dev/ino 0x%llx/0x%llx): Cannot add CNID: %u",
+ ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rply->cnid));
/* abort/rollback, see above */
return 0;
} else {
return -1;
}
}
- LOG(log_debug, logtype_cnid, "dbd_add: Added dev/ino 0x%llx/0x%llx did %u name %s cnid %u",
- (unsigned long long)rqst->dev, (unsigned long long)rqst->ino,
- ntohl(rqst->did), rqst->name, ntohl(rply->cnid));
+ LOG(log_debug, logtype_cnid, "dbd_add(DID: %u/\"%s\", dev/ino 0x%llx/0x%llx): Added with CNID: %u",
+ ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rply->cnid));
rply->result = CNID_DBD_RES_OK;
return 1;
/*
- * $Id: dbd_lookup.c,v 1.10 2009-11-24 12:01:04 franklahm Exp $
+ * $Id: dbd_lookup.c,v 1.11 2009-11-25 14:59:15 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* Copyright (C) Frank Lahm 2009
*/
/*
- ATTENTION:
- whatever you change here, also change cmd_dbd_lookup.c !
- cmd_dbd_lookup has an read-only mode but besides that it's the same.
-*/
+CNID salvation spec:
+general rule: better safe then sorry, so we always delete CNIDs and assing
+new ones in case of a lookup mismatch.
+
-/*
The lines...
Id Did T Dev Inode Name
-->
f g h i h name2
-...are the expected results of certain operations.
+...are the expected results of certain operations. (f) is the speced CNID, in some
+cases it's only intermediate as described in the text and is overridden by another
+spec.
+1) UNIX rename (via mv) or inode reusage(!)
+-------------------------------------------
+Name is possibly changed (rename case) but inode is the same.
+We should try to keep the CNID, but we cant, because inode reusage is probably
+much to frequent.
-1) UNIX rename (mv)
--------------------
-Name is changed but inode stays the same. We should try to keep the CNID.
+rename:
+15 2 f 1 1 file
+-->
+15 x f 1 1 renamedfile
+inode reusage:
15 2 f 1 1 file
-->
-15 2 f 1 1 movedfile
+16 y f 1 1 inodereusagefile
Result in dbd_lookup (-: not found, +: found):
-- devino
-+ didname
++ devino
+- didname
Possible solution:
-Update.
+None. Delete old data, file gets new CNID in both cases (rename and inode).
-
-2) UNIX copy (cp)
------------------
-Changed inode and name. Result is just a new file which will get a fresh CNID.
-Unfortunately the old one gets orphaned.
+2) UNIX mv from one folder to another
+----------------------------------------
+Name is unchanged and inode stays the same, but DID is different.
+We should try to keep the CNID.
15 2 f 1 1 file
-->
-16 2 f 1 2 copyfile
+15 x f 1 1 file
Result in dbd_lookup:
-- devino
++ devino
- didname
-Possible fixup solution:
-Not possible. Only dbd -re can delete the orphaned CNID 15
-
+Possible solution:
+strcmp names, if they match keep CNID.
3) Restore from backup
----------------------
Possible fixup solution:
Update.
-
-4) inode reusage eg. UNIX emacs
--------------------------------
-This one is tough:
+4) emacs
+--------
emacs uses a backup file (file~). When saving because of inode reusage of the fs,
-both files exchange inodes. There's probably no appropiate solution for all
-scenarios where this might occur eg. for the emacs case it would be good to
-preserve the CNIDs while probably in the general case we should assign new CNIDs
-to both files:
+both files exchange inodes.
-General case:
+General case for inode reusage:
15 2 f 1 1 file
-->
16 2 f 1 1 new_file_with_reused_inode
+Result in dbd_lookup:
++ devino
+- didname
+
Emacs case:
15 2 f 1 1 file
16 2 f 1 2 file~
--->
-?? 2 f 1 2 file
-?? 2 f 1 1 file~
+--> this would be nice:
+15 2 f 1 2 file
+16 2 f 1 1 file~
+--> but because we must follow the general case you get this:
+17 2 f 1 2 file
+18 2 f 1 1 file~
-Result in dbd_lookup:
-+ devino
-+ didname
+Result in dbd_lookup for the emacs case:
++ devino --> CNID: 16
++ didname -> CNID: 15
+devino search and didname search result in different CNIDs !!
Possible fixup solution:
to be safe we must implement the general case, sorry emacs.
* up the database if there's a problem.
*/
-int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
+int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int roflag)
{
unsigned char *buf;
DBT key, devdata, diddata;
- char dev[CNID_DEV_LEN];
int devino = 1, didname = 1;
int rc;
cnid_t id_devino, id_didname;
u_int32_t type_didname = (unsigned)-1;
int update = 0;
-
memset(&key, 0, sizeof(key));
memset(&diddata, 0, sizeof(diddata));
memset(&devdata, 0, sizeof(devdata));
rply->cnid = 0;
buf = pack_cnid_data(rqst);
- memcpy(dev, buf + CNID_DEV_OFS, CNID_DEV_LEN);
/* Look for a CNID. We have two options: dev/ino or did/name. If we
only get a match in one of them, that means a file has moved. */
if ((rc = dbif_get(dbd, DBIF_IDX_DEVINO, &key, &devdata, 0)) < 0) {
LOG(log_error, logtype_cnid, "dbd_lookup: Unable to get CNID %u, name %s",
- ntohl(rqst->did), rqst->name);
+ ntohl(rqst->did), rqst->name);
rply->result = CNID_DBD_RES_ERR_DB;
return -1;
}
if ((rc = dbif_get(dbd, DBIF_IDX_DIDNAME, &key, &diddata, 0)) < 0) {
LOG(log_error, logtype_cnid, "dbd_lookup: Unable to get CNID %u, name %s",
- ntohl(rqst->did), rqst->name);
+ ntohl(rqst->did), rqst->name);
rply->result = CNID_DBD_RES_ERR_DB;
return -1;
}
memcpy(&type_didname, (char *)diddata.data +CNID_TYPE_OFS, sizeof(type_didname));
type_didname = ntohl(type_didname);
}
-
- if (!devino && !didname) {
- /* not found */
-
- LOG(log_debug, logtype_cnid, "cnid_lookup: dev/ino 0x%llx/0x%llx did %u name %s neither in devino nor didname",
- (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rqst->did), rqst->name);
+ /* Have we found anything at all ? */
+ if (!devino && !didname) {
+ /* nothing found */
+ LOG(log_debug, logtype_cnid, "dbd_lookup: name: '%s', did: %u, dev/ino: 0x%llx/0x%llx is not in the CNID database",
+ rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
rply->result = CNID_DBD_RES_NOTFOUND;
return 1;
}
- if (devino && didname && id_devino == id_didname && type_devino == rqst->type) {
- /* the same */
-
- LOG(log_debug, logtype_cnid, "cnid_lookup: Looked up dev/ino 0x%llx/0x%llx did %u name %s as %u",
- (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rqst->did), rqst->name, ntohl(id_didname));
+ /* Check for type (file/dir) mismatch */
+ if (devino && (type_devino != rqst->type)) {
+ /* one is a dir one is a file, remove from db */
+ rqst->cnid = id_devino;
+ if (! roflag)
+ if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+ return -1;
+ rply->result = CNID_DBD_RES_NOTFOUND;
+ return 1;
+ } else if (didname && (type_didname != rqst->type)) {
+ /* same: one is a dir one is a file, remove from db */
+ rqst->cnid = id_didname;
+ if (! roflag)
+ if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+ return -1;
+ rply->result = CNID_DBD_RES_NOTFOUND;
+ return 1;
+ }
+ if (devino && didname && id_devino == id_didname) {
+ /* everything is fine */
+ LOG(log_debug, logtype_cnid, "dbd_lookup(DID:%u/'%s',0x%llx/0x%llx): Got CNID: %u",
+ ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, htonl(id_didname));
rply->cnid = id_didname;
rply->result = CNID_DBD_RES_OK;
return 1;
}
-
- /*
- Order matters for the next 2 ifs because both found a CNID but they do not match.
- So in order to pick the CNID from "didname" it must come after devino.
- See test cases laid out in dbd_lookup.c.
- */
- if (devino) {
- LOG(log_maxdebug, logtype_cnid, "CNID resolve problem: server side rename oder reused inode for '%s'", rqst->name);
- rqst->cnid = id_devino;
- if (type_devino != rqst->type) {
- /* same dev:inode but not same type one is a folder the other
- * is a file,it's an inode reused, delete the record
- */
- if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0) {
+
+ if (devino && didname && id_devino != id_didname) {
+ /* CNIDs don't match, something of a worst case! */
+ LOG(log_debug, logtype_cnid, "dbd_lookup: CNID mismatch: (DID:%u/'%s') --> %u , (0x%llx/0x%llx) --> %u",
+ ntohl(rqst->did), rqst->name, ntohl(id_didname),
+ (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(id_devino));
+
+ /* Something like 5), the emacs case (see above), remove it all */
+ if (! roflag) {
+ rqst->cnid = id_devino;
+ if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+ return -1;
+
+ rqst->cnid = id_didname;
+ if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
return -1;
- }
}
- else {
+ rply->result = CNID_DBD_RES_NOTFOUND;
+ return 1;
+ }
+
+ if ( ! didname) {
+ LOG(log_debug, logtype_cnid, "dbd_lookup(DID:%u/'%s',0x%llx/0x%llx): CNID resolve problem: server side rename oder reused inode",
+ ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
+ rqst->cnid = id_devino;
+ /* Case 2) ? */
+ if (strcmp(rqst->name, (char *)devdata.data + CNID_NAME_OFS) == 0) {
+ LOG(log_debug, logtype_cnid, "dbd_lookup: server side mv from one dir to another");
update = 1;
+ } else {
+ if ( ! roflag)
+ if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+ return -1;
+ rply->result = CNID_DBD_RES_NOTFOUND;
+ return 1;
}
}
- if (didname) {
- LOG(log_maxdebug, logtype_cnid, "CNID resolve problem: changed dev/ino for '%s'", rqst->name);
+
+ if ( ! devino) {
+ LOG(log_debug, logtype_cnid, "dbd_lookup(DID:%u/'%s',0x%llx/0x%llx): CNID resolve problem: changed dev/ino",
+ ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
rqst->cnid = id_didname;
- /* we have a did:name
- * if it's the same dev or not the same type
- * just delete it
- */
- if (!memcmp(dev, (char *)diddata.data + CNID_DEV_OFS, CNID_DEV_LEN) ||
- type_didname != rqst->type) {
- if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0) {
- return -1;
- }
- }
- else {
- update = 1;
- }
+ update = 1;
}
- if (!update) {
+
+ /* This is also a catch all if we've forgot to catch some possibility with the preceding ifs*/
+ if (!update || roflag) {
rply->result = CNID_DBD_RES_NOTFOUND;
return 1;
}
- /* Fix up the database. assume it was a file move and rename */
+
+ /* Fix up the database */
rc = dbd_update(dbd, rqst, rply);
if (rc >0) {
rply->cnid = rqst->cnid;
}
- LOG(log_debug, logtype_cnid, "cnid_lookup: Looked up dev/ino 0x%llx/0x%llx did %u name %s as %u (needed update)",
- (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rqst->did), rqst->name, ntohl(rply->cnid));
+ LOG(log_debug, logtype_cnid, "dbd_lookup(DID:%u/'%s',0x%llx/0x%llx): Got CNID (needed update): %u",
+ ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rply->cnid));
return rc;
}
/*
- * $Id: dbif.c,v 1.16 2009-10-14 01:38:28 didg Exp $
+ * $Id: dbif.c,v 1.17 2009-11-25 14:59:15 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* Copyright (C) Frank Lahm 2009
}
if ((stat(dbd->db_filename, &st)) == 0) {
- LOG(log_debug, logtype_cnid, "See if we can upgrade the CNID database");
+ LOG(log_debug, logtype_cnid, "See if we can upgrade the CNID database...");
if ((ret = db_create(&upgrade_db, dbd->db_env, 0))) {
LOG(log_error, logtype_cnid, "error creating handle for database: %s", db_strerror(ret));
return -1;
LOG(log_error, logtype_cnid, "error forcing checkpoint: %s", db_strerror(ret));
return -1;
}
+ LOG(log_debug, logtype_cnid, "Finished CNID database upgrade check");
}
if ((fchdir(cwd)) != 0) {
/*
- * $Id: main.c,v 1.15 2009-10-19 08:09:07 didg Exp $
+ * $Id: main.c,v 1.16 2009-11-25 14:59:15 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* Copyright (c) Frank Lahm 2009
ret = 1;
break;
case CNID_DBD_OP_ADD:
- ret = dbd_add(dbd, &rqst, &rply);
+ ret = dbd_add(dbd, &rqst, &rply, 0);
break;
case CNID_DBD_OP_GET:
ret = dbd_get(dbd, &rqst, &rply);
ret = dbd_resolve(dbd, &rqst, &rply);
break;
case CNID_DBD_OP_LOOKUP:
- ret = dbd_lookup(dbd, &rqst, &rply);
+ ret = dbd_lookup(dbd, &rqst, &rply, 0);
break;
case CNID_DBD_OP_UPDATE:
ret = dbd_update(dbd, &rqst, &rply);