diff options
-rw-r--r-- | namedev.c | 1 | ||||
-rw-r--r-- | namedev.h | 2 | ||||
-rw-r--r-- | namedev_parse.c | 8 | ||||
-rw-r--r-- | test/udev-test.pl | 25 | ||||
-rw-r--r-- | udev.8.in | 7 | ||||
-rw-r--r-- | udev.h | 1 | ||||
-rw-r--r-- | udev_db.c | 18 | ||||
-rw-r--r-- | udev_remove.c | 5 |
8 files changed, 62 insertions, 5 deletions
@@ -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, @@ -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 4afa85cfa9..cb1760fd57 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 1e06df5220..d584579584 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 => <<EOF +BUS="scsi", KERNEL="sda", NAME{ignore_remove}="node" +EOF + }, + { + desc => "ignore remove event test (with all partitions)", + subsys => "block", + devpath => "/block/sda", + exp_name => "node14", + exp_error => "yes", + option => "clear", + conf => <<EOF +BUS="scsi", KERNEL="sda", NAME{ignore_remove, all_partitions}="node" +EOF + }, + { + desc => "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", @@ -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 @@ -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; @@ -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 32cd785984..8887125dd8 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); |