From 7efa217db0db946e68e6274e2b9cbe0a973ec47a Mon Sep 17 00:00:00 2001 From: "kay.sievers@vrfy.org" Date: Sat, 13 Nov 2004 14:43:24 +0100 Subject: [PATCH] [PATCH] add NAME{ignore_remove} attribute Some broken ide drivers are generating high event traffic, with add/remove events. With this attribute, it can be specified, that the node is always available. It may be used in conjunction with the new DRIVER= match to catch specific kernel device drivers. --- namedev.c | 1 + namedev.h | 2 ++ namedev_parse.c | 8 +++++++- test/udev-test.pl | 25 +++++++++++++++++++++++-- udev.8.in | 7 +++++++ udev.h | 1 + udev_db.c | 18 ++++++++++++++++-- udev_remove.c | 5 +++++ 8 files changed, 62 insertions(+), 5 deletions(-) diff --git a/namedev.c b/namedev.c index c5c7929a..69669709 100644 --- a/namedev.c +++ b/namedev.c @@ -807,6 +807,7 @@ found: goto done; udev->partitions = dev->partitions; + udev->ignore_remove = dev->ignore_remove; /* get permissions given in rule */ set_empty_perms(udev, dev->mode, diff --git a/namedev.h b/namedev.h index 7a98d66c..8e552c85 100644 --- a/namedev.h +++ b/namedev.h @@ -52,6 +52,7 @@ struct sysfs_class_device; #define FIELD_MODE "MODE" #define ATTR_PARTITIONS "all_partitions" +#define ATTR_IGNORE_REMOVE "ignore_remove" #define PARTITIONS_COUNT 15 #define MAX_SYSFS_PAIRS 5 @@ -90,6 +91,7 @@ struct config_device { char group[GROUP_SIZE]; unsigned int mode; int partitions; + int ignore_remove; char config_file[NAME_SIZE]; int config_line; }; diff --git a/namedev_parse.c b/namedev_parse.c index 4afa85cf..cb1760fd 100644 --- a/namedev_parse.c +++ b/namedev_parse.c @@ -278,10 +278,16 @@ static int namedev_parse_rules(const char *filename, void *data) if (strncasecmp(temp2, FIELD_NAME, sizeof(FIELD_NAME)-1) == 0) { attr = get_key_attribute(temp2 + sizeof(FIELD_NAME)-1); - if (attr != NULL && strcasecmp(attr, ATTR_PARTITIONS) == 0) { + if (attr != NULL) { + if (strstr(attr, ATTR_PARTITIONS) != NULL) { dbg_parse("creation of partition nodes requested"); dev.partitions = PARTITIONS_COUNT; } + if (strstr(attr, ATTR_IGNORE_REMOVE) != NULL) { + dbg_parse("remove event should be ignored"); + dev.ignore_remove = 1; + } + } strfieldcpy(dev.name, temp3); valid = 1; continue; diff --git a/test/udev-test.pl b/test/udev-test.pl index 1e06df52..d5845795 100644 --- a/test/udev-test.pl +++ b/test/udev-test.pl @@ -1105,7 +1105,28 @@ KERNEL="sda", NAME="cdrom%e" EOF }, { - desc => "SUBSYSTEM test", + desc => "ignore remove event test", + subsys => "block", + devpath => "/block/sda", + exp_name => "node", + exp_error => "yes", + conf => < "ignore remove event test (with all partitions)", + subsys => "block", + devpath => "/block/sda", + exp_name => "node14", + exp_error => "yes", + option => "clear", + conf => < "SUBSYSTEM match test", subsys => "block", devpath => "/block/sda", exp_name => "node", @@ -1116,7 +1137,7 @@ BUS="scsi", KERNEL="sda", NAME="should_not_match2", SUBSYSTEM="vc" EOF }, { - desc => "DRIVER test", + desc => "DRIVER match test", subsys => "block", devpath => "/block/sda", exp_name => "node", diff --git a/udev.8.in b/udev.8.in index b5296b47..728ddb1a 100644 --- a/udev.8.in +++ b/udev.8.in @@ -216,6 +216,13 @@ If given with the attribute .BR NAME{ all_partitions } it will create all 15 partitions of a blockdevice. This may be useful for removable media devices. +.br +If given with the attribute +.BR NAME{ ignore_remove } +it will will ignore any later remove event for this device. +This may be useful as a workaround for broken device drivers. +.sp +Multiple attributes may be separated by comma. .TP .B SYMLINK The name of a symlink targeting the node. Multiple symlinks may be diff --git a/udev.h b/udev.h index 73733ad3..d9a775ae 100644 --- a/udev.h +++ b/udev.h @@ -57,6 +57,7 @@ struct udevice { mode_t mode; char symlink[NAME_SIZE]; int partitions; + int ignore_remove; int config_line; char config_file[NAME_SIZE]; long config_uptime; diff --git a/udev_db.c b/udev_db.c index f2a890ea..e07e72b8 100644 --- a/udev_db.c +++ b/udev_db.c @@ -79,7 +79,8 @@ int udev_db_add_device(struct udevice *udev) fprintf(f, "P:%s\n", udev->devpath); fprintf(f, "N:%s\n", udev->name); fprintf(f, "S:%s\n", udev->symlink); - fprintf(f, "A:%d\n", udev->partitions); + fprintf(f, "A:%u\n", udev->partitions); + fprintf(f, "R:%u\n", udev->ignore_remove); fclose(f); @@ -111,21 +112,34 @@ static int parse_db_file(struct udevice *udev, const char *filename) if (count > DEVPATH_SIZE) count = DEVPATH_SIZE-1; strncpy(udev->devpath, &bufline[2], count-2); + udev->devpath[count-2] = '\0'; break; case 'N': if (count > NAME_SIZE) count = NAME_SIZE-1; strncpy(udev->name, &bufline[2], count-2); + udev->name[count-2] = '\0'; break; case 'S': if (count > NAME_SIZE) count = NAME_SIZE-1; strncpy(udev->symlink, &bufline[2], count-2); + udev->symlink[count-2] = '\0'; break; case 'A': - strfieldcpy(line, &bufline[2]); + if (count > NAME_SIZE) + count = NAME_SIZE-1; + strncpy(line, &bufline[2], count-2); + line[count-2] = '\0'; udev->partitions = atoi(line); break; + case 'R': + if (count > NAME_SIZE) + count = NAME_SIZE-1; + strncpy(line, &bufline[2], count-2); + line[count-2] = '\0'; + udev->ignore_remove = atoi(line); + break; } } diff --git a/udev_remove.c b/udev_remove.c index 32cd7859..8887125d 100644 --- a/udev_remove.c +++ b/udev_remove.c @@ -185,6 +185,11 @@ int udev_remove_device(struct udevice *udev) dbg("'%s' not found in database, falling back on default name", udev->name); } + if (udev->ignore_remove) { + dbg("remove event for '%s' requested to be ignored by rule", udev->name); + return 0; + } + dbg("remove name='%s'", udev->name); udev_db_delete_device(udev); -- 2.39.5