Subject: Re: broken LKM, modload and so on.
To: None <current-users@netbsd.org>
From: MAEKAWA Masahide <bishop@rr.iij4u.or.jp>
List: current-users
Date: 09/09/2002 23:51:05
----Next_Part(Mon_Sep__9_23:51:05_2002_989)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
MAEKAWA Masahide <bishop@rr.iij4u.or.jp> wrote:
>Jaromir Dolecek <jdolecek@netbsd.org> wrote:
>>Please do NOT expose struct lkm_* to userland.
>
>How about attached one?
I have slightly modified.
Here is two types.
base1.diff/sys1.diff and base2.diff/sys2.diff
Type 1: base1 and sys1.diff
The major number is unsigned 12 bit value.
We can overload block/character majors into u_long variable and
can split to two majors.
These operations are wrapped by macros.
Type 2: base2.diff and sys2.diff
The ``offset'' field is meaningful for LM_SYSCALL/LM_DEV.
So remove this field and add union priv data.
For LM_SYSCALL, define lmc_stat_syscall structure.
For LM_DEV, define lmc_stat_dev structure.
modload(8) call post script with
3rd (syscall number) argument if LM_SYSCALL
3rd (char major)/4th (block major) arguments if LM_DEV
no more arguments if others.
Which is better? type 1? type 2? I can't decide...
--- MAEKAWA Masahide
--- Key fingerprint = BC5E D8CB 816C 2CB5 8560 FDE3 6CB8 BF5D 8D50 F2EE
----Next_Part(Mon_Sep__9_23:51:05_2002_989)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="base1.diff"
Index: sbin/modload/modload.c
===================================================================
RCS file: /cvsroot/cvs/NetBSD/basesrc/sbin/modload/modload.c,v
retrieving revision 1.30
diff -u -r1.30 modload.c
--- sbin/modload/modload.c 2001/11/08 15:33:15 1.30
+++ sbin/modload/modload.c 2002/09/09 12:59:24
@@ -454,21 +454,27 @@
*/
if (post) {
struct lmc_stat sbuf;
- char id[16], type[16], offset[16];
+ char id[16], type[16], offset[2][16];
sbuf.id = resrv.slot;
if (ioctl(devfd, LMSTAT, &sbuf) == -1)
err(15, "error fetching module stats for post-install");
(void)snprintf(id, sizeof(id), "%d", sbuf.id);
(void)snprintf(type, sizeof(type), "0x%x", sbuf.type);
- (void)snprintf(offset, sizeof(offset), "%ld",
- (long)sbuf.offset);
- /*
- * XXX
- * The modload docs say that drivers can install bdevsw &
- * cdevsw, but the interface only supports one at a time.
- */
- execl(post, post, id, type, offset, 0);
+ if (sbuf.type == LM_DEV) {
+ int bmajor, cmajor;
+ bmajor = block_major(sbuf.offset);
+ cmajor = char_major(sbuf.offset);
+ (void)snprintf(offset[0], sizeof(offset[0]), "%d",
+ cmajor);
+ (void)snprintf(offset[1], sizeof(offset[1]), "%d",
+ bmajor);
+ execl(post, post, id, type, offset[0], offset[1], 0);
+ } else {
+ (void)snprintf(offset[0], sizeof(offset[0]), "%ld",
+ (long)sbuf.offset);
+ execl(post, post, id, type, offset[0], 0);
+ }
err(16, "can't exec `%s'", post);
}
----Next_Part(Mon_Sep__9_23:51:05_2002_989)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="sys1.diff"
Index: sys/kern/kern_lkm.c
===================================================================
RCS file: /cvsroot/cvs/NetBSD/syssrc/sys/kern/kern_lkm.c,v
retrieving revision 1.58
diff -u -r1.58 kern_lkm.c
--- sys/kern/kern_lkm.c 2002/09/06 13:23:47 1.58
+++ sys/kern/kern_lkm.c 2002/09/09 13:15:23
@@ -733,7 +733,7 @@
int cmd;
{
struct lkm_dev *args = lkmtp->private.lkm_dev;
- int error = 0;
+ int error;
switch(cmd) {
case LKM_E_LOAD:
@@ -744,6 +744,12 @@
error = devsw_attach(args->lkm_devname,
args->lkm_bdev, &args->lkm_bdevmaj,
args->lkm_cdev, &args->lkm_cdevmaj);
+ if (error != 0)
+ return (error);
+
+ args->lkm_offset = makemajor(args->lkm_bdevmaj,
+ args->lkm_cdevmaj);
+
break;
case LKM_E_UNLOAD:
@@ -756,7 +762,7 @@
break;
}
- return (error);
+ return (0);
}
#ifdef STREAMS
Index: sys/kern/subr_devsw.c
===================================================================
RCS file: /cvsroot/cvs/NetBSD/syssrc/sys/kern/subr_devsw.c,v
retrieving revision 1.2
diff -u -r1.2 subr_devsw.c
--- sys/kern/subr_devsw.c 2002/09/06 13:23:49 1.2
+++ sys/kern/subr_devsw.c 2002/09/09 01:32:43
@@ -172,9 +172,9 @@
}
if (i != max_devsw_convs)
continue;
- *devmajor = bmajor;
break;
}
+ *devmajor = bmajor;
}
if (*devmajor >= MAXDEVSW) {
#ifdef DEVSW_DEBUG
@@ -226,9 +226,9 @@
}
if (i != max_devsw_convs)
continue;
- *devmajor = cmajor;
break;
}
+ *devmajor = cmajor;
}
if (*devmajor >= MAXDEVSW) {
#ifdef DEVSW_DEBUG
Index: sys/sys/lkm.h
===================================================================
RCS file: /cvsroot/cvs/NetBSD/syssrc/sys/sys/lkm.h,v
retrieving revision 1.21
diff -u -r1.21 lkm.h
--- sys/sys/lkm.h 2002/09/06 13:24:09 1.21
+++ sys/sys/lkm.h 2002/09/09 12:55:14
@@ -392,4 +392,8 @@
int ver; /* OUT: lkm compile version */
};
+#define makemajor(b, c) ((((b) & 0xffff) << 16) | ((c) & 0xffff))
+#define block_major(v) (int)((int16_t)(((v) >> 16) & 0xffff))
+#define char_major(v) (int)((int16_t)((v) & 0xffff))
+
#endif /* !_SYS_LKM_H_ */
----Next_Part(Mon_Sep__9_23:51:05_2002_989)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="base2.diff"
Index: sbin/modload/modload.c
===================================================================
RCS file: /cvsroot/cvs/NetBSD/basesrc/sbin/modload/modload.c,v
retrieving revision 1.30
diff -u -r1.30 modload.c
--- sbin/modload/modload.c 2001/11/08 15:33:15 1.30
+++ sbin/modload/modload.c 2002/09/09 14:34:24
@@ -454,21 +454,38 @@
*/
if (post) {
struct lmc_stat sbuf;
- char id[16], type[16], offset[16];
+ char id[16], type[16];
sbuf.id = resrv.slot;
if (ioctl(devfd, LMSTAT, &sbuf) == -1)
err(15, "error fetching module stats for post-install");
(void)snprintf(id, sizeof(id), "%d", sbuf.id);
(void)snprintf(type, sizeof(type), "0x%x", sbuf.type);
- (void)snprintf(offset, sizeof(offset), "%ld",
- (long)sbuf.offset);
- /*
- * XXX
- * The modload docs say that drivers can install bdevsw &
- * cdevsw, but the interface only supports one at a time.
- */
- execl(post, post, id, type, offset, 0);
+ switch (sbuf.type) {
+ case LM_SYSCALL:
+ {
+ struct lmc_stat_syscall *sys = &sbuf.priv.u_syscall;
+ char arg[16];
+
+ (void)snprintf(arg, sizeof(arg), "%ld",
+ (long)sys->number);
+ execl(post, post, id, type, arg);
+ }
+ case LM_DEV:
+ {
+ struct lmc_stat_dev *dev = &sbuf.priv.u_dev;
+ char args[2][16];
+
+ (void)snprintf(args[0], sizeof(args[0]), "%d",
+ dev->cmajor);
+ (void)snprintf(args[1], sizeof(args[1]), "%d",
+ dev->bmajor);
+ execl(post, post, id, type, args[0], args[1], 0);
+ }
+ default:
+ execl(post, post, id, type, 0);
+ break;
+ }
err(16, "can't exec `%s'", post);
}
----Next_Part(Mon_Sep__9_23:51:05_2002_989)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="sys2.diff"
Index: sys/kern/kern_lkm.c
===================================================================
RCS file: /cvsroot/cvs/NetBSD/syssrc/sys/kern/kern_lkm.c,v
retrieving revision 1.58
diff -u -r1.58 kern_lkm.c
--- sys/kern/kern_lkm.c 2002/09/06 13:23:47 1.58
+++ sys/kern/kern_lkm.c 2002/09/09 14:10:32
@@ -546,7 +546,6 @@
* Copy out stat information for this module...
*/
statp->id = curp->id;
- statp->offset = curp->private.lkm_any->lkm_offset;
statp->type = curp->private.lkm_any->lkm_type;
statp->area = curp->area;
statp->size = curp->size / PAGESIZE;
@@ -556,6 +555,28 @@
statp->name,
MAXLKMNAME - 2,
(size_t *)0);
+
+ switch (statp->type) {
+ case LM_SYSCALL:
+ {
+ struct lkm_syscall *sys = curp->private.lkm_syscall;
+ struct lmc_stat_syscall *lmc_sys =
+ &statp->priv.u_syscall;
+ lmc_sys->number = sys->lkm_offset;
+ break;
+ }
+ case LM_DEV:
+ {
+ struct lkm_dev *dev = curp->private.lkm_dev;
+ struct lmc_stat_dev *lmc_dev = &statp->priv.u_dev;
+ lmc_dev->bmajor = dev->lkm_bdevmaj;
+ lmc_dev->cmajor = dev->lkm_cdevmaj;
+ break;
+ }
+ default:
+ /* do nothing */
+ break;
+ }
break;
Index: sys/kern/subr_devsw.c
===================================================================
RCS file: /cvsroot/cvs/NetBSD/syssrc/sys/kern/subr_devsw.c,v
retrieving revision 1.2
diff -u -r1.2 subr_devsw.c
--- sys/kern/subr_devsw.c 2002/09/06 13:23:49 1.2
+++ sys/kern/subr_devsw.c 2002/09/09 01:32:43
@@ -172,9 +172,9 @@
}
if (i != max_devsw_convs)
continue;
- *devmajor = bmajor;
break;
}
+ *devmajor = bmajor;
}
if (*devmajor >= MAXDEVSW) {
#ifdef DEVSW_DEBUG
@@ -226,9 +226,9 @@
}
if (i != max_devsw_convs)
continue;
- *devmajor = cmajor;
break;
}
+ *devmajor = cmajor;
}
if (*devmajor >= MAXDEVSW) {
#ifdef DEVSW_DEBUG
Index: sys/sys/lkm.h
===================================================================
RCS file: /cvsroot/cvs/NetBSD/syssrc/sys/sys/lkm.h,v
retrieving revision 1.21
diff -u -r1.21 lkm.h
--- sys/sys/lkm.h 2002/09/06 13:24:09 1.21
+++ sys/sys/lkm.h 2002/09/09 13:47:58
@@ -381,15 +381,28 @@
/*
* Get module information for a given id (or name if id == -1).
*/
+
+struct lmc_stat_syscall {
+ int number; /* system call number */
+};
+
+struct lmc_stat_dev {
+ int bmajor; /* block device major number */
+ int cmajor; /* character device major number */
+};
+
struct lmc_stat {
int id; /* IN: module ID to unload */
char name[MAXLKMNAME]; /* IN/OUT: name of module */
- u_long offset; /* OUT: target table offset */
MODTYPE type; /* OUT: type of module */
u_long area; /* OUT: kernel load addr */
u_long size; /* OUT: module size (pages) */
u_long private; /* OUT: module private data */
int ver; /* OUT: lkm compile version */
+ union {
+ struct lmc_stat_syscall u_syscall;
+ struct lmc_stat_dev u_dev;
+ } priv;
};
#endif /* !_SYS_LKM_H_ */
----Next_Part(Mon_Sep__9_23:51:05_2002_989)----