diff options
author | Gilles Chehade <gilles@cvs.openbsd.org> | 2013-03-30 10:41:04 +0000 |
---|---|---|
committer | Gilles Chehade <gilles@cvs.openbsd.org> | 2013-03-30 10:41:04 +0000 |
commit | e34d4a6fa236b2ca32a90ada7f8df3b87646308a (patch) | |
tree | ffe7a8f21f3be222e875d0a48811f9e63708a9ca /usr.sbin/smtpd/queue_fsqueue.c | |
parent | 480bb7a895db405907b783bab099fc91d09e9001 (diff) |
have smtpd temporarily refuse new messages if file system holding the queue
has less than 10% of disk space or inodes left. a warning is logged and the
clients will get a temporarily failure asking them to retry later.
prompted by deraadt@
Diffstat (limited to 'usr.sbin/smtpd/queue_fsqueue.c')
-rw-r--r-- | usr.sbin/smtpd/queue_fsqueue.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/usr.sbin/smtpd/queue_fsqueue.c b/usr.sbin/smtpd/queue_fsqueue.c index c4a10fcbe54..67845936b41 100644 --- a/usr.sbin/smtpd/queue_fsqueue.c +++ b/usr.sbin/smtpd/queue_fsqueue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: queue_fsqueue.c,v 1.58 2013/01/31 18:34:43 eric Exp $ */ +/* $OpenBSD: queue_fsqueue.c,v 1.59 2013/03/30 10:41:03 gilles Exp $ */ /* * Copyright (c) 2011 Gilles Chehade <gilles@poolp.org> @@ -22,6 +22,8 @@ #include <sys/param.h> #include <sys/socket.h> #include <sys/stat.h> +#include <sys/param.h> +#include <sys/mount.h> #include <ctype.h> #include <err.h> @@ -76,6 +78,10 @@ struct tree evpcount; #define PATH_EVPTMP PATH_INCOMING "/envelope.tmp" +/* percentage of remaining space / inodes required to accept new messages */ +#define MINSPACE 99 +#define MININODES 10 + struct queue_backend queue_backend_fs = { fsqueue_init, fsqueue_message, @@ -84,6 +90,43 @@ struct queue_backend queue_backend_fs = { static struct timespec startup; +static int +fsqueue_check_space(void) +{ + struct statfs buf; + uint64_t used; + uint64_t total; + + if (statfs(PATH_QUEUE, &buf) < 0) { + log_warn("warn: fsqueue_check_space: statfs"); + return 0; + } + + used = buf.f_blocks - buf.f_bfree; + total = buf.f_bavail + used; + if (total != 0) + used = (float)used / (float)total * 100; + else + used = 100; + if (100 - used < MINSPACE) { + log_warnx("warn: not enough disk space: %lu%% left", 100 - used); + return 0; + } + + used = buf.f_files - buf.f_ffree; + total = buf.f_favail + used; + if (total != 0) + used = (float)used / (float)total * 100; + else + used = 100; + if (100 - used < MININODES) { + log_warnx("warn: not enough inodes: %lu%% left", 100 - used); + return 0; + } + + return 1; +} + static void fsqueue_message_path(uint32_t msgid, char *buf, size_t len) { @@ -331,6 +374,9 @@ fsqueue_message_create(uint32_t *msgid) char rootdir[MAXPATHLEN]; struct stat sb; + if (! fsqueue_check_space()) + return 0; + again: *msgid = queue_generate_msgid(); |