summaryrefslogtreecommitdiff
path: root/db/fileops
diff options
context:
space:
mode:
authorjbj <devnull@localhost>2003-01-24 17:11:36 +0000
committerjbj <devnull@localhost>2003-01-24 17:11:36 +0000
commit19884892c015cd7371f0b2cee666484f159fbf43 (patch)
tree8669e9f9684dc0a2af4deef8d8ad3bf78a5762ba /db/fileops
parent7e716b70fb68cbef5bd35e154a734269067f1e37 (diff)
downloadrpm-19884892c015cd7371f0b2cee666484f159fbf43.tar.gz
rpm-19884892c015cd7371f0b2cee666484f159fbf43.tar.bz2
rpm-19884892c015cd7371f0b2cee666484f159fbf43.zip
Apply patches 9+10, equivalent to db-4.1.25 now.
CVS patchset: 6024 CVS date: 2003/01/24 17:11:36
Diffstat (limited to 'db/fileops')
-rw-r--r--db/fileops/fop_rec.c23
-rw-r--r--db/fileops/fop_util.c139
2 files changed, 116 insertions, 46 deletions
diff --git a/db/fileops/fop_rec.c b/db/fileops/fop_rec.c
index 8150a81e4..766b74151 100644
--- a/db/fileops/fop_rec.c
+++ b/db/fileops/fop_rec.c
@@ -8,7 +8,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "Id: fop_rec.c,v 1.16 2002/07/08 19:54:51 margo Exp ";
+static const char revid[] = "Id: fop_rec.c,v 1.18 2002/08/14 20:27:01 bostic Exp ";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -156,7 +156,7 @@ __fop_rename_recover(dbenv, dbtp, lsnp, op, info)
__fop_rename_args *argp;
DBMETA *meta;
char *real_new, *real_old, *src;
- int ret, t_ret;
+ int ret;
u_int8_t *fileid, mbuf[DBMETASIZE];
real_new = NULL;
@@ -189,12 +189,10 @@ __fop_rename_recover(dbenv, dbtp, lsnp, op, info)
* way, shape or form, incorrect, so that we should not restore
* it.
*/
- if ((ret = __fop_read_meta(dbenv,
- src, mbuf, DBMETASIZE, NULL, 1, 0)) != 0) {
- ret = 0;
+ if (__fop_read_meta(
+ dbenv, src, mbuf, DBMETASIZE, NULL, 1, NULL, 0) != 0)
goto done;
- }
- if ((t_ret = __db_chk_meta(dbenv, NULL, meta, 1)) != 0)
+ if (__db_chk_meta(dbenv, NULL, meta, 1) != 0)
goto done;
if (memcmp(argp->fileid.data, meta->uid, DB_FILE_ID_LEN) != 0)
goto done;
@@ -239,6 +237,7 @@ __fop_file_remove_recover(dbenv, dbtp, lsnp, op, info)
DBMETA *meta;
char *real_name;
int is_real, is_tmp, ret;
+ size_t len;
u_int8_t mbuf[DBMETASIZE];
u_int32_t cstat;
@@ -262,7 +261,15 @@ __fop_file_remove_recover(dbenv, dbtp, lsnp, op, info)
/* Verify that we are manipulating the correct file. */
if ((ret = __fop_read_meta(dbenv,
- real_name, mbuf, DBMETASIZE, NULL, 1, 0)) != 0) {
+ real_name, mbuf, DBMETASIZE, NULL, 1, &len, 0)) != 0) {
+ /*
+ * If len is non-zero, then the file exists and has something
+ * in it, but that something isn't a full meta-data page, so
+ * this is very bad. Bail out!
+ */
+ if (len != 0)
+ goto out;
+
/* File does not exist. */
cstat = TXN_EXPECTED;
} else {
diff --git a/db/fileops/fop_util.c b/db/fileops/fop_util.c
index 2c89f61e6..329ec3f28 100644
--- a/db/fileops/fop_util.c
+++ b/db/fileops/fop_util.c
@@ -8,7 +8,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "Id: fop_util.c,v 1.49 2002/08/07 15:40:06 margo Exp ";
+static const char revid[] = "Id: fop_util.c,v 1.52 2002/09/10 02:41:42 bostic Exp ";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -61,8 +61,11 @@ static int __fop_set_pgsize __P((DB *, DB_FH *, const char *));
if (F_ISSET((F), DB_FH_VALID)) { \
if (LF_ISSET(DB_FCNTL_LOCKING)) \
(D)->saved_open_fhp = (F); \
- else if ((ret = __os_closehandle((D)->dbenv,(F))) != 0) \
+ else if ((t_ret = __os_closehandle((D)->dbenv,(F))) != 0) { \
+ if (ret == 0) \
+ ret = t_ret; \
goto err; \
+ } \
} \
}
@@ -167,13 +170,13 @@ __fop_file_setup(dbp, txn, name, mode, flags, retidp)
DB_ENV *dbenv;
DB_FH fh, *fhp;
DB_LOCK elock, tmp_lock;
- DB_LSN lsn;
DB_TXN *stxn;
+ char *real_name, *real_tmpname, *tmpname;
db_lockmode_t lmode;
+ int created_fhp, created_locker, ret, tmp_created, t_ret, truncating;
+ size_t len;
u_int32_t locker, oflags;
u_int8_t mbuf[DBMETASIZE];
- int created_fhp, created_locker, ret, tmp_created, truncating;
- char *real_name, *real_tmpname, *tmpname;
DB_ASSERT(name != NULL);
@@ -190,7 +193,7 @@ __fop_file_setup(dbp, txn, name, mode, flags, retidp)
/*
* If we open a file handle and our caller is doing fcntl(2) locking,
* we can't close it because that would discard the caller's lock.
- * Save it until we close the DB handle.
+ * Save it until we close or refresh the DB handle.
*/
if (LF_ISSET(DB_FCNTL_LOCKING)) {
if ((ret = __os_malloc(dbenv, sizeof(*fhp), &fhp)) != 0)
@@ -234,8 +237,40 @@ retry: if (!F_ISSET(dbp, DB_AM_COMPENSATE))
ret = EEXIST;
goto err;
}
-reopen: if ((ret = __fop_read_meta(dbenv, real_name,
- mbuf, sizeof(mbuf), fhp, 0, oflags)) != 0)
+
+ /*
+ * This is special handling for applications that
+ * are locking outside of Berkeley DB (e.g., Sendmail,
+ * Postfix). If we are relying on external FCNTL
+ * locking and we're going to truncate the file, we
+ * cannot first open the file to verify that it is
+ * a DB file and then close/reopen to do the truncate
+ * since that will lose the external FCNTL lock.
+ * So, we special case it and leap right into the
+ * truncate code.
+ */
+ if (LF_ISSET(DB_FCNTL_LOCKING) && LF_ISSET(DB_TRUNCATE))
+ goto do_trunc;
+
+reopen: ret = __fop_read_meta(dbenv, real_name,
+ mbuf, sizeof(mbuf), fhp,
+ LF_ISSET(DB_FCNTL_LOCKING) && txn == NULL ? 1 : 0,
+ &len, oflags);
+ /*
+ * This is special handling for applications that are doing
+ * file locking outside of Berkeley DB (e.g., Sendmail,
+ * Postfix). So, if you're doing FCNTL_LOCKING and are non
+ * transactional, we're going to treat 0-length files as a
+ * special case and let you proceed.
+ */
+ if (ret != 0 &&
+ LF_ISSET(DB_FCNTL_LOCKING) && txn == NULL && len == 0) {
+ tmpname = (char *)real_name;
+ real_name = NULL;
+ goto creat2;
+ }
+
+ if (ret != 0)
goto err;
if ((ret = __db_meta_setup(dbenv,
@@ -249,7 +284,14 @@ reopen: if ((ret = __fop_read_meta(dbenv, real_name,
if ((ret = REL_ENVLOCK(dbenv, &elock)) != 0)
goto err;
} else {
- /* Someone else has file locked; need to wait. */
+ /*
+ * If someone is doing FCNTL locking outside of us,
+ * then we should never have a lock conflict and
+ * should never get to here. We need to assert that
+ * because we are about to close the fd which will
+ * release the FCNTL locks.
+ */
+ DB_ASSERT(!LF_ISSET(DB_FCNTL_LOCKING));
if ((ret = __os_closehandle(dbenv, fhp)) != 0)
goto err;
ret = __fop_lock_handle(dbenv,
@@ -281,7 +323,7 @@ reopen: if ((ret = __fop_read_meta(dbenv, real_name,
*/
if ((ret = __os_closehandle(dbenv, fhp)) != 0)
goto err;
- if ((ret = __os_open(dbenv,
+do_trunc: if ((ret = __os_open(dbenv,
real_name, DB_OSO_TRUNC, 0, fhp)) != 0)
goto err;
/*
@@ -324,11 +366,7 @@ reopen: if ((ret = __fop_read_meta(dbenv, real_name,
if ((ret = REL_ENVLOCK(dbenv, &elock)) != 0)
goto err;
-create: if (txn == NULL)
- ZERO_LSN(lsn);
- else
- lsn = txn->last_lsn;
- if ((ret = __db_backup_name(dbenv, name, txn, &tmpname, &lsn)) != 0)
+create: if ((ret = __db_backup_name(dbenv, name, txn, &tmpname)) != 0)
goto err;
if (TXN_ON(dbenv) && txn != NULL &&
(ret = dbenv->txn_begin(dbenv, txn, &stxn, 0)) != 0)
@@ -413,7 +451,7 @@ err: if (stxn != NULL)
(void)__fop_remove(dbenv,
NULL, NULL, tmpname, DB_APP_DATA);
if (F_ISSET(fhp, DB_FH_VALID))
- (void)__os_closehandle(dbenv, fhp);
+ CLOSE_HANDLE(dbp, fhp);
if (LOCK_ISSET(tmp_lock))
__lock_put(dbenv, &tmp_lock);
if (LOCK_ISSET(dbp->handle_lock) && txn == NULL)
@@ -424,11 +462,16 @@ err: if (stxn != NULL)
(void)__lock_id_free(dbenv, dbp->lid);
dbp->lid = DB_LOCK_INVALIDID;
}
- if (created_fhp)
+ if (created_fhp && !F_ISSET(fhp, DB_FH_VALID))
__os_free(dbenv, fhp);
}
-done: if (!truncating && tmpname != NULL)
+done: /*
+ * There are cases where real_name and tmpname take on the
+ * exact same string, so we need to make sure that we do not
+ * free twice.
+ */
+ if (!truncating && tmpname != NULL && tmpname != real_name)
__os_free(dbenv, tmpname);
if (real_name != NULL)
__os_free(dbenv, real_name);
@@ -509,7 +552,7 @@ __fop_subdb_setup(dbp, txn, mname, name, mode, flags)
{
DB *mdbp;
DB_ENV *dbenv;
- int remove, ret;
+ int do_remove, ret;
mdbp = NULL;
dbenv = dbp->dbenv;
@@ -581,7 +624,7 @@ __fop_subdb_setup(dbp, txn, mname, name, mode, flags)
/*
* The master's handle lock is under the control of the
- * subdb (it acquired the master's locker. We want to
+ * subdb (it acquired the master's locker). We want to
* keep the master's handle lock so that no one can remove
* the file while the subdb is open. If we register the
* trade event and then invalidate the copy of the lock
@@ -610,11 +653,11 @@ DB_TEST_RECOVERY_LABEL
/* If we created the master file then we need to remove it. */
if (mdbp != NULL) {
- remove = F_ISSET(mdbp, DB_AM_CREATED) ? 1 : 0;
- if (remove)
+ do_remove = F_ISSET(mdbp, DB_AM_CREATED) ? 1 : 0;
+ if (do_remove)
F_SET(mdbp, DB_AM_DISCARD);
(void)__db_close_i(mdbp, txn, 0);
- if (remove) {
+ if (do_remove) {
(void)db_create(&mdbp, dbp->dbenv, 0);
(void)__db_remove_i(mdbp, txn, mname, NULL);
}
@@ -637,6 +680,7 @@ __fop_remove_setup(dbp, txn, name, flags)
u_int32_t flags;
{
DB_ENV *dbenv;
+ DB_FH *fhp;
DB_LOCK elock;
u_int8_t mbuf[DBMETASIZE];
int ret;
@@ -657,13 +701,27 @@ __fop_remove_setup(dbp, txn, name, flags)
}
/*
+ * We are about to open a file handle and then possibly close it.
+ * We cannot close handles if we are doing FCNTL locking. However,
+ * there is no way to pass the FCNTL flag into this routine via the
+ * user API. The only way we can get in here and be doing FCNTL
+ * locking is if we are trying to clean up an open that was called
+ * with FCNTL locking. In that case, the save_fhp should already be
+ * set. So, we use that field to tell us if we need to make sure
+ * that we shouldn't close the handle.
+ */
+ fhp = dbp->saved_open_fhp;
+ DB_ASSERT(LF_ISSET(DB_FCNTL_LOCKING) ||
+ fhp == NULL || !F_ISSET(fhp, DB_FH_VALID));
+
+ /*
* Lock environment to protect file open. That will enable us to
* read the meta-data page and get the fileid so that we can lock
* the handle.
*/
GET_ENVLOCK(dbenv, dbp->lid, &elock);
if ((ret = __fop_read_meta(dbenv,
- name, mbuf, sizeof(mbuf), NULL, 0, 0)) != 0)
+ name, mbuf, sizeof(mbuf), fhp, 0, NULL, 0)) != 0)
goto err;
if ((ret =
@@ -686,26 +744,30 @@ err: (void)REL_ENVLOCK(dbenv, &elock);
* Read the meta-data page from a file and return it in buf. The
* open file handle is returned in fhp.
*
- * PUBLIC: int __fop_read_meta __P((DB_ENV *,
- * PUBLIC: const char *, u_int8_t *, size_t, DB_FH *, int, u_int32_t));
+ * PUBLIC: int __fop_read_meta __P((DB_ENV *, const char *,
+ * PUBLIC: u_int8_t *, size_t, DB_FH *, int, size_t *, u_int32_t));
*/
int
-__fop_read_meta(dbenv, name, buf, size, fhp, errok, flags)
+__fop_read_meta(dbenv, name, buf, size, fhp, errok, nbytesp, flags)
DB_ENV *dbenv;
const char *name;
u_int8_t *buf;
size_t size;
DB_FH *fhp;
int errok;
+ size_t *nbytesp;
u_int32_t flags;
{
DB_FH fh, *lfhp;
size_t nr;
- int ret;
+ int myfhp, ret;
+ nr = 0;
+ myfhp = 0;
+ memset(&fh, 0, sizeof(fh));
lfhp = fhp == NULL ? &fh : fhp;
- memset(lfhp, 0, sizeof(*fhp));
- if ((ret = __os_open(dbenv, name, flags, 0, lfhp)) != 0)
+ myfhp = F_ISSET(lfhp, DB_FH_VALID);
+ if (!myfhp && (ret = __os_open(dbenv, name, flags, 0, lfhp)) != 0)
goto err;
if ((ret = __os_read(dbenv, lfhp, buf, size, &nr)) != 0) {
if (!errok)
@@ -722,13 +784,15 @@ __fop_read_meta(dbenv, name, buf, size, fhp, errok, flags)
}
err: /*
- * On error, we always close the handle. If there is no error,
- * then we only return the handle if the user didn't pass us
- * a handle into which to return it. If fhp is valid, then
- * lfhp is the same as fhp.
+ * On error, we would like to close the handle. However, if the
+ * handle was opened in the caller, we cannot. If there is no error,
+ * then we only close the handle if we opened it here.
*/
- if (F_ISSET(lfhp, DB_FH_VALID) && (ret != 0 || fhp == NULL))
+ if (!myfhp && F_ISSET((lfhp), DB_FH_VALID) && (ret != 0 || fhp == NULL))
__os_closehandle(dbenv, lfhp);
+
+ if (nbytesp != NULL)
+ *nbytesp = nr;
return (ret);
}
@@ -778,8 +842,7 @@ __fop_dummy(dbp, txn, old, new, flags)
goto err;
/* We need to create a dummy file as a place holder. */
- if ((ret =
- __db_backup_name(dbenv, new, txn, &back, &txn->last_lsn)) != 0)
+ if ((ret = __db_backup_name(dbenv, new, stxn, &back)) != 0)
goto err;
if ((ret = __db_appname(dbenv,
DB_APP_DATA, back, flags, NULL, &realback)) != 0)
@@ -847,7 +910,7 @@ __fop_dummy(dbp, txn, old, new, flags)
tmpdbt.data = tmpdbp->fileid;
tmpdbt.size = DB_FILE_ID_LEN;
namedbt.data = (void *)old;
- namedbt.size = strlen(old) + 1;
+ namedbt.size = (u_int32_t)strlen(old) + 1;
if ((t_ret =
__fop_file_remove_log(dbenv, txn, &lsn, 0, &fiddbt,
&tmpdbt, &namedbt, DB_APP_DATA, stxnid)) != 0 && ret == 0)