Skip to content

Commit

Permalink
udev: cleanup stack directory /run/udev/links when all workers exited
Browse files Browse the repository at this point in the history
By the previous commit, the stack directories are not removed even if
it is empty. To reduce the inode usage of /run, let's cleanup the
directories.
  • Loading branch information
yuwata committed Jul 20, 2022
1 parent b688ed9 commit 4cdeb8b
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 0 deletions.
39 changes: 39 additions & 0 deletions src/udev/udev-node.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,45 @@

#define UDEV_NODE_HASH_KEY SD_ID128_MAKE(b9,6a,f1,ce,40,31,44,1a,9e,19,ec,8b,ae,f3,e3,2f)

int udev_node_cleanup(void) {
_cleanup_closedir_ DIR *dir = NULL;

/* This must not be called when any workers exist. It would cause a race between mkdir() called
* by stack_directory_lock() and unlinkat() called by this. */

dir = opendir("/run/udev/links");
if (!dir) {
if (errno == ENOENT)
return 0;

return log_debug_errno(errno, "Failed to open directory '/run/udev/links', ignoring: %m");
}

FOREACH_DIRENT_ALL(de, dir, break) {
_cleanup_free_ char *lockfile = NULL;

if (de->d_name[0] == '.')
continue;

if (de->d_type != DT_DIR)
continue;

lockfile = path_join(de->d_name, ".lock");
if (!lockfile)
return log_oom_debug();

if (unlinkat(dirfd(dir), lockfile, 0) < 0 && errno != ENOENT) {
log_debug_errno(errno, "Failed to remove '/run/udev/links/%s', ignoring: %m", lockfile);
continue;
}

if (unlinkat(dirfd(dir), de->d_name, AT_REMOVEDIR) < 0 && errno != ENOTEMPTY)
log_debug_errno(errno, "Failed to remove '/run/udev/links/%s', ignoring: %m", de->d_name);
}

return 0;
}

static int node_symlink(sd_device *dev, const char *devnode, const char *slink) {
_cleanup_free_ char *target = NULL, *slink_tmp = NULL;
struct stat st;
Expand Down
1 change: 1 addition & 0 deletions src/udev/udev-node.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ int static_node_apply_permissions(

int udev_node_remove(sd_device *dev);
int udev_node_update(sd_device *dev, sd_device *dev_old);
int udev_node_cleanup(void);

size_t udev_node_escape_path(const char *src, char *dest, size_t size);
10 changes: 10 additions & 0 deletions src/udev/udevd.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
#include "udev-builtin.h"
#include "udev-ctrl.h"
#include "udev-event.h"
#include "udev-node.h"
#include "udev-util.h"
#include "udev-watch.h"
#include "user-util.h"
Expand Down Expand Up @@ -111,6 +112,7 @@ typedef struct Manager {

usec_t last_usec;

bool udev_node_needs_cleanup;
bool stop_exec_queue;
bool exit;
} Manager;
Expand Down Expand Up @@ -1151,6 +1153,9 @@ static int on_uevent(sd_device_monitor *monitor, sd_device *dev, void *userdata)

(void) event_queue_assume_block_device_unlocked(manager, dev);

/* To make the stack directory /run/udev/links cleaned up later. */
manager->udev_node_needs_cleanup = true;

/* we have fresh events, try to schedule them */
event_queue_start(manager);

Expand Down Expand Up @@ -1593,6 +1598,11 @@ static int on_post(sd_event_source *s, void *userdata) {

/* There are no idle workers. */

if (manager->udev_node_needs_cleanup) {
(void) udev_node_cleanup();
manager->udev_node_needs_cleanup = false;
}

if (manager->exit)
return sd_event_exit(manager->event, 0);

Expand Down

0 comments on commit 4cdeb8b

Please sign in to comment.