[Dovecot] Rename file opened for read-write -- cannot edit subscriptions
Howdy, Here is a problem with fix affecting dovecot-1.0.10 (and 1.1rc13). On a linux system's CIFS mounted filesystem, it is not possible to rename a file opened read-write: $ sleep 5 >> .subscriptions.lock & mv .subscriptions.lock .subscriptions mv: cannot move `.subscriptions.lock' to `.subscriptions': Text file busy This causes problems in editing subscriptions, as the new subscription list is still open for writing before it is renamed in: lib-storage/subscription-file/subscription-file.c line 169 in dovecot version 1.0.10 (and 1.1rc13) This is an unpatched linux 2.6.21-5, CIFS mounted filesystem from a windows 2003 sp2 server. The documentation for rename(2) indicates that it is allowed to return an error when the file is already opened, so perhaps the file should be closed before the replace. Should this be done in file_dotlock_replace (before line 672) generally? Here is a patch that does so: diff -rw -U3 dovecot-1.0.10/src/lib/file-dotlock.c dovecot-1.0.10-patch/src/lib/file-dotlock.c --- dovecot-1.0.10/src/lib/file-dotlock.c 2007-12-11 13:52:08.000000000 -0500 +++ dovecot-1.0.10/src/lib/file-dotlock.c 2008-01-23 08:53:33.000000000 -0500 @@ -635,7 +635,7 @@ struct dotlock *dotlock; struct stat st, st2; const char *lock_path; - int fd; + int fd, old_errno; dotlock = *dotlock_p; *dotlock_p = NULL; @@ -669,6 +669,14 @@ } } + if (dotlock->fd != -1) { + old_errno = errno; + if (close(dotlock->fd) < 0) + i_error("close(%s) failed: %m", dotlock->path); + dotlock->fd = -1; + errno = old_errno; + } + if (rename(lock_path, dotlock->path) < 0) { i_error("rename(%s, %s) failed: %m", lock_path, dotlock->path); file_dotlock_free(dotlock);
On Wed, 2008-01-23 at 09:20 -0500, Jack Schmidt wrote:
On a linux system's CIFS mounted filesystem, it is not possible to rename a file opened read-write:
$ sleep 5 >> .subscriptions.lock & mv .subscriptions.lock .subscriptions mv: cannot move
.subscriptions.lock' to
.subscriptions': Text file busy
Does this happen only if the file is opened by the same process, or also if it's opened by another process? Sounds like it happens no matter who has the file open.
The documentation for rename(2) indicates that it is allowed to return an error when the file is already opened,
I don't see it saying that in Debian unstable or in UNIX98 specs.
so perhaps the file should be closed before the replace. Should this be done in file_dotlock_replace (before line 672) generally?
This is a similar patch than I've previously suggested to people having similar NFS problems: http://dovecot.org/list/dovecot/2006-December/018145.html
But I don't really want to make it work like that as default. It most likely doesn't fix all the possible places in code where this can happen. Or if this same problem happens when another process has the file opened, this doesn't help with it either. So if someone is using a system where this is a problem, I'd rather have them patch this code themselves so they know that Dovecot may not always work correctly.
participants (2)
-
Jack Schmidt
-
Timo Sirainen