index = path_open_index(argv[1]);
if (index == NULL ||
- mail_index_open(index, MAIL_INDEX_OPEN_FLAG_READONLY,
- FILE_LOCK_METHOD_FCNTL) <= 0)
+ mail_index_open(index, MAIL_INDEX_OPEN_FLAG_READONLY) <= 0)
i_fatal("Couldn't open index %s", argv[1]);
if (argv[2] != NULL)
uid = atoi(argv[2]);
if (index == NULL)
return FALSE;
- ret = mail_index_open(index, MAIL_INDEX_OPEN_FLAG_READONLY,
- FILE_LOCK_METHOD_FCNTL) > 0;
+ ret = mail_index_open(index, MAIL_INDEX_OPEN_FLAG_READONLY) > 0;
if (ret > 0)
mail_index_close(index);
mail_index_free(&index);
(index->flags & MAIL_INDEX_OPEN_FLAG_DOTLOCK_USE_EXCL) != 0;
cache->dotlock_settings.nfs_flush =
(index->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0;
- cache->dotlock_settings.timeout = MAIL_CACHE_LOCK_TIMEOUT;
+ cache->dotlock_settings.timeout =
+ I_MIN(MAIL_CACHE_LOCK_TIMEOUT, index->max_lock_timeout_secs);
cache->dotlock_settings.stale_timeout = MAIL_CACHE_LOCK_CHANGE_TIMEOUT;
if (!MAIL_INDEX_IS_IN_MEMORY(index) &&
static int mail_cache_lock_file(struct mail_cache *cache, bool nonblock)
{
+ unsigned int timeout_secs;
int ret;
if (cache->last_lock_failed) {
if (cache->index->lock_method != FILE_LOCK_METHOD_DOTLOCK) {
i_assert(cache->file_lock == NULL);
+ timeout_secs = I_MIN(MAIL_CACHE_LOCK_TIMEOUT,
+ cache->index->max_lock_timeout_secs);
+
ret = mail_index_lock_fd(cache->index, cache->filepath,
cache->fd, F_WRLCK,
- nonblock ? 0 : MAIL_CACHE_LOCK_TIMEOUT,
+ nonblock ? 0 : timeout_secs,
&cache->file_lock);
} else {
enum dotlock_create_flags flags =
int mail_index_lock_shared(struct mail_index *index, unsigned int *lock_id_r)
{
+ unsigned int timeout_secs;
int ret;
- ret = mail_index_lock(index, F_RDLCK, MAIL_INDEX_SHARED_LOCK_TIMEOUT,
- lock_id_r);
+ timeout_secs = I_MIN(MAIL_INDEX_SHARED_LOCK_TIMEOUT,
+ index->max_lock_timeout_secs);
+ ret = mail_index_lock(index, F_RDLCK, timeout_secs, lock_id_r);
if (ret > 0) {
mail_index_flush_read_cache(index, index->filepath,
index->fd, TRUE);
int lock_type, shared_lock_count, excl_lock_count;
unsigned int lock_id_counter;
enum file_lock_method lock_method;
+ unsigned int max_lock_timeout_secs;
struct file_lock *file_lock;
struct dotlock *dotlock;
static int mail_index_strmap_lock(struct mail_index_strmap *strmap)
{
+ unsigned int timeout_secs;
int ret;
i_assert(strmap->fd != -1);
if (strmap->index->lock_method != FILE_LOCK_METHOD_DOTLOCK) {
i_assert(strmap->file_lock == NULL);
+ timeout_secs = I_MIN(MAIL_INDEX_STRMAP_TIMEOUT_SECS,
+ strmap->index->max_lock_timeout_secs);
ret = file_wait_lock(strmap->fd, strmap->path, F_WRLCK,
- strmap->index->lock_method,
- MAIL_INDEX_STRMAP_TIMEOUT_SECS,
+ strmap->index->lock_method, timeout_secs,
&strmap->file_lock);
if (ret <= 0) {
mail_index_strmap_set_syscall_error(strmap,
index->mode = 0600;
index->gid = (gid_t)-1;
+ index->lock_method = FILE_LOCK_METHOD_FCNTL;
+ index->max_lock_timeout_secs = -1U;
index->keywords_ext_id =
mail_index_ext_register(index, MAIL_INDEX_EXT_KEYWORDS,
index->gid_origin = i_strdup(gid_origin);
}
+void mail_index_set_lock_method(struct mail_index *index,
+ enum file_lock_method lock_method,
+ unsigned int max_timeout_secs)
+{
+ index->lock_method = lock_method;
+ index->max_lock_timeout_secs = max_timeout_secs;
+}
+
uint32_t mail_index_ext_register(struct mail_index *index, const char *name,
uint32_t default_hdr_size,
uint16_t default_record_size,
return 1;
}
-int mail_index_open(struct mail_index *index, enum mail_index_open_flags flags,
- enum file_lock_method lock_method)
+int mail_index_open(struct mail_index *index, enum mail_index_open_flags flags)
{
int ret;
index->log_locked = FALSE;
index->flags = flags;
index->readonly = (flags & MAIL_INDEX_OPEN_FLAG_READONLY) != 0;
- index->lock_method = lock_method;
if ((flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0 &&
(flags & MAIL_INDEX_OPEN_FLAG_FSYNC_DISABLE) != 0)
}
int mail_index_open_or_create(struct mail_index *index,
- enum mail_index_open_flags flags,
- enum file_lock_method lock_method)
+ enum mail_index_open_flags flags)
{
int ret;
flags |= MAIL_INDEX_OPEN_FLAG_CREATE;
- ret = mail_index_open(index, flags, lock_method);
+ ret = mail_index_open(index, flags);
i_assert(ret != 0);
return ret < 0 ? -1 : 0;
}
enum mail_index_sync_type fsync_mask);
void mail_index_set_permissions(struct mail_index *index,
mode_t mode, gid_t gid, const char *gid_origin);
+/* Set locking method and maximum time to wait for a lock (-1U = default). */
+void mail_index_set_lock_method(struct mail_index *index,
+ enum file_lock_method lock_method,
+ unsigned int max_timeout_secs);
/* Open index. Returns 1 if ok, 0 if index doesn't exist and CREATE flags
wasn't given, -1 if error. */
-int mail_index_open(struct mail_index *index, enum mail_index_open_flags flags,
- enum file_lock_method lock_method);
+int mail_index_open(struct mail_index *index, enum mail_index_open_flags flags);
/* Open or create index. Returns 0 if ok, -1 if error. */
int mail_index_open_or_create(struct mail_index *index,
- enum mail_index_open_flags flags,
- enum file_lock_method lock_method);
+ enum mail_index_open_flags flags);
void mail_index_close(struct mail_index *index);
/* unlink() all the index files. */
int mail_index_unlink(struct mail_index *index);
int mail_transaction_log_file_lock(struct mail_transaction_log_file *file)
{
+ unsigned int lock_timeout_secs;
int ret;
if (file->locked)
return mail_transaction_log_file_dotlock(file);
i_assert(file->file_lock == NULL);
+ lock_timeout_secs = I_MIN(MAIL_TRANSCATION_LOG_LOCK_TIMEOUT,
+ file->log->index->max_lock_timeout_secs);
ret = mail_index_lock_fd(file->log->index, file->filepath, file->fd,
- F_WRLCK, MAIL_TRANSCATION_LOG_LOCK_TIMEOUT,
+ F_WRLCK, lock_timeout_secs,
&file->file_lock);
if (ret > 0) {
file->locked = TRUE;
log = i_new(struct mail_transaction_log, 1);
log->index = index;
- log->dotlock_settings.timeout = MAIL_TRANSCATION_LOG_LOCK_TIMEOUT;
+ log->dotlock_settings.timeout =
+ I_MIN(MAIL_TRANSCATION_LOG_LOCK_TIMEOUT,
+ index->max_lock_timeout_secs);;
log->dotlock_settings.stale_timeout =
MAIL_TRANSCATION_LOG_LOCK_CHANGE_TIMEOUT;
if (box->storage->set->mmap_disable)
#endif
open_flags |= MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE;
- if (mail_index_open(ctx->backup_index, open_flags,
- box->storage->set->parsed_lock_method) <= 0)
+ mail_index_set_lock_method(ctx->backup_index,
+ box->storage->set->parsed_lock_method, -1U);
+ if (mail_index_open(ctx->backup_index, open_flags) <= 0)
mail_index_free(&ctx->backup_index);
else
ctx->backup_view = mail_index_view_open(ctx->backup_index);
map->set = storage->set;
map->path = i_strdup(path);
map->index = mail_index_alloc(path, MDBOX_GLOBAL_INDEX_PREFIX);
+ mail_index_set_lock_method(map->index,
+ MAP_STORAGE(map)->set->parsed_lock_method,
+ mail_storage_get_lock_timeout(MAP_STORAGE(map), -1U));
map->root_list = root_list;
map->map_ext_id = mail_index_ext_register(map->index, "map",
sizeof(struct mdbox_map_mail_index_header),
if (mdbox_map_mkdir_storage(map) < 0)
return -1;
}
- ret = mail_index_open(map->index, open_flags,
- MAP_STORAGE(map)->set->parsed_lock_method);
+ ret = mail_index_open(map->index, open_flags);
if (ret < 0) {
mail_storage_set_internal_error(MAP_STORAGE(map));
mail_index_reset_error(map->index);
int index_storage_mailbox_open(struct mailbox *box, bool move_to_memory)
{
struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
- enum file_lock_method lock_method =
- box->storage->set->parsed_lock_method;
enum mail_index_open_flags index_flags;
int ret;
return -1;
}
- ret = mail_index_open(box->index, index_flags, lock_method);
+ ret = mail_index_open(box->index, index_flags);
if (ret <= 0 || move_to_memory) {
if ((index_flags & MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY) != 0) {
i_assert(ret <= 0);
/* try opening once more. it should be created
directly into memory now. */
if (mail_index_open_or_create(box->index,
- index_flags,
- lock_method) < 0)
+ index_flags) < 0)
i_panic("in-memory index creation failed");
}
}
mail_index_set_permissions(box->index, box->file_create_mode,
box->file_create_gid,
box->file_create_gid_origin);
+ mail_index_set_lock_method(box->index,
+ box->storage->set->parsed_lock_method,
+ mail_storage_get_lock_timeout(box->storage, -1U));
}
int index_storage_mailbox_enable(struct mailbox *box,
box->storage->set->dotlock_use_excl;
mk->dotlock_settings.nfs_flush =
box->storage->set->mail_nfs_storage;
- mk->dotlock_settings.timeout = KEYWORDS_LOCK_STALE_TIMEOUT + 2;
+ mk->dotlock_settings.timeout =
+ mail_storage_get_lock_timeout(box->storage,
+ KEYWORDS_LOCK_STALE_TIMEOUT + 2);
mk->dotlock_settings.stale_timeout = KEYWORDS_LOCK_STALE_TIMEOUT;
mk->dotlock_settings.temp_prefix =
mailbox_list_get_temp_prefix(box->list);
uidlist->dotlock_settings.nfs_flush =
mbox->box.storage->set->mail_nfs_storage;
uidlist->dotlock_settings.timeout =
- MAILDIR_UIDLIST_LOCK_STALE_TIMEOUT + 2;
+ mail_storage_get_lock_timeout(&mbox->storage->storage,
+ MAILDIR_UIDLIST_LOCK_STALE_TIMEOUT + 2);
uidlist->dotlock_settings.stale_timeout =
MAILDIR_UIDLIST_LOCK_STALE_TIMEOUT;
uidlist->dotlock_settings.callback = dotlock_callback;
memset(&set, 0, sizeof(set));
set.use_excl_lock = mbox->storage->storage.set->dotlock_use_excl;
set.nfs_flush = mbox->storage->storage.set->mail_nfs_storage;
- set.timeout = mbox->storage->set->mbox_lock_timeout;
+ set.timeout = mail_storage_get_lock_timeout(&mbox->storage->storage,
+ mbox->storage->set->mbox_lock_timeout);
set.stale_timeout = mbox->storage->set->mbox_dotlock_change_timeout;
set.callback = dotlock_callback;
set.context = ctx;
return 1;
}
- max_wait_time = time(NULL) + mbox->storage->set->mbox_lock_timeout;
+ max_wait_time = time(NULL) +
+ mail_storage_get_lock_timeout(&mbox->storage->storage,
+ mbox->storage->set->mbox_lock_timeout);
memset(&ctx, 0, sizeof(ctx));
ctx.mbox = mbox;
struct index_mailbox_list *ilist = INDEX_LIST_CONTEXT(list);
const char *path;
enum mail_index_open_flags index_flags = 0;
- enum file_lock_method lock_method = list->mail_set->parsed_lock_method;
int ret;
index_flags = mail_storage_settings_to_index_flags(list->mail_set);
- if (mail_index_open_or_create(ilist->mail_index, index_flags,
- lock_method) < 0) {
+ mail_index_set_lock_method(ilist->mail_index,
+ list->mail_set->parsed_lock_method, -1U);
+ if (mail_index_open_or_create(ilist->mail_index, index_flags) < 0) {
if (mail_index_move_to_memory(ilist->mail_index) < 0) {
/* try opening once more. it should be created
directly into memory now. */
ret = mail_index_open_or_create(ilist->mail_index,
- index_flags,
- lock_method);
+ index_flags);
if (ret < 0) {
/* everything failed. there's a bug in the
code, but just work around it by disabling
/* Returns -1 if error, 0 if failed with EEXIST, 1 if ok */
int mailbox_create_fd(struct mailbox *box, const char *path, int flags,
int *fd_r);
+unsigned int mail_storage_get_lock_timeout(struct mail_storage *storage,
+ unsigned int secs);
#endif
DEF(SET_UINT, mail_cache_min_mail_count),
DEF(SET_TIME, mailbox_idle_check_interval),
DEF(SET_UINT, mail_max_keyword_length),
+ DEF(SET_TIME, mail_max_lock_timeout),
DEF(SET_BOOL, mail_save_crlf),
DEF(SET_BOOL, fsync_disable),
DEF(SET_BOOL, mmap_disable),
.mail_cache_min_mail_count = 0,
.mailbox_idle_check_interval = 30,
.mail_max_keyword_length = 50,
+ .mail_max_lock_timeout = 0,
.mail_save_crlf = FALSE,
.fsync_disable = FALSE,
.mmap_disable = FALSE,
unsigned int mail_cache_min_mail_count;
unsigned int mailbox_idle_check_interval;
unsigned int mail_max_keyword_length;
+ unsigned int mail_max_lock_timeout;
bool mail_save_crlf;
bool fsync_disable;
bool mmap_disable;
*fd_r = fd;
return 1;
}
+
+unsigned int mail_storage_get_lock_timeout(struct mail_storage *storage,
+ unsigned int secs)
+{
+ return storage->set->mail_max_lock_timeout == 0 ? secs :
+ I_MIN(secs, storage->set->mail_max_lock_timeout);
+}