mail-index-lock.c revision 325d4ad220bd13f6d176391d962a0e33c856a7f6
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (C) 2003-2004 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/*
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen Locking should never fail or timeout. Exclusive locks must be kept as short
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen time as possible. Shared locks can be long living, so if we can't get
1171f0abf442638bac1827bb24a0b6b8eb682a82Timo Sirainen exclusive lock directly within 2 seconds, we'll replace the index file with
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen a copy of it. That means the shared lock holders can keep using the old file
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while we're modifying the new file.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1d738cce754bc64bbc66d3355ebdaf3f6eac55f1Timo Sirainen lock_id is used to figure out if acquired lock is still valid. When index
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen file is reopened, the lock_id can become invalid. It doesn't matter however,
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen as no-one's going to modify the old file anymore.
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lock_id also tells if we're referring to shared or exclusive lock. This
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen allows us to drop back to shared locking once all exclusive locks are
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen dropped. Shared locks have even numbers, exclusive locks have odd numbers.
9bd08aa09ea0cbd7b221aae9fc0534eb762d3de6Timo Sirainen The number is increased by two every time the lock is dropped or index file
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen is reopened.
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen*/
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8a4851655777e484d70b77bed6a7a8fac5c0c98cTimo Sirainen#include "lib.h"
8a4851655777e484d70b77bed6a7a8fac5c0c98cTimo Sirainen#include "buffer.h"
8a4851655777e484d70b77bed6a7a8fac5c0c98cTimo Sirainen#include "mmap-util.h"
8a4851655777e484d70b77bed6a7a8fac5c0c98cTimo Sirainen#include "write-full.h"
8a4851655777e484d70b77bed6a7a8fac5c0c98cTimo Sirainen#include "mail-index-private.h"
8a4851655777e484d70b77bed6a7a8fac5c0c98cTimo Sirainen
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen#include <stdio.h>
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen#include <sys/stat.h>
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen#ifdef HAVE_FLOCK
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# include <sys/file.h>
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen#define MAIL_INDEX_LOCK_WAIT_TIME 120
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainenint mail_index_lock_fd(struct mail_index *index, const char *path, int fd,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int lock_type, unsigned int timeout_secs)
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int ret;
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (timeout_secs != 0)
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen alarm(MAIL_INDEX_LOCK_WAIT_TIME);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
9bd08aa09ea0cbd7b221aae9fc0534eb762d3de6Timo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(index))
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen return 1;
9bd08aa09ea0cbd7b221aae9fc0534eb762d3de6Timo Sirainen
9bd08aa09ea0cbd7b221aae9fc0534eb762d3de6Timo Sirainen switch (index->lock_method) {
9bd08aa09ea0cbd7b221aae9fc0534eb762d3de6Timo Sirainen case MAIL_INDEX_LOCK_FCNTL: {
9bd08aa09ea0cbd7b221aae9fc0534eb762d3de6Timo Sirainen#ifndef HAVE_FCNTL
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen i_fatal("fcntl() locks not supported");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#else
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct flock fl;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen fl.l_type = lock_type;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fl.l_whence = SEEK_SET;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fl.l_start = 0;
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen fl.l_len = 0;
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = fcntl(fd, timeout_secs ? F_SETLKW : F_SETLK, &fl);
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen if (timeout_secs != 0) alarm(0);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ret == 0)
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen return 1;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
03860f6dd70abfa2551a846e77a5c41cb40dc141Timo Sirainen if (timeout_secs == 0 &&
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen (errno == EACCES || errno == EAGAIN)) {
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen /* locked by another process */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return 0;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen if (errno == EINTR) {
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen /* most likely alarm hit, meaning we timeouted.
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen even if not, we probably want to be killed
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen so stop blocking. */
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen errno = EAGAIN;
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen return 0;
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen }
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen mail_index_file_set_syscall_error(index, path,
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen "mail_index_lock_fd()");
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen return -1;
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen#endif
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen }
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen case MAIL_INDEX_LOCK_FLOCK: {
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen#ifndef HAVE_FLOCK
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen i_fatal("flock() locks not supported");
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen#else
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen int operation = timeout_secs != 0 ? 0 : LOCK_NB;
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen switch (lock_type) {
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen case F_RDLCK:
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen operation |= LOCK_SH;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen break;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen case F_WRLCK:
aff3354de83df9d683587e27461697193ff36591Timo Sirainen operation |= LOCK_EX;
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen break;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen case F_UNLCK:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen operation |= LOCK_UN;
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainen break;
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainen }
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainen
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainen ret = flock(fd, operation);
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainen if (timeout_secs != 0) alarm(0);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen if (ret == 0)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return 1;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (errno == EWOULDBLOCK || errno == EINTR) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen /* a) locked by another process,
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen b) timeouted */
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_file_set_syscall_error(index, path,
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen "mail_index_lock_fd()");
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen return -1;
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen#endif
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen }
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen case MAIL_INDEX_LOCK_DOTLOCK:
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen /* we shouldn't get here */
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen break;
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen }
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen i_unreached();
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen}
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainenstatic int mail_index_lock(struct mail_index *index, int lock_type,
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen unsigned int timeout_secs, int update_index,
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen unsigned int *lock_id_r)
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen{
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen int ret, ret2;
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen i_assert(lock_type == F_RDLCK || lock_type == F_WRLCK);
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen if (lock_type == F_RDLCK && index->lock_type != F_UNLCK) {
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen index->shared_lock_count++;
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen *lock_id_r = index->lock_id;
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen ret = 1;
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen } else if (lock_type == F_WRLCK && index->lock_type == F_WRLCK) {
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen index->excl_lock_count++;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen *lock_id_r = index->lock_id + 1;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen ret = 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen ret = 0;
73a44af966c790560a72a0447f37bb35b1031a83Timo Sirainen }
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if (update_index && index->excl_lock_count == 0) {
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen i_assert(index->lock_type != F_WRLCK);
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if ((ret2 = mail_index_reopen_if_needed(index)) < 0)
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch return -1;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (ret > 0 && ret2 == 0) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen i_assert(lock_type == F_RDLCK);
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen i_assert(index->lock_type == F_RDLCK);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return 1;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
73a44af966c790560a72a0447f37bb35b1031a83Timo Sirainen ret = 0;
73a44af966c790560a72a0447f37bb35b1031a83Timo Sirainen }
73a44af966c790560a72a0447f37bb35b1031a83Timo Sirainen
73a44af966c790560a72a0447f37bb35b1031a83Timo Sirainen if (ret > 0)
73a44af966c790560a72a0447f37bb35b1031a83Timo Sirainen return 1;
73a44af966c790560a72a0447f37bb35b1031a83Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (index->lock_method == MAIL_INDEX_LOCK_DOTLOCK) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen /* FIXME: exclusive locking will rewrite the index file every
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen time. shouldn't really be needed.. reading doesn't require
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch locks then, though */
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (lock_type == F_WRLCK)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return 0;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen if (update_index && index->lock_type == F_UNLCK) {
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen if (mail_index_reopen_if_needed(index) < 0)
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen return -1;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen }
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen index->shared_lock_count++;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen index->lock_type = F_RDLCK;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen *lock_id_r = index->lock_id;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen return 1;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen }
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen if (lock_type == F_RDLCK || !index->log_locked) {
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen ret = mail_index_lock_fd(index, index->filepath, index->fd,
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen lock_type, timeout_secs);
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen } else {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen /* this is kind of kludgy. we wish to avoid deadlocks while
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen trying to lock transaction log, but it can happen if our
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen process is holding transaction log lock and waiting for
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen index write lock, while the other process is holding index
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen read lock and waiting for transaction log lock.
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen we don't have a problem with grabbing read index lock
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen because the only way for it to block is if it's
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen write-locked, which isn't allowed unless transaction log
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen is also locked.
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen so, the workaround for this problem is that we simply try
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen locking once. if it doesn't work, just rewrite the file.
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen hopefully there won't be any other deadlocking issues. :) */
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen ret = mail_index_lock_fd(index, index->filepath, index->fd,
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen lock_type, 0);
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen }
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen if (ret <= 0)
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen return ret;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen if (index->lock_type == F_UNLCK)
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen index->lock_id += 2;
96a4e105f7c990a786af909bf710eb6431c1f227Timo Sirainen index->lock_type = lock_type;
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen if (lock_type == F_RDLCK) {
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen index->shared_lock_count++;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen *lock_id_r = index->lock_id;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen } else {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen index->excl_lock_count++;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen *lock_id_r = index->lock_id + 1;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return 1;
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch}
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainenint mail_index_lock_shared(struct mail_index *index, int update_index,
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen unsigned int *lock_id_r)
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen{
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen int ret;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen ret = mail_index_lock(index, F_RDLCK, MAIL_INDEX_LOCK_SECS,
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen update_index, lock_id_r);
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen if (ret > 0)
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen return 0;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (ret < 0)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return -1;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen mail_index_set_error(index, "Timeout while waiting for release of "
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen "shared lock for index file %s",
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen index->filepath);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen index->index_lock_timeout = TRUE;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return -1;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen}
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainenstatic int mail_index_copy(struct mail_index *index)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen{
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen const char *path;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen int ret, fd;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen i_assert(!MAIL_INDEX_IS_IN_MEMORY(index));
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen fd = mail_index_create_tmp_file(index, &path);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (fd == -1)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return -1;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen /* write base header */
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen ret = write_full(fd, &index->map->hdr,
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen index->map->hdr.base_header_size);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (ret == 0) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen /* write extended headers */
58febed28f2af78b2d8a281c851d9b67160c4bd3Timo Sirainen const struct mail_index_header *hdr;
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen const void *hdr_ext;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen hdr = index->map->hdr_base;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen hdr_ext = CONST_PTR_OFFSET(hdr, hdr->base_header_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = write_full(fd, hdr_ext, hdr->header_size -
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen hdr->base_header_size);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (ret < 0 || write_full(fd, index->map->records,
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen index->map->records_count *
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen index->map->hdr.record_size) < 0) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen mail_index_file_set_syscall_error(index, path, "write_full()");
5e4f94015f5bbc9eefb1f2cb7af81ed50dcd2b39Timo Sirainen (void)close(fd);
5e4f94015f5bbc9eefb1f2cb7af81ed50dcd2b39Timo Sirainen (void)unlink(path);
5e4f94015f5bbc9eefb1f2cb7af81ed50dcd2b39Timo Sirainen fd = -1;
5e4f94015f5bbc9eefb1f2cb7af81ed50dcd2b39Timo Sirainen } else {
5e4f94015f5bbc9eefb1f2cb7af81ed50dcd2b39Timo Sirainen i_assert(index->copy_lock_path == NULL);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen index->copy_lock_path = i_strdup(path);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return fd;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen}
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainenstatic int mail_index_lock_exclusive_copy(struct mail_index *index)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen{
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen int fd, old_lock_type;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen i_assert(index->log_locked);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen if (index->copy_lock_path != NULL) {
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen index->excl_lock_count++;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return 0;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen i_assert(index->excl_lock_count == 0);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen /* copy the index to index.tmp and use it */
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen fd = mail_index_copy(index);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (fd == -1)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen old_lock_type = index->lock_type;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen index->lock_type = F_WRLCK;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen index->excl_lock_count++;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (mail_index_reopen(index, fd) < 0) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen i_assert(index->excl_lock_count == 1);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen (void)close(fd);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (unlink(index->copy_lock_path) < 0) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen mail_index_file_set_syscall_error(index,
8ac66221e8fdc2c5523cff1893e0d1c5de25fa49Timo Sirainen index->copy_lock_path,
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen "unlink()");
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen i_free(index->copy_lock_path);
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen index->copy_lock_path = NULL;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->lock_type = old_lock_type;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen index->excl_lock_count = 0;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen return -1;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenint mail_index_lock_exclusive(struct mail_index *index,
f6d5c9fbdac9af5c4d3f467f828dc6f056309d5eTimo Sirainen unsigned int *lock_id_r)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen int ret;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen /* exclusive transaction log lock protects exclusive locking
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen for the main index file */
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen i_assert(index->log_locked);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen /* if header size is smaller than what we have, we'll have to recreate
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen the index to grow it. so don't even try regular locking. */
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (index->map->hdr.base_header_size >= sizeof(*index->hdr) ||
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen index->excl_lock_count > 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* wait two seconds for exclusive lock */
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen ret = mail_index_lock(index, F_WRLCK, 2, TRUE, lock_id_r);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen if (ret > 0)
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen return 0;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen if (ret < 0)
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen return -1;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen }
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen if (mail_index_lock_exclusive_copy(index) < 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return -1;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen *lock_id_r = index->lock_id + 1;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic int mail_index_copy_lock_finish(struct mail_index *index)
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen{
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if (fsync(index->fd) < 0) {
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen mail_index_file_set_syscall_error(index, index->copy_lock_path,
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen "fsync()");
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen if (rename(index->copy_lock_path, index->filepath) < 0) {
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen mail_index_set_error(index, "rename(%s, %s) failed: %m",
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen index->copy_lock_path, index->filepath);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
f65602dff8a85170176ddaa790db6df56006d132Timo Sirainen i_free(index->copy_lock_path);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen index->copy_lock_path = NULL;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
58816241cbaf79e3f8dd7d831b7c6f02c6c38ee6Timo Sirainen
58816241cbaf79e3f8dd7d831b7c6f02c6c38ee6Timo Sirainenstatic void mail_index_excl_unlock_finish(struct mail_index *index)
58816241cbaf79e3f8dd7d831b7c6f02c6c38ee6Timo Sirainen{
58816241cbaf79e3f8dd7d831b7c6f02c6c38ee6Timo Sirainen int fd;
58816241cbaf79e3f8dd7d831b7c6f02c6c38ee6Timo Sirainen
58816241cbaf79e3f8dd7d831b7c6f02c6c38ee6Timo Sirainen if (index->map != NULL && index->map->write_to_disk) {
58816241cbaf79e3f8dd7d831b7c6f02c6c38ee6Timo Sirainen i_assert(index->log_locked);
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen index->map->write_to_disk = FALSE;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen if (index->copy_lock_path != NULL) {
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen /* new mapping replaces the old */
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen (void)unlink(index->copy_lock_path);
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen i_free(index->copy_lock_path);
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen index->copy_lock_path = NULL;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen }
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (!MAIL_INDEX_IS_IN_MEMORY(index)) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen fd = mail_index_copy(index);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (fd == -1)
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen mail_index_set_inconsistent(index);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen else
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen (void)close(fd);
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (index->shared_lock_count > 0 &&
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen index->lock_method != MAIL_INDEX_LOCK_DOTLOCK) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen /* leave ourself shared locked. */
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen (void)mail_index_lock_fd(index, index->filepath, index->fd,
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen F_RDLCK, 0);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen i_assert(index->lock_type == F_WRLCK);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen index->lock_type = F_RDLCK;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (index->copy_lock_path != NULL) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen i_assert(index->log_locked);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (mail_index_copy_lock_finish(index) < 0)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen mail_index_set_inconsistent(index);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen}
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainenvoid mail_index_unlock(struct mail_index *index, unsigned int lock_id)
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen{
1171f0abf442638bac1827bb24a0b6b8eb682a82Timo Sirainen if ((lock_id & 1) == 0) {
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen /* shared lock */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!mail_index_is_locked(index, lock_id)) {
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen /* unlocking some older generation of the index file.
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen we've already closed the file so just ignore this. */
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
0beb5d6c661ee68130a954ed0f31a34c19195fb7Timo Sirainen i_assert(index->shared_lock_count > 0);
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen index->shared_lock_count--;
0beb5d6c661ee68130a954ed0f31a34c19195fb7Timo Sirainen } else {
0beb5d6c661ee68130a954ed0f31a34c19195fb7Timo Sirainen /* exclusive lock */
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen i_assert(lock_id == index->lock_id + 1);
0beb5d6c661ee68130a954ed0f31a34c19195fb7Timo Sirainen i_assert(index->excl_lock_count > 0);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (--index->excl_lock_count == 0)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen mail_index_excl_unlock_finish(index);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (index->shared_lock_count == 0 && index->excl_lock_count == 0) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen index->lock_id += 2;
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen index->lock_type = F_UNLCK;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (index->lock_method != MAIL_INDEX_LOCK_DOTLOCK) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen (void)mail_index_lock_fd(index, index->filepath,
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen index->fd, F_UNLCK, 0);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen}
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainenint mail_index_is_locked(struct mail_index *index, unsigned int lock_id)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen{
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if ((index->lock_id ^ lock_id) <= 1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(index->lock_type != F_UNLCK);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return TRUE;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
6d8082441e480cf481bfb3f935d17fc419d789c6Timo Sirainen return FALSE;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen