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