udevadm: info --cleanup-db

Most of the udev database from initramfs should be deleted before
starting udev in the real root. udevadm: info --cleanup-db deletes
all database entries in /run/udev. Events that processed IMPORT{db},
or mark devices explicitely as persistent, will be excluded.
This commit is contained in:
Kay Sievers 2011-04-13 22:33:01 +02:00
parent 09913ced8c
commit 9ead662791
8 changed files with 132 additions and 3 deletions

6
NEWS
View File

@ -2,6 +2,12 @@ udev 168
========
Bugfixes.
warning if /run is not writable.
udevadm control --exit
udevadm info --cleanup-db
udev 167
========
Bugfixes.

2
TODO
View File

@ -1,5 +1,3 @@
- do not write age/configured in initramfs
- remove deprecated trigger --type=failed logic
- remove deprecated BUS=, SYSFS{}=, ID= keys

View File

@ -134,6 +134,13 @@ int udev_device_update_db(struct udev_device *udev_device)
return -1;
}
/*
* set 'sticky' bit to indicate that we should not clean the
* database when we transition from initramfs to the real root
*/
if (udev_device_get_db_persist(udev_device))
fchmod(fileno(f), 01644);
if (has_info) {
size_t devlen = strlen(udev_get_dev_path(udev))+1;
struct udev_list_entry *list_entry;

View File

@ -89,6 +89,7 @@ struct udev_device {
bool uevent_loaded;
bool is_initialized;
bool sysattr_list_read;
bool db_persist;
};
struct udev_list_entry *udev_device_add_property(struct udev_device *udev_device, const char *key, const char *value)
@ -1774,3 +1775,13 @@ int udev_device_set_ifindex(struct udev_device *udev_device, int ifindex)
udev_device_add_property(udev_device, "IFINDEX", num);
return 0;
}
bool udev_device_get_db_persist(struct udev_device *udev_device)
{
return udev_device->db_persist;
}
void udev_device_set_db_persist(struct udev_device *udev_device)
{
udev_device->db_persist = true;
}

View File

@ -109,6 +109,8 @@ int udev_device_set_watch_handle(struct udev_device *udev_device, int handle);
int udev_device_get_ifindex(struct udev_device *udev_device);
int udev_device_set_ifindex(struct udev_device *udev_device, int ifindex);
void udev_device_set_info_loaded(struct udev_device *device);
bool udev_device_get_db_persist(struct udev_device *udev_device);
void udev_device_set_db_persist(struct udev_device *udev_device);
/* libudev-device-private.c */
int udev_device_update_db(struct udev_device *udev_device);

View File

@ -150,6 +150,7 @@ enum token_type {
TK_A_STRING_ESCAPE_NONE,
TK_A_STRING_ESCAPE_REPLACE,
TK_A_DB_PERSIST,
TK_A_INOTIFY_WATCH, /* int */
TK_A_DEVLINK_PRIO, /* int */
TK_A_OWNER, /* val */
@ -284,6 +285,7 @@ static const char *token_str(enum token_type type)
[TK_A_STRING_ESCAPE_NONE] = "A STRING_ESCAPE_NONE",
[TK_A_STRING_ESCAPE_REPLACE] = "A STRING_ESCAPE_REPLACE",
[TK_A_DB_PERSIST] = "A DB_PERSIST",
[TK_A_INOTIFY_WATCH] = "A INOTIFY_WATCH",
[TK_A_DEVLINK_PRIO] = "A DEVLINK_PRIO",
[TK_A_OWNER] = "A OWNER",
@ -370,6 +372,7 @@ static void dump_token(struct udev_rules *rules, struct token *token)
break;
case TK_A_STRING_ESCAPE_NONE:
case TK_A_STRING_ESCAPE_REPLACE:
case TK_A_DB_PERSIST:
dbg(rules->udev, "%s\n", token_str(type));
break;
case TK_M_TEST:
@ -1045,6 +1048,7 @@ static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
break;
case TK_A_STRING_ESCAPE_NONE:
case TK_A_STRING_ESCAPE_REPLACE:
case TK_A_DB_PERSIST:
break;
case TK_A_RUN:
token->key.value_off = add_string(rule_tmp->rules, value);
@ -1572,6 +1576,7 @@ static int add_rule(struct udev_rules *rules, char *line,
rule_add_key(&rule_tmp, TK_A_DEVLINK_PRIO, op, NULL, &prio);
dbg(rules->udev, "link priority=%i\n", prio);
}
pos = strstr(value, "event_timeout=");
if (pos != NULL) {
int tout = atoi(&pos[strlen("event_timeout=")]);
@ -1579,6 +1584,7 @@ static int add_rule(struct udev_rules *rules, char *line,
rule_add_key(&rule_tmp, TK_A_EVENT_TIMEOUT, op, NULL, &tout);
dbg(rules->udev, "event timeout=%i\n", tout);
}
pos = strstr(value, "string_escape=");
if (pos != NULL) {
pos = &pos[strlen("string_escape=")];
@ -1587,6 +1593,11 @@ static int add_rule(struct udev_rules *rules, char *line,
else if (strncmp(pos, "replace", strlen("replace")) == 0)
rule_add_key(&rule_tmp, TK_A_STRING_ESCAPE_REPLACE, op, NULL, NULL);
}
pos = strstr(value, "db_persist=");
if (pos != NULL)
rule_add_key(&rule_tmp, TK_A_DB_PERSIST, op, NULL, NULL);
pos = strstr(value, "nowatch");
if (pos != NULL) {
const int off = 0;
@ -1602,11 +1613,13 @@ static int add_rule(struct udev_rules *rules, char *line,
dbg(rules->udev, "inotify watch of device requested\n");
}
}
pos = strstr(value, "static_node=");
if (pos != NULL) {
rule_add_key(&rule_tmp, TK_A_STATIC_NODE, op, &pos[strlen("static_node=")], NULL);
rule_tmp.rule.rule.has_static_node = true;
}
continue;
}
err(rules->udev, "unknown key '%s' in %s:%u\n", key, filename, lineno);
@ -2332,6 +2345,9 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
const char *key = &rules->buf[cur->key.value_off];
const char *value;
/* implicitely mark database as persistent across initramfs transition */
udev_device_set_db_persist(event->dev);
value = udev_device_get_property_value(event->dev_db, key);
if (value != NULL) {
struct udev_list_entry *entry;
@ -2407,6 +2423,9 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
case TK_A_STRING_ESCAPE_REPLACE:
esc = ESCAPE_REPLACE;
break;
case TK_A_DB_PERSIST:
udev_device_set_db_persist(event->dev);
break;
case TK_A_INOTIFY_WATCH:
if (event->inotify_watch_final)
break;

View File

@ -200,6 +200,81 @@ static int export_devices(struct udev *udev)
return 0;
}
static void cleanup_dir(DIR *dir, mode_t mask, int depth)
{
struct dirent *dent;
if (depth <= 0)
return;
for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
struct stat stats;
if (dent->d_name[0] == '.')
continue;
if (fstatat(dirfd(dir), dent->d_name, &stats, AT_SYMLINK_NOFOLLOW) != 0)
continue;
if ((stats.st_mode & mask) != 0)
continue;
if (S_ISDIR(stats.st_mode)) {
DIR *dir2;
dir2 = fdopendir(openat(dirfd(dir), dent->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC));
if (dir2 != NULL) {
cleanup_dir(dir2, mask, depth-1);
closedir(dir2);
}
unlinkat(dirfd(dir), dent->d_name, AT_REMOVEDIR);
} else {
unlinkat(dirfd(dir), dent->d_name, 0);
}
}
}
static void cleanup_db(struct udev *udev)
{
char filename[UTIL_PATH_SIZE];
DIR *dir;
util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/queue.bin", NULL);
unlink(filename);
util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/data", NULL);
dir = opendir(filename);
if (dir != NULL) {
cleanup_dir(dir, S_ISVTX, 1);
closedir(dir);
}
util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/links", NULL);
dir = opendir(filename);
if (dir != NULL) {
cleanup_dir(dir, 0, 2);
closedir(dir);
}
util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/tags", NULL);
dir = opendir(filename);
if (dir != NULL) {
cleanup_dir(dir, 0, 2);
closedir(dir);
}
util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/watch", NULL);
dir = opendir(filename);
if (dir != NULL) {
cleanup_dir(dir, 0, 1);
closedir(dir);
}
util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/firmware-missing", NULL);
dir = opendir(filename);
if (dir != NULL) {
cleanup_dir(dir, 0, 1);
closedir(dir);
}
}
int udevadm_info(struct udev *udev, int argc, char *argv[])
{
struct udev_device *device = NULL;
@ -216,6 +291,7 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
{ "path", required_argument, NULL, 'p' },
{ "query", required_argument, NULL, 'q' },
{ "attribute-walk", no_argument, NULL, 'a' },
{ "cleanup-db", no_argument, NULL, 'c' },
{ "export-db", no_argument, NULL, 'e' },
{ "root", no_argument, NULL, 'r' },
{ "run", no_argument, NULL, 'R' },
@ -248,7 +324,7 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
int option;
struct stat statbuf;
option = getopt_long(argc, argv, "aed:n:p:q:rxP:RVh", options, NULL);
option = getopt_long(argc, argv, "aced:n:p:q:rxP:RVh", options, NULL);
if (option == -1)
break;
@ -345,6 +421,9 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
case 'e':
export_devices(udev);
goto exit;
case 'c':
cleanup_db(udev);
goto exit;
case 'x':
export = true;
break;
@ -371,6 +450,7 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
" --export export key/value pairs\n"
" --export-prefix export the key name with a prefix\n"
" --export-db export the content of the udev database\n"
" --cleanup-db cleanup the udev database\n"
" --help\n\n");
goto exit;
default:

View File

@ -149,6 +149,12 @@
<para>Export the content of the udev database.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--cleanup-db</option></term>
<listitem>
<para>Cleanup the udev database.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--version</option></term>
<listitem>