[dovecot-cvs] dovecot/src/lib-storage/index/maildir maildir-storage.c, 1.143, 1.144 maildir-storage.h, 1.60, 1.61 maildir-util.c, 1.19, 1.20

tss at dovecot.org tss at dovecot.org
Tue Jan 16 16:59:11 UTC 2007


Update of /var/lib/cvs/dovecot/src/lib-storage/index/maildir
In directory talvi:/tmp/cvs-serv25388/src/lib-storage/index/maildir

Modified Files:
	maildir-storage.c maildir-storage.h maildir-util.c 
Log Message:
When opening maildir, check if tmp/'s atime is over 8h old. If it is, delete
old files in it. However if atime - ctime > 36h, it means there's nothing to
be deleted so the scanning isn't done then. We update atime if filesystem is
mounted with noatime.



Index: maildir-storage.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-storage.c,v
retrieving revision 1.143
retrieving revision 1.144
diff -u -d -r1.143 -r1.144
--- maildir-storage.c	14 Jan 2007 01:47:21 -0000	1.143
+++ maildir-storage.c	16 Jan 2007 16:59:06 -0000	1.144
@@ -32,8 +32,6 @@
 extern struct mail_storage maildir_storage;
 extern struct mailbox maildir_mailbox;
 
-static const char *maildirs[] = { "cur", "new", "tmp", NULL  };
-
 static int verify_inbox(struct mail_storage *storage);
 
 static const char *strip_tail_slash(const char *path)
@@ -257,25 +255,26 @@
 	struct stat st;
 
 	if (verify) {
-		if (lstat(dir, &st) == 0)
+		if (stat(dir, &st) == 0)
 			return 0;
 
 		if (errno != ENOENT) {
 			mail_storage_set_critical(storage,
-						  "lstat(%s) failed: %m", dir);
+						  "stat(%s) failed: %m", dir);
 			return -1;
 		}
 	}
 
-	if (mkdir_parents(dir, CREATE_MODE) < 0 &&
-	    (errno != EEXIST || !verify)) {
-		if (errno != EEXIST && (!verify || errno != ENOENT)) {
+	if (mkdir_parents(dir, CREATE_MODE) < 0) {
+		if (errno == EEXIST) {
+			if (!verify)
+				return -1;
+		} else {
 			mail_storage_set_critical(storage,
 						  "mkdir(%s) failed: %m", dir);
+			return -1;
 		}
-		return -1;
 	}
-
 	return 0;
 }
 
@@ -283,26 +282,31 @@
 static int create_maildir(struct mail_storage *storage,
 			  const char *dir, bool verify)
 {
-	const char **tmp, *path;
+	const char *path;
+	struct stat st;
 
-	if (!verify && mkdir_verify(storage, dir, verify) < 0)
+	if (mkdir_verify(storage, t_strconcat(dir, "/cur", NULL), verify) < 0)
+		return -1;
+	if (mkdir_verify(storage, t_strconcat(dir, "/new", NULL), verify) < 0)
 		return -1;
 
-	for (tmp = maildirs; *tmp != NULL; tmp++) {
-		path = t_strconcat(dir, "/", *tmp, NULL);
-
-		if (mkdir_verify(storage, path, verify) < 0) {
-			if (!verify || errno != ENOENT)
-				return -1;
-
-			/* small optimization. if we're verifying, we don't
-			   check that the root dir actually exists unless we
-			   fail here. */
-			if (mkdir_verify(storage, dir, verify) < 0)
-				return -1;
-			if (mkdir_verify(storage, path, verify) < 0)
-				return -1;
+	/* if tmp/ directory exists, we need to clean it up once in a while */
+	path = t_strconcat(dir, "/tmp", NULL);
+	if (stat(path, &st) == 0) {
+		if (st.st_atime >
+		    st.st_ctime + MAILDIR_TMP_DELETE_SECS) {
+			/* the directory should be empty. we won't do anything
+			   until ctime changes. */
+		} else if (st.st_atime < ioloop_time - MAILDIR_TMP_SCAN_SECS) {
+			/* time to scan */
+			(void)maildir_tmp_cleanup(storage, path);
 		}
+	} else if (errno == ENOENT) {
+		if (mkdir_verify(storage, path, verify) < 0)
+			return -1;
+	} else {
+		mail_storage_set_critical(storage, "stat(%s) failed: %m", path);
+		return -1;
 	}
 
 	return 0;

Index: maildir-storage.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-storage.h,v
retrieving revision 1.60
retrieving revision 1.61
diff -u -d -r1.60 -r1.61
--- maildir-storage.h	22 Dec 2006 14:20:38 -0000	1.60
+++ maildir-storage.h	16 Jan 2007 16:59:06 -0000	1.61
@@ -29,6 +29,11 @@
    calculating file's virtual size (added missing CRs). */
 #define MAILDIR_EXTRA_VIRTUAL_SIZE 'W'
 
+/* How often to scan tmp/ directory for old files (based on dir's atime) */
+#define MAILDIR_TMP_SCAN_SECS (8*60*60)
+/* Delete files having ctime older than this from tmp/. 36h is standard. */
+#define MAILDIR_TMP_DELETE_SECS (36*60*60)
+
 #define MAILDIR_SAVE_FLAG_HARDLINK 0x10000000
 #define MAILDIR_SAVE_FLAG_DELETED  0x20000000
 
@@ -105,6 +110,7 @@
 const char *maildir_generate_tmp_filename(const struct timeval *tv);
 int maildir_create_tmp(struct maildir_mailbox *mbox, const char *dir,
 		       mode_t mode, const char **fname_r);
+void maildir_tmp_cleanup(struct mail_storage *storage, const char *dir);
 bool maildir_filename_get_size(const char *fname, char type, uoff_t *size_r);
 
 void maildir_transaction_created(struct mail_index_transaction *t);

Index: maildir-util.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-util.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- maildir-util.c	15 Dec 2006 18:11:06 -0000	1.19
+++ maildir-util.c	16 Jan 2007 16:59:06 -0000	1.20
@@ -10,7 +10,9 @@
 #include "maildir-sync.h"
 
 #include <unistd.h>
+#include <dirent.h>
 #include <fcntl.h>
+#include <utime.h>
 #include <sys/stat.h>
 
 static int maildir_file_do_try(struct maildir_mailbox *mbox, uint32_t uid,
@@ -136,6 +138,83 @@
 	return fd;
 }
 
+void maildir_tmp_cleanup(struct mail_storage *storage, const char *dir)
+{
+	DIR *dirp;
+	struct dirent *d;
+	struct stat st;
+	string_t *path;
+	unsigned int dir_len;
+
+	dirp = opendir(dir);
+	if (dirp == NULL) {
+		if (errno != ENOENT) {
+			mail_storage_set_critical(storage,
+				"opendir(%s) failed: %m", dir);
+		}
+		return;
+	}
+
+	t_push();
+	path = t_str_new(256);
+	str_printfa(path, "%s/", dir);
+	dir_len = str_len(path);
+
+	while ((d = readdir(dirp)) != NULL) {
+		if (d->d_name[0] == '.' &&
+		    (d->d_name[1] == '\0' ||
+		     (d->d_name[1] == '.' && d->d_name[2] == '\0'))) {
+			/* skip . and .. */
+			continue;
+		}
+
+		str_truncate(path, dir_len);
+		str_append(path, d->d_name);
+		if (stat(str_c(path), &st) < 0) {
+			if (errno != ENOENT) {
+				mail_storage_set_critical(storage,
+					"stat(%s) failed: %m", str_c(path));
+			}
+		} else if (st.st_ctime <=
+			   ioloop_time - MAILDIR_TMP_DELETE_SECS) {
+			if (unlink(str_c(path)) < 0 && errno != ENOENT) {
+				mail_storage_set_critical(storage,
+					"unlink(%s) failed: %m", str_c(path));
+			}
+		}
+	}
+	t_pop();
+
+#ifdef HAVE_DIRFD
+	if (fstat(dirfd(dirp), &st) < 0) {
+		mail_storage_set_critical(storage,
+			"fstat(%s) failed: %m", dir);
+	}
+#else
+	if (stat(dir, &st) < 0) {
+		mail_storage_set_critical(storage,
+			"stat(%s) failed: %m", dir);
+	}
+#endif
+	else if (st.st_atime < ioloop_time) {
+		/* mounted with noatime. update it ourself. */
+		struct utimbuf ut;
+
+		ut.actime = ioloop_time;
+		ut.modtime = st.st_mtime;
+
+		if (utime(dir, &ut) < 0 && errno != ENOENT) {
+			mail_storage_set_critical(storage,
+				"utime(%s) failed: %m", dir);
+		}
+	}
+
+	if (closedir(dirp) < 0) {
+		mail_storage_set_critical(storage,
+			"closedir(%s) failed: %m", dir);
+	}
+}
+
 bool maildir_filename_get_size(const char *fname, char type, uoff_t *size_r)
 {
 	uoff_t size = 0;



More information about the dovecot-cvs mailing list