Driver development question
John Baldwin
jhb at freebsd.org
Wed Jul 29 19:51:15 UTC 2009
On Wednesday 29 July 2009 2:51:06 pm Chris Harrer wrote:
> >The problem is that kernel threads do not have a valid file descriptor
> table,
> >hence fd_cdir is NULL. You could work around this if you create a
> dedicated
> >kproc and set fd_cdir to rootvnode (but vref() rootvnode when you do this).
>
> >You should also set fd_rdir and fd_jdir to rootvnode as well (also doing
> >appropriate vref() of rootvnode for each reference). Something like this:
> >
> > struct filedesc *fdp;
> >
> > fdp = curthread->td_proc->p_fd;
> > FILEDESC_XLOCK(fdp);
> > fd->fd_rdir = rootvnode;
> > vref(rootvnode);
> > fd->fd_jdir = rootvnode;
> > vref(rootvnode);
> > fd->fd_cdir = rootvnode;
> > vref(rootvnode);
> > FILEDESC_XUNLOCK(fdp);
> >
> >You should not do this from a callout routine or interrupt handler however.
>
> >You could do this via a TASK to a private taskqueue with a dedicated kernel
>
> >process however. (i.e. queue a task that does the above during after
> >creating the taskqueue and then queue a task to create the file later).
> >
> >--
> >John Baldwin
>
> Hi John,
>
> I tried this and rootvnode = 0x0, so I am still getting a SIGSEGV. I create
> a thread in my "attach" routine via:
>
> status = kproc_create(sxg_dump_thread, adapter, &adapter->dumpproc,
> RFNOWAIT , 0, "sxgdump");
> if (status) {
> SXG_DBG_MSG(adapter->dev, "%s[%p], Cannot create dump
> thread, status: %d\n",
> __func__, adapter, status);
> return (status);
> }
>
> Then my thread does:
>
> static void
> sxg_dump_thread(void * arg)
> {
> adapter_t *adapter = (adapter_t *)arg;
> struct filedesc *fdp;
> ulong32 index = 0;
>
> // Set up some file descriptor stuff so we can
> // actually open/create a dump file. Kernel
> // threads, by design, do not have a valid
> // file descriptor table. So, we're gonna
> // make this thread point to one!
> fdp = curthread->td_proc->p_fd;
> FILEDESC_XLOCK(fdp);
> fdp->fd_rdir = rootvnode;
> vref(rootvnode); <----- SIGSEGV on this line, rootvnode = 0x0
> fdp->fd_jdir = rootvnode;
> vref(rootvnode);
> fdp->fd_cdir = rootvnode;
> vref(rootvnode);
> FILEDESC_XUNLOCK(fdp);
> for (;;){
> ...
>
> Sorry if I'm doing something obviously wrong, I'm trying to come up to speed
> as quickly as I can.
Ah, this could happen if you do this during boot. You can work around that by
using an EVENTHANDLER() to hook into the 'mountroot' event and not start your
kproc until then. To support loading your driver as a module post-boot, you
can instead just start the kproc directly if rootvnode != NULL instead of
hooking into 'mountroot'.
--
John Baldwin
More information about the freebsd-drivers
mailing list