From 31a60a6f886b47c4630925572bbe14d4aa772f90 Mon Sep 17 00:00:00 2001 From: CHTEKK Date: Thu, 19 Apr 2007 17:03:37 +0000 Subject: New version, should dramatically improve performance by using maildirsize now if present. Also improves some logic. Fixes the message on bounce. svn path=/; revision=32 --- vda/postfix-2.4.0-vda-e-chtekk.patch | 300 +++++++++++++++++++++++------------ 1 file changed, 198 insertions(+), 102 deletions(-) diff --git a/vda/postfix-2.4.0-vda-e-chtekk.patch b/vda/postfix-2.4.0-vda-e-chtekk.patch index e7dca76..f5824c8 100644 --- a/vda/postfix-2.4.0-vda-e-chtekk.patch +++ b/vda/postfix-2.4.0-vda-e-chtekk.patch @@ -1,6 +1,6 @@ diff -Nru postfix-2.4.0/README_FILES/VDA_README postfix-2.4.0-vda/README_FILES/VDA_README --- postfix-2.4.0/README_FILES/VDA_README 1970-01-01 01:00:00.000000000 +0100 -+++ postfix-2.4.0-vda/README_FILES/VDA_README 2007-04-14 00:24:44.000000000 +0200 ++++ postfix-2.4.0-vda/README_FILES/VDA_README 2007-04-19 10:57:41.000000000 +0200 @@ -0,0 +1,94 @@ +Installation: + @@ -98,7 +98,7 @@ diff -Nru postfix-2.4.0/README_FILES/VDA_README postfix-2.4.0-vda/README_FILES/V +More informations can be found at http://vda.sourceforge.net/ diff -Nru postfix-2.4.0/src/global/mail_params.h postfix-2.4.0-vda/src/global/mail_params.h --- postfix-2.4.0/src/global/mail_params.h 2007-02-25 03:15:42.000000000 +0100 -+++ postfix-2.4.0-vda/src/global/mail_params.h 2007-04-13 23:02:09.000000000 +0200 ++++ postfix-2.4.0-vda/src/global/mail_params.h 2007-04-19 10:57:41.000000000 +0200 @@ -2099,6 +2099,54 @@ #define DEF_VIRT_GID_MAPS "" extern char *var_virt_gid_maps; @@ -156,7 +156,7 @@ diff -Nru postfix-2.4.0/src/global/mail_params.h postfix-2.4.0-vda/src/global/ma extern int var_virt_minimum_uid; diff -Nru postfix-2.4.0/src/util/file_limit.c postfix-2.4.0-vda/src/util/file_limit.c --- postfix-2.4.0/src/util/file_limit.c 2003-10-22 20:48:36.000000000 +0200 -+++ postfix-2.4.0-vda/src/util/file_limit.c 2007-04-13 23:02:09.000000000 +0200 ++++ postfix-2.4.0-vda/src/util/file_limit.c 2007-04-19 10:57:41.000000000 +0200 @@ -85,7 +85,11 @@ #else struct rlimit rlim; @@ -172,7 +172,7 @@ diff -Nru postfix-2.4.0/src/util/file_limit.c postfix-2.4.0-vda/src/util/file_li #ifdef SIGXFSZ diff -Nru postfix-2.4.0/src/virtual/mailbox.c postfix-2.4.0-vda/src/virtual/mailbox.c --- postfix-2.4.0/src/virtual/mailbox.c 2006-06-26 14:59:19.000000000 +0200 -+++ postfix-2.4.0-vda/src/virtual/mailbox.c 2007-04-13 23:02:09.000000000 +0200 ++++ postfix-2.4.0-vda/src/virtual/mailbox.c 2007-04-19 10:57:41.000000000 +0200 @@ -70,6 +70,58 @@ #define YES 1 #define NO 0 @@ -338,8 +338,8 @@ diff -Nru postfix-2.4.0/src/virtual/mailbox.c postfix-2.4.0-vda/src/virtual/mail * Cleanup. diff -Nru postfix-2.4.0/src/virtual/maildir.c postfix-2.4.0-vda/src/virtual/maildir.c --- postfix-2.4.0/src/virtual/maildir.c 2006-06-26 14:59:19.000000000 +0200 -+++ postfix-2.4.0-vda/src/virtual/maildir.c 2007-04-13 23:02:09.000000000 +0200 -@@ -63,10 +63,243 @@ ++++ postfix-2.4.0-vda/src/virtual/maildir.c 2007-04-19 19:02:05.000000000 +0200 +@@ -63,10 +63,339 @@ #include #include @@ -362,6 +362,76 @@ diff -Nru postfix-2.4.0/src/virtual/maildir.c postfix-2.4.0-vda/src/virtual/mail #include "virtual.h" ++/* Maildirsize maximal size. */ ++#define SIZEFILE_MAX 5120 ++ ++/* ++ * Chris Stratford ++ * Read the maildirsize file to get quota info. ++ * ++ * Arguments: ++ * dirname: the maildir ++ * countptr: number of messages ++ * ++ * Returns the size of all mails as read from maildirsize, ++ * zero if it couldn't read the file. ++ */ ++static long read_maildirsize(char *dirname, long *countptr) ++{ ++ struct stat statbuf; ++ VSTRING *sizefilename = vstring_alloc(1024); ++ VSTRING *sizebuf = vstring_alloc(SIZEFILE_MAX); ++ VSTREAM *sizefile; ++ char *p; ++ int len, first; ++ long sum = 0, count = 0; ++ ++ vstring_sprintf(sizefilename, "%s/%s", dirname, "maildirsize"); ++ sizefile = vstream_fopen(vstring_str(sizefilename), O_RDONLY, 0); ++ if (!sizefile || (stat(vstring_str(sizefilename), &statbuf) < 0) || (statbuf.st_size > SIZEFILE_MAX)) { ++ if (sizefile) { ++ vstream_fclose(sizefile); ++ } ++ ++ return 0; ++ } ++ ++ len = vstream_fread(sizefile, vstring_str(sizebuf), SIZEFILE_MAX); ++ ++ p = vstring_str(sizebuf); ++ *(p + len) = '\0'; ++ first = 1; ++ ++ while (*p) { ++ long n = 0, c = 0; ++ char *q = p; ++ ++ while (*p) { ++ if (*p++ == '\n') { ++ p[-1] = 0; ++ break; ++ } ++ } ++ ++ if (first) { ++ first = 0; ++ continue; ++ } ++ ++ sscanf(q, "%ld %ld", &n, &c); ++ sum += n; ++ count += c; ++ } ++ ++ vstream_fclose(sizefile); ++ vstring_free(sizefilename); ++ vstring_free(sizebuf); ++ ++ *countptr = count; ++ ++ return sum; ++} ++ +/* + * Gives the size of the file according to the Maildir++ extension + * present in the filename (code taken from courier-imap). @@ -411,21 +481,20 @@ diff -Nru postfix-2.4.0/src/virtual/maildir.c postfix-2.4.0-vda/src/virtual/mail +/* + * Computes quota usage for a directory (taken from exim). + * -+ * This function is called if quota is set for a virtual maildir box. -+ * It scans the directory and stats all the files in order to get a total -+ * size and count. This is an expensive thing to do. But by doing it this -+ * way no write access is needed to a single file that can be erased or -+ * meddled with because of lock problems. ++ * This function is called to determine the exact quota usage of a virtual ++ * maildir box. To achieve maximum possible speed while doing this, it takes ++ * advantage of the maildirsize file and the Maildir++ extensions to filenames, ++ * when applicable and configured to be used. In all other cases it simply ++ * stats all the files as needed to get the size information. + * + * Arguments: + * dirname: the name of the directory + * countptr: where to add the file count (because this function recurses) -+ * mailplus: if the check will make use of the Maildir++ file extension + * + * Returns the sum of the sizes of all measurable files, + * zero if the directory could not be opened. + */ -+static long check_dir_size(char *dirname, long *countptr, bool mailplus) ++static long check_dir_size(char *dirname, long *countptr) +{ + char *myname = "check_dir_size"; + DIR *dir; @@ -433,6 +502,12 @@ diff -Nru postfix-2.4.0/src/virtual/maildir.c postfix-2.4.0-vda/src/virtual/mail + struct dirent *ent; + struct stat statbuf; + ++ if (!var_virt_mailbox_limit_inbox && var_virt_maildir_extended && var_virt_create_maildirsize && (sum = read_maildirsize(dirname, countptr))) { ++ if (msg_verbose) ++ msg_info("%s: maildirsize used: dir=%s sum=%ld count=%ld", myname, dirname, sum, *countptr); ++ return sum; ++ } ++ + dir = opendir(dirname); + if (dir == NULL) { + if (make_dirs(dirname, 0700) == 0) { /* Try to create the dirs. */ @@ -450,6 +525,7 @@ diff -Nru postfix-2.4.0/src/virtual/maildir.c postfix-2.4.0-vda/src/virtual/mail + + while ((ent = readdir(dir)) != NULL) { + char *name = ent->d_name; ++ long tmpsum = 0; + VSTRING *buffer; + + if (var_virt_trash_count) { @@ -461,10 +537,30 @@ diff -Nru postfix-2.4.0/src/virtual/maildir.c postfix-2.4.0-vda/src/virtual/mail + continue; + } + -+ if (var_virt_maildir_extended && mailplus) { -+ /* Using Maildir++ file extension. */ -+ sum += maildir_parsequota(name); -+ (*countptr)++; ++ /* ++ * Here comes the real logic behind this function. ++ * Optimized to be the most efficient possible, ++ * depending on the settings given. ++ * See above for a more detailed description. ++ */ ++ if (var_virt_mailbox_limit_inbox) { ++ if (var_virt_maildir_extended && (tmpsum = maildir_parsequota(name))) { ++ sum += tmpsum; ++ (*countptr)++; ++ } ++ else { ++ buffer = vstring_alloc(1024); ++ vstring_sprintf(buffer, "%s/%s", dirname, name); ++ if (stat(vstring_str(buffer), &statbuf) < 0) { ++ vstring_free(buffer); ++ continue; ++ } ++ if ((statbuf.st_mode & S_IFREG) != 0) { ++ sum += (long) statbuf.st_size; ++ (*countptr)++; ++ } ++ vstring_free(buffer); ++ } + } + else { + buffer = vstring_alloc(1024); @@ -479,7 +575,7 @@ diff -Nru postfix-2.4.0/src/virtual/maildir.c postfix-2.4.0-vda/src/virtual/mail + (*countptr)++; + } + } else if ((statbuf.st_mode & S_IFDIR) != 0) { -+ sum += check_dir_size(vstring_str(buffer), countptr, mailplus); ++ sum += check_dir_size(vstring_str(buffer), countptr); + } + vstring_free(buffer); + } @@ -487,7 +583,7 @@ diff -Nru postfix-2.4.0/src/virtual/maildir.c postfix-2.4.0-vda/src/virtual/mail + closedir(dir); + + if (msg_verbose) -+ msg_info("%s: dir=%s sum=%ld count=%ld", myname, dirname, sum, *countptr); ++ msg_info("%s: full scan done: dir=%s sum=%ld count=%ld", myname, dirname, sum, *countptr); + + return sum; +} @@ -583,7 +679,7 @@ diff -Nru postfix-2.4.0/src/virtual/maildir.c postfix-2.4.0-vda/src/virtual/mail /* deliver_maildir - delivery to maildir-style mailbox */ int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr) -@@ -86,6 +319,27 @@ +@@ -86,6 +415,27 @@ struct stat st; struct timeval starttime; @@ -611,10 +707,14 @@ diff -Nru postfix-2.4.0/src/virtual/maildir.c postfix-2.4.0-vda/src/virtual/mail GETTIMEOFDAY(&starttime); /* -@@ -122,6 +376,81 @@ - curdir = concatenate(usr_attr.mailbox, "cur/", (char *) 0); +@@ -117,9 +467,74 @@ + copy_flags = MAIL_COPY_TOFILE | MAIL_COPY_RETURN_PATH + | MAIL_COPY_DELIVERED | MAIL_COPY_ORIG_RCPT; - /* +- newdir = concatenate(usr_attr.mailbox, "new/", (char *) 0); +- tmpdir = concatenate(usr_attr.mailbox, "tmp/", (char *) 0); +- curdir = concatenate(usr_attr.mailbox, "cur/", (char *) 0); ++ /* + * Concatenate the maildir suffix (if set). + */ + if (*var_virt_maildir_suffix == 0) { @@ -671,29 +771,21 @@ diff -Nru postfix-2.4.0/src/virtual/maildir.c postfix-2.4.0-vda/src/virtual/mail + if (n != 0) { + set_eugid(usr_attr.uid, usr_attr.gid); + if (var_virt_mailbox_limit_inbox) { -+ /* Check Inbox only (new and cur dirs) with Maildir++. */ -+ saved_size = check_dir_size(newdir, &saved_count, 1); -+ saved_size += check_dir_size(curdir, &saved_count, 1); -+ /* Check tmp dir without Maildir++. */ -+ saved_size += check_dir_size(tmpdir, &saved_count, 0); ++ /* Check Inbox only (new, cur and tmp dirs). */ ++ saved_size = check_dir_size(newdir, &saved_count); ++ saved_size += check_dir_size(curdir, &saved_count); ++ saved_size += check_dir_size(tmpdir, &saved_count); + } + else { -+ /* -+ * Check all boxes. -+ * This will use "old" stat() calls instead of the faster -+ * Maildir++ support because we cannot afford the -+ * time to test all filename types. -+ */ -+ saved_size = check_dir_size(usr_attr.mailbox, &saved_count, 0); ++ /* Check all boxes. */ ++ saved_size = check_dir_size(usr_attr.mailbox, &saved_count); + } + set_eugid(var_owner_uid, var_owner_gid); + } -+ -+ /* + + /* * Create and write the file as the recipient, so that file quota work. - * Create any missing directories on the fly. The file name is chosen - * according to ftp://koobera.math.uic.edu/www/proto/maildir.html: -@@ -178,6 +507,7 @@ +@@ -178,6 +593,7 @@ (unsigned long) starttime.tv_sec, var_pid, get_hostname()); tmpfile = concatenate(tmpdir, STR(buf), (char *) 0); newfile = 0; @@ -701,7 +793,7 @@ diff -Nru postfix-2.4.0/src/virtual/maildir.c postfix-2.4.0-vda/src/virtual/mail if ((dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0 && (errno != ENOENT || make_dirs(tmpdir, 0700) < 0 -@@ -200,17 +530,254 @@ +@@ -200,17 +616,251 @@ (unsigned long) starttime.tv_usec, get_hostname()); newfile = concatenate(newdir, STR(buf), (char *) 0); @@ -709,6 +801,14 @@ diff -Nru postfix-2.4.0/src/virtual/maildir.c postfix-2.4.0-vda/src/virtual/mail if ((mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr), dst, copy_flags, "\n", why)) == 0) { +- if (sane_link(tmpfile, newfile) < 0 +- && (errno != ENOENT +- || (make_dirs(curdir, 0700), make_dirs(newdir, 0700)) < 0 +- || sane_link(tmpfile, newfile) < 0)) { +- dsb_simple(why, mbox_dsn(errno, "4.2.0"), +- "create maildir file %s: %m", newfile); +- mail_copy_status = MAIL_COPY_STAT_WRITE; +- } + + /* + * Add a ",S=" to the newly written file according to the @@ -734,8 +834,7 @@ diff -Nru postfix-2.4.0/src/virtual/maildir.c postfix-2.4.0-vda/src/virtual/mail + */ + if (saved_size > n) { + mail_copy_status = MAIL_COPY_STAT_WRITE; -+ vstring_sprintf(why->reason, "%s", var_virt_maildir_limit_message); -+ if (((long) statbuf.st_size > n) || (var_virt_overquota_bounce)) ++ if (((long) statbuf.st_size > n) || (var_virt_overquota_bounce)) + errno = EFBIG; + else + errno = EDQUOT; @@ -891,83 +990,80 @@ diff -Nru postfix-2.4.0/src/virtual/maildir.c postfix-2.4.0-vda/src/virtual/mail + myfree(filtername); + } /* End-Of-Maildirfilter */ + -+ /* Deliver to curdir. */ -+ if (mail_copy_status == 0) { ++ /* Deliver to curdir. */ ++ if (mail_copy_status == 0) { ++ if (sane_link(tmpfile, newfile) < 0 ++ && (errno != ENOENT ++ || (make_dirs(curdir, 0700), make_dirs(newdir, 0700), make_dirs(tmpdir,0700)) < 0 ++ || sane_link(tmpfile, newfile) < 0)) { ++ dsb_simple(why, mbox_dsn(errno, "4.2.0"), "create maildir file %s: %m", newfile); ++ mail_copy_status = MAIL_COPY_STAT_WRITE; ++ } + - if (sane_link(tmpfile, newfile) < 0 - && (errno != ENOENT -- || (make_dirs(curdir, 0700), make_dirs(newdir, 0700)) < 0 -+ || (make_dirs(curdir, 0700), make_dirs(newdir, 0700), make_dirs(tmpdir,0700)) < 0 - || sane_link(tmpfile, newfile) < 0)) { - dsb_simple(why, mbox_dsn(errno, "4.2.0"), - "create maildir file %s: %m", newfile); - mail_copy_status = MAIL_COPY_STAT_WRITE; - } -+ -+ if (var_virt_create_maildirsize) { -+ time(&tm); -+ -+ if (*var_virt_maildir_suffix == 0) { -+ sizefilename = concatenate(usr_attr.mailbox, "maildirsize", (char *) 0); -+ } -+ else { -+ sizefilename = concatenate(usr_attr.mailbox, var_virt_maildir_suffix, (char *) 0); -+ sizefilename = concatenate(sizefilename, "maildirsize", (char *) 0); -+ } ++ if (var_virt_create_maildirsize) { ++ time(&tm); + -+ /* Check if the quota in the file is the same as the current one, if not, delete the file. */ -+ sizefile = vstream_fopen(sizefilename, O_RDONLY, 0); -+ if (sizefile) { -+ filequota = vstring_alloc(128); -+ vstring_get_null_bound(filequota, sizefile, 127); -+ vstream_fclose(sizefile); -+ if (atol(vstring_export(filequota)) != n) -+ unlink(sizefilename); -+ } ++ if (*var_virt_maildir_suffix == 0) { ++ sizefilename = concatenate(usr_attr.mailbox, "maildirsize", (char *) 0); ++ } ++ else { ++ sizefilename = concatenate(usr_attr.mailbox, var_virt_maildir_suffix, (char *) 0); ++ sizefilename = concatenate(sizefilename, "maildirsize", (char *) 0); ++ } + -+ /* Open maildirsize file to append this transaction. */ -+ sizefile = vstream_fopen(sizefilename, O_WRONLY | O_APPEND, 0640); ++ /* Check if the quota in the file is the same as the current one, if not, delete the file. */ ++ sizefile = vstream_fopen(sizefilename, O_RDONLY, 0); ++ if (sizefile) { ++ filequota = vstring_alloc(128); ++ vstring_get_null_bound(filequota, sizefile, 127); ++ vstream_fclose(sizefile); ++ if (atol(vstring_export(filequota)) != n) ++ unlink(sizefilename); ++ } + -+ /* If the open fails (maildirsize doesn't exist), or it's too large, overwrite it. */ -+ if(!sizefile || (stat(sizefilename, &sizefile_stat) != 0) || (int) sizefile_stat.st_size > 5120 || (int) sizefile_stat.st_mtime + 10*60 < tm) { -+ /* If the file exists, sizefile has been opened above, so close it first. */ -+ if (sizefile) { -+ vstream_fclose(sizefile); -+ sizefile = vstream_fopen(sizefilename, O_WRONLY | O_TRUNC, 0640); -+ } -+ else { -+ sizefile = vstream_fopen(sizefilename, O_WRONLY | O_CREAT, 0640); -+ } ++ /* Open maildirsize file to append this transaction. */ ++ sizefile = vstream_fopen(sizefilename, O_WRONLY | O_APPEND, 0640); + -+ /* If the creation worked, write to the file, otherwise just give up. */ -+ if (sizefile) { -+ vstream_fprintf(sizefile, "%ldS\n%ld %ld\n", n, saved_size, saved_count); -+ vstream_fclose(sizefile); ++ /* If the open fails (maildirsize doesn't exist), or it's too large, or too old, overwrite it. */ ++ if(!sizefile || (stat(sizefilename, &sizefile_stat) < 0) || (sizefile_stat.st_size > SIZEFILE_MAX) || (sizefile_stat.st_mtime + 30*60 < tm)) { ++ /* If the file exists, sizefile has been opened above, so close it first. */ ++ if (sizefile) { ++ vstream_fclose(sizefile); ++ sizefile = vstream_fopen(sizefilename, O_WRONLY | O_TRUNC, 0640); ++ } ++ else { ++ sizefile = vstream_fopen(sizefilename, O_WRONLY | O_CREAT, 0640); ++ } ++ ++ /* If the creation worked, write to the file, otherwise just give up. */ ++ if (sizefile) { ++ vstream_fprintf(sizefile, "%ldS\n%ld %ld\n", n, saved_size, saved_count); ++ vstream_fclose(sizefile); ++ } ++ } ++ else { ++ /* We opened maildirsize, so let's just append this transaction and close it. */ ++ vstream_fprintf(sizefile, "%ld 1\n", (long) statbuf.st_size); ++ vstream_fclose(sizefile); ++ } + } + } -+ else { -+ /* We opened maildirsize, so let's just append this transaction and close it. */ -+ vstream_fprintf(sizefile, "%ld 1\n", (long) statbuf.st_size); -+ vstream_fclose(sizefile); -+ } + } -+ } -+} + } if (unlink(tmpfile) < 0) msg_warn("remove %s: %m", tmpfile); -@@ -231,6 +798,9 @@ +@@ -231,6 +881,9 @@ STR(why->reason)); msg_warn("perhaps you need to create the maildirs in advance"); } + if (errno == EFBIG) { -+ dsb_simple(why, "5.0.0", "The user has overdrawn his diskspace quota"); ++ dsb_simple(why, "5.0.0", var_virt_maildir_limit_message); + } vstring_sprintf_prepend(why->reason, "maildir delivery failed: "); deliver_status = (STR(why->status)[0] == '4' ? -@@ -246,6 +816,8 @@ +@@ -246,6 +899,8 @@ myfree(newdir); myfree(tmpdir); myfree(curdir); @@ -978,7 +1074,7 @@ diff -Nru postfix-2.4.0/src/virtual/maildir.c postfix-2.4.0-vda/src/virtual/mail myfree(newfile); diff -Nru postfix-2.4.0/src/virtual/virtual.c postfix-2.4.0-vda/src/virtual/virtual.c --- postfix-2.4.0/src/virtual/virtual.c 2007-03-27 02:07:43.000000000 +0200 -+++ postfix-2.4.0-vda/src/virtual/virtual.c 2007-04-13 23:02:09.000000000 +0200 ++++ postfix-2.4.0-vda/src/virtual/virtual.c 2007-04-19 10:57:42.000000000 +0200 @@ -330,12 +330,27 @@ int var_virt_mailbox_limit; char *var_mail_spool_dir; /* XXX dependency fix */ @@ -1085,7 +1181,7 @@ diff -Nru postfix-2.4.0/src/virtual/virtual.c postfix-2.4.0-vda/src/virtual/virt } diff -Nru postfix-2.4.0/src/virtual/virtual.h postfix-2.4.0-vda/src/virtual/virtual.h --- postfix-2.4.0/src/virtual/virtual.h 2006-01-08 00:59:47.000000000 +0100 -+++ postfix-2.4.0-vda/src/virtual/virtual.h 2007-04-13 23:02:09.000000000 +0200 ++++ postfix-2.4.0-vda/src/virtual/virtual.h 2007-04-19 10:57:42.000000000 +0200 @@ -34,6 +34,8 @@ extern MAPS *virtual_mailbox_maps; extern MAPS *virtual_uid_maps; -- cgit v1.2.3-65-gdbad