mail-transaction-log-file.c revision 1d738cce754bc64bbc66d3355ebdaf3f6eac55f1
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2003-2010 Dovecot authors, see the included COPYING file */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen#define MEMORY_LOG_NAME "(in-memory transaction log file)"
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenlog_file_set_syscall_error(struct mail_transaction_log_file *file,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return mail_index_file_set_syscall_error(file->log->index,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenmail_transaction_log_mark_corrupted(struct mail_transaction_log_file *file)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen unsigned int offset =
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen offsetof(struct mail_transaction_log_header, indexid);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file) ||
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* indexid=0 marks the log file as corrupted */
04870054863757edf048c81dcce3c5e7dec453cdTimo Sirainen mail_index_file_set_syscall_error(file->log->index,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenmail_transaction_log_file_set_corrupted(struct mail_transaction_log_file *file,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen const char *fmt, ...)
eacce2276278ce6a8176a9a100807dba50bbfb36Timo Sirainen "Corrupted transaction log file %s seq %u: %s "
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen t_strdup_vprintf(fmt, va), file->sync_offset);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenmail_transaction_log_file_alloc(struct mail_transaction_log *log,
4145cbac82bfc0c8bfeceeca0ef841700117930cTimo Sirainen file = i_new(struct mail_transaction_log_file, 1);
eacce2276278ce6a8176a9a100807dba50bbfb36Timo Sirainenvoid mail_transaction_log_file_free(struct mail_transaction_log_file **_file)
eacce2276278ce6a8176a9a100807dba50bbfb36Timo Sirainen struct mail_transaction_log_file *file = *_file;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen for (p = &file->log->files; *p != NULL; p = &(*p)->next) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (munmap(file->mmap_base, file->mmap_size) < 0)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenmail_transaction_log_file_skip_to_head(struct mail_transaction_log_file *file)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen const struct mail_index_modseq_header *modseq_hdr;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (map == NULL || file->hdr.file_seq != map->hdr.log_file_seq ||
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* we can get a valid log offset from index file. initialize
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen sync_offset from it so we don't have to read the whole log
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen file from beginning. */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen modseq_hdr = mail_index_map_get_modseq_header(map);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen "%s: log_file_head_offset too small",
714e2da5096fb52b8845d3c79f9bb26225a606c9Timo Sirainen file->sync_highest_modseq = file->hdr.initial_modseq;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen } else if (modseq_hdr == NULL && file->hdr.initial_modseq == 0) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* modseqs not used yet */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* highest_modseq not synced, start from beginning */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen file->sync_highest_modseq = file->hdr.initial_modseq;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen } else if (modseq_hdr->log_offset > head_offset) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen "%s: modseq_hdr.log_offset too large",
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen file->sync_highest_modseq = file->hdr.initial_modseq;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* start from where we last stopped tracking modseqs */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen file->sync_highest_modseq = modseq_hdr->highest_modseq;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (file->hdr.file_seq == log->index->map->hdr.log_file_seq) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen file->saved_tail_sync_offset = file->saved_tail_offset;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (file->saved_tail_offset > file->max_tail_offset)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen file->max_tail_offset = file->saved_tail_offset;
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainenmail_transaction_log_file_add_to_list(struct mail_transaction_log_file *file)
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen file->sync_highest_modseq = file->hdr.initial_modseq;
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen /* insert it to correct position */
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen for (p = &file->log->files; *p != NULL; p = &(*p)->next) {
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen i_assert((*p)->hdr.file_seq < file->hdr.file_seq);
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainenmail_transaction_log_init_hdr(struct mail_transaction_log *log,
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen hdr->major_version = MAIL_TRANSACTION_LOG_MAJOR_VERSION;
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen hdr->minor_version = MAIL_TRANSACTION_LOG_MINOR_VERSION;
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen hdr->hdr_size = sizeof(struct mail_transaction_log_header);
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen hdr->compat_flags |= MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen /* not creating index - make sure we have latest header */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* if we got here from mapping, the .log file is
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen corrupted. use whatever values we got from index
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen hdr->prev_file_seq = index->map->hdr.log_file_seq;
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen hdr->prev_file_offset = index->map->hdr.log_file_head_offset;
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen hdr->file_seq = index->map->hdr.log_file_seq + 1;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen mail_index_map_modseq_get_highest(index->map);
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen if (hdr->file_seq <= log->head->hdr.file_seq) {
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen /* make sure the sequence grows */
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen if (hdr->initial_modseq < log->head->sync_highest_modseq) {
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen /* this should be always up-to-date */
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen hdr->initial_modseq = log->head->sync_highest_modseq;
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainenmail_transaction_log_file_alloc_in_memory(struct mail_transaction_log *log)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen file = mail_transaction_log_file_alloc(log, MEMORY_LOG_NAME);
34015eb0b74735f2fac07c12697bde20a94735e6Timo Sirainen if (mail_transaction_log_init_hdr(log, &file->hdr) < 0) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen file->buffer = buffer_create_dynamic(default_pool, 4096);
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainenmail_transaction_log_file_dotlock(struct mail_transaction_log_file *file)
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen ret = file_dotlock_create(&file->log->dotlock_settings,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen log_file_set_syscall_error(file, "file_dotlock_create()");
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen "Timeout while waiting for "
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen "dotlock for transaction log file %s",
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenmail_transaction_log_file_undotlock(struct mail_transaction_log_file *file)
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen ret = file_dotlock_delete(&file->log->dotlock);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen log_file_set_syscall_error(file, "file_dotlock_delete()");
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen "Dotlock was lost for transaction log file %s",
ec5fec7eab19e134a2607b7e224b3e14a1771ee0Timo Sirainenint mail_transaction_log_file_lock(struct mail_transaction_log_file *file)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (file->log->index->lock_method == FILE_LOCK_METHOD_DOTLOCK)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return mail_transaction_log_file_dotlock(file);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen ret = mail_index_lock_fd(file->log->index, file->filepath, file->fd,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen log_file_set_syscall_error(file, "mail_index_wait_lock_fd()");
e1203014de25c8c3d3975a9f4b4a04616df4bba2Timo Sirainen "Timeout while waiting for lock for transaction log file %s",
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenvoid mail_transaction_log_file_unlock(struct mail_transaction_log_file *file)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file))
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (file->log->index->lock_method == FILE_LOCK_METHOD_DOTLOCK) {
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainenmail_transaction_log_file_read_header(struct mail_transaction_log_file *file)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* try to read the whole header, but it's not necessarily an error to
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen read less since the older versions of the log format could be
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen ret = pread(file->fd, PTR_OFFSET(&file->hdr, pos),
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen } while (ret > 0 && pos < (ssize_t)sizeof(file->hdr));
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenmail_transaction_log_file_read_hdr(struct mail_transaction_log_file *file,
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen i_assert(!MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file));
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen ret = mail_transaction_log_file_read_header(file);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (file->hdr.major_version != MAIL_TRANSACTION_LOG_MAJOR_VERSION) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* incompatible version - fix silently */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (ret < MAIL_TRANSACTION_LOG_HEADER_MIN_SIZE) {
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen "unexpected end of file while reading header");
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen if (file->hdr.minor_version >= 2 || file->hdr.major_version > 1) {
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen /* we have compatibility flags */
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen enum mail_index_header_compat_flags compat_flags = 0;
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen compat_flags |= MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen /* architecture change */
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen "Rebuilding index file %s: "
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen "CPU architecture changed",
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (file->hdr.hdr_size < MAIL_TRANSACTION_LOG_HEADER_MIN_SIZE) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen "Header size too small");
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen /* @UNSAFE: smaller than we expected - zero out the fields we
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen shouldn't have filled */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen memset(PTR_OFFSET(&file->hdr, file->hdr.hdr_size), 0,
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen /* corrupted */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen "Transaction log file %s: marked corrupted",
714e2da5096fb52b8845d3c79f9bb26225a606c9Timo Sirainen if (file->hdr.indexid != file->log->index->indexid) {
714e2da5096fb52b8845d3c79f9bb26225a606c9Timo Sirainen /* index file was probably just rebuilt and we don't
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen know about it yet */
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen "indexid changed %u -> %u",
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen file->log->index->indexid, file->hdr.indexid);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen /* creating index file. since transaction log is created
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen first, use the indexid in it to create the main index
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen to avoid races. */
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen file->log->index->indexid = file->hdr.indexid;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* make sure we already don't have a file with the same sequence
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen opened. it shouldn't happen unless the old log file was
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen corrupted. */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen for (f = file->log->files; f != NULL; f = f->next) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* mark the old file corrupted. we can't safely remove
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen it from the list however, so return failure. */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (strcmp(f->filepath, f->log->head->filepath) != 0) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* only mark .2 corrupted, just to make sure
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen we don't lose any changes from .log in case
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen we're somehow wrong */
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen "Transaction log %s: "
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen "duplicate transaction log sequence (%u)",
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen file->sync_highest_modseq = file->hdr.initial_modseq;
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainenmail_transaction_log_file_stat(struct mail_transaction_log_file *file,
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainenmail_transaction_log_file_is_dupe(struct mail_transaction_log_file *file)
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen for (tmp = file->log->files; tmp != NULL; tmp = tmp->next) {
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainenmail_transaction_log_file_create2(struct mail_transaction_log_file *file,
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen if ((file->log->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0) {
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen /* although we check also mtime and file size below, it's done
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen only to fix broken log files. we don't bother flushing
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen attribute cache just for that. */
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen /* log creation is locked now - see if someone already created it.
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen note that if we're rotating, we need to keep the log locked until
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen the file has been rewritten. and because fcntl() locks are stupid,
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen if we go and open()+close() the file and we had it already opened,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen its locks are lost. so we use stat() to check if the file has been
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen recreated, although it almost never is. */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen else if (nfs_safe_stat(file->filepath, &st) < 0) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return log_file_set_syscall_error(file, "stat()");
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* inode/dev checks are enough when we're rotating the file,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen but not when we're replacing a broken log file */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* no-one else recreated the file */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* recreated. use the file if its header is ok */
c3d40f3092af25cad9e807a85eaad4d92aab107bTimo Sirainen mail_transaction_log_file_stat(file, FALSE) == 0) {
c3d40f3092af25cad9e807a85eaad4d92aab107bTimo Sirainen /* yes, it was ok */
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen if (mail_transaction_log_init_hdr(file->log, &file->hdr) < 0)
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen /* don't reset modseqs. if we're reseting due to rebuilding
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen indexes we'll probably want to keep uidvalidity and in such
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen cases we really don't want to shrink modseqs. */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (write_full(new_fd, &file->hdr, sizeof(file->hdr)) < 0)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return log_file_set_syscall_error(file, "write_full()");
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen if ((file->log->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0) {
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen /* the header isn't important, so don't bother calling
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen fdatasync() unless NFS is used */
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen return log_file_set_syscall_error(file, "fdatasync()");
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen ret = mail_transaction_log_file_stat(file, FALSE);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (file->log->head != NULL && file->log->head->locked) {
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen /* we'll need to preserve the lock */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* if we return -1 the dotlock deletion code closes the fd */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* keep two log files */
714e2da5096fb52b8845d3c79f9bb26225a606c9Timo Sirainen /* rename() would be nice and easy way to do this, except then
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen there's a race condition between the rename and
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen file_dotlock_replace(). during that time the log file
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen doesn't exist, which could cause problems. */
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen path2 = t_strconcat(file->filepath, ".2", NULL);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen mail_index_set_error(index, "unlink(%s) failed: %m",
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* try to link() anyway */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (nfs_safe_link(file->filepath, path2, FALSE) < 0 &&
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen mail_index_set_error(index, "link(%s, %s) failed: %m",
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* ignore the error. we don't care that much about the
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen second log file and we're going to overwrite this
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen first one. */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* success */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenint mail_transaction_log_file_create(struct mail_transaction_log_file *file,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen "Can't create log file %s: Index is read-only",
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* With dotlocking we might already have path.lock created, so this
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen filename has to be different. */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen fd = file_dotlock_open(&file->log->new_dotlock_settings,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return log_file_set_syscall_error(file, "file_dotlock_open()");
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen mail_index_fchown(index, fd, file_dotlock_get_lock_path(dotlock));
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* either fd gets used or the dotlock gets deleted and returned fd
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen is for the existing file */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (mail_transaction_log_file_create2(file, fd, reset, &dotlock) < 0) {
23fdad6c7e2581921f511e24cd9371c9eaebcef9Timo Sirainenint mail_transaction_log_file_open(struct mail_transaction_log_file *file,
bool ignore_estale;
int ret;
else if (check_existing &&
if (ret > 0) {
if (ret == 0) {
i == MAIL_INDEX_ESTALE_RETRY_COUNT) {
const unsigned int offset_pos =
sizeof(tail_offset));
if (*cur_modseq != 0) {
const unsigned int modseq_ext_len =
modseq_ext_len) == 0) {
case MAIL_TRANSACTION_APPEND:
case MAIL_TRANSACTION_MODSEQ_UPDATE: {
static struct modseq_cache *
if (idx > 0) {
static struct modseq_cache *
return NULL;
best = i;
return NULL;
static struct modseq_cache *
return NULL;
best = i;
return NULL;
int ret;
if (ret <= 0) {
if (ret < 0)
int ret;
if (ret <= 0) {
if (ret < 0)
unsigned int trans_size)
int ret;
sizeof(*hdr));
if (ret != 0)
const void *data;
if (trans_size == 0) {
trans_size = 0;
if (trans_size != 0) {
void *data;
if (ret > 0) {
if (ret == 0) {
void *data;
if (ret > 0)
if (ret < 0) {
return TRUE;
return TRUE;
return FALSE;
bool index_nfs_flush =
int ret;
if (ret <= 0)
return ret;
return ret;
MADV_SEQUENTIAL) < 0)
int ret;
if (ret > 0)
FALSE);
} while (ret == 0);
int ret;
end_offset) == 0)
*file)