dovecot-2.1: Keep track of seen mountpoints and warn at startup ...

dovecot at dovecot.org dovecot at dovecot.org
Wed Feb 1 20:12:10 EET 2012


details:   http://hg.dovecot.org/dovecot-2.1/rev/51324056af4f
changeset: 14040:51324056af4f
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Feb 01 19:29:31 2012 +0200
description:
Keep track of seen mountpoints and warn at startup if one is missing.
doveadm mount commands can be used to manipulate the list.

The list is kept in $rundir/mounts, but since it may be deleted after a
reboot a copy is kept also in $statedir/mounts. If it's not found from
$rundir at startup, it's copied there from $statedir. (The reason why
only $statedir isn't used is because it's often not world-readable.)

diffstat:

 src/doveadm/Makefile.am          |    2 +
 src/doveadm/doveadm-mount.c      |  125 +++++++++++++++
 src/doveadm/doveadm.c            |    1 +
 src/doveadm/doveadm.h            |    1 +
 src/lib-master/Makefile.am       |    2 +
 src/lib-master/mountpoint-list.c |  313 +++++++++++++++++++++++++++++++++++++++
 src/lib-master/mountpoint-list.h |   60 +++++++
 src/master/main.c                |   40 ++++-
 8 files changed, 543 insertions(+), 1 deletions(-)

diffs (truncated from 640 to 300 lines):

diff -r 56ff22125b7d -r 51324056af4f src/doveadm/Makefile.am
--- a/src/doveadm/Makefile.am	Wed Feb 01 19:13:04 2012 +0200
+++ b/src/doveadm/Makefile.am	Wed Feb 01 19:29:31 2012 +0200
@@ -21,6 +21,7 @@
 	-DMODULEDIR=\""$(moduledir)"\" \
 	-DDOVEADM_MODULEDIR=\""$(doveadm_moduledir)"\" \
 	-DPKG_RUNDIR=\""$(rundir)"\" \
+	-DPKG_STATEDIR=\""$(statedir)"\" \
 	-DBINDIR=\""$(bindir)"\" \
 	-DMANDIR=\""$(mandir)"\"
 
@@ -93,6 +94,7 @@
 	doveadm-kick.c \
 	doveadm-log.c \
 	doveadm-master.c \
+	doveadm-mount.c \
 	doveadm-mutf7.c \
 	doveadm-penalty.c \
 	doveadm-print-flow.c \
diff -r 56ff22125b7d -r 51324056af4f src/doveadm/doveadm-mount.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/doveadm/doveadm-mount.c	Wed Feb 01 19:29:31 2012 +0200
@@ -0,0 +1,125 @@
+/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "mountpoint-list.h"
+#include "doveadm.h"
+#include "doveadm-print.h"
+
+extern struct doveadm_cmd doveadm_cmd_mount[];
+
+static void mount_cmd_help(doveadm_command_t *cmd) ATTR_NORETURN;
+
+static struct mountpoint_list *mountpoint_list_get(void)
+{
+	const char *perm_path, *state_path;
+
+	perm_path = t_strconcat(PKG_STATEDIR"/"MOUNTPOINT_LIST_FNAME, NULL);
+	state_path = t_strconcat(doveadm_settings->base_dir,
+				 "/"MOUNTPOINT_LIST_FNAME, NULL);
+	return mountpoint_list_init(perm_path, state_path);
+}
+
+static void cmd_mount_status(int argc, char *argv[])
+{
+	struct mountpoint_list *mountpoints;
+	struct mountpoint_list_iter *iter;
+	struct mountpoint_list_rec *rec;
+	bool mounts_known;
+
+	if (argc > 2)
+		mount_cmd_help(cmd_mount_status);
+
+	doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE);
+	doveadm_print_header_simple(" ");
+	doveadm_print_header("path", "path", DOVEADM_PRINT_HEADER_FLAG_EXPAND);
+	doveadm_print_header_simple("state");
+
+	mountpoints = mountpoint_list_get();
+	mounts_known = mountpoint_list_update_mounted(mountpoints) == 0;
+	iter = mountpoint_list_iter_init(mountpoints);
+	while ((rec = mountpoint_list_iter_next(iter)) != NULL) {
+		if (argv[1] != NULL && strcmp(argv[1], rec->mount_path) != 0)
+			continue;
+
+		if (mounts_known && MOUNTPOINT_WRONGLY_NOT_MOUNTED(rec))
+			doveadm_print("!");
+		else
+			doveadm_print(" ");
+		doveadm_print(!rec->wildcard ? rec->mount_path :
+			      t_strconcat(rec->mount_path, "*", NULL));
+
+		doveadm_print(rec->state);
+	}
+	mountpoint_list_iter_deinit(&iter);
+	mountpoint_list_deinit(&mountpoints);
+}
+
+static void cmd_mount_add(int argc, char *argv[])
+{
+	struct mountpoint_list *mountpoints;
+	struct mountpoint_list_rec rec;
+	unsigned int len;
+
+	if (argc > 3)
+		mount_cmd_help(cmd_mount_add);
+
+	mountpoints = mountpoint_list_get();
+	if (argv[1] == NULL) {
+		mountpoint_list_add_missing(mountpoints, MOUNTPOINT_STATE_DEFAULT,
+					    mountpoint_list_default_ignore_types);
+	} else {
+		memset(&rec, 0, sizeof(rec));
+		rec.mount_path = argv[1];
+		rec.state = argv[2] != NULL ? argv[2] :
+			MOUNTPOINT_STATE_DEFAULT;
+
+		len = strlen(rec.mount_path);
+		if (len > 0 && rec.mount_path[len-1] == '*') {
+			rec.wildcard = TRUE;
+			rec.mount_path = t_strndup(rec.mount_path, len-1);
+		}
+		mountpoint_list_add(mountpoints, &rec);
+	}
+	(void)mountpoint_list_save(mountpoints);
+	mountpoint_list_deinit(&mountpoints);
+}
+
+static void cmd_mount_remove(int argc, char *argv[])
+{
+	struct mountpoint_list *mountpoints;
+
+	if (argc != 2)
+		mount_cmd_help(cmd_mount_remove);
+
+	mountpoints = mountpoint_list_get();
+	if (!mountpoint_list_remove(mountpoints, argv[1]))
+		i_error("Mountpoint not found: %s", argv[1]);
+	else
+		(void)mountpoint_list_save(mountpoints);
+	mountpoint_list_deinit(&mountpoints);
+}
+
+struct doveadm_cmd doveadm_cmd_mount[] = {
+	{ cmd_mount_status, "mount status", "[<path>]" },
+	{ cmd_mount_add, "mount add", "[<path> [<state>]]" },
+	{ cmd_mount_remove, "mount remove", "<path>" }
+};
+
+static void mount_cmd_help(doveadm_command_t *cmd)
+{
+	unsigned int i;
+
+	for (i = 0; i < N_ELEMENTS(doveadm_cmd_mount); i++) {
+		if (doveadm_cmd_mount[i].cmd == cmd)
+			help(&doveadm_cmd_mount[i]);
+	}
+	i_unreached();
+}
+
+void doveadm_register_mount_commands(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < N_ELEMENTS(doveadm_cmd_mount); i++)
+		doveadm_register_cmd(&doveadm_cmd_mount[i]);
+}
diff -r 56ff22125b7d -r 51324056af4f src/doveadm/doveadm.c
--- a/src/doveadm/doveadm.c	Wed Feb 01 19:13:04 2012 +0200
+++ b/src/doveadm/doveadm.c	Wed Feb 01 19:29:31 2012 +0200
@@ -321,6 +321,7 @@
 	} else {
 		quick_init = FALSE;
 		doveadm_register_director_commands();
+		doveadm_register_mount_commands();
 		doveadm_register_proxy_commands();
 		doveadm_register_log_commands();
 		doveadm_dump_init();
diff -r 56ff22125b7d -r 51324056af4f src/doveadm/doveadm.h
--- a/src/doveadm/doveadm.h	Wed Feb 01 19:13:04 2012 +0200
+++ b/src/doveadm/doveadm.h	Wed Feb 01 19:29:31 2012 +0200
@@ -38,5 +38,6 @@
 void doveadm_register_director_commands(void);
 void doveadm_register_proxy_commands(void);
 void doveadm_register_log_commands(void);
+void doveadm_register_mount_commands(void);
 
 #endif
diff -r 56ff22125b7d -r 51324056af4f src/lib-master/Makefile.am
--- a/src/lib-master/Makefile.am	Wed Feb 01 19:13:04 2012 +0200
+++ b/src/lib-master/Makefile.am	Wed Feb 01 19:29:31 2012 +0200
@@ -19,6 +19,7 @@
 	master-service.c \
 	master-service-settings.c \
 	master-service-settings-cache.c \
+	mountpoint-list.c \
 	syslog-util.c
 
 headers = \
@@ -34,6 +35,7 @@
 	master-service-settings.h \
 	master-service-settings-cache.h \
 	service-settings.h \
+	mountpoint-list.h \
 	syslog-util.h
 
 pkginc_libdir=$(pkgincludedir)
diff -r 56ff22125b7d -r 51324056af4f src/lib-master/mountpoint-list.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-master/mountpoint-list.c	Wed Feb 01 19:29:31 2012 +0200
@@ -0,0 +1,313 @@
+/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "istream.h"
+#include "file-copy.h"
+#include "safe-mkstemp.h"
+#include "str.h"
+#include "write-full.h"
+#include "mountpoint.h"
+#include "mountpoint-list.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+struct mountpoint_list {
+	pool_t pool;
+	const char *perm_path, *state_path;
+	ARRAY_DEFINE(recs, struct mountpoint_list_rec *);
+	bool load_failed;
+};
+
+struct mountpoint_list_iter {
+	struct mountpoint_list *list;
+	unsigned int idx;
+};
+
+const char *const mountpoint_list_default_ignore_types[] = {
+	"proc", /* Linux, Solaris */
+	"procfs", /* AIX, BSD */
+	"tmpfs", /* Linux */
+	"sysfs", /* Linux */
+	"debugfs", /* Linux */
+	"securityfs", /* Linux */
+	"devpts", /* Linux */
+	"devtmpfs", /* Linux */
+	"rpc_pipefs", /* Linux */
+	"fusectl", /* Linux */
+	"nfsd", /* Linux */
+	"binfmt_misc", /* Linux */
+	"devfs", /* Solaris, OSX, BSD */
+	"ctfs", /* Solaris */
+	"mntfs", /* Solaris */
+	"objfs", /* Solaris */
+	"sharefs", /* Solaris */
+	"lofs", /* Solaris */
+	"fd", /* Solaris */
+	NULL
+};
+
+static int mountpoint_list_load(struct mountpoint_list *list);
+
+struct mountpoint_list *
+mountpoint_list_init(const char *perm_path, const char *state_path)
+{
+	struct mountpoint_list *list;
+	pool_t pool;
+
+	pool = pool_alloconly_create("mountpoint list", 512);
+	list = p_new(pool, struct mountpoint_list, 1);
+	list->pool = pool;
+	list->perm_path = p_strdup(pool, perm_path);
+	list->state_path = p_strdup(pool, state_path);
+	p_array_init(&list->recs, pool, 16);
+
+	(void)mountpoint_list_load(list);
+	return list;
+}
+
+void mountpoint_list_deinit(struct mountpoint_list **_list)
+{
+	struct mountpoint_list *list = *_list;
+
+	*_list = NULL;
+	pool_unref(&list->pool);
+}
+
+static int mountpoint_list_load(struct mountpoint_list *list)
+{
+	struct mountpoint_list_rec rec;
+	struct istream *input;
+	char *p, *line;
+	unsigned int len;
+	int fd, ret = 0;
+
+	memset(&rec, 0, sizeof(rec));
+
+	fd = open(list->state_path, O_RDONLY);
+	if (fd == -1) {
+		if (errno != ENOENT) {
+			i_error("open(%s) failed: %m", list->state_path);
+			return -1;
+		}
+		if (file_copy(list->perm_path, list->state_path, FALSE) < 0)
+			return -1;
+		fd = open(list->perm_path, O_RDONLY);
+		if (fd == -1) {
+			if (errno == ENOENT) {
+				/* perm_path didn't exist either */
+				return 0;
+			}
+			i_error("open(%s) failed: %m", list->state_path);
+			return -1;
+		}
+	}
+	input = i_stream_create_fd(fd, (size_t)-1, TRUE);
+	while ((line = i_stream_read_next_line(input)) != NULL) {


More information about the dovecot-cvs mailing list