Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 27 Jul 2013 12:35:40 -0400
From:      ret val <retval42@gmail.com>
To:        Konstantin Belousov <kostikbel@gmail.com>
Cc:        freebsd-drivers@freebsd.org
Subject:   Re: mysterious locking issue
Message-ID:  <CAHORHLmJnz3BW1411rmb0ojr3vAFAL3Riq=jbZRexbn%2B9x0r%2Bg@mail.gmail.com>
In-Reply-To: <20130727061201.GU5991@kib.kiev.ua>
References:  <CAHORHL=yF3V2--HxuahNDQjYRwThKZY0_gUXk0SsZA8gu8FDAQ@mail.gmail.com> <20130727061201.GU5991@kib.kiev.ua>

next in thread | previous in thread | raw e-mail | index | archive | help
Alright, this is making much more sense now. Thank you.

Would it be possible to create a new thread and sleep until the kernel is
fully initialized? Is there some event I could possible wait for? While my
approach now seems wrong, It seems like this should be doable.


On Sat, Jul 27, 2013 at 2:12 AM, Konstantin Belousov <kostikbel@gmail.com>wrote:

> On Sat, Jul 27, 2013 at 12:46:09AM -0400, ret val wrote:
> > I'm working on porting a driver form Linux that uses the usermode helper
> > API to call a user land program from the driver. Yes, I know this is
> ugly.
> > Yes, I'm sure sure there would of been many better other ways to go about
> > this... For right now I'm just doing a straight port.
> Kernel startup is single-threaded and owns the Giant.  You are trying
> to call kern_execve() from the startup thread, which is the immediate
> cause of your problem.
>
> If you think about this some more, you would see that this cannot work
> when module is initialized at the boot. Because kernel is not fully
> initialized yet, the scheduler and usermode does not work, and there
> is no filesystem mounted from which to execute the image. Much worse
> is that you are trying to change the executing image of the usermode
> program for a situation where there is no usermode and the process which
> is executing is the kernel startup.
>
> FWIW, your code also does not quite work for the kldload case as well.
> You are execing in the context of the kldload, not allowing the normal
> kldload operation to finish.
>
> >
> > Anyway, I working on my own routine for this but unfortunately I get a
> > kernel panic on boot when my module is loaded. Oddly enough it works fine
> > if I load it by hand after boot. I get the following: panic: mutex Giant
> > owned at /usr/src/sys/kern/kern_thread.c:616
> >
> > The backtrace looks like:
> > panic
> > _mtx_assert
> > thread_single
> > kern_execve
> > event_handler
> >
> > Ive tried switching to SI_SUB_EXEC without any luck. Does anyone know how
> > to go about fixing this? I cant seem to wrap my head around this.
> This is not fixable.
>
> >
> > Incase I cant attach my code, here it is:
> > #include <sys/param.h>
> > #include <sys/module.h>
> > #include <sys/kernel.h>
> > #include <sys/systm.h>
> > #include <sys/syscallsubr.h>
> > #include <sys/imgact.h>
> > #include <vm/vm_extern.h>
> > #include <sys/kthread.h>
> > #include <sys/proc.h>
> >
> > int DEBUG=1;
> >
> > static int make_args(struct image_args *args, char *fname, char **argv,
> > char **envv) {
> > int i;
> >         size_t length;
> >
> > memset(args, 0, sizeof(struct image_args));
> > if(exec_alloc_args(args) != 0) {
> > if(DEBUG) {
> > printf("exec_alloc_args() failed\n");
> > uprintf("exec_alloc_args() failed\n");
> > }
> >  return ENOMEM;
> > }
> >  // fname
> > args->fname = args->buf;
> > length = 1 + strlen(fname);
> > memcpy(args->fname, fname, length);
> >  // args
> > args->begin_argv = args->buf + 1 + strlen(fname);
> >         args->endp = args->begin_argv;
> >
> > for(i = 0; argv[i] != NULL; ++i) {
> > length = 1 + strlen(argv[i]);
> > memcpy(args->endp, argv[i], length);
> >  args->stringspace -= length;
> >                 args->endp += length;
> >                 (args->argc)++;
> > }
> >  // envv
> > args->begin_envv = args->endp;
> >         args->endp = args->begin_envv;
> > for(i = 0; envv[i] != NULL; ++i) {
> > length = 1 + strlen(envv[i]);
> > memcpy(args->endp, envv[i], length);
> >  args->stringspace -= length;
> >                 args->endp += length;
> >                 (args->envc)++;
> > }
> >  return 0;
> > }
> >
> > static int runapp_init(void) {
> > int error;
> > char *argv[] = { "/usr/bin/logger", "it works", NULL };
> > char *envv[] = { NULL };
> > struct image_args args;
> >  error = make_args(&args, argv[0], argv, envv);
> > if(error != 0) {
> > return error;
> > }
> >  error = kern_execve(curthread, &args, NULL);
> > if(error != 0) {
> > if(DEBUG) {
> > printf("kern_execve() failed\n");
> > uprintf("kern_execve() failed\n");
> > }
> >  return error;
> > }
> >  return 0;
> > }
> >
> > static int event_handler(struct module *module, int event, void *arg) {
> > switch(event) {
> > case MOD_LOAD:
> > printf("Hello, World! I'm loaded!\n");
> > uprintf("Hello, World! I'm loaded!\n");
> >     return runapp_init();
> >   case MOD_UNLOAD:
> >   case MOD_QUIESCE:
> >     printf("Bye Bye Cruel World!\n");
> >     printf("Bye Bye Cruel World!\n");
> >      return 0;
> > }
> >
> > return EOPNOTSUPP;
> > }
> >
> > static moduledata_t runapp_conf = {
> > "runapp",     /* module name */
> > event_handler,  /* event handler */
> > NULL            /* extra data */
> > };
> >
> > DECLARE_MODULE(runapp, runapp_conf, SI_SUB_DRIVERS, SI_ORDER_ANY);
>
> > _______________________________________________
> > freebsd-drivers@freebsd.org mailing list
> > http://lists.freebsd.org/mailman/listinfo/freebsd-drivers
> > To unsubscribe, send any mail to "
> freebsd-drivers-unsubscribe@freebsd.org"
>
>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAHORHLmJnz3BW1411rmb0ojr3vAFAL3Riq=jbZRexbn%2B9x0r%2Bg>