Kernel/modutils major and minor dev number patch

Jason Spangler (jasons@usemail.com)
Sat, 07 Mar 1998 06:41:57 +0000


Hello,

Here is something I tossed together that makes the kernel always pass both the
major and minor device numbers for character special devices to kerneld. Also
included is a necessary patch for modprobe that will first check for an alias
matching char-major-major#-minor#, then for char-major-major#.

The modprobe patch will work without the kernel patch, but not the other way
around (an unpatched modprobe won't deal with getting both the major and minor
device numbers well).

This is handy for sound module users who use different modules for different
minor device numbers. I saw a similar patch a week or two ago which was
specific for sound modules, but I think this a more general purpose solution
that may be reusable for other things.

This has only been tested my system... Input/bugs/bug fixes welcome.

*** v2.1.88/fs/devices.c Tue Aug 12 19:15:15 1997
--- linux/fs/devices.c Fri Mar 6 19:36:02 1998
***************
*** 89,99 ****
* though we need the minor here to check if serial dev,
* we pass only the normal major char dev to kerneld
* as there is no other loadable dev on these majors
*/
if ((isa_tty_dev(major) && need_serial(major,minor)) ||
(major != 0 && !tb[major].fops)) {
char name[20];
! sprintf(name, mangle, major);
request_module(name);
}
#endif
--- 89,106 ----
* though we need the minor here to check if serial dev,
* we pass only the normal major char dev to kerneld
* as there is no other loadable dev on these majors
+ *
+ * Jason Spangler <jasons@usemail.com>: made this pass both
+ * major and minor device numbers to kerneld so that module
+ * loading can be done on specific minor device numbers
+ * (handy for sound modules). Requires kerneld that will
+ * check for major-minor modules, then major modules
+ * afterward.
*/
if ((isa_tty_dev(major) && need_serial(major,minor)) ||
(major != 0 && !tb[major].fops)) {
char name[20];
! sprintf(name, mangle, major, minor);
request_module(name);
}
#endif
***************
*** 109,120 ****
*/
struct file_operations * get_blkfops(unsigned int major)
{
! return get_fops (major,0,MAX_BLKDEV,"block-major-%d",blkdevs);
}

struct file_operations * get_chrfops(unsigned int major, unsigned int minor)
{
! return get_fops (major,minor,MAX_CHRDEV,"char-major-%d",chrdevs);
}

int register_chrdev(unsigned int major, const char * name, struct
file_operations *fops)
--- 116,127 ----
*/
struct file_operations * get_blkfops(unsigned int major)
{
! return get_fops (major,0,MAX_BLKDEV,"block-major-%d-%d",blkdevs);
}

struct file_operations * get_chrfops(unsigned int major, unsigned int minor)
{
! return get_fops (major,minor,MAX_CHRDEV,"char-major-%d-%d",chrdevs);
}

int register_chrdev(unsigned int major, const char * name, struct
file_operations *fops)

*** modutils-2.1.85/depmod/misc.c Fri Feb 6 03:25:59 1998
--- modutils-2.1.89/depmod/misc.c Fri Mar 6 17:16:14 1998
***************
*** 61,66 ****
--- 61,118 ----
return xstrdup (fname);
}

+ /*
+ * Strip the minor number off of a major-minor string
+ * Example: "char-major-14-1" becomes "char-major-14"
+ * Return a pointer to a malloc()ed buffer, or NULL if not a major-minor
string
+ */
+ char *
+ strip_minor_dev_num (char *fname)
+ {
+ char *begin = fname;
+ char *end = fname + strlen(fname) - 1;
+ char *startofminor = NULL;
+ char *iter;
+
+ int numcount = 0;
+ int dashcount = 0;
+ int indigit = 0;
+
+ for (iter = end; iter > (begin-1); iter--)
+ {
+ if (isdigit(*iter))
+ {
+ if (!indigit)
+ {
+ numcount++;
+ indigit = 1;
+ }
+ }
+ else if (*iter == '-')
+ {
+ dashcount++;
+ indigit = 0;
+ if (numcount == 1)
+ if (startofminor == NULL)
+ startofminor = iter;
+ else
+ break;
+ }
+ else
+ break;
+
+ if ((numcount == 2) && (dashcount == 2) && (startofminor != NULL))
+ {
+ char *leak = (char *) xmalloc (startofminor - begin + 1);
+ strncpy (leak, begin, startofminor - begin);
+ leak[startofminor - begin] = '\0';
+ return(leak);
+ }
+ }
+
+ return(NULL);
+ }
+
/*=================================================================*/

/*
*** modutils-2.1.85/depmod/conf_file.c Fri Feb 6 03:25:56 1998
--- modutils-2.1.89/depmod/conf_file.c Fri Mar 6 17:17:03 1998
***************
*** 734,739 ****
--- 734,741 ----

/*
* Check if a module name is indeed an alias for another module.
+ * Allows major-minor number alias to override major number alias
+ * Example: "char-major-14-1" will override "char-major-14"
* Return the real module or this one (mod) if it is not an alias
*/
static char *
***************
*** 743,773 ****
char *mod = orig_mod;
char *modname = strip_o (mod);
int count = 0;

! restart:
! for (alias = mod_alias; alias; alias = alias->next)
! if (!fnmatch (alias->name, mod, 0)
! || (modname && !fnmatch (alias->name, modname, 0)))
{
! if (modname)
! {
! free (modname);
! modname = NULL;
! }
! if (++count > 1000)
! {
! lprintf ("warning: alias loop resolving \"%s\"\n", orig_mod);
! return orig_mod;
! }
! mod = alias->alias;
! goto restart;
}

- if (modname)
- free (modname);
return mod;
}
-

/*
* Locate all modules matching the "match".
--- 745,795 ----
char *mod = orig_mod;
char *modname = strip_o (mod);
int count = 0;
+ char *majorname = strip_minor_dev_num (mod);
+ char *normalmatch;
+ char *majormatch;

!
! do
! {
! normalmatch = NULL;
! majormatch = NULL;
!
! for (alias = mod_alias; alias; alias = alias->next)
! {
! if (!normalmatch && (!fnmatch (alias->name, mod, 0)
! || (modname && !fnmatch (alias->name, modname, 0))))
! normalmatch = alias->alias;
! else if (!majormatch && majorname && !fnmatch (alias->name, majorname,
0))
! majormatch = alias->alias;
! }
!
! if (normalmatch || majormatch)
{
! if (++count > 1000)
! {
! lprintf ("warning: alias loop resolving \"%s\"\n", orig_mod);
! return orig_mod;
! }
!
! if (modname)
! {
! free (modname);
! modname = NULL;
! }
! if (majorname)
! {
! free (majorname);
! majorname = NULL;
! }
!
! mod = normalmatch ? normalmatch : majormatch;
}
+ }
+ while (normalmatch || majormatch);

return mod;
}

/*
* Locate all modules matching the "match".

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu