On Thu, Mar 25, 2010 at 05:25:53PM +0200, Timo Sirainen wrote:
> Are you using ext4 on the Linux NFS server?

Yes:

/dev/sda1 on / type ext4 (rw,errors=remount-ro)

> Nano/microsecond resolution timestamps fix the worst caching problems.

I can't see whether that's true through stat mtime though.

I've tried adding some extra debugging but it seems a variety of situations
are occurring:

Mar 25 15:49:36 freebsd-dev dovecot: IMAP(br...@dev.example.com): Our dotlock 
file /mail/0/6/37/30/brian%dev.example.com/dovecot-uidlist.lock was deleted 
(kept it 1 secs) file_dotlock_delete: unlink gave ENOENT
Mar 25 15:49:40 freebsd-dev dovecot: IMAP(br...@dev.example.com): Our dotlock 
file /mail/0/6/37/30/brian%dev.example.com/dovecot-uidlist.lock was overridden 
(kept it 0 secs) file_dotlock_delete: inode changed
Mar 25 15:49:54 freebsd-dev dovecot: IMAP(br...@dev.example.com): dotlock 
/mail/0/6/37/30/brian%dev.example.com/dovecot-uidlist.lock was immediately 
recreated under us
Mar 25 15:49:56 freebsd-dev dovecot: IMAP(br...@dev.example.com): dotlock 
/mail/0/6/37/30/brian%dev.example.com/dovecot-uidlist.lock was immediately 
recreated under us
Mar 25 15:50:18 freebsd-dev dovecot: IMAP(br...@dev.example.com): Our dotlock 
file /mail/0/6/37/30/brian%dev.example.com/dovecot-uidlist.lock was overridden 
(kept it 0 secs) file_dotlock_delete: inode changed
Mar 25 15:50:22 freebsd-dev dovecot: IMAP(br...@dev.example.com): dotlock 
/mail/0/6/37/30/brian%dev.example.com/dovecot-uidlist.lock was immediately 
recreated under us
Mar 25 15:50:27 freebsd-dev dovecot: IMAP(br...@dev.example.com): dotlock 
/mail/0/6/37/30/brian%dev.example.com/dovecot-uidlist.lock was immediately 
recreated under us

Out of interest, why is dot locking used instead of fcntl here?

Regards,

Brian.
--- src/lib/file-dotlock.c.orig	2010-03-25 15:40:12.000000000 +0000
+++ src/lib/file-dotlock.c	2010-03-25 15:48:17.000000000 +0000
@@ -671,7 +671,8 @@
 	return ret;
 }
 
-static void dotlock_replaced_warning(struct dotlock *dotlock, bool deleted)
+static void dotlock_replaced_warning(struct dotlock *dotlock, bool deleted,
+	const char *debug)
 {
 	const char *lock_path;
 	time_t now = time(NULL);
@@ -679,15 +680,17 @@
 	lock_path = file_dotlock_get_lock_path(dotlock);
 	if (dotlock->mtime == dotlock->lock_time) {
 		i_warning("Our dotlock file %s was %s "
-			  "(locked %d secs ago, touched %d secs ago)",
+			  "(locked %d secs ago, touched %d secs ago) %s",
 			  lock_path, deleted ? "deleted" : "overridden",
 			  (int)(now - dotlock->lock_time),
-			  (int)(now - dotlock->mtime));
+			  (int)(now - dotlock->mtime),
+			  debug ? debug : "");
 	} else {
 		i_warning("Our dotlock file %s was %s "
-			  "(kept it %d secs)", lock_path,
+			  "(kept it %d secs) %s", lock_path,
 			  deleted ? "deleted" : "overridden",
-			  (int)(now - dotlock->lock_time));
+			  (int)(now - dotlock->lock_time),
+			  debug ? debug : "");
 	}
 }
 
@@ -703,7 +706,9 @@
 	lock_path = file_dotlock_get_lock_path(dotlock);
 	if (nfs_safe_lstat(lock_path, &st) < 0) {
 		if (errno == ENOENT) {
-			dotlock_replaced_warning(dotlock, TRUE);
+			dotlock_replaced_warning(dotlock, TRUE,
+				"file_dotlock_delete: "
+				"nfs_safe_lstat gave ENOENT");
 			file_dotlock_free(&dotlock);
 			return 0;
 		}
@@ -715,7 +720,8 @@
 
 	if (dotlock->ino != st.st_ino ||
 	    !CMP_DEV_T(dotlock->dev, st.st_dev)) {
-		dotlock_replaced_warning(dotlock, FALSE);
+		dotlock_replaced_warning(dotlock, FALSE,
+			"file_dotlock_delete: inode changed");
 		errno = EEXIST;
 		file_dotlock_free(&dotlock);
 		return 0;
@@ -731,7 +737,8 @@
 
 	if (unlink(lock_path) < 0) {
 		if (errno == ENOENT) {
-			dotlock_replaced_warning(dotlock, TRUE);
+			dotlock_replaced_warning(dotlock, TRUE,
+				"file_dotlock_delete: unlink gave ENOENT");
 			file_dotlock_free(&dotlock);
 			return 0;
 		}
@@ -835,7 +842,8 @@
 	lock_path = file_dotlock_get_lock_path(dotlock);
 	if ((flags & DOTLOCK_REPLACE_FLAG_VERIFY_OWNER) != 0 &&
 	    !file_dotlock_is_locked(dotlock)) {
-		dotlock_replaced_warning(dotlock, FALSE);
+		dotlock_replaced_warning(dotlock, FALSE,
+			"file_dotlock_replace: FLAG_VERIFY_OWNER failed");
 		errno = EEXIST;
 		file_dotlock_free(&dotlock);
 		return 0;
@@ -844,7 +852,8 @@
 	if (rename(lock_path, dotlock->path) < 0) {
 		i_error("rename(%s, %s) failed: %m", lock_path, dotlock->path);
 		if (errno == ENOENT)
-			dotlock_replaced_warning(dotlock, TRUE);
+			dotlock_replaced_warning(dotlock, TRUE,
+				"file_dotlock_replace: rename gave ENOENT");
 		file_dotlock_free(&dotlock);
 		return -1;
 	}

Reply via email to