linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] netdev - udevdb+dev.d changes
@ 2004-03-28 18:48 Kay Sievers
  2004-03-31 23:14 ` Greg KH
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Kay Sievers @ 2004-03-28 18:48 UTC (permalink / raw)
  To: linux-hotplug

[-- Attachment #1: Type: text/plain, Size: 1724 bytes --]

Hey, Chris fixed the udevd hole and Treeve found the timestamp bug,
so there was nothing left for me at the weekend :)

Here is a patch to change the netdev handling in the database and for
the dev.d/ calls. I applies on top of the udevd.patch, cause klibc has
no sysinfo().

 o netdev's are also put into our database now. I want this for the
   udevruler gui to get a list of all handled devices.
   All devices in the db are stamped with the system uptime value at
   the creation time. 'udevinfo -d' prints it.

 o the DEVPATH value is the key for udevdb, but if we rename
   a netdev, the name is replaced in the kernel, so we add
   the changed name to the db to match with the remove event.
   
   NOTE: The dev.d/ scripts still get the original name from the
   hotplug call. Should we replace DEVPATH with the new name too?

 o We now only add a device to the db, if we have successfully created
   the main node or successfully renamed a netdev. This is the main part
   of the patch, cause I needed to clean the retval passing trough all
   the functions used for node creation.

 o DEVNODE sounds a bit ugly for netdev's so I exported DEVNAME too.
   Can we change the name?

 o I've added a UDEV_NO_DEVD to possibly skip the script execution
   and used it in udev-test.pl.
   udevstart is the same horror now, if you have scripts with logging
   statements in dev.d/ it takes minutes to finish, can we skip the
   scripts here too?

 o The get_device_type() function is changed to be more strict, cause
   'udevinfo -a -p /block/' gets a class device for it and tries to
   print the major/minor values.

 o bugfix, the RESULT value has now a working newline removal and a test
   for this case.
 
thanks,
Kay

[-- Attachment #2: 02-netdev-dev_d.patch --]
[-- Type: text/plain, Size: 15588 bytes --]

===== dev_d.c 1.3 vs edited =====
--- 1.3/dev_d.c	Thu Mar 25 15:38:22 2004
+++ edited/dev_d.c	Sun Mar 28 14:39:40 2004
@@ -64,11 +64,20 @@
 void dev_d_send(struct udevice *dev, char *subsystem)
 {
 	char dirname[256];
-	char devnode[NAME_SIZE];
+	char devname[NAME_SIZE];
 
-	strfieldcpy(devnode, udev_root);
-	strfieldcat(devnode, dev->name);
-	setenv("DEVNODE", devnode, 1);
+	if (udev_dev_d == 0)
+		return;
+
+	if (dev->type == 'b' || dev->type == 'c') {
+		strfieldcpy(devname, udev_root);
+		strfieldcat(devname, dev->name);
+	} else if (dev->type == 'n') {
+		strfieldcpy(devname, dev->name);
+	}
+	setenv("DEVNODE", devname, 1); /* FIXME: bad name for netif */
+	setenv("DEVNAME", devname, 1);
+	dbg("DEVNAME='%s'", devname);
 
 	strcpy(dirname, DEVD_DIR);
 	strfieldcat(dirname, dev->name);
@@ -81,4 +90,3 @@
 	strcpy(dirname, DEVD_DIR "default");
 	call_foreach_file(run_program, dirname, DEVD_SUFFIX);
 }
-
===== namedev.c 1.137 vs edited =====
--- 1.137/namedev.c	Thu Mar 25 02:47:08 2004
+++ edited/namedev.c	Sun Mar 28 19:35:32 2004
@@ -32,6 +32,9 @@
 #include <time.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
+#ifndef __KLIBC__
+#include <sys/sysinfo.h>
+#endif
 
 #include "libsysfs/sysfs/libsysfs.h"
 #include "list.h"
@@ -454,7 +457,7 @@
 			retval = -1;
 		}
 
-		if (i > 0 && value[i] == '\n')
+		if (i > 0 && value[i-1] == '\n')
 			i--;
 		value[i] = '\0';
 		dbg("result is '%s'", value);
@@ -776,6 +779,7 @@
 	struct sysfs_device *sysfs_device = NULL;
 	struct config_device *dev;
 	struct perm_device *perm;
+	struct sysinfo info;
 	char *pos;
 
 	udev->mode = 0;
@@ -837,22 +841,18 @@
 			}
 		}
 	}
-
-	/* no rule was found for the net device */
-	if (udev->type == 'n') {
-		dbg("no name for net device '%s' configured", udev->kernel_name);
-		return -1;
-	}
-
 	/* no rule was found so we use the kernel name */
 	strfieldcpy(udev->name, udev->kernel_name);
-	goto done;
+	if (udev->type == 'n')
+		goto done;
+	else
+		goto perms;
 
 found:
 	apply_format(udev, udev->name, sizeof(udev->name), class_dev, sysfs_device);
 
 	if (udev->type == 'n')
-		return 0;
+		goto done;
 
 	udev->partitions = dev->partitions;
 	strfieldcpy(udev->config_file, dev->config_file);
@@ -863,7 +863,7 @@
 			      dev->owner,
 			      dev->group);
 
-done:
+perms:
 	/* get permissions given in config file or set defaults */
 	perm = find_perm(udev->name);
 	if (perm != NULL) {
@@ -879,8 +879,10 @@
 	dbg("name, '%s' is going to have owner='%s', group='%s', mode = %#o",
 	    udev->name, udev->owner, udev->group, udev->mode);
 
+done:
 	/* store time of action */
-	udev->config_time = time(NULL);
+	sysinfo(&info);
+	udev->config_uptime = info.uptime;
 
 	return 0;
 }
===== udev-add.c 1.67 vs edited =====
--- 1.67/udev-add.c	Thu Mar 25 14:25:50 2004
+++ edited/udev-add.c	Sun Mar 28 20:12:39 2004
@@ -61,21 +61,20 @@
  */
 static int get_major_minor(struct sysfs_class_device *class_dev, struct udevice *udev)
 {
-	int retval = -ENODEV;
 	struct sysfs_attribute *attr = NULL;
 
 	attr = sysfs_get_classdev_attr(class_dev, "dev");
 	if (attr == NULL)
-		goto exit;
+		goto error;
 	dbg("dev='%s'", attr->value);
 
 	if (sscanf(attr->value, "%u:%u", &udev->major, &udev->minor) != 2)
-		goto exit;
+		goto error;
 	dbg("found major=%d, minor=%d", udev->major, udev->minor);
 
-	retval = 0;
-exit:
-	return retval;
+	return 0;
+error:
+	return -1;
 }
 
 static int create_path(char *file)
@@ -114,28 +113,27 @@
 	if (retval != 0) {
 		dbg("mknod(%s, %#o, %u, %u) failed with error '%s'",
 		    filename, mode, major, minor, strerror(errno));
-		return retval;
+		goto exit;
 	}
 
 	dbg("chmod(%s, %#o)", filename, mode);
-	retval = chmod(filename, mode);
-	if (retval != 0) {
+	if (chmod(filename, mode) != 0) {
 		dbg("chmod(%s, %#o) failed with error '%s'",
 		    filename, mode, strerror(errno));
-		return retval;
+		goto exit;
 	}
 
 	if (uid != 0 || gid != 0) {
 		dbg("chown(%s, %u, %u)", filename, uid, gid);
-		retval = chown(filename, uid, gid);
-		if (retval != 0) {
+		if (chown(filename, uid, gid) != 0) {
 			dbg("chown(%s, %u, %u) failed with error '%s'",
 			    filename, uid, gid, strerror(errno));
-			return retval;
+			goto exit;
 		}
 	}
 
-	return 0;
+exit:
+	return retval;
 }
 
 /* get the local logged in user */
@@ -169,7 +167,6 @@
 	endutent();
 }
 
-/* Used to unlink existing files to ensure that our new file/symlink is created */
 static int unlink_entry(char *filename)
 {
 	struct stat stats;
@@ -193,7 +190,6 @@
 	char linkname[NAME_SIZE];
 	char linktarget[NAME_SIZE];
 	char partitionname[NAME_SIZE];
-	int retval = 0;
 	uid_t uid = 0;
 	gid_t gid = 0;
 	int i;
@@ -259,14 +255,15 @@
 	if (!fake) {
 		unlink_entry(filename);
 		info("creating device node '%s'", filename);
-		make_node(filename, dev->major, dev->minor, dev->mode, uid, gid);
+		if (make_node(filename, dev->major, dev->minor, dev->mode, uid, gid) != 0)
+			goto error;
 	} else {
 		info("creating device node '%s', major = '%d', minor = '%d', "
 		     "mode = '%#o', uid = '%d', gid = '%d'", filename,
 		     dev->major, dev->minor, (mode_t)dev->mode, uid, gid);
 	}
 
-	/* create partitions if requested */
+	/* create all_partitions if requested */
 	if (dev->partitions > 0) {
 		info("creating device partition nodes '%s[1-%i]'", filename, dev->partitions);
 		if (!fake) {
@@ -280,7 +277,7 @@
 		}
 	}
 
-	/* create symlink if requested */
+	/* create symlink(s) if requested */
 	foreach_strpart(dev->symlink, " ", pos, len) {
 		strfieldcpymax(linkname, pos, len+1);
 		strfieldcpy(filename, udev_root);
@@ -312,14 +309,15 @@
 
 		dbg("symlink(%s, %s)", linktarget, filename);
 		if (!fake) {
-			retval = symlink(linktarget, filename);
-			if (retval != 0)
+			if (symlink(linktarget, filename) != 0)
 				dbg("symlink(%s, %s) failed with error '%s'",
 				    linktarget, filename, strerror(errno));
 		}
 	}
 
-	return retval;
+	return 0;
+error:
+	return -1;
 }
 
 static struct sysfs_class_device *get_class_dev(char *device_name)
@@ -373,12 +371,16 @@
 	return retval;
 }
 
-static int rename_net_if(struct udevice *dev)
+static int rename_net_if(struct udevice *dev, int fake)
 {
 	int sk;
 	struct ifreq ifr;
 	int retval;
 
+	dbg("changing net interface name from '%s' to '%s'", dev->kernel_name, dev->name);
+	if (fake)
+		return 0;
+
 	sk = socket(PF_INET, SOCK_DGRAM, 0);
 	if (sk < 0) {
 		dbg("error opening socket");
@@ -389,7 +391,6 @@
 	strfieldcpy(ifr.ifr_name, dev->kernel_name);
 	strfieldcpy(ifr.ifr_newname, dev->name);
 
-	dbg("changing net interface name from '%s' to '%s'", dev->kernel_name, dev->name);
 	retval = ioctl(sk, SIOCSIFNAME, &ifr);
 	if (retval != 0)
 		dbg("error changing net interface name");
@@ -400,16 +401,15 @@
 
 int udev_add_device(char *path, char *subsystem, int fake)
 {
-	struct sysfs_class_device *class_dev = NULL;
+	struct sysfs_class_device *class_dev;
 	struct udevice dev;
-	int retval = -EINVAL;
+	char key[DEVPATH_SIZE];
+	char *pos;
+	int retval;
 
 	memset(&dev, 0x00, sizeof(dev));
 
-	/* for now, the block layer is the only place where block devices are */
-
 	dev.type = get_device_type(path, subsystem);
-
 	switch (dev.type) {
 	case 'b':
 	case 'c':
@@ -422,12 +422,12 @@
 
 	default:
 		dbg("unknown device type '%c'", dev.type);
-		retval = -EINVAL;
+		return -1;
 	}
 
 	class_dev = get_class_dev(path);
 	if (class_dev == NULL)
-		goto exit;
+		return -1;
 
 	if (dev.type == 'b' || dev.type == 'c') {
 		retval = get_major_minor(class_dev, &dev);
@@ -437,37 +437,48 @@
 		}
 	}
 
-	retval = namedev_name_device(class_dev, &dev);
-	if (retval != 0)
+	if (namedev_name_device(class_dev, &dev) != 0)
 		goto exit;
 
-	if (!fake && (dev.type == 'b' || dev.type == 'c')) {
-		retval = udevdb_add_dev(path, &dev);
-		if (retval != 0)
-			dbg("udevdb_add_dev failed, but we are going to try "
-			    "to create the node anyway. But remove might not "
-			    "work properly for this device.");
-	}
-
 	dbg("name='%s'", dev.name);
+
 	switch (dev.type) {
 	case 'b':
 	case 'c':
 		retval = create_node(&dev, fake);
-		if ((retval == 0) && (!fake))
-			dev_d_send(&dev, subsystem);
+		if (fake || retval != 0)
+			goto exit;
+		if (udevdb_add_dev(path, &dev) != 0)
+			dbg("udevdb_add_dev failed, but we are going to try "
+			    "to create the node anyway. But remove might not "
+			    "work properly for this device.");
 		break;
 
 	case 'n':
-		retval = rename_net_if(&dev);
-		if (retval != 0)
-			dbg("net device naming failed");
+		strfieldcpy(key, path);
+		if (strcmp(dev.name, dev.kernel_name) != 0) {
+			retval = rename_net_if(&dev, fake);
+			if (fake || retval != 0)
+				goto exit;
+			/* netif's are keyed with the configured name, cause
+			 * the original kernel name sleeps with the fishes
+			 */
+			pos = strrchr(key, '/');
+			if (pos != NULL) {
+				pos[1] = '\0';
+				strfieldcat(key, dev.name);
+			}
+		}
+		if (udevdb_add_dev(key, &dev) != 0)
+			dbg("udevdb_add_dev failed");
 		break;
 	}
 
+	/* execute programs in dev.d/ with the name in the environment */
+	dev_d_send(&dev, subsystem);
+
 exit:
-	if (class_dev)
-		sysfs_close_class_device(class_dev);
+	sysfs_close_class_device(class_dev);
 
 	return retval;
 }
===== udev-remove.c 1.29 vs edited =====
--- 1.29/udev-remove.c	Thu Mar 25 00:34:31 2004
+++ edited/udev-remove.c	Sun Mar 28 05:20:27 2004
@@ -137,36 +137,24 @@
 
 	memset(&dev, 0x00, sizeof(dev));
 
-	dev.type = get_device_type(path, subsystem);
-
-	switch (dev.type) {
-	case 'b':
-	case 'c':
-		retval = udevdb_get_dev(path, &dev);
-		if (retval) {
-			dbg("'%s' not found in database, falling back on default name", path);
-			temp = strrchr(path, '/');
-			if (temp == NULL)
-				return -ENODEV;
-			strfieldcpy(dev.name, &temp[1]);
-		}
-
-		dbg("name='%s'", dev.name);
-		udevdb_delete_dev(path);
+	retval = udevdb_get_dev(path, &dev);
+	if (retval != 0) {
+		dbg("'%s' not found in database, falling back on default name", path);
+		temp = strrchr(path, '/');
+		if (temp == NULL)
+			return -ENODEV;
+		strfieldcpy(dev.name, &temp[1]);
+	}
+	dbg("name='%s'", dev.name);
 
-		dev_d_send(&dev, subsystem);
+	dev.type = get_device_type(path, subsystem);
+	dev_d_send(&dev, subsystem);
+	udevdb_delete_dev(path);
 
+	if (dev.type == 'b' || dev.type == 'c')
 		retval = delete_node(&dev);
-		break;
-
-	case 'n':
+	else if (dev.type == 'n')
 		retval = 0;
-		break;
-
-	default:
-		dbg("unknown device type '%c'", dev.type);
-		retval = -EINVAL;
-	}
 
 	return retval;
 }
===== udev.h 1.55 vs edited =====
--- 1.55/udev.h	Wed Mar 24 21:46:58 2004
+++ edited/udev.h	Sun Mar 28 16:34:01 2004
@@ -52,7 +52,7 @@
 	int partitions;
 	int config_line;
 	char config_file[NAME_SIZE];
-	time_t config_time;
+	long config_uptime;
 
 	/* private data that help us in building strings */
 	char bus_id[SYSFS_NAME_LEN];
@@ -80,5 +80,6 @@
 extern char default_group_str[GROUP_SIZE];
 extern int udev_log;
 extern int udev_sleep;
+extern int udev_dev_d;
 
 #endif
===== udev_config.c 1.15 vs edited =====
--- 1.15/udev_config.c	Wed Mar 17 23:40:12 2004
+++ edited/udev_config.c	Sun Mar 28 05:20:28 2004
@@ -51,6 +51,7 @@
 char default_group_str[GROUP_SIZE];
 int udev_log;
 int udev_sleep;
+int udev_dev_d;
 
 
 static int string_is_true(char *str)
@@ -77,6 +78,10 @@
 	udev_sleep = 1;
 	if (getenv("UDEV_NO_SLEEP") != NULL)
 		udev_sleep = 0;
+
+	udev_dev_d = 1;
+	if (getenv("UDEV_NO_DEVD") != NULL)
+		udev_dev_d = 0;
 }
 
 #define set_var(_name, _var)				\
===== udev_lib.c 1.4 vs edited =====
--- 1.4/udev_lib.c	Thu Mar 25 14:29:50 2004
+++ edited/udev_lib.c	Sun Mar 28 05:20:28 2004
@@ -86,17 +86,28 @@
 	return subsystem;
 }
 
+#define BLOCK_PATH		"/block/"
+#define CLASS_PATH		"/class/"
+#define NET_PATH		"/class/net/"
+
 char get_device_type(const char *path, const char *subsystem)
 {
-	if (strcmp(subsystem, "block") == 0 ||
-	    strstr(path, "/block/") != NULL)
+	if (strcmp(subsystem, "block") == 0)
+		return 'b';
+
+	if (strcmp(subsystem, "net") == 0)
+		return 'n';
+
+	if (strncmp(path, BLOCK_PATH, strlen(BLOCK_PATH)) == 0 &&
+	    strlen(path) > strlen(BLOCK_PATH))
 		return 'b';
 
-	if (strcmp(subsystem, "net") == 0 ||
-	    strstr(path, "/class/net/") != NULL)
+	if (strncmp(path, NET_PATH, strlen(NET_PATH)) == 0 &&
+	    strlen(path) > strlen(NET_PATH))
 		return 'n';
 
-	if (strstr(path, "/class/") != NULL)
+	if (strncmp(path, CLASS_PATH, strlen(CLASS_PATH)) == 0 &&
+	    strlen(path) > strlen(CLASS_PATH))
 		return 'c';
 
 	return '\0';
===== udevdb.c 1.28 vs edited =====
--- 1.28/udevdb.c	Wed Mar 17 23:40:12 2004
+++ edited/udevdb.c	Sun Mar 28 16:06:50 2004
@@ -59,6 +59,7 @@
 
 	data.dptr = (void *)dev;
 	data.dsize = UDEVICE_LEN;
+	dbg("store key '%s' for device '%s'", path, dev->name);
 
 	return tdb_store(udevdb, key, data, TDB_REPLACE); 
 }
===== udevinfo.c 1.22 vs edited =====
--- 1.22/udevinfo.c	Thu Mar 25 00:28:42 2004
+++ edited/udevinfo.c	Sun Mar 28 05:20:28 2004
@@ -108,13 +108,14 @@
 {
 	printf("P: %s\n", path);
 	printf("N: %s\n", dev->name);
+	printf("T: %c\n", dev->type);
 	printf("M: %#o\n", dev->mode);
 	printf("S: %s\n", dev->symlink);
 	printf("O: %s\n", dev->owner);
 	printf("G: %s\n", dev->group);
 	printf("F: %s\n", dev->config_file);
 	printf("L: %i\n", dev->config_line);
-	printf("T: %li\n", dev->config_time);
+	printf("U: %li\n", dev->config_uptime);
 	printf("\n");
 	return 0;
 }
===== udevruler.c 1.2 vs edited =====
--- 1.2/udevruler.c	Thu Mar 25 13:45:16 2004
+++ edited/udevruler.c	Sun Mar 28 16:33:33 2004
@@ -77,7 +77,7 @@
 	char devpath[DEVPATH_SIZE];
 	int config_line;
 	char config_file[NAME_SIZE];
-	time_t config_time;
+	long config_uptime;
 	int added;
 };
 
@@ -106,7 +106,7 @@
 	strfieldcpy(dev->devpath, path);
 	dev->config_line = udev->config_line;
 	strfieldcpy(dev->config_file, udev->config_file);
-	dev->config_time = udev->config_time;
+	dev->config_uptime = udev->config_uptime;
 	dev->added = 0;
 
 	/* sort in lexical order */
@@ -308,7 +308,7 @@
 	char roottext[81];
 	char path[NAME_SIZE];
 	struct device *dev;
-	time_t time_last;
+	long time_last;
 	int count_last;
 
 	newtInit();
@@ -332,13 +332,13 @@
 	/* look for last discovered device */
 	time_last = 0;
 	list_for_each_entry(dev, &device_list, list)
-		if (dev->config_time > time_last)
-			time_last = dev->config_time;
+		if (dev->config_uptime > time_last)
+			time_last = dev->config_uptime;
 
 	/* skip if more than 16 recent devices */
 	count_last = 0;
 	list_for_each_entry(dev, &device_list, list) {
-		if (dev->config_time < time_last - 10)
+		if (dev->config_uptime < time_last - 10)
 			continue;
 		count_last++;
 	}
@@ -347,7 +347,7 @@
 	if (count_last < 16) {
 		newtListboxAppendEntry(lbox, "--- last dicovered ---", NULL);
 		list_for_each_entry(dev, &device_list, list) {
-			if (dev->config_time < time_last - 10)
+			if (dev->config_uptime < time_last - 10)
 				continue;
 
 			dbg("%s %i", dev->name, dev->config_line);
===== test/udev-test.pl 1.53 vs edited =====
--- 1.53/test/udev-test.pl	Thu Mar 25 00:50:17 2004
+++ edited/test/udev-test.pl	Sun Mar 28 19:48:18 2004
@@ -235,6 +235,15 @@
 EOF
 	},
 	{
+		desc		=> "program result substitution (newline removal)",
+		subsys		=> "block",
+		devpath		=> "/block/sda/sda3",
+		exp_name	=> "newline_removed" ,
+		conf		=> <<EOF
+BUS="scsi", PROGRAM="/bin/echo test", RESULT="test", NAME="newline_removed"
+EOF
+	},
+	{
 		desc		=> "program result substitution",
 		subsys		=> "block",
 		devpath		=> "/block/sda/sda3",
@@ -580,6 +589,8 @@
 $ENV{UDEV_TEST} = "yes";
 $ENV{SYSFS_PATH} = $sysfs;
 $ENV{UDEV_CONFIG_FILE} = $main_conf;
+$ENV{UDEV_NO_SLEEP} = "yes";
+$ENV{UDEV_NO_DEVD} = "yes";
 
 
 sub udev {

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2004-04-01  1:02 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-03-28 18:48 [PATCH] netdev - udevdb+dev.d changes Kay Sievers
2004-03-31 23:14 ` Greg KH
2004-03-31 23:40 ` Kay Sievers
2004-04-01  0:22 ` Greg KH
2004-04-01  0:41 ` Kay Sievers
2004-04-01  1:02 ` Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).