linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Several fixes and enhancements for extented naming rules parameters
@ 2005-01-07 17:07 Alexey Morozov
  2005-01-08  5:11 ` Several fixes and enhancements for extented naming rules Kay Sievers
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Alexey Morozov @ 2005-01-07 17:07 UTC (permalink / raw)
  To: linux-hotplug

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

Hello!

Playing with udev naming rules, I notices that existing '%e' macro can't 
be really used in several cases (important at least for me). This 
'extended' macro is quite useful if e.g. we try to build nice 
"human-friendly" device naming scheme and strictly separate devices 
names and permissions assignment (to rules.d/* and permissions.d/* 
respectively)

First of all, if one tries to give several names to a device (say, 
create additional symlinks for a CD-RW device like /dev/cdrom, 
/dev/cdwriter) udev ends up w/ errors.

Also I really doubt if %e w/ existing rules processing code can be used 
in constructions like /dev/discs/disc%e/disc and other devfs-like naming 
schemes.

So I decided to patch it a bit to achieve such functionality. You can 
find this patch in the attachment.

Also I'd like to have another macro. While %e is substituted w/ nothing for
'mydevice%e' if /dev/mydevice doesn't exist yet, this new macro always 
substituted w/ a non-negative number. I called it %N, but in fact these 
names can be changed in future. This is particularly useful for names 
like /dev/discs/disc%N/{.....} and allows to simplify devfs-like naming 
scripts.

And the last macro I have invented so far ;-) (don't be scared, I'm 
almost satisfied ;-)), is also about unique file names. I'd like to 
create entries like /dev/cdrom (i.e. only for a first CD-ROM in the 
system) w/o extra script work, just because udev anyway has all required 
info in its database. So this macro (which I called %U) just does a 
small subset of what %e does.

I should note, that all these three macros should be used only once per 
name token (currently, constructions like discs/disc%N/part%N are 
prohibited, I doubt this is a real limitation anyway), but the could be 
freely used in constructions like the following: SYMLINK="cdroms/cdrom%N 
cdroms/cdwriter%N cdrom/cdrom%U".

Also I made a patch for (optional) compilation of udev w/ a system-wide 
installed sysfs libraries. I'm not sure it's a good idea 'for everyone' 
but if we anyway have libsysfs and it's fresh enough to seamlessly work 
w/ udev, I don't see any reasons to have a separate copy right in udev 
source tree. Probably I make a mistake, but it worked /for me/ so far, 
and hey, it's optional anyway.

Hopefully, I'm not just another another wheel re-inventer, and if so, 
please tell me that, I'll try to be more cautious next time ;-).

In the attachments you'll find described patches (for the udev-0.50), 
sample rules file and scripts, mentioned in rules files. Patches should 
be applied in next order:

%patch -p1 -b .system_sysfs (optional)
%patch1 -p1 -b .efmt_fixes
%patch2 -p1 -b .Nfmt
%patch3 -p1 -b .Ufmt
%patch4 -p1 -b .compile_warnings (probably, also optional)

These patches probably could peacefully co-exist w/ recent Mandrake's 
patches for udev.

Thank you for your attention.

Sincerely yours,
Alexey Morozov.

[-- Attachment #2: cd-names.conf --]
[-- Type: text/plain, Size: 1692 bytes --]

# -*- mode: shell-script; coding: utf-8 -*-
# Configuration options for cd-names.sh
#
# DRIVETYPE_PRIO (= <string>)
# Allows to change order in which capabilities will be examined (and
# thus reported). This can lead to naming schemes with different
# primary names. Possible capabilities names are: CD, DVD, CDRW and
# DVDRW. CDROMs are always assumed as being capable to handle CD
# (obvious :-))
# If value isn't set "DVDRW CDRW DVD" is used by default.
DRIVETYPE_PRIO="DVDRW CDRW DVD"

# DO_ALL_LINKS (= 0/1)
# Report all possible names for a given device, not only one for most
# priority capability supported by the device. This can lean to e.g.
# DVD-RW drive to get '/dev/cdroms/dvdwriter0' as its name and
# '/dev/cdroms/dvd0', '/dev/cdroms/cdwriter0' and '/dev/cdroms/cdrom0'
# as symlinks to '/dev/cdroms/dvdwriter0'
# Default is to report all names
#DO_ALL_LINKS=0

# DO_ROOT_LINKS (= 0/1)
# Additionally to all entries in '/dev/cdroms/' folder, make symbolic
# links to a given device right from '/dev/'. This allows to have
# links like '/dev/cdrom' -> '/dev/cdroms/cdrom0' etc
# Default is to do root links
#DO_ROOT_LINKS=0

# PRIMARY_SUFFIX (= <udev device pattern>)
# This suffix will be appended to all device names from '/dev/cdroms/'
# folder. See 'man 8 udev' for more info.
# Default value is '%N' (NOTE: '%N' requires additional patch to
# udev as of version 046!)
#PRIMARY_SUFFIX="%e"

# SECONDARY_SUFFIX (= <udev device pattern>)
# This suffix will be appended to all device names from '/dev/' if
# such entries are to be created (see DO_ROOT_LINKS)
# Default value is '%V" (NOTE: '%U' requires additional patch to
# udev as of version 046!)
#SECONDARY_SUFFIX="%e"



[-- Attachment #3: cd-names.sh --]
[-- Type: application/x-shellscript, Size: 5678 bytes --]

[-- Attachment #4: drive-names.sh --]
[-- Type: application/x-shellscript, Size: 3247 bytes --]

[-- Attachment #5: udev-0.46-alt-Nfmt.patch --]
[-- Type: text/x-patch, Size: 3494 bytes --]

diff -urN udev-046.orig/namedev.c udev-046/namedev.c
--- udev-046.orig/namedev.c	2004-12-28 02:44:57 +0600
+++ udev-046/namedev.c	2004-12-28 02:48:45 +0600
@@ -178,19 +178,13 @@
 	return -1;
 }
 
-/** Finds the lowest positive N such that <name>N isn't present in 
- *  $(udevroot) either as a file or a symlink.
- *
- *  @param  name                Name to check for
- *  @return                     0 if <name> didn't exist and N otherwise.
+/** Internal function used by find_free_number and
+ *  find_free_number_zerobase
  */
-static int find_free_number(struct udevice *udev, const char *name, const char *tail)
+static int find_free_number_internal(struct udevice *udev, const char *name, const char* tail, char *filename, int maxsize)
 {
-	char filename[NAME_SIZE];
 	int num = 0;
 	struct udevice db_udev;
-
-	snprintf(filename, NAME_SIZE, "%s%s", name, tail);
 	while (1) {
 		dbg("look for existing node '%s'", filename);
 		memset(&db_udev, 0x00, sizeof(struct udevice));
@@ -204,11 +198,36 @@
 			info("find_free_number gone crazy (num=%d), aborted", num);
 			return -1;
 		}
-		snprintf(filename, NAME_SIZE, "%s%d%s", name, num, tail);
-		filename[NAME_SIZE-1] = '\0';
+		snprintf(filename, maxsize, "%s%d%s", name, num, tail);
 	}
 }
 
+/** Finds the lowest positive N such that <name>N isn't present in 
+ *  $(udevroot) either as a file or a symlink.
+ *
+ *  @param  name                Name to check for
+ *  @return                     0 if <name> didn't exist and N otherwise.
+ */
+static int find_free_number(struct udevice *udev, const char *name, const char *tail)
+{
+	char filename[NAME_SIZE];
+	snprintf(filename, NAME_SIZE, "%s%s", name, tail);
+	return find_free_number_internal(udev, name, tail, filename, NAME_SIZE);
+}
+
+/** Finds the lowest non-negative N such that <name>N isn't present in 
+ *  $(udevroot) either as a file or a symlink.
+ *
+ *  @param  name                Name to check for
+ *  @return                     0 if <name> didn't exist and N otherwise.
+ */
+static int find_free_number_zerobase(struct udevice *udev, const char *name, const char *tail)
+{
+	char filename[NAME_SIZE];
+	snprintf(filename, NAME_SIZE, "%s%d%s", name, 0, tail);
+	return find_free_number_internal(udev, name, tail, filename, NAME_SIZE);
+}
+
 static void apply_format(struct udevice *udev, char *string, size_t maxsize,
 			 struct sysfs_class_device *class_dev,
 			 struct sysfs_device *sysfs_device);
@@ -344,6 +363,18 @@
 			}
 			strfieldcatmax(string, tail, maxsize);
 			return;
+		case 'N':
+			if (!use_ext) {
+				dbg("prohibited usage of attribute %%e");
+				break;
+			}
+			/* prohibite "extended" attributes in tail */
+			apply_format_token(udev, tail, NAME_SIZE, class_dev, sysfs_device, 0);
+			next_free_number = find_free_number_zerobase(udev, string, tail);
+			sprintf(temp2, "%d", next_free_number);
+			strfieldcatmax(string, temp2, maxsize);
+			strfieldcatmax(string, tail, maxsize);
+			return;
 		default:
 			dbg("unknown substitution type '%%%c'", c);
 			break;
diff -urN udev-046.orig/udev.8.in udev-046/udev.8.in
--- udev-046.orig/udev.8.in	2004-11-19 01:39:15 +0600
+++ udev-046/udev.8.in	2004-12-28 02:49:59 +0600
@@ -285,6 +285,10 @@
 can be used to create compatibility symlinks and enumerate devices of
 the same type originating from different kernel subsystems.
 .TP
+.B %N
+Similar to %e but always substituted by a smallest non-negative number
+giving an unique device node.
+.TP
 .B %%
 The '%' character itself.
 .P

[-- Attachment #6: udev-0.46-alt-Ufmt.patch --]
[-- Type: text/x-patch, Size: 1318 bytes --]

diff -urN udev-046.orig/namedev.c udev-046/namedev.c
--- udev-046.orig/namedev.c	2004-12-28 02:50:52 +0600
+++ udev-046/namedev.c	2004-12-28 02:51:21 +0600
@@ -375,6 +375,22 @@
 			strfieldcatmax(string, temp2, maxsize);
 			strfieldcatmax(string, tail, maxsize);
 			return;
+		case 'U':
+			if (!use_ext) {
+				dbg("prohibited usage of attribute %%e");
+				break;
+			}
+			/* prohibite "extended" attributes in tail */
+			apply_format_token(udev, tail, NAME_SIZE, class_dev, sysfs_device, 0);
+			{
+				struct udevice db_udev;
+				strfieldcatmax(string, tail, maxsize);
+				if (0 == udev_db_get_device_byname(&db_udev, string)) {
+					/* device exists */
+					string[0] = '\0';
+				}
+			}
+			return;
 		default:
 			dbg("unknown substitution type '%%%c'", c);
 			break;
diff -urN udev-046.orig/udev.8.in udev-046/udev.8.in
--- udev-046.orig/udev.8.in	2004-12-28 02:50:52 +0600
+++ udev-046/udev.8.in	2004-12-28 02:52:36 +0600
@@ -289,6 +289,11 @@
 similar to %e but always substituted by a smallest non-negative number
 giving an unique device node.
 .TP
+.B %N
+If a device node already exists with the name, the entire name is skipped.
+This allows to create, say, /dev/cdrom (usually a link) but not /dev/cdrom1
+and only if /dev/cdrom doesn't exist before
+.TP
 .B %%
 The '%' character itself.
 .P

[-- Attachment #7: udev-0.46-alt-compile_warnings.patch --]
[-- Type: text/x-patch, Size: 307 bytes --]

diff -urN udev-046.orig/udev_db.c udev-046/udev_db.c
--- udev-046.orig/udev_db.c	2004-12-09 22:10:53 +0600
+++ udev-046/udev_db.c	2004-12-09 22:12:28 +0600
@@ -30,6 +30,7 @@
 #include <string.h>
 #include <errno.h>
 #include <dirent.h>
+#include <unistd.h>
 
 #include <sysfs/libsysfs.h>
 #include "udev.h"

[-- Attachment #8: udev-0.50-alt-system_sysfs.patch --]
[-- Type: text/x-patch, Size: 26971 bytes --]

diff -urN udev-050.orig/extras/scsi_id/Makefile udev-050/extras/scsi_id/Makefile
--- udev-050.orig/extras/scsi_id/Makefile	2004-12-18 11:53:07 +0600
+++ udev-050/extras/scsi_id/Makefile	2005-01-02 22:15:19 +0600
@@ -31,6 +31,11 @@
 override CFLAGS+=-Wall -fno-builtin
 
 PROG=scsi_id
+
+ifeq ($(strip $(SYS_SYSFS)),)
+CPPFLAGS = -I../../libsysfs
+endif
+
 SYSFS=-lsysfs
 
 #
@@ -53,7 +58,7 @@
 		echo $(INSTALL_DATA) -D ./scsi_id.config  $(DESTDIR)$(etcdir); \
 		$(INSTALL_DATA) -D ./scsi_id.config $(DESTDIR)$(etcdir)/scsi_id.config; \
 	fi
-	
+
 uninstall:
 	-rm $(DESTDIR)$(sbindir)/$(PROG)
 	-rm $(DESTDIR)$(mandir)/man8/scsi_id.8
@@ -73,7 +78,7 @@
 spotless: clean
 
 .c.o:
-	$(QUIET) $(CC) $(CFLAGS) -c -o $@ $<
+	$(QUIET) $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
 
 $(PROG):	$(OBJS)
 	$(QUIET) $(LD) $(LDFLAGS) -o $(PROG) $(CRT0) $(OBJS) $(SYSFS) $(LIB_OBJS) $(ARCH_LIB_OBJS)
diff -urN udev-050.orig/extras/volume_id/Makefile udev-050/extras/volume_id/Makefile
--- udev-050.orig/extras/volume_id/Makefile	2004-12-18 11:53:07 +0600
+++ udev-050/extras/volume_id/Makefile	2005-01-02 22:13:39 +0600
@@ -28,14 +28,24 @@
 INSTALL_DATA  = ${INSTALL} -m 644
 INSTALL_SCRIPT = ${INSTALL_PROGRAM}
 
+ifeq ($(strip $(SYS_SYSFS)),)
+CPPFLAGS = -I../../libsysfs
+endif
+
 override CFLAGS+=-Wall -fno-builtin -Wchar-subscripts \
 		 -Wpointer-arith -Wcast-align -Wsign-compare
 
 override CFLAGS+=-D_FILE_OFFSET_BITS=64
 
-OBJS = volume_id.o udev_volume_id.o dasdlabel.o $(SYSFS)
+OBJS = volume_id.o udev_volume_id.o dasdlabel.o
 HEADERS = volume_id.h dasdlabel.h
 
+ifeq ($(strip $(SYS_SYSFS)),)
+OBJS += $(SYSFS)
+else
+LDFLAGS += $(SYS_SYSFS)
+endif
+
 $(OBJS): $(HEADERS)
 
 .c.o:
diff -urN udev-050.orig/extras/volume_id/udev_volume_id.c udev-050/extras/volume_id/udev_volume_id.c
--- udev-050.orig/extras/volume_id/udev_volume_id.c	2004-12-18 11:53:07 +0600
+++ udev-050/extras/volume_id/udev_volume_id.c	2005-01-02 20:09:11 +0600
@@ -28,7 +28,7 @@
 #include <ctype.h>
 #include <sys/ioctl.h>
 
-#include "../../libsysfs/sysfs/libsysfs.h"
+#include <sysfs/libsysfs.h>
 #include "../../udev_utils.h"
 #include "../../logging.h"
 #include "volume_id.h"
diff -urN udev-050.orig/libsysfs/dlist.c udev-050/libsysfs/dlist.c
--- udev-050.orig/libsysfs/dlist.c	2004-12-18 11:53:07 +0600
+++ udev-050/libsysfs/dlist.c	2005-01-02 20:09:11 +0600
@@ -27,7 +27,7 @@
  * delete function.  Otherwise dlist will just use free.
 
 */
-#include "dlist.h"
+#include "sysfs/dlist.h"
 
 /*
  * Return pointer to node at marker.
diff -urN udev-050.orig/libsysfs/dlist.h udev-050/libsysfs/dlist.h
--- udev-050.orig/libsysfs/dlist.h	2004-12-18 11:53:07 +0600
+++ udev-050/libsysfs/dlist.h	1970-01-01 07:00:00 +0700
@@ -1,205 +0,0 @@
-/*
- * dlist.h
- *
- * Copyright (C) 2003 Eric J Bohm
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#ifndef _DLIST_H_
-#define _DLIST_H_
-
-/* Double linked list header.
-   
-* navigate your list with DLIST_PREV and DLIST_NEXT.  These are macros
-* so function call overhead is minimized.
-
-* Supports perl style push, pop, shift, unshift list semantics.
-
-* You allocate the data and give dlist the pointer.  If your data is
-* complex set the dlist->del_func to a an appropriate delete using
-* dlist_new_with_delete.  Your delete function must match 
-(void * )(del(void *)
-*Otherwise dlist will just use free.
-
-* NOTE: The small amount of pain involved in doing that allows us to
-* avoid copy in copy out semantics.
-
-* Dlist uses an internal mark pointer to keep track of where you are
-* in the list.
-
-* insert and delete take a directional parameter. Where direction
-* corresponds to the direction in which you want the list to go.
-* true direction corresponded to progressing forward in the last
-* false to regressing in the list.
-* so a dlist_insert(yourlist,item,1) will insert it after the mark
-* so a dlist_insert(yourlist,item,0) will insert it before the mark
-* any insert will move the mark to the new node regardless of the direction.
-
-* Just use the dlist_(insert|delete)_(before|after) macros if you do not want
-* to think about it.
-
-*/
-#include <malloc.h>
-typedef struct dl_node {
-  struct dl_node *prev;
-  struct dl_node *next;
-  void *data;
-} DL_node;
-
-typedef struct dlist {
-  DL_node *marker;
-  unsigned long count;
-  size_t data_size;
-  void (*del_func)(void *);
-  DL_node headnode;
-  DL_node *head;
-} Dlist;
-
-Dlist *dlist_new(size_t datasize);
-Dlist *dlist_new_with_delete(size_t datasize,void (*del_func)(void*));
-void *_dlist_mark_move(Dlist *list,int direction);
-void *dlist_mark(Dlist *);
-void dlist_start(Dlist *);
-void dlist_end(Dlist *);
-void dlist_move(struct dlist *source, struct dlist *dest, struct dl_node *target,int direction);
-void *dlist_insert(Dlist *,void *,int) ;
-
-void *dlist_insert_sorted(struct dlist *list, void *new_elem, int (*sorter)(void *, void *));
-
-void dlist_delete(Dlist *,int);
-
-void dlist_push(Dlist *,void *);
-
-void dlist_unshift(Dlist *,void *);
-void dlist_unshift_sorted(Dlist *,void *,int (*sorter)(void *, void *));
-
-void *dlist_pop(Dlist *);
-
-void *dlist_shift(Dlist *);
-
-void dlist_destroy(Dlist *);
-
-int _dlist_merge(struct dlist *listsource, struct dlist *listdest, unsigned int passcount, int (*compare)(void *, void *));
-
-void *dlist_find_custom(struct dlist *list, void *target, int (*comp)(void *, void *));
-
-void dlist_sort_custom(struct dlist *list, int (*compare)(void *, void *));
-
-
-void _dlist_swap(struct dlist *list, struct dl_node *a, struct dl_node *b);
-
-void dlist_transform(struct dlist *list, void (*node_operation)(void *));
-
-
-/* 
- * _dlist_remove is for internal use only
- * _dlist_mark_move is for internal use only
- */
-void *_dlist_remove(struct dlist *,struct dl_node *,int );
-void *_dlist_insert_dlnode(struct dlist *list,struct dl_node *new_node,int direction);
-
-#define dlist_prev(A) _dlist_mark_move((A),0)
-#define dlist_next(A) _dlist_mark_move((A),1)
-
-#define dlist_insert_before(A,B) dlist_insert((A),(B),0)
-#define dlist_insert_after(A,B) dlist_insert((A),(B),1)
-
-#define dlist_delete_before(A) dlist_delete((A),0)
-#define dlist_delete_after(A) dlist_delete((A),1)
-
-/**
- * provide for loop header which iterates the mark from start to end
- * list: the dlist pointer, use dlist_mark(list) to get iterator
- */
-#define dlist_for_each(list) \
-	for(dlist_start(list),dlist_next(list); \
-		(list)->marker!=(list)->head;dlist_next(list))
-
-/**
- * provide for loop header which iterates the mark from end to start
- * list: the dlist pointer, use dlist_mark(list) to get iterator
- */
-#define dlist_for_each_rev(list) \
-	for(dlist_end(list),dlist_prev(list); \
-		(list)->marker!=(list)->head;dlist_prev(list))
-
-/**
- * provide for loop header which iterates through the list without moving mark
- * list: the dlist_pointer
- * iterator: dl_node pointer to iterate
- */
-#define dlist_for_each_nomark(list,iterator) \
-	for((iterator)=(list)->head->next; (iterator)!=(list)->head; \
-		(iterator)=(iterator)->next)
-
-/**
- * provide for loop header which iterates through the list without moving mark
- * in reverse
- * list: the dlist_pointer
- * iterator: dl_node pointer to iterate
- */
-#define dlist_for_each_nomark_rev(list,iterator) \
-	for((iterator)=(list)->head->prev; (iterator)!=(list)->head; \
-		(iterator)=(iterator)->prev)
-/**
- * provide for loop header which iterates through the list providing a
- * data iterator
- * list: the dlist pointer
- * data_iterator: the pointer of type datatype to iterate
- * datatype:  actual type of the contents in the dl_node->data
- */
-
-#define dlist_for_each_data(list,data_iterator,datatype) \
-	for(dlist_start(list), (data_iterator)=(datatype *) dlist_next(list); \
-	(list)->marker!=(list)->head;(data_iterator)=(datatype *) dlist_next(list))
-
-/**
- * provide for loop header which iterates through the list providing a
- * data iterator in reverse
- * list: the dlist pointer
- * data_iterator: the pointer of type datatype to iterate
- * datatype:  actual type of the contents in the dl_node->data
- */
-#define dlist_for_each_data_rev(list,data_iterator,datatype) \
-	for(dlist_end(list), (data_iterator)=(datatype *) dlist_prev(list); \
-	(list)->marker!=(list)->head;(data_iterator)=(datatype *) dlist_prev(list))
-
-/**
- * provide for loop header which iterates through the list providing a
- * data iterator without moving the mark
- * list: the dlist pointer
- * iterator: the dl_node pointer to iterate
- * data_iterator: the pointer of type datatype to iterate
- * datatype:  actual type of the contents in the dl_node->data
- */
-
-#define dlist_for_each_data_nomark(list,iterator,data_iterator,datatype) \
-	for((iterator)=(list)->head->next, (data_iterator)=(datatype *) (iterator)->data; \
-	(iterator)!=(list)->head;(iterator)=(iterator)->next,(data_iterator)=(datatype *) (iterator))
-
-/**
- * provide for loop header which iterates through the list providing a
- * data iterator in reverse without moving the mark
- * list: the dlist pointer
- * iterator: the dl_node pointer to iterate
- * data_iterator: the pointer of type datatype to iterate
- * datatype:  actual type of the contents in the dl_node->data
- */
-#define dlist_for_each_data_nomark_rev(list,iterator, data_iterator,datatype) \
-	for((iterator)=(list)->head->prev, (data_iterator)=(datatype *) (iterator)->data; \
-	(iterator)!=(list)->head;(iterator)=(iterator)->prev,(data_iterator)=(datatype *) (iterator))
-
-#endif /* _DLIST_H_ */
diff -urN udev-050.orig/libsysfs/sysfs/dlist.h udev-050/libsysfs/sysfs/dlist.h
--- udev-050.orig/libsysfs/sysfs/dlist.h	1970-01-01 07:00:00 +0700
+++ udev-050/libsysfs/sysfs/dlist.h	2005-01-02 20:09:11 +0600
@@ -0,0 +1,205 @@
+/*
+ * dlist.h
+ *
+ * Copyright (C) 2003 Eric J Bohm
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef _DLIST_H_
+#define _DLIST_H_
+
+/* Double linked list header.
+   
+* navigate your list with DLIST_PREV and DLIST_NEXT.  These are macros
+* so function call overhead is minimized.
+
+* Supports perl style push, pop, shift, unshift list semantics.
+
+* You allocate the data and give dlist the pointer.  If your data is
+* complex set the dlist->del_func to a an appropriate delete using
+* dlist_new_with_delete.  Your delete function must match 
+(void * )(del(void *)
+*Otherwise dlist will just use free.
+
+* NOTE: The small amount of pain involved in doing that allows us to
+* avoid copy in copy out semantics.
+
+* Dlist uses an internal mark pointer to keep track of where you are
+* in the list.
+
+* insert and delete take a directional parameter. Where direction
+* corresponds to the direction in which you want the list to go.
+* true direction corresponded to progressing forward in the last
+* false to regressing in the list.
+* so a dlist_insert(yourlist,item,1) will insert it after the mark
+* so a dlist_insert(yourlist,item,0) will insert it before the mark
+* any insert will move the mark to the new node regardless of the direction.
+
+* Just use the dlist_(insert|delete)_(before|after) macros if you do not want
+* to think about it.
+
+*/
+#include <malloc.h>
+typedef struct dl_node {
+  struct dl_node *prev;
+  struct dl_node *next;
+  void *data;
+} DL_node;
+
+typedef struct dlist {
+  DL_node *marker;
+  unsigned long count;
+  size_t data_size;
+  void (*del_func)(void *);
+  DL_node headnode;
+  DL_node *head;
+} Dlist;
+
+Dlist *dlist_new(size_t datasize);
+Dlist *dlist_new_with_delete(size_t datasize,void (*del_func)(void*));
+void *_dlist_mark_move(Dlist *list,int direction);
+void *dlist_mark(Dlist *);
+void dlist_start(Dlist *);
+void dlist_end(Dlist *);
+void dlist_move(struct dlist *source, struct dlist *dest, struct dl_node *target,int direction);
+void *dlist_insert(Dlist *,void *,int) ;
+
+void *dlist_insert_sorted(struct dlist *list, void *new_elem, int (*sorter)(void *, void *));
+
+void dlist_delete(Dlist *,int);
+
+void dlist_push(Dlist *,void *);
+
+void dlist_unshift(Dlist *,void *);
+void dlist_unshift_sorted(Dlist *,void *,int (*sorter)(void *, void *));
+
+void *dlist_pop(Dlist *);
+
+void *dlist_shift(Dlist *);
+
+void dlist_destroy(Dlist *);
+
+int _dlist_merge(struct dlist *listsource, struct dlist *listdest, unsigned int passcount, int (*compare)(void *, void *));
+
+void *dlist_find_custom(struct dlist *list, void *target, int (*comp)(void *, void *));
+
+void dlist_sort_custom(struct dlist *list, int (*compare)(void *, void *));
+
+
+void _dlist_swap(struct dlist *list, struct dl_node *a, struct dl_node *b);
+
+void dlist_transform(struct dlist *list, void (*node_operation)(void *));
+
+
+/* 
+ * _dlist_remove is for internal use only
+ * _dlist_mark_move is for internal use only
+ */
+void *_dlist_remove(struct dlist *,struct dl_node *,int );
+void *_dlist_insert_dlnode(struct dlist *list,struct dl_node *new_node,int direction);
+
+#define dlist_prev(A) _dlist_mark_move((A),0)
+#define dlist_next(A) _dlist_mark_move((A),1)
+
+#define dlist_insert_before(A,B) dlist_insert((A),(B),0)
+#define dlist_insert_after(A,B) dlist_insert((A),(B),1)
+
+#define dlist_delete_before(A) dlist_delete((A),0)
+#define dlist_delete_after(A) dlist_delete((A),1)
+
+/**
+ * provide for loop header which iterates the mark from start to end
+ * list: the dlist pointer, use dlist_mark(list) to get iterator
+ */
+#define dlist_for_each(list) \
+	for(dlist_start(list),dlist_next(list); \
+		(list)->marker!=(list)->head;dlist_next(list))
+
+/**
+ * provide for loop header which iterates the mark from end to start
+ * list: the dlist pointer, use dlist_mark(list) to get iterator
+ */
+#define dlist_for_each_rev(list) \
+	for(dlist_end(list),dlist_prev(list); \
+		(list)->marker!=(list)->head;dlist_prev(list))
+
+/**
+ * provide for loop header which iterates through the list without moving mark
+ * list: the dlist_pointer
+ * iterator: dl_node pointer to iterate
+ */
+#define dlist_for_each_nomark(list,iterator) \
+	for((iterator)=(list)->head->next; (iterator)!=(list)->head; \
+		(iterator)=(iterator)->next)
+
+/**
+ * provide for loop header which iterates through the list without moving mark
+ * in reverse
+ * list: the dlist_pointer
+ * iterator: dl_node pointer to iterate
+ */
+#define dlist_for_each_nomark_rev(list,iterator) \
+	for((iterator)=(list)->head->prev; (iterator)!=(list)->head; \
+		(iterator)=(iterator)->prev)
+/**
+ * provide for loop header which iterates through the list providing a
+ * data iterator
+ * list: the dlist pointer
+ * data_iterator: the pointer of type datatype to iterate
+ * datatype:  actual type of the contents in the dl_node->data
+ */
+
+#define dlist_for_each_data(list,data_iterator,datatype) \
+	for(dlist_start(list), (data_iterator)=(datatype *) dlist_next(list); \
+	(list)->marker!=(list)->head;(data_iterator)=(datatype *) dlist_next(list))
+
+/**
+ * provide for loop header which iterates through the list providing a
+ * data iterator in reverse
+ * list: the dlist pointer
+ * data_iterator: the pointer of type datatype to iterate
+ * datatype:  actual type of the contents in the dl_node->data
+ */
+#define dlist_for_each_data_rev(list,data_iterator,datatype) \
+	for(dlist_end(list), (data_iterator)=(datatype *) dlist_prev(list); \
+	(list)->marker!=(list)->head;(data_iterator)=(datatype *) dlist_prev(list))
+
+/**
+ * provide for loop header which iterates through the list providing a
+ * data iterator without moving the mark
+ * list: the dlist pointer
+ * iterator: the dl_node pointer to iterate
+ * data_iterator: the pointer of type datatype to iterate
+ * datatype:  actual type of the contents in the dl_node->data
+ */
+
+#define dlist_for_each_data_nomark(list,iterator,data_iterator,datatype) \
+	for((iterator)=(list)->head->next, (data_iterator)=(datatype *) (iterator)->data; \
+	(iterator)!=(list)->head;(iterator)=(iterator)->next,(data_iterator)=(datatype *) (iterator))
+
+/**
+ * provide for loop header which iterates through the list providing a
+ * data iterator in reverse without moving the mark
+ * list: the dlist pointer
+ * iterator: the dl_node pointer to iterate
+ * data_iterator: the pointer of type datatype to iterate
+ * datatype:  actual type of the contents in the dl_node->data
+ */
+#define dlist_for_each_data_nomark_rev(list,iterator, data_iterator,datatype) \
+	for((iterator)=(list)->head->prev, (data_iterator)=(datatype *) (iterator)->data; \
+	(iterator)!=(list)->head;(iterator)=(iterator)->prev,(data_iterator)=(datatype *) (iterator))
+
+#endif /* _DLIST_H_ */
diff -urN udev-050.orig/libsysfs/sysfs_bus.c udev-050/libsysfs/sysfs_bus.c
--- udev-050.orig/libsysfs/sysfs_bus.c	2004-12-18 11:53:07 +0600
+++ udev-050/libsysfs/sysfs_bus.c	2005-01-02 20:09:11 +0600
@@ -20,7 +20,7 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  */
-#include "libsysfs.h"
+#include "sysfs/libsysfs.h"
 #include "sysfs.h"
 
 static void sysfs_close_dev(void *dev)
diff -urN udev-050.orig/libsysfs/sysfs_class.c udev-050/libsysfs/sysfs_class.c
--- udev-050.orig/libsysfs/sysfs_class.c	2004-12-18 11:53:07 +0600
+++ udev-050/libsysfs/sysfs_class.c	2005-01-02 20:09:11 +0600
@@ -20,7 +20,7 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  */
-#include "libsysfs.h"
+#include "sysfs/libsysfs.h"
 #include "sysfs.h"
 
 static void sysfs_close_cls_dev(void *dev)
diff -urN udev-050.orig/libsysfs/sysfs_device.c udev-050/libsysfs/sysfs_device.c
--- udev-050.orig/libsysfs/sysfs_device.c	2004-12-18 11:53:07 +0600
+++ udev-050/libsysfs/sysfs_device.c	2005-01-02 20:09:11 +0600
@@ -20,7 +20,7 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  */
-#include "libsysfs.h"
+#include "sysfs/libsysfs.h"
 #include "sysfs.h"
 
 /**
diff -urN udev-050.orig/libsysfs/sysfs_dir.c udev-050/libsysfs/sysfs_dir.c
--- udev-050.orig/libsysfs/sysfs_dir.c	2004-12-18 11:53:07 +0600
+++ udev-050/libsysfs/sysfs_dir.c	2005-01-02 20:09:11 +0600
@@ -20,7 +20,7 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  */
-#include "libsysfs.h"
+#include "sysfs/libsysfs.h"
 #include "sysfs.h"
 
 /**
diff -urN udev-050.orig/libsysfs/sysfs_driver.c udev-050/libsysfs/sysfs_driver.c
--- udev-050.orig/libsysfs/sysfs_driver.c	2004-12-18 11:53:07 +0600
+++ udev-050/libsysfs/sysfs_driver.c	2005-01-02 20:09:11 +0600
@@ -20,7 +20,7 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  */
-#include "libsysfs.h"
+#include "sysfs/libsysfs.h"
 #include "sysfs.h"
 
 static void sysfs_close_driver_device(void *device)
diff -urN udev-050.orig/libsysfs/sysfs_utils.c udev-050/libsysfs/sysfs_utils.c
--- udev-050.orig/libsysfs/sysfs_utils.c	2004-12-18 11:53:07 +0600
+++ udev-050/libsysfs/sysfs_utils.c	2005-01-02 20:09:11 +0600
@@ -20,7 +20,7 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  */
-#include "libsysfs.h"
+#include "sysfs/libsysfs.h"
 #include "sysfs.h"
 
 static int sort_char(void *new, void *old)
diff -urN udev-050.orig/Makefile udev-050/Makefile
--- udev-050.orig/Makefile	2004-12-18 11:53:07 +0600
+++ udev-050/Makefile	2005-01-02 22:12:55 +0600
@@ -92,7 +92,11 @@
 RANLIB = $(CROSS)ranlib
 HOSTCC = gcc
 
-export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS ARCH_LIB_OBJS CRT0
+ifeq ($(strip $(SYS_SYSFS)),)
+CPPFLAGS = -I`pwd`/libsysfs
+endif
+
+export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS ARCH_LIB_OBJS CRT0 CPPFLAGS
 
 # code taken from uClibc to determine the current arch
 ARCH := ${shell $(CC) -dumpmachine | sed -e s'/-.*//' -e 's/i.86/i386/' -e 's/sparc.*/sparc/' \
@@ -170,9 +174,6 @@
 	LIB_OBJS += -lselinux
 endif
 
-CFLAGS +=	-I$(PWD)/libsysfs/sysfs \
-		-I$(PWD)/libsysfs
-
 # config files automatically generated
 GEN_CONFIGS =	$(LOCAL_CFG_DIR)/udev.conf
 
@@ -182,6 +183,7 @@
 		$(MAKE) prefix=$(prefix) \
 			LD="$(LD)" \
 			SYSFS="$(SYSFS)" \
+			SYS_SYSFS=$(SYS_SYSFS) \
 			KERNEL_DIR="$(KERNEL_DIR)" \
 			QUIET="$(QUIET)" \
 			-C $$target $@ ; \
@@ -227,11 +229,13 @@
 	namedev.o		\
 	namedev_parse.o
 
-OBJS = \
-	libsysfs/sysfs.a	\
-	udev.a
-
+ifneq ($(strip $(SYS_SYSFS)),)
+LIB_OBJS += $(SYS_SYSFS)
+else
 SYSFS = $(PWD)/libsysfs/sysfs.a
+endif
+
+OBJS = udev.a $(SYSFS)
 
 ifeq ($(strip $(USE_KLIBC)),true)
 	HEADERS	+= \
@@ -258,7 +262,7 @@
 	$(QUIET) $(AR) cq $@ $(UDEV_OBJS)
 	$(QUIET) $(RANLIB) $@
 
-libsysfs/sysfs.a: $(SYSFS_OBJS)
+$(PWD)/libsysfs/sysfs.a: $(SYSFS_OBJS)
 	rm -f $@
 	$(QUIET) $(AR) cq $@ $(SYSFS_OBJS)
 	$(QUIET) $(RANLIB) $@
@@ -331,7 +335,7 @@
 	$(QUIET) $(STRIPCMD) $@
 
 .c.o:
-	$(QUIET) $(CC) $(CFLAGS) -c -o $@ $<
+	$(QUIET) $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
 
 
 clean:
@@ -342,7 +346,7 @@
 	$(MAKE) -C klibc SUBDIRS=klibc clean
 	@extras="$(EXTRAS)" ; for target in $$extras ; do \
 		echo $$target ; \
-		$(MAKE) prefix=$(prefix) LD="$(LD)" SYSFS="$(SYSFS)" \
+		$(MAKE) prefix=$(prefix) LD="$(LD)" SYS_SYSFS=$(SYS_SYSFS) SYSFS="$(SYSFS)" \
 			-C $$target $@ ; \
 	done ; \
 
@@ -437,7 +441,7 @@
 endif
 	@extras="$(EXTRAS)" ; for target in $$extras ; do \
 		echo $$target ; \
-		$(MAKE) prefix=$(prefix) LD="$(LD)" SYSFS="$(SYSFS)" \
+		$(MAKE) prefix=$(prefix) LD="$(LD)" SYS_SYSFS=$(SYS_SYSFS) SYSFS="$(SYSFS)" \
 			-C $$target $@ ; \
 	done ; \
 
@@ -461,7 +465,7 @@
 	- killall $(DAEMON)
 	@extras="$(EXTRAS)" ; for target in $$extras ; do \
 		echo $$target ; \
-		$(MAKE) prefix=$(prefix) LD="$(LD)" SYSFS="$(SYSFS)" \
+		$(MAKE) prefix=$(prefix) LD="$(LD)" SYS_SYSFS=$(SYS_SYSFS) SYSFS="$(SYSFS)" \
 			-C $$target $@ ; \
 	done ; \
 
diff -urN udev-050.orig/namedev.c udev-050/namedev.c
--- udev-050.orig/namedev.c	2004-12-18 11:53:07 +0600
+++ udev-050/namedev.c	2005-01-02 20:09:11 +0600
@@ -32,7 +32,7 @@
 #include <sys/wait.h>
 #include <sys/stat.h>
 
-#include "libsysfs/sysfs/libsysfs.h"
+#include <sysfs/libsysfs.h>
 #include "list.h"
 #include "udev.h"
 #include "udev_utils.h"
diff -urN udev-050.orig/udev_add.c udev-050/udev_add.c
--- udev-050.orig/udev_add.c	2004-12-18 11:53:07 +0600
+++ udev-050/udev_add.c	2005-01-02 20:09:11 +0600
@@ -36,7 +36,7 @@
 #include <linux/sockios.h>
 #include <pwd.h>
 
-#include "libsysfs/sysfs/libsysfs.h"
+#include <sysfs/libsysfs.h>
 #include "udev.h"
 #include "udev_utils.h"
 #include "udev_version.h"
diff -urN udev-050.orig/udev.c udev-050/udev.c
--- udev-050.orig/udev.c	2004-12-18 11:53:07 +0600
+++ udev-050/udev.c	2005-01-02 20:09:11 +0600
@@ -31,7 +31,7 @@
 #include <signal.h>
 #include <unistd.h>
 
-#include "libsysfs/sysfs/libsysfs.h"
+#include <sysfs/libsysfs.h>
 #include "udev.h"
 #include "udev_utils.h"
 #include "udev_sysfs.h"
diff -urN udev-050.orig/udev_config.c udev-050/udev_config.c
--- udev-050.orig/udev_config.c	2004-12-18 11:53:07 +0600
+++ udev-050/udev_config.c	2005-01-02 20:09:11 +0600
@@ -32,7 +32,7 @@
 #include <errno.h>
 #include <ctype.h>
 
-#include "libsysfs/sysfs/libsysfs.h"
+#include <sysfs/libsysfs.h>
 #include "udev.h"
 #include "udev_utils.h"
 #include "udev_version.h"
diff -urN udev-050.orig/udev_db.c udev-050/udev_db.c
--- udev-050.orig/udev_db.c	2004-12-18 11:53:07 +0600
+++ udev-050/udev_db.c	2005-01-02 20:09:11 +0600
@@ -31,7 +31,7 @@
 #include <errno.h>
 #include <dirent.h>
 
-#include "libsysfs/sysfs/libsysfs.h"
+#include <sysfs/libsysfs.h>
 #include "udev.h"
 #include "udev_utils.h"
 #include "logging.h"
diff -urN udev-050.orig/udev.h udev-050/udev.h
--- udev-050.orig/udev.h	2004-12-18 11:53:07 +0600
+++ udev-050/udev.h	2005-01-02 20:09:11 +0600
@@ -24,7 +24,7 @@
 #define _UDEV_H_
 
 #include <sys/param.h>
-#include "libsysfs/sysfs/libsysfs.h"
+#include <sysfs/libsysfs.h>
 
 #define ALARM_TIMEOUT			120
 #define COMMENT_CHARACTER		'#'
diff -urN udev-050.orig/udevinfo.c udev-050/udevinfo.c
--- udev-050.orig/udevinfo.c	2004-12-18 11:53:07 +0600
+++ udev-050/udevinfo.c	2005-01-02 20:09:11 +0600
@@ -27,8 +27,8 @@
 #include <unistd.h>
 #include <errno.h>
 
-#include "libsysfs/sysfs/libsysfs.h"
-#include "libsysfs/dlist.h"
+#include <sysfs/libsysfs.h>
+#include <sysfs/dlist.h>
 #include "udev.h"
 #include "udev_utils.h"
 #include "udev_version.h"
diff -urN udev-050.orig/udev_start.c udev-050/udev_start.c
--- udev-050.orig/udev_start.c	2004-12-18 11:53:07 +0600
+++ udev-050/udev_start.c	2005-01-02 20:09:11 +0600
@@ -33,7 +33,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include "libsysfs/sysfs/libsysfs.h"
+#include <sysfs/libsysfs.h>
 #include "logging.h"
 #include "udev_utils.h"
 #include "list.h"
diff -urN udev-050.orig/udev_sysfs.c udev-050/udev_sysfs.c
--- udev-050.orig/udev_sysfs.c	2004-12-18 11:53:07 +0600
+++ udev-050/udev_sysfs.c	2005-01-02 20:09:11 +0600
@@ -28,7 +28,7 @@
 #include <errno.h>
 #include <sys/stat.h>
 
-#include "libsysfs/sysfs/libsysfs.h"
+#include <sysfs/libsysfs.h>
 #include "udev_version.h"
 #include "udev_sysfs.h"
 #include "udev_utils.h"
diff -urN udev-050.orig/udev_sysfs.h udev-050/udev_sysfs.h
--- udev-050.orig/udev_sysfs.h	2004-12-18 11:53:07 +0600
+++ udev-050/udev_sysfs.h	2005-01-02 20:09:11 +0600
@@ -22,7 +22,7 @@
 #ifndef _UDEV_SYSFS_H_
 #define _UDEV_SYSFS_H_
 
-#include "libsysfs/sysfs/libsysfs.h"
+#include <sysfs/libsysfs.h>
 
 #define WAIT_MAX_SECONDS		5
 #define WAIT_LOOP_PER_SECOND		20
diff -urN udev-050.orig/udevtest.c udev-050/udevtest.c
--- udev-050.orig/udevtest.c	2004-12-18 11:53:07 +0600
+++ udev-050/udevtest.c	2005-01-02 20:09:11 +0600
@@ -27,7 +27,7 @@
 #include <ctype.h>
 #include <signal.h>
 
-#include "libsysfs/sysfs/libsysfs.h"
+#include <sysfs/libsysfs.h>
 #include "udev.h"
 #include "udev_sysfs.h"
 #include "udev_utils.h"

[-- Attachment #9: udev-0.46-alt-efmt_fixes.patch --]
[-- Type: text/x-patch, Size: 5002 bytes --]

diff -urN udev-046.orig/namedev.c udev-046/namedev.c
--- udev-046.orig/namedev.c	2004-12-28 02:43:18 +0600
+++ udev-046/namedev.c	2004-12-28 02:43:54 +0600
@@ -184,13 +184,13 @@
  *  @param  name                Name to check for
  *  @return                     0 if <name> didn't exist and N otherwise.
  */
-static int find_free_number(struct udevice *udev, const char *name)
+static int find_free_number(struct udevice *udev, const char *name, const char *tail)
 {
 	char filename[NAME_SIZE];
 	int num = 0;
 	struct udevice db_udev;
 
-	strfieldcpy(filename, name);
+	snprintf(filename, NAME_SIZE, "%s%s", name, tail);
 	while (1) {
 		dbg("look for existing node '%s'", filename);
 		memset(&db_udev, 0x00, sizeof(struct udevice));
@@ -204,14 +204,18 @@
 			info("find_free_number gone crazy (num=%d), aborted", num);
 			return -1;
 		}
-		snprintf(filename, NAME_SIZE, "%s%d", name, num);
+		snprintf(filename, NAME_SIZE, "%s%d%s", name, num, tail);
 		filename[NAME_SIZE-1] = '\0';
 	}
 }
 
 static void apply_format(struct udevice *udev, char *string, size_t maxsize,
 			 struct sysfs_class_device *class_dev,
-			 struct sysfs_device *sysfs_device)
+			 struct sysfs_device *sysfs_device);
+
+static void apply_format_token(struct udevice *udev, char *string, size_t maxsize,
+			       struct sysfs_class_device *class_dev,
+			       struct sysfs_device *sysfs_device, int use_ext)
 {
 	char temp[NAME_SIZE];
 	char temp2[NAME_SIZE];
@@ -291,12 +295,12 @@
 					strfieldcpy(temp2, spos);
 				else
 					strfieldcpymax(temp2, spos, slen+1);
-				strfieldcatmax(string, temp2, maxsize);
-				dbg("substitute part of result string '%s'", temp2);
 			} else {
-				strfieldcatmax(string, udev->program_result, maxsize);
-				dbg("substitute result string '%s'", udev->program_result);
+				strfieldcpy(temp2, udev->program_result);
 			}
+			apply_format(udev, temp2, NAME_SIZE, class_dev, sysfs_device);
+			strfieldcatmax(string, temp2, maxsize);
+			dbg("substitute part of result string '%s'", temp2);
 			break;
 		case 's':
 			if (attr != NULL) {
@@ -327,12 +331,19 @@
 			pos++;
 			break;
 		case 'e':
-			next_free_number = find_free_number(udev, string);
+			if (!use_ext) {
+				dbg("prohibited usage of attribute %%e");
+				break;
+			}
+			/* prohibite "extended" attributes in tail */
+			apply_format_token(udev, tail, NAME_SIZE, class_dev, sysfs_device, 0);
+			next_free_number = find_free_number(udev, string, tail);
 			if (next_free_number > 0) {
 				sprintf(temp2, "%d", next_free_number);
 				strfieldcatmax(string, temp2, maxsize);
 			}
-			break;
+			strfieldcatmax(string, tail, maxsize);
+			return;
 		default:
 			dbg("unknown substitution type '%%%c'", c);
 			break;
@@ -345,6 +356,67 @@
 	}
 }
 
+#define declare_string_size(strname, strsize) char (strname)[strsize]
+/* A decimal number can't be more then 30 symbols wide */
+#define maxint_digits 30
+static void apply_format(struct udevice *udev, char *string, size_t maxsize,
+			 struct sysfs_class_device *class_dev,
+			 struct sysfs_device *sysfs_device)
+{
+	int consumed;
+	char *tokenptr;
+	size_t tokenspace;
+	size_t tokenlen;
+	char *stringptr = string;
+	char sscanf_ptrn[5 + maxint_digits];
+	declare_string_size(token, maxsize);
+	snprintf(sscanf_ptrn, 5 + maxint_digits, "%%%ds%%n", maxsize - 1);
+	tokenptr = token;
+	tokenptr[0] = '\0';
+	tokenspace = maxsize;
+	while (0 < sscanf(stringptr, sscanf_ptrn, tokenptr, &consumed)) {
+		/* next token now has been put into 'token'
+		 * let's process it...
+		 */
+		apply_format_token(udev, tokenptr, tokenspace, class_dev, sysfs_device, 1);
+
+		/* Now we need to add a trailing whitespace to the
+		 * processed token and advance to the next string's
+		 * token...
+		 */
+		stringptr += consumed;
+		tokenlen = strlen(tokenptr);
+		/* hopefully I didn't make a mistake in bound
+		 * checks... tokenlen is always less than tokenspace
+		 * at least by one. But we need to check if there's a
+		 * space for additional whitespace and next token
+		 * (i.e. tokenlen must be at least 3 bytes less than
+		 * tokenspace). Additionally we should prevent int
+		 * overflow errors...
+		 */
+		if (tokenspace < 3 || tokenspace - 3 <= tokenlen) {
+			if (*stringptr)
+				dbg("Space exhausted while some trailing data left in format string");
+			break;
+		}
+		strncat(tokenptr + tokenlen, " ", tokenspace - tokenlen - 1);
+		tokenptr += tokenlen + 1;
+		tokenspace -= tokenlen + 1;
+		/* and finally adjust sscanf_ptrn to prevent buffer
+		 * overflow in sscanf
+		 */
+		snprintf(sscanf_ptrn, 5 + maxint_digits, "%%%ds%%n", tokenspace - 1);
+	}
+	/* remove leading and trailing whitespace. They do matter sometimes */
+	for(tokenptr = token;isspace(*tokenptr);tokenptr++);
+	tokenlen = strlen(tokenptr);
+	if (tokenlen > 0)
+		tokenptr[tokenlen - 1] = '\0';
+	strncpy(string, tokenptr, maxsize);
+}
+#undef declare_string_size
+#undef maxint_digits
+
 static void fix_kernel_name(struct udevice *udev)
 {
 	char *temp = udev->kernel_name;

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

* Re: Several fixes and enhancements for extented naming rules
  2005-01-07 17:07 Several fixes and enhancements for extented naming rules parameters Alexey Morozov
@ 2005-01-08  5:11 ` Kay Sievers
  2005-01-08  8:34 ` Several fixes and enhancements for extented naming rules parameters Alexey Morozov
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Kay Sievers @ 2005-01-08  5:11 UTC (permalink / raw)
  To: linux-hotplug

On Fri, 2005-01-07 at 23:07 +0600, Alexey Morozov wrote:
> Playing with udev naming rules, I notices that existing '%e' macro can't 
> be really used in several cases (important at least for me).

Please explain the several cases!

> This 
> 'extended' macro is quite useful if e.g. we try to build nice 
> "human-friendly" device naming scheme and strictly separate devices 
> names and permissions assignment (to rules.d/* and permissions.d/* 
> respectively)

permissions.d/ is gone. We have the permissions in the rules file form
the next version on.

> First of all, if one tries to give several names to a device (say, 
> create additional symlinks for a CD-RW device like /dev/cdrom, 
> /dev/cdwriter) udev ends up w/ errors.

What kind of errors? Please explain!

> Also I really doubt if %e w/ existing rules processing code can be used 
> in constructions like /dev/discs/disc%e/disc and other devfs-like naming 
> schemes.

Yes, this doesn't work, but the scripts can do this, right?

> So I decided to patch it a bit to achieve such functionality. You can 
> find this patch in the attachment.
> 
> Also I'd like to have another macro. While %e is substituted w/ nothing for
> 'mydevice%e' if /dev/mydevice doesn't exist yet, this new macro always 
> substituted w/ a non-negative number. I called it %N, but in fact these 
> names can be changed in future. This is particularly useful for names 
> like /dev/discs/disc%N/{.....} and allows to simplify devfs-like naming 
> scripts.

Is there really the need to move this into udev? What is the limitation
of the scripts?

> Also I made a patch for (optional) compilation of udev w/ a system-wide 
> installed sysfs libraries. I'm not sure it's a good idea 'for everyone' 
> but if we anyway have libsysfs and it's fresh enough to seamlessly work 
> w/ udev, I don't see any reasons to have a separate copy right in udev 
> source tree. Probably I make a mistake, but it worked /for me/ so far, 
> and hey, it's optional anyway.

Does this work with the klibc build, which cannot use the system
installed version of sysfs?

Kay



-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues
Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek.
It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
_______________________________________________
Linux-hotplug-devel mailing list  http://linux-hotplug.sourceforge.net
Linux-hotplug-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel

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

* Re: Several fixes and enhancements for extented naming rules parameters
  2005-01-07 17:07 Several fixes and enhancements for extented naming rules parameters Alexey Morozov
  2005-01-08  5:11 ` Several fixes and enhancements for extented naming rules Kay Sievers
@ 2005-01-08  8:34 ` Alexey Morozov
  2005-01-08 14:53 ` Several fixes and enhancements for extented naming Kay Sievers
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Alexey Morozov @ 2005-01-08  8:34 UTC (permalink / raw)
  To: linux-hotplug

Kay Sievers writes:

>On Fri, 2005-01-07 at 23:07 +0600, Alexey Morozov wrote:
>  
>
>>Playing with udev naming rules, I notices that existing '%e' macro can't 
>>be really used in several cases (important at least for me).
>>    
>>
>
>Please explain the several cases!
>  
>
Well, I tried to describe them below in that letter, right? I can show 
you entire contents of /dev on my workstation.

>>This 
>>'extended' macro is quite useful if e.g. we try to build nice 
>>"human-friendly" device naming scheme and strictly separate devices 
>>names and permissions assignment (to rules.d/* and permissions.d/* 
>>respectively)
>>    
>>
>
>permissions.d/ is gone. We have the permissions in the rules file form
>the next version on.
>  
>
Hmm, well, maybe it's a good idea, but I doubt it can increase 
maintainability of udev setups. But perhaps I'm wrong, I need to think a 
bit about possible consequences and undestand how things change in this 
case.

>>First of all, if one tries to give several names to a device (say, 
>>create additional symlinks for a CD-RW device like /dev/cdrom, 
>>/dev/cdwriter) udev ends up w/ errors.
>>    
>>
>
>What kind of errors? Please explain!
>  
>
Sure. Existing 'if such a name already assigned by udev to a device' 
code works poorly if e.g. _several_ symlinks are to be considered. It 
simply doesn't split entire string SYMLINK="a_name1 another_name2 ... 
generic_name%e" into tokens and therefore can't really check if 
corresponding /dev/generic_name* etc are already assigned to some 
devices. You may try it yourself.

>>Also I really doubt if %e w/ existing rules processing code can be used 
>>in constructions like /dev/discs/disc%e/disc and other devfs-like naming 
>>schemes.
>>    
>>
>
>Yes, this doesn't work, but the scripts can do this, right?
>  
>
Please see the answer below.

>>So I decided to patch it a bit to achieve such functionality. You can 
>>find this patch in the attachment.
>>
>>Also I'd like to have another macro. While %e is substituted w/ nothing for
>>'mydevice%e' if /dev/mydevice doesn't exist yet, this new macro always 
>>substituted w/ a non-negative number. I called it %N, but in fact these 
>>names can be changed in future. This is particularly useful for names 
>>like /dev/discs/disc%N/{.....} and allows to simplify devfs-like naming 
>>scripts.
>>    
>>
>
>Is there really the need to move this into udev? What is the limitation
>of the scripts?
>  
>
Speed. Complexity. As you may notice, I mostly re-used existing udev 
code in these patches. W/ a "pure scripts" solution I would had to do 
all the things from scratch. I looked at existing udev supporting 
scripts (from debian, gentoo and Mdk) and found that they works really 
harder than my code to achieve corresponding or even lesser level of 
functionality (at least in implementing equivalents of those 'extended 
attributes' like '%e').

Sure namedev stuff can probably be taken out of  main udev binary. But 
in any case a stateless script which has to calculate everything it 
needs to form a name each time it's launched, well, that script will be 
more complex and slow than a solution w/ a binary and pre-built database 
in a convenient format.

BTW, my current /dev/.udevdb eats ~2.8Mb of space (/dev is on tmpfs) on 
an ordinary workstation w/o much hardware plugged in. Is that intended 
result? ;-) Are there plans to change its format? Now it's a lot, ~700 
files, each 40-50 bytes long. I guess smth like a berkeley db will be 
more appropriate in this case, but I'm not sure if it's a good idea to 
take even statically linked db1 to Early User Space stuff. Maybe 
there're some other workarounds for the problem?

There's another little problem to be considered. E.g. I noticed that 
sda1 creation event for my flash drive often comes when entire sda event 
hasn't been processed completely yet. So we have to deal w/ such 
concurrency, and I really believe that C provides better tools and 
techniques for that than bash-programming.

>>Also I made a patch for (optional) compilation of udev w/ a system-wide 
>>installed sysfs libraries. I'm not sure it's a good idea 'for everyone' 
>>but if we anyway have libsysfs and it's fresh enough to seamlessly work 
>>w/ udev, I don't see any reasons to have a separate copy right in udev 
>>source tree. Probably I make a mistake, but it worked /for me/ so far, 
>>and hey, it's optional anyway.
>>    
>>
>Does this work with the klibc build, which cannot use the system
>installed version of sysfs?
>  
>
Well, it's just a linker flag. Instead of explicitly link 
libsysfs/sysfs.a, it can pass to the linker anything from $(SYS_SYSFS).
It can be -lsysfs, or just a /usr/lib/libsysfs.a if one wants. So the 
answer is yes, it works if we build udev on a system w/ an appropriate 
libsysfs installed.

Yours faithfully,
Alexey Morozov


-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues
Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek.
It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
_______________________________________________
Linux-hotplug-devel mailing list  http://linux-hotplug.sourceforge.net
Linux-hotplug-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel

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

* Re: Several fixes and enhancements for extented naming
  2005-01-07 17:07 Several fixes and enhancements for extented naming rules parameters Alexey Morozov
  2005-01-08  5:11 ` Several fixes and enhancements for extented naming rules Kay Sievers
  2005-01-08  8:34 ` Several fixes and enhancements for extented naming rules parameters Alexey Morozov
@ 2005-01-08 14:53 ` Kay Sievers
  2005-01-10  8:37 ` Several fixes and enhancements for extented naming rules parameters Alexey Morozov
  2005-01-10 12:03 ` Several fixes and enhancements for extented naming rules Kay Sievers
  4 siblings, 0 replies; 6+ messages in thread
From: Kay Sievers @ 2005-01-08 14:53 UTC (permalink / raw)
  To: linux-hotplug

On Sat, 2005-01-08 at 14:34 +0600, Alexey Morozov wrote:
> Kay Sievers writes:
> >On Fri, 2005-01-07 at 23:07 +0600, Alexey Morozov wrote:
> >>First of all, if one tries to give several names to a device (say, 
> >>create additional symlinks for a CD-RW device like /dev/cdrom, 
> >>/dev/cdwriter) udev ends up w/ errors.
> >> 
> >
> >What kind of errors? Please explain!
> > 
> Sure. Existing 'if such a name already assigned by udev to a device' 
> code works poorly if e.g. _several_ symlinks are to be considered. It 
> simply doesn't split entire string SYMLINK="a_name1 another_name2 ... 
> generic_name%e" into tokens and therefore can't really check if 
> corresponding /dev/generic_name* etc are already assigned to some 
> devices. You may try it yourself.

A separate rule with only one SYMLINK works. That's not perfect, but see
later in this mail.

> >>So I decided to patch it a bit to achieve such functionality. You can 
> >>find this patch in the attachment.
> >>
> >>Also I'd like to have another macro. While %e is substituted w/ nothing for
> >>'mydevice%e' if /dev/mydevice doesn't exist yet, this new macro always 
> >>substituted w/ a non-negative number. I called it %N, but in fact these 
> >>names can be changed in future. This is particularly useful for names 
> >>like /dev/discs/disc%N/{.....} and allows to simplify devfs-like naming 
> >>scripts.
> >
> >Is there really the need to move this into udev? What is the limitation
> >of the scripts?
> >
> Speed. Complexity. As you may notice, I mostly re-used existing udev 
> code in these patches. W/ a "pure scripts" solution I would had to do 
> all the things from scratch. I looked at existing udev supporting 
> scripts (from debian, gentoo and Mdk) and found that they works really 
> harder than my code to achieve corresponding or even lesser level of 
> functionality (at least in implementing equivalents of those 'extended 
> attributes' like '%e').

I've never heard any complains about the speed of udev. :)

> Sure namedev stuff can probably be taken out of  main udev binary. But 
> in any case a stateless script which has to calculate everything it 
> needs to form a name each time it's launched, well, that script will be 
> more complex and slow than a solution w/ a binary and pre-built database 
> in a convenient format.

Well, the problem is that the %e is just a dirty hack to provide compatibility
symlinks. It works only in the udevstart case. If driven by hotplug events,
it's slippery cause of the concurrently running processes for each device.
It happens, that you get the same enumeration number for multiple
devices. I don't feel comfortable to move more of this conceptually broken stuff
into udev.

How about creating _and_ supporting a callout in the extras/ folder, that is
able to store and retrieve information from its own database stored in a
dotfile in /dev? devfs scripts can use that extra and it may use a file lock to
serialize the events. It is still not guaranteed that the enum is in the event
order, but doubles may be avoided this way. Also the stupid reverse lookup of the
udevdb is avoided this way, which needs to read all db-files every time again.

> BTW, my current /dev/.udevdb eats ~2.8Mb of space (/dev is on tmpfs) on 
> an ordinary workstation w/o much hardware plugged in. Is that intended 
> result? ;-) Are there plans to change its format? Now it's a lot, ~700 
> files, each 40-50 bytes long. I guess smth like a berkeley db will be 
> more appropriate in this case, but I'm not sure if it's a good idea to 
> take even statically linked db1 to Early User Space stuff. Maybe 
> there're some other workarounds for the problem?

There are no plans. The only current workaround is to use a different
filesystem. The db operations need to be completely lockless. We already
have had a single file database but some setups got several hundred
processes concurrently locking this file and waiting for a slot to write
to and it failed badly...

> There's another little problem to be considered. E.g. I noticed that 
> sda1 creation event for my flash drive often comes when entire sda event 
> hasn't been processed completely yet. So we have to deal w/ such 
> concurrency, and I really believe that C provides better tools and 
> techniques for that than bash-programming.

This should not happen. sda1 is a child of sda and these events are
serialized from version 049 on. sda, sdb, ... still run in parallel.

> >>Also I made a patch for (optional) compilation of udev w/ a system-wide 
> >>installed sysfs libraries. I'm not sure it's a good idea 'for everyone' 
> >>but if we anyway have libsysfs and it's fresh enough to seamlessly work 
> >>w/ udev, I don't see any reasons to have a separate copy right in udev 
> >>source tree. Probably I make a mistake, but it worked /for me/ so far, 
> >>and hey, it's optional anyway.
> >> 
> >Does this work with the klibc build, which cannot use the system
> >installed version of sysfs?
> >  
> Well, it's just a linker flag. Instead of explicitly link 
> libsysfs/sysfs.a, it can pass to the linker anything from $(SYS_SYSFS).
> It can be -lsysfs, or just a /usr/lib/libsysfs.a if one wants. So the 
> answer is yes, it works if we build udev on a system w/ an appropriate 
> libsysfs installed.

We sometimes make changes to the in-tree version and therefore we don't
want to officially support a system wide version. So the system-wide
compile must be the optional one which is only linked if the user asks
for it.

The sources of the in-tree libsysfs should not be changed, it better
matches the upstream version. Otherwise it would be nice to be able to
offer this switch.

Kay



-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues
Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek.
It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
_______________________________________________
Linux-hotplug-devel mailing list  http://linux-hotplug.sourceforge.net
Linux-hotplug-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel

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

* Re: Several fixes and enhancements for extented naming rules parameters
  2005-01-07 17:07 Several fixes and enhancements for extented naming rules parameters Alexey Morozov
                   ` (2 preceding siblings ...)
  2005-01-08 14:53 ` Several fixes and enhancements for extented naming Kay Sievers
@ 2005-01-10  8:37 ` Alexey Morozov
  2005-01-10 12:03 ` Several fixes and enhancements for extented naming rules Kay Sievers
  4 siblings, 0 replies; 6+ messages in thread
From: Alexey Morozov @ 2005-01-10  8:37 UTC (permalink / raw)
  To: linux-hotplug

Kay Sievers пишет:

>>Sure. Existing 'if such a name already assigned by udev to a device' 
>>code works poorly if e.g. _several_ symlinks are to be considered. It 
>>simply doesn't split entire string SYMLINK="a_name1 another_name2 ... 
>>generic_name%e" into tokens and therefore can't really check if 
>>corresponding /dev/generic_name* etc are already assigned to some 
>>devices. You may try it yourself.
>>    
>>
>>Speed. Complexity. As you may notice, I mostly re-used existing udev 
>>code in these patches. 
>>    
>>
>I've never heard any complains about the speed of udev. :)
>  
>
I've heard indeed. Particularly about the speed of udevstart ;-). But 
the main worries about complexity.

>  
>
>>Sure namedev stuff can probably be taken out of  main udev binary. But 
>>in any case a stateless script which has to calculate everything it 
>>needs to form a name each time it's launched, well, that script will be 
>>more complex and slow than a solution w/ a binary and pre-built database 
>>in a convenient format.
>>    
>>
>
>Well, the problem is that the %e is just a dirty hack to provide compatibility
>symlinks. It works only in the udevstart case. If driven by hotplug events,
>  
>
Hmm, with my patches it works everywhere ;-). Trust me ;-). At least in 
'real userlevel' (haven't played w/ early userland stuff yet).

>it's slippery cause of the concurrently running processes for each device.
>It happens, that you get the same enumeration number for multiple
>devices. I don't feel comfortable to move more of this conceptually broken stuff
>into udev.
>  
>
Well, it's understandable.

>How about creating _and_ supporting a callout in the extras/ folder, that is
>able to store and retrieve information from its own database stored in a
>dotfile in /dev? devfs scripts can use that extra and it may use a file lock to
>serialize the events. It is still not guaranteed that the enum is in the event
>order, but doubles may be avoided this way. Also the stupid reverse lookup of the
>udevdb is avoided this way, which needs to read all db-files every time again.
>  
>
> The db operations need to be completely lockless. We already
>have had a single file database but some setups got several hundred
>processes concurrently locking this file and waiting for a slot to write
>to and it failed badly...
>  
>
Well, as I understand you propose [me] to take away [most of] namedev.* 
and udev_db.* stuff out of main udev binary sources and create an 
'user-level' (well, even more user-level :-)) utility, which does 
basically the same upon a request from scrips, right? Are there any 
works in that direction already? Are there some sort of strict 
specifications for the task?

As I can see it now, any usage of 'extended substs' like '%e' will cause 
a need in some sort of serialized/synchronous operations (in case two 
hotplug events got delivered in the same time), so I just can't see a 
solution w/o any locks at all. Sure these locks can be, well, cheap or 
lightweight, 'row-locks' etc, but all my previous experience tells me 
there must be some serialization anyway. BTW, existing udevdb stuff 
seems not to be a reentrant safe at least in the 
udev_db_get_device_byname part.

Maybe this new utility should act like a small daemon listening a 
[unix-domain] socket (a FIFO? hmm) for incoming name pattern requests 
and responding w/ substitutions performed. This way we can avoid 
re-parsing device DB on each request and serialize things properly so 
parallel devices creation events won't be blocked for a too long time. 
I'm not sure about availability of corresponding kernel functionality in 
early userland stages. We also can avoid 'on disk' DB if needed.


>>BTW, my current /dev/.udevdb eats ~2.8Mb of space (/dev is on tmpfs) on 
>>    
>>
>There are no plans. The only current workaround is to use a different
>filesystem.
>
Umm... tmpfs already has useful hacks like this one: 
http://www.uwsg.indiana.edu/hypermail/linux/kernel/0411.0/1568.html

I doubt it's worth to intend /dev functionality to an 'adult' filesystem 
w/ tail packing, resident files and other super-cool and awesome features.

>>E.g. I noticed that sda1 creation event for my flash drive often comes when entire sda event 
>>hasn't been processed completely yet.
>>    
>>
>This should not happen. sda1 is a child of sda and these events are
>serialized from version 049 on. sda, sdb, ... still run in parallel.
>  
>
Well, I noticed that partition node creation script is running when the 
entire device node hasn't been created yet. I even had to put some ugly 
polling into drive-names.sh (lines 60-73), which solved the problem. 
Probably, it's not an udev, but e.g. tmpfs fault, but anyway it exists 
(at least on my 2.6.9 w/ corresponding Con Kolivas patchset applied).

>>Well, it's just a linker flag. Instead of explicitly link 
>>libsysfs/sysfs.a, it can pass to the linker anything from $(SYS_SYSFS).
>>It can be -lsysfs, or just a /usr/lib/libsysfs.a if one wants. So the 
>>answer is yes, it works if we build udev on a system w/ an appropriate 
>>libsysfs installed.
>>    
>>
>
>We sometimes make changes to the in-tree version and therefore we don't
>want to officially support a system wide version. So the system-wide
>compile must be the optional one which is only linked if the user asks
>for it.
>  
>
It's completely optional. If you don't provide SYS_SYSFS=<smth suitable 
to linker> flag as a make parameter, then it goes just as w/o any patch.

That's extracts from udev.spec I use to build it for my distro:

...
# (Near the beginning of the spec):
# whether we want to use system-wide sysfs or udev local copy
# Note udev-0.50 requires a recent version of sysfs,
%def_with system_sysfs
...
%if_with system_sysfs
BuildRequires: libsysfs-devel > 1.2.0-alt2
%endif
...
%make_build \
         udevdir=/dev \
...
%if_with system_sysfs
        SYS_SYSFS=-lsysfs \
%endif
...



-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues
Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek.
It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
_______________________________________________
Linux-hotplug-devel mailing list  http://linux-hotplug.sourceforge.net
Linux-hotplug-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel

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

* Re: Several fixes and enhancements for extented naming rules
  2005-01-07 17:07 Several fixes and enhancements for extented naming rules parameters Alexey Morozov
                   ` (3 preceding siblings ...)
  2005-01-10  8:37 ` Several fixes and enhancements for extented naming rules parameters Alexey Morozov
@ 2005-01-10 12:03 ` Kay Sievers
  4 siblings, 0 replies; 6+ messages in thread
From: Kay Sievers @ 2005-01-10 12:03 UTC (permalink / raw)
  To: linux-hotplug

On Mon, 2005-01-10 at 14:37 +0600, Alexey Morozov wrote:
> Kay Sievers пишет:
> >>Sure namedev stuff can probably be taken out of  main udev binary. But 
> >>in any case a stateless script which has to calculate everything it 
> >>needs to form a name each time it's launched, well, that script will be 
> >>more complex and slow than a solution w/ a binary and pre-built database 
> >>in a convenient format.
> >
> >Well, the problem is that the %e is just a dirty hack to provide compatibility
> >symlinks. It works only in the udevstart case. If driven by hotplug events,
> >
> Hmm, with my patches it works everywhere ;-). Trust me ;-). At least in 
> 'real userlevel' (haven't played w/ early userland stuff yet).

You still have the same races as the current %e used outside of udevstart.

> >it's slippery cause of the concurrently running processes for each device.
> >It happens, that you get the same enumeration number for multiple
> >devices. I don't feel comfortable to move more of this conceptually broken stuff
> >into udev.
> > 
> Well, it's understandable.
> 
> >How about creating _and_ supporting a callout in the extras/ folder, that is
> >able to store and retrieve information from its own database stored in a
> >dotfile in /dev? devfs scripts can use that extra and it may use a file lock to
> >serialize the events. It is still not guaranteed that the enum is in the event
> >order, but doubles may be avoided this way. Also the stupid reverse lookup of the
> >udevdb is avoided this way, which needs to read all db-files every time again.
> > 
> > The db operations need to be completely lockless. We already
> >have had a single file database but some setups got several hundred
> >processes concurrently locking this file and waiting for a slot to write
> >to and it failed badly...
> > 
> Well, as I understand you propose [me] to take away [most of] namedev.* 
> and udev_db.* stuff out of main udev binary sources and create an 
> 'user-level' (well, even more user-level :-)) utility,

No, only the enumeration part of namedev should be taken out, as in our
current model of independent running event processes, we can't really do
this inside of udev.

> which does 
> basically the same upon a request from scrips, right? Are there any 
> works in that direction already? Are there some sort of strict 
> specifications for the task?

No, it is just an idea and was mainly a question, what you/others think.

> As I can see it now, any usage of 'extended substs' like '%e' will cause 
> a need in some sort of serialized/synchronous operations (in case two 
> hotplug events got delivered in the same time), so I just can't see a 
> solution w/o any locks at all.

Right, the callout could do this kind of serialization.

> Sure these locks can be, well, cheap or 
> lightweight, 'row-locks' etc, but all my previous experience tells me 
> there must be some serialization anyway. BTW, existing udevdb stuff 
> seems not to be a reentrant safe at least in the 
> udev_db_get_device_byname part.

What may be the reason for reentrancy here. udevd serialized the
execution of events with the same devpath.

> Maybe this new utility should act like a small daemon listening a 
> [unix-domain] socket (a FIFO? hmm) for incoming name pattern requests 
> and responding w/ substitutions performed. This way we can avoid 
> re-parsing device DB on each request and serialize things properly so 
> parallel devices creation events won't be blocked for a too long time. 
> I'm not sure about availability of corresponding kernel functionality in 
> early userland stages. We also can avoid 'on disk' DB if needed.

I don't know what's the best architecture for that kind of counters, but
I don't think that we should replace our current udevdb with something
like that.

> >>BTW, my current /dev/.udevdb eats ~2.8Mb of space (/dev is on tmpfs) on 
> >>    
> >>
> >There are no plans. The only current workaround is to use a different
> >filesystem.
> >
> Umm... tmpfs already has useful hacks like this one: 
> http://www.uwsg.indiana.edu/hypermail/linux/kernel/0411.0/1568.html
> 
> I doubt it's worth to intend /dev functionality to an 'adult' filesystem 
> w/ tail packing, resident files and other super-cool and awesome features.
> 
> >>E.g. I noticed that sda1 creation event for my flash drive often comes when entire sda event 
> >>hasn't been processed completely yet.
> >> 
> >This should not happen. sda1 is a child of sda and these events are
> >serialized from version 049 on. sda, sdb, ... still run in parallel.
> >
> Well, I noticed that partition node creation script is running when the 
> entire device node hasn't been created yet. I even had to put some ugly 
> polling into drive-names.sh (lines 60-73), which solved the problem. 
> Probably, it's not an udev, but e.g. tmpfs fault, but anyway it exists 
> (at least on my 2.6.9 w/ corresponding Con Kolivas patchset applied).

I can't reproduce this. The partition events are delayed by udevd until
the main block device event has exited. It works on my box.

> >>Well, it's just a linker flag. Instead of explicitly link 
> >>libsysfs/sysfs.a, it can pass to the linker anything from $(SYS_SYSFS).
> >>It can be -lsysfs, or just a /usr/lib/libsysfs.a if one wants. So the 
> >>answer is yes, it works if we build udev on a system w/ an appropriate 
> >>libsysfs installed.
> >>    
> >We sometimes make changes to the in-tree version and therefore we don't
> >want to officially support a system wide version. So the system-wide
> >compile must be the optional one which is only linked if the user asks
> >for it.
> >  
> It's completely optional. If you don't provide SYS_SYSFS=<smth suitable 
> to linker> flag as a make parameter, then it goes just as w/o any patch.

Ok, fine. Is it possible to do the same without changing our in-tree
libsysfs version?

Kay



-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues
Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek.
It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
_______________________________________________
Linux-hotplug-devel mailing list  http://linux-hotplug.sourceforge.net
Linux-hotplug-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel

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

end of thread, other threads:[~2005-01-10 12:03 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-01-07 17:07 Several fixes and enhancements for extented naming rules parameters Alexey Morozov
2005-01-08  5:11 ` Several fixes and enhancements for extented naming rules Kay Sievers
2005-01-08  8:34 ` Several fixes and enhancements for extented naming rules parameters Alexey Morozov
2005-01-08 14:53 ` Several fixes and enhancements for extented naming Kay Sievers
2005-01-10  8:37 ` Several fixes and enhancements for extented naming rules parameters Alexey Morozov
2005-01-10 12:03 ` Several fixes and enhancements for extented naming rules Kay Sievers

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).