mirror of
https://github.com/systemd/systemd.git
synced 2025-01-27 18:04:05 +03:00
fs-util: introduce inotify_add_watch_and_warn() helper
The default message for ENOSPC is very misleading: it says that the disk is filled, but in fact the inotify watch limit is the problem. So let's introduce and use a wrapper that simply calls inotify_add_watch(2) and which fixes the error message up in case ENOSPC is returned.
This commit is contained in:
parent
5461cdebfa
commit
27c3112dcb
@ -660,6 +660,21 @@ int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask) {
|
||||||
|
if (inotify_add_watch(fd, pathname, mask) < 0) {
|
||||||
|
const char *reason;
|
||||||
|
|
||||||
|
if (errno == ENOSPC)
|
||||||
|
reason = "inotify watch limit reached";
|
||||||
|
else
|
||||||
|
reason = strerror_safe(errno);
|
||||||
|
|
||||||
|
return log_error_errno(errno, "Failed to add a watch for %s: %s", pathname, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static bool unsafe_transition(const struct stat *a, const struct stat *b) {
|
static bool unsafe_transition(const struct stat *a, const struct stat *b) {
|
||||||
/* Returns true if the transition from a to b is safe, i.e. that we never transition from unprivileged to
|
/* Returns true if the transition from a to b is safe, i.e. that we never transition from unprivileged to
|
||||||
* privileged files or directories. Why bother? So that unprivileged code can't symlink to privileged files
|
* privileged files or directories. Why bother? So that unprivileged code can't symlink to privileged files
|
||||||
|
@ -72,6 +72,7 @@ union inotify_event_buffer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int inotify_add_watch_fd(int fd, int what, uint32_t mask);
|
int inotify_add_watch_fd(int fd, int what, uint32_t mask);
|
||||||
|
int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CHASE_PREFIX_ROOT = 1 << 0, /* The specified path will be prefixed by the specified root before beginning the iteration */
|
CHASE_PREFIX_ROOT = 1 << 0, /* The specified path will be prefixed by the specified root before beginning the iteration */
|
||||||
|
@ -295,10 +295,12 @@ static int manager_check_ask_password(Manager *m) {
|
|||||||
if (m->ask_password_inotify_fd < 0)
|
if (m->ask_password_inotify_fd < 0)
|
||||||
return log_error_errno(errno, "Failed to create inotify object: %m");
|
return log_error_errno(errno, "Failed to create inotify object: %m");
|
||||||
|
|
||||||
if (inotify_add_watch(m->ask_password_inotify_fd, "/run/systemd/ask-password", IN_CREATE|IN_DELETE|IN_MOVE) < 0) {
|
r = inotify_add_watch_and_warn(m->ask_password_inotify_fd,
|
||||||
log_error_errno(errno, "Failed to watch \"/run/systemd/ask-password\": %m");
|
"/run/systemd/ask-password",
|
||||||
|
IN_CREATE|IN_DELETE|IN_MOVE);
|
||||||
|
if (r < 0) {
|
||||||
manager_close_ask_password(m);
|
manager_close_ask_password(m);
|
||||||
return -errno;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_event_add_io(m->event, &m->ask_password_event_source,
|
r = sd_event_add_io(m->event, &m->ask_password_event_source,
|
||||||
|
@ -89,24 +89,29 @@ int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = log_warning_errno(errno, "Failed to add watch on %s: %s", s->path, errno == ENOSPC ? "too many watches" : strerror_safe(r));
|
/* This second call to inotify_add_watch() should fail like the previous
|
||||||
if (cut)
|
* one and is done for logging the error in a comprehensive way. */
|
||||||
*cut = tmp;
|
r = inotify_add_watch_and_warn(s->inotify_fd, s->path, flags);
|
||||||
goto fail;
|
if (r < 0) {
|
||||||
} else {
|
if (cut)
|
||||||
exists = true;
|
*cut = tmp;
|
||||||
|
goto fail;
|
||||||
/* Path exists, we don't need to watch parent too closely. */
|
|
||||||
if (oldslash) {
|
|
||||||
char *cut2 = oldslash + (oldslash == s->path);
|
|
||||||
char tmp2 = *cut2;
|
|
||||||
*cut2 = '\0';
|
|
||||||
|
|
||||||
(void) inotify_add_watch(s->inotify_fd, s->path, IN_MOVE_SELF);
|
|
||||||
/* Error is ignored, the worst can happen is we get spurious events. */
|
|
||||||
|
|
||||||
*cut2 = tmp2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Hmm, we succeeded in adding the watch this time... let's continue. */
|
||||||
|
}
|
||||||
|
exists = true;
|
||||||
|
|
||||||
|
/* Path exists, we don't need to watch parent too closely. */
|
||||||
|
if (oldslash) {
|
||||||
|
char *cut2 = oldslash + (oldslash == s->path);
|
||||||
|
char tmp2 = *cut2;
|
||||||
|
*cut2 = '\0';
|
||||||
|
|
||||||
|
(void) inotify_add_watch(s->inotify_fd, s->path, IN_MOVE_SELF);
|
||||||
|
/* Error is ignored, the worst can happen is we get spurious events. */
|
||||||
|
|
||||||
|
*cut2 = tmp2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cut)
|
if (cut)
|
||||||
|
@ -225,9 +225,9 @@ static int run(int argc, char * argv[]) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to create notify event source: %m");
|
return log_error_errno(r, "Failed to create notify event source: %m");
|
||||||
|
|
||||||
r = inotify_add_watch(state.inotify_fd, "/run/systemd/", IN_CREATE);
|
r = inotify_add_watch_and_warn(state.inotify_fd, "/run/systemd/", IN_CREATE);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(errno, "Failed to watch /run/systemd/: %m");
|
return r;
|
||||||
|
|
||||||
state.run_systemd_wd = r;
|
state.run_systemd_wd = r;
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/inotify.h>
|
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
#include <sys/signalfd.h>
|
#include <sys/signalfd.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
@ -29,6 +28,7 @@
|
|||||||
#include "exit-status.h"
|
#include "exit-status.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
|
#include "fs-util.h"
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
#include "io-util.h"
|
#include "io-util.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
@ -510,12 +510,9 @@ static int process_and_watch_password_files(void) {
|
|||||||
if (notify < 0)
|
if (notify < 0)
|
||||||
return log_error_errno(errno, "Failed to allocate directory watch: %m");
|
return log_error_errno(errno, "Failed to allocate directory watch: %m");
|
||||||
|
|
||||||
if (inotify_add_watch(notify, "/run/systemd/ask-password", IN_CLOSE_WRITE|IN_MOVED_TO) < 0) {
|
r = inotify_add_watch_and_warn(notify, "/run/systemd/ask-password", IN_CLOSE_WRITE|IN_MOVED_TO);
|
||||||
if (errno == ENOSPC)
|
if (r < 0)
|
||||||
return log_error_errno(errno, "Failed to add /run/systemd/ask-password to directory watch: inotify watch limit reached");
|
return r;
|
||||||
else
|
|
||||||
return log_error_errno(errno, "Failed to add /run/systemd/ask-password to directory watch: %m");
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_se(sigemptyset(&mask) >= 0);
|
assert_se(sigemptyset(&mask) >= 0);
|
||||||
assert_se(sigset_add_many(&mask, SIGINT, SIGTERM, -1) >= 0);
|
assert_se(sigset_add_many(&mask, SIGINT, SIGTERM, -1) >= 0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user