summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorGilles Chehade <gilles@cvs.openbsd.org>2013-03-30 10:41:04 +0000
committerGilles Chehade <gilles@cvs.openbsd.org>2013-03-30 10:41:04 +0000
commite34d4a6fa236b2ca32a90ada7f8df3b87646308a (patch)
treeffe7a8f21f3be222e875d0a48811f9e63708a9ca /usr.sbin
parent480bb7a895db405907b783bab099fc91d09e9001 (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')
-rw-r--r--usr.sbin/smtpd/queue_fsqueue.c48
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();