[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