I've been thinking about mountpoints recently. There have been a few problems 
related to them:

 - If dbox mails and indexes are in different filesystems, and index fs isn't 
mounted and mailbox is accessed -> Dovecot rebuilds indexes from scratch, which 
changes UIDVALIDITY, which causes client to redownload mails. All mails will 
also show up as unread. Once index fs gets mounted again, the UIDVALIDITY 
changes again and client again redownloads mails. What should happen instead is 
that Dovecot simply refuses to rebuild indexes when the index fs isn't mounted. 
This isn't as critical for mbox/maildir, but probably a good idea to do there 
as well.

 - If dbox's alternative storage isn't mounted and a mail from there is tried 
to be accessed -> Dovecot rebuilds indexes and sees that all mails in alt path 
are gone, so Dovecot also deletes them from indexes as well. Once alt fs is 
mounted again, the mails in there won't come back without manual index rebuild 
and then they have also lost flags and have updated UIDs causing clients to 
redownload them. So again what should happen is that Dovecot won't rebuild 
indexes while alt fs isn't mounted.

 - For dsync-based replication I need to keep a state of each mountpoint 
(online, offline, failover) to determine how to access user's mails.

So in the first two cases the main problem is: How does Dovecot know where a 
mountpoint begins? If the mountpoint is actually mounted there is no problem, 
because there are functions to find it (e.g. from /etc/mtab). So how to find a 
mountpoint that should exist, but doesn't? In some OSes Dovecot could maybe 
read and parse /etc/fstab, but that doesn't exist in all OSes, and do all 
installations even have all of the filesystems listed there anyway? (They could 
be in some startup script.)

So, I was thinking about adding doveadm commands to explicitly tell Dovecot 
about the mountpoints that it needs to care about. When no mountpoints are 
defined Dovecot would behave as it does now.

doveadm mount add|remove <path>

 - add/remove mountpoint

doveadm mount state [<path> [<state>]]

 - get/set state of mountpoint (used by replication)
 - if path isn't given list states of all mountpoints

List of mountpoints is kept in /var/lib/dovecot/mounts. But because the dovecot 
directory is only accessible to root (and probably too much trouble to change 
that), there's another list in /var/run/dovecot/mounts. This one also contains 
the states of the mounts. When Dovecot starts up and can't find the mounts from 
rundir, it creates it from vardir's mounts.

When mail processes notice that a directory is missing, it usually autocreates 
it. With mountpoints enabled, Dovecot first finds the root mountpoint for the 
directory. The mount root is stat()ed and its parent is stat()ed. If their 
device numbers equal, the filesystem is unmounted currently, and Dovecot fails 
instead of creating a new directory. Similar logic is used to avoid doing a 
dbox rebuild if its alt dir is currently in unmounted filesystem.

The main problem I see with all this is how to make sysadmins remember to use 
these commands when they add/remove mountpoints?.. Perhaps the additions could 
be automatic at startup. Whenever Dovecot sees a new mountpoint, it's added. If 
an old mountpoint doesn't exist at startup a warning is logged about it. Of 
course many of the mountpoints aren't intended for mail storage. They could be 
hidden from the "mount state" list by setting their state to "ignore". Dovecot 
could also skip some of the common known mountpoints, such as where type is 
proc/tmpfs/sysfs.

Thoughts?

Reply via email to