[dovecot-cvs] dovecot/src/lib-index mail-index.c, 1.188,
1.189 mail-transaction-log-append.c, 1.2,
1.3 mail-transaction-log-view.c, 1.35,
1.36 mail-transaction-log.c, 1.88, 1.89 mail-transaction-log.h,
1.25, 1.26
cras at dovecot.org
cras at dovecot.org
Sat Mar 5 14:41:24 EET 2005
Update of /var/lib/cvs/dovecot/src/lib-index
In directory talvi:/tmp/cvs-serv8384
Modified Files:
mail-index.c mail-transaction-log-append.c
mail-transaction-log-view.c mail-transaction-log.c
mail-transaction-log.h
Log Message:
We could have gone past the transaction log view's boundaries if log was
just rotated. Plus other transaction log cleanups, fixes and new asserts.
Index: mail-index.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index.c,v
retrieving revision 1.188
retrieving revision 1.189
diff -u -d -r1.188 -r1.189
--- mail-index.c 8 Feb 2005 22:44:47 -0000 1.188
+++ mail-index.c 5 Mar 2005 12:41:22 -0000 1.189
@@ -732,7 +732,10 @@
mail_transaction_log_view_get_prev_pos(log_view, &prev_seq,
&prev_offset);
- index->map->hdr.log_file_seq = prev_seq;
+ i_assert(prev_seq <= max_seq &&
+ (prev_seq != max_seq || prev_offset <= max_offset));
+
+ index->map->hdr.log_file_seq = prev_seq;
index->map->hdr.log_file_int_offset =
index->map->hdr.log_file_ext_offset = prev_offset;
Index: mail-transaction-log-append.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-log-append.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- mail-transaction-log-append.c 5 Mar 2005 10:19:37 -0000 1.2
+++ mail-transaction-log-append.c 5 Mar 2005 12:41:22 -0000 1.3
@@ -345,7 +345,7 @@
if (log->head->sync_offset > MAIL_TRANSACTION_LOG_ROTATE_SIZE &&
(time_t)log->head->hdr.create_stamp <
- ioloop_time - MAIL_TRANSACTION_LOG_ROTATE_MIN_TIME) {
+ ioloop_time - MAIL_TRANSACTION_LOG_ROTATE_TIME) {
/* we might want to rotate, but check first that everything is
synced in index. */
if (mail_index_lock_shared(log->index, TRUE, &lock_id) < 0) {
Index: mail-transaction-log-view.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-log-view.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -d -r1.35 -r1.36
--- mail-transaction-log-view.c 14 Nov 2004 01:23:21 -0000 1.35
+++ mail-transaction-log-view.c 5 Mar 2005 12:41:22 -0000 1.36
@@ -91,24 +91,19 @@
if (min_file_seq == 0) {
/* new index, transaction file not synced yet */
min_file_seq = 1;
- min_file_offset = sizeof(struct mail_transaction_log_header);
+ min_file_offset = 0;
if (max_file_seq == 0) {
max_file_seq = min_file_seq;
max_file_offset = min_file_offset;
}
- } else if (min_file_offset == 0) {
- /* this could happen if internal transactions haven't yet been
- committed but external are. just assume we're at the
- beginning. */
- min_file_offset = sizeof(struct mail_transaction_log_header);
- }
+ }
if (min_file_seq == view->log->tail->hdr.prev_file_seq &&
min_file_offset == view->log->tail->hdr.prev_file_offset) {
/* we can skip this */
min_file_seq = view->log->tail->hdr.file_seq;
- min_file_offset = sizeof(struct mail_transaction_log_header);
+ min_file_offset = 0;
if (min_file_seq > max_file_seq) {
/* empty view */
@@ -127,13 +122,20 @@
return -1;
}
+ if (min_file_offset == 0) {
+ /* this could happen if internal transactions haven't yet been
+ committed but external are. just assume we're at the
+ beginning. */
+ min_file_offset = file->hdr.hdr_size;
+ if (max_file_offset == 0 && min_file_seq == max_file_seq)
+ max_file_offset = min_file_offset;
+ }
+
/* check these later than others as index file may have corrupted
log_file_offset. we should have recreated the log file and
skipped min_file_seq file above.. max_file_offset can be broken
only if min_file_seq = max_file_seq. */
- i_assert(min_file_offset >= sizeof(struct mail_transaction_log_header));
- i_assert(max_file_offset >= sizeof(struct mail_transaction_log_header));
-
+ i_assert(min_file_offset >= file->hdr.hdr_size);
i_assert(min_file_seq != max_file_seq ||
min_file_offset <= max_file_offset);
@@ -167,9 +169,8 @@
end_offset = file->hdr.file_seq == max_file_seq ?
max_file_offset : (uoff_t)-1;
- ret = mail_transaction_log_file_map(file,
- sizeof(struct mail_transaction_log_header),
- end_offset);
+ ret = mail_transaction_log_file_map(file, file->hdr.hdr_size,
+ end_offset);
if (ret == 0) {
mail_index_set_error(view->log->index,
"Lost transaction log file %s seq %u",
@@ -211,6 +212,8 @@
view->max_file_offset = max_file_offset;
view->type_mask = type_mask;
view->broken = FALSE;
+
+ i_assert(view->cur->hdr.file_seq == min_file_seq);
return 0;
}
@@ -258,23 +261,27 @@
uint32_t hdr_size;
size_t file_size;
+ if (view->cur == NULL)
+ return 0;
+
+ view->prev_file_seq = view->cur->hdr.file_seq;
+ view->prev_file_offset = view->cur_offset;
+
for (;;) {
file = view->cur;
if (file == NULL)
return 0;
- view->prev_file_seq = file->hdr.file_seq;
- view->prev_file_offset = view->cur_offset;
-
if (view->cur_offset != file->sync_offset)
break;
view->cur = file->next;
- view->cur_offset = sizeof(struct mail_transaction_log_header);
+ view->cur_offset = file->hdr.hdr_size;
}
- if (view->cur_offset >= view->max_file_offset &&
- file->hdr.file_seq == view->max_file_seq)
+ if (file->hdr.file_seq > view->max_file_seq ||
+ (view->cur_offset >= view->max_file_offset &&
+ file->hdr.file_seq == view->max_file_seq))
return 0;
data = buffer_get_data(file->buffer, &file_size);
Index: mail-transaction-log.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-log.c,v
retrieving revision 1.88
retrieving revision 1.89
diff -u -d -r1.88 -r1.89
--- mail-transaction-log.c 5 Mar 2005 10:25:09 -0000 1.88
+++ mail-transaction-log.c 5 Mar 2005 12:41:22 -0000 1.89
@@ -233,9 +233,12 @@
if (index->fd != -1 &&
INDEX_HAS_MISSING_LOGS(index, log->head)) {
/* head log file isn't same as head index file -
- shouldn't happen except in race conditions. lock them and
- check again - FIXME: missing error handling. */
- (void)mail_transaction_log_check_file_seq(log);
+ shouldn't happen except in race conditions.
+ lock them and check again */
+ if (mail_transaction_log_check_file_seq(log) < 0) {
+ mail_transaction_log_close(log);
+ return NULL;
+ }
}
return log;
}
@@ -256,6 +259,11 @@
static void
mail_transaction_log_file_close(struct mail_transaction_log_file *file)
{
+ if (file == file->log->head)
+ file->log->head = NULL;
+ if (file == file->log->tail)
+ file->log->tail = file->next;
+
mail_transaction_log_file_unlock(file);
if (file->buffer != NULL)
@@ -340,7 +348,8 @@
static int
mail_transaction_log_file_create2(struct mail_transaction_log *log,
const char *path, int fd,
- dev_t dev, ino_t ino)
+ struct dotlock **dotlock,
+ dev_t dev, ino_t ino, uoff_t file_size)
{
struct mail_index *index = log->index;
struct mail_transaction_log_header hdr;
@@ -354,10 +363,11 @@
if ((ret = fstat(fd2, &st)) < 0) {
mail_index_file_set_syscall_error(index, path,
"fstat()");
- } else if (st.st_ino == ino && CMP_DEV_T(st.st_dev, dev)) {
+ } else if (st.st_ino == ino && CMP_DEV_T(st.st_dev, dev) &&
+ (uoff_t)st.st_size == file_size) {
/* same file, still broken */
} else {
- (void)file_dotlock_delete(&log->dotlock);
+ (void)file_dotlock_delete(dotlock);
return fd2;
}
@@ -400,31 +410,27 @@
return -1;
}
- fd2 = dup(fd);
- if (fd2 < 0) {
- mail_index_file_set_syscall_error(index, path, "dup()");
- return -1;
- }
-
- if (file_dotlock_replace(&log->dotlock, 0) <= 0)
+ if (file_dotlock_replace(dotlock,
+ DOTLOCK_REPLACE_FLAG_DONT_CLOSE_FD) <= 0)
return -1;
/* success */
- return fd2;
+ return fd;
}
static int
mail_transaction_log_file_create(struct mail_transaction_log *log,
- const char *path, dev_t dev, ino_t ino)
+ const char *path,
+ dev_t dev, ino_t ino, uoff_t file_size)
{
+ struct dotlock *dotlock;
mode_t old_mask;
int fd, fd2;
/* With dotlocking we might already have path.lock created, so this
filename has to be different. */
old_mask = umask(log->index->mode ^ 0666);
- fd = file_dotlock_open(&log->new_dotlock_settings, path, 0,
- &log->dotlock);
+ fd = file_dotlock_open(&log->new_dotlock_settings, path, 0, &dotlock);
umask(old_mask);
if (fd == -1) {
@@ -436,13 +442,14 @@
if (log->index->gid != (gid_t)-1 &&
fchown(fd, (uid_t)-1, log->index->gid) < 0) {
mail_index_file_set_syscall_error(log->index, path, "fchown()");
- (void)file_dotlock_delete(&log->dotlock);
+ (void)file_dotlock_delete(&dotlock);
return -1;
}
- fd2 = mail_transaction_log_file_create2(log, path, fd, dev, ino);
+ fd2 = mail_transaction_log_file_create2(log, path, fd, &dotlock,
+ dev, ino, file_size);
if (fd2 < 0) {
- (void)file_dotlock_delete(&log->dotlock);
+ (void)file_dotlock_delete(&dotlock);
return -1;
}
return fd2;
@@ -475,8 +482,8 @@
ret = mail_transaction_log_file_read_hdr(file);
if (ret == 0) {
/* corrupted header */
- fd = mail_transaction_log_file_create(log, path,
- st.st_dev, st.st_ino);
+ fd = mail_transaction_log_file_create(log, path, st.st_dev,
+ st.st_ino, st.st_size);
if (fd == -1)
ret = -1;
else if (fstat(fd, &st) < 0) {
@@ -520,6 +527,8 @@
/* log replaced with file having same sequence as
previous one. shouldn't happen unless previous
log file was corrupted.. */
+ file->next = (*p)->next;
+ (*p)->next = NULL;
break;
}
}
@@ -542,7 +551,7 @@
return NULL;
}
- fd = mail_transaction_log_file_create(log, path, 0, 0);
+ fd = mail_transaction_log_file_create(log, path, 0, 0, 0);
if (fd == -1)
return NULL;
}
@@ -563,9 +572,6 @@
*p = next;
}
}
-
- if (log->tail == NULL)
- log->head = NULL;
}
int mail_transaction_log_rotate(struct mail_transaction_log *log, int lock)
@@ -574,6 +580,8 @@
struct stat st;
int fd;
+ i_assert(log->head->locked);
+
if (fstat(log->head->fd, &st) < 0) {
mail_index_file_set_syscall_error(log->index,
log->head->filepath,
@@ -582,7 +590,7 @@
}
fd = mail_transaction_log_file_create(log, log->head->filepath,
- st.st_dev, st.st_ino);
+ st.st_dev, st.st_ino, st.st_size);
if (fd == -1)
return -1;
@@ -609,19 +617,6 @@
return 0;
}
-static int mail_transaction_log_recreate(struct mail_transaction_log *log)
-{
- unsigned int lock_id;
- int ret;
-
- if (mail_index_lock_shared(log->index, TRUE, &lock_id) < 0)
- return -1;
-
- ret = mail_transaction_log_rotate(log, FALSE);
- mail_index_unlock(log->index, lock_id);
- return ret;
-}
-
static int mail_transaction_log_refresh(struct mail_transaction_log *log)
{
struct mail_transaction_log_file *file;
@@ -632,10 +627,6 @@
MAIL_TRANSACTION_LOG_PREFIX, NULL);
if (stat(path, &st) < 0) {
mail_index_file_set_syscall_error(log->index, path, "stat()");
- if (errno == ENOENT && log->head->locked) {
- /* lost? */
- return mail_transaction_log_recreate(log);
- }
return -1;
}
Index: mail-transaction-log.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-log.h,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- mail-transaction-log.h 5 Mar 2005 10:19:37 -0000 1.25
+++ mail-transaction-log.h 5 Mar 2005 12:41:22 -0000 1.26
@@ -7,7 +7,7 @@
#define MAIL_TRANSACTION_LOG_PREFIX ".log"
#define MAIL_TRANSACTION_LOG_ROTATE_SIZE (1024*128)
-#define MAIL_TRANSACTION_LOG_ROTATE_MIN_TIME (60*5)
+#define MAIL_TRANSACTION_LOG_ROTATE_TIME (60*5)
struct mail_transaction_log_header {
uint8_t major_version;
More information about the dovecot-cvs
mailing list