forget about device fd, we don't need it
[arla.git] / nnpfs / bsd / nnpfs_dev-common.c
blob4e46e00d313b998853eee72ec71889d7ee6f5e35
1 /*
2 * Copyright (c) 1995 - 2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
35 #include <nnpfs/nnpfs_locl.h>
36 #include <nnpfs/nnpfs_message.h>
37 #include <nnpfs/nnpfs_msg_locl.h>
38 #include <nnpfs/nnpfs_fs.h>
39 #include <nnpfs/nnpfs_dev.h>
40 #include <nnpfs/nnpfs_deb.h>
42 RCSID("$Id$");
44 struct nnpfs nnpfs_dev[NNNPFS];
46 /* helper struct for sending messages without sleeping */
47 struct async_link {
48 struct nnpfs_link this_link;
49 struct nnpfs_message_header msg;
53 * Only allow one open.
55 int
56 nnpfs_devopen_common(nnpfs_dev_t dev)
58 struct nnpfs *chan;
60 if (minor(dev) < 0 || minor(dev) >= NNNPFS)
61 return ENXIO;
63 chan = &nnpfs_dev[minor(dev)];
65 nnpfs_dev_lock(chan);
67 /* Only allow one reader/writer */
68 if (chan->status & (CHANNEL_OPENED | CHANNEL_CLOSING)) {
69 nnpfs_dev_unlock(chan);
70 NNPFSDEB(XDEBDEV, ("nnpfs_devopen: already open\n"));
71 return EBUSY;
74 chan->message_buffer = nnpfs_alloc(NNPFS_MAX_MSG_SIZE, M_NNPFS_MSG);
76 /* initalize the queues */
77 NNPFSDEB(XDEBDEV, ("nnpfs_devopen before queue init\n"));
78 NNPQUEUE_INIT(&chan->messageq);
79 NNPQUEUE_INIT(&chan->sleepq);
81 chan->proc = NULL;
82 chan->status |= CHANNEL_OPENED;
84 nnpfs_dev_unlock(chan);
86 return 0;
89 #if defined(__APPLE__)
90 #define nnpfs_vfs_busy(mp, flags, lock, proc) 0
91 #define nnpfs_vfs_unbusy(mp, proc)
92 #elif defined(HAVE_THREE_ARGUMENT_VFS_BUSY)
93 #define nnpfs_vfs_busy(mp, flags, lock, proc) vfs_busy((mp), (flags), (lock))
94 #define nnpfs_vfs_unbusy(mp, proc) vfs_unbusy((mp))
95 #elif defined(HAVE_FOUR_ARGUMENT_VFS_BUSY)
96 #define nnpfs_vfs_busy(mp, flags, lock, proc) vfs_busy((mp), (flags), (lock), (proc))
97 #define nnpfs_vfs_unbusy(mp, proc) vfs_unbusy((mp), (proc))
98 #else
99 #define nnpfs_vfs_busy(mp, flags, lock, proc) vfs_busy((mp), (flags))
100 #define nnpfs_vfs_unbusy(mp, proc) vfs_unbusy((mp))
101 #endif
104 * Wakeup all sleepers and cleanup.
107 nnpfs_devclose_common(nnpfs_dev_t dev, d_thread_t *proc)
109 struct nnpfs *chan = &nnpfs_dev[minor(dev)];
110 struct nnpfs_link *first;
112 nnpfs_dev_lock(chan);
114 /* Sanity check, paranoia? */
115 if (!(chan->status & CHANNEL_OPENED))
116 panic("nnpfs_devclose never opened?");
118 chan->status |= CHANNEL_CLOSING;
119 chan->status &= ~CHANNEL_OPENED;
121 /* No one is going to read those messages so empty queue! */
122 while (!NNPQUEUE_EMPTY(&chan->messageq)) {
123 NNPFSDEB(XDEBDEV, ("before outq(messageq)\n"));
125 first = NNPQUEUE_FIRST(&chan->messageq);
126 NNPQUEUE_REMOVE(first, &chan->messageq, qentry);
127 if (first->error_or_size != 0)
128 nnpfs_free(first, first->error_or_size, M_NNPFS_LINK);
130 NNPFSDEB(XDEBDEV, ("after outq(messageq)\n"));
133 /* Wakeup those waiting for replies that will never arrive. */
134 while (!NNPQUEUE_EMPTY(&chan->sleepq)) {
135 NNPFSDEB(XDEBDEV, ("before outq(sleepq)\n"));
136 first = NNPQUEUE_FIRST(&chan->sleepq);
137 NNPQUEUE_REMOVE(first, &chan->sleepq, qentry);
138 first->error_or_size = ENODEV;
139 wakeup((caddr_t) first);
140 NNPFSDEB(XDEBDEV, ("after outq(sleepq)\n"));
143 if (chan->status & CHANNEL_WAITING)
144 wakeup((caddr_t) chan);
146 if (chan->status & NNPFS_QUOTAWAIT)
147 wakeup((caddr_t)&chan->appendquota);
149 #ifdef __APPLE__ /* XXX should be nnpfs_dev_lock_cancel */
150 wakeup((caddr_t)&chan->lock);
151 #endif
153 if (chan->message_buffer) {
154 nnpfs_free(chan->message_buffer, NNPFS_MAX_MSG_SIZE, M_NNPFS_MSG);
155 chan->message_buffer = NULL;
159 * Free all nnpfs nodes.
162 if (chan->mp != NULL) {
163 if (nnpfs_vfs_busy(chan->mp, 0, NULL, proc)) {
164 NNPFSDEB(XDEBNODE, ("nnpfs_dev_close: vfs_busy() --> BUSY\n"));
165 nnpfs_dev_unlock(chan);
166 return EBUSY;
169 nnpfs_dev_unlock(chan);
170 nnpfs_free_all_nodes(chan, FORCECLOSE, 0);
171 nnpfs_dev_lock(chan);
173 nnpfs_vfs_unbusy(chan->mp, proc);
176 /* free all freed nodes */
177 while (!NNPQUEUE_EMPTY(&chan->freehead)) {
178 struct nnpfs_node *xn = NNPQUEUE_FIRST(&chan->freehead);
179 nnpfs_free_node(chan, xn);
182 #ifdef __APPLE__
183 if (chan->proc != NULL)
184 proc_rele(chan->proc);
185 #endif
187 chan->proc = NULL;
189 nnpfs_vfs_context_rele(chan->ctx);
190 memset(&chan->ctx, 0, sizeof(chan->ctx));
192 chan->status &= ~CHANNEL_CLOSING;
194 nnpfs_dev_unlock(chan);
196 return 0;
199 #ifdef NNPFS_DEBUG
201 * debugging glue for CURSIG
204 static long
205 nnpfs_cursig (d_thread_t *p)
207 #if defined(HAVE_FREEBSD_THREAD)
208 #ifndef CURSIG
209 return 0; /* XXX we would like to use sig_ffs, but that isn't
210 * exported */
211 #else
212 return CURSIG(p->td_proc);
213 #endif
214 #else
215 #if defined(__NetBSD__) && __NetBSD_Version__ >= 106130000
216 return 0; /* XXX CURSIG operates on a struct lwp */
217 #elif !defined(CURSIG)
218 return 0;
219 #else
220 return CURSIG(p);
221 #endif
222 #endif
224 #endif
227 * Move messages from kernel to user space.
231 nnpfs_devread(nnpfs_dev_t dev, struct uio * uiop, int ioflag)
233 struct nnpfs *chan = &nnpfs_dev[minor(dev)];
234 struct nnpfs_link *first;
235 int error = 0;
236 #ifdef NNPFS_DEBUG
237 char devname[64];
238 #endif
240 nnpfs_dev_lock(chan);
242 NNPFSDEB(XDEBDEV, ("nnpfs_devread dev = %s\n",
243 nnpfs_devtoname_r(dev, devname, sizeof(devname))));
245 if (chan->proc == NULL)
246 chan->proc = nnpfs_curproc();
248 again:
250 if (!NNPQUEUE_EMPTY(&chan->messageq)) {
251 while (!NNPQUEUE_EMPTY(&chan->messageq)) {
252 /* Remove message */
253 first = NNPQUEUE_FIRST(&chan->messageq);
254 NNPFSDEB(XDEBDEV, ("nnpfs_devread: first = %lx size = %u\n",
255 (unsigned long)first,
256 first->message->size));
258 if (first->message->size > nnpfs_uio_resid(uiop))
259 break;
261 error = uiomove((caddr_t) first->message, first->message->size,
262 uiop);
263 if (error)
264 break;
266 NNPQUEUE_REMOVE(first, &chan->messageq, qentry);
268 if (first->error_or_size != 0)
269 nnpfs_free(first, first->error_or_size, M_NNPFS_LINK);
271 } else {
272 int ret;
273 chan->status |= CHANNEL_WAITING;
275 ret = nnpfs_dev_msleep(chan, (caddr_t) chan,
276 (PZERO + 1) | PCATCH, "nnpfsread");
277 if (ret) {
278 NNPFSDEB(XDEBMSG,
279 ("caught signal nnpfs_devread\n"));
280 error = EINTR;
281 } else if ((chan->status & CHANNEL_WAITING) == 0) {
282 goto again;
283 } else
284 error = EIO;
287 nnpfs_dev_unlock(chan);
289 NNPFSDEB(XDEBDEV, ("nnpfs_devread done error = %d\n", error));
291 return error;
295 * Move messages from user space to kernel space,
296 * wakeup sleepers, insert new data in VFS.
299 nnpfs_devwrite(nnpfs_dev_t dev, struct uio *uiop, int ioflag)
301 struct nnpfs *chan = &nnpfs_dev[minor(dev)];
302 char *p;
303 int ret, error = 0;
304 u_int cnt;
305 struct nnpfs_message_header *msg_buf;
306 d_thread_t *pp;
307 #ifdef NNPFS_DEBUG
308 char devname[64];
309 #endif
311 nnpfs_dev_lock(chan);
313 NNPFSDEB(XDEBDEV, ("nnpfs_devwrite dev = %s\n",
314 nnpfs_devtoname_r (dev, devname, sizeof(devname))));
316 if (chan->proc == NULL)
317 chan->proc = nnpfs_curproc();
319 pp = chan->proc;
321 cnt = nnpfs_uio_resid(uiop);
322 error = uiomove((caddr_t) chan->message_buffer, NNPFS_MAX_MSG_SIZE, uiop);
323 if (error != 0) {
324 printf("nnpfs_devwrite: uiomove -> %d\n", error);
325 nnpfs_dev_unlock(chan);
326 return error;
329 cnt -= nnpfs_uio_resid(uiop);
332 * This thread handles the received message.
335 p = (char *)chan->message_buffer;
336 while (cnt > 0) {
337 msg_buf = (struct nnpfs_message_header *)p;
338 if (cnt < msg_buf->size) {
339 NNPFSDEB(XDEBDEV, ("nnpfs_devwrite badly formed message\n"));
340 error = EINVAL;
341 break;
343 ret = nnpfs_message_receive(chan,
344 msg_buf,
345 msg_buf->size,
346 pp);
347 if (ret)
348 error = ret;
350 p += msg_buf->size;
351 cnt -= msg_buf->size;
354 nnpfs_dev_unlock(chan);
356 NNPFSDEB(XDEBDEV, ("nnpfs_devwrite error = %d\n", error));
357 return error;
361 * Send a message to user space.
364 nnpfs_message_send(struct nnpfs *chan,
365 struct nnpfs_message_header *message, u_int size)
367 struct async_link *t;
369 NNPFSDEB(XDEBMSG, ("nnpfs_message_send opcode = %d\n", message->opcode));
371 if (!(chan->status & CHANNEL_OPENED)) /* No receiver? */
372 return ENODEV;
374 /* Prepare message and copy it later */
375 message->size = size;
376 message->sequence_num = chan->nsequence++;
378 t = nnpfs_alloc(sizeof(t->this_link) + size, M_NNPFS_LINK);
379 t->this_link.error_or_size = sizeof(t->this_link) + size;
380 bcopy(message, &t->msg, size);
382 t->this_link.message = &t->msg;
383 NNPQUEUE_INSERT_TAIL(&chan->messageq, &t->this_link, qentry);
384 if (chan->status & CHANNEL_WAITING) {
385 chan->status &= ~CHANNEL_WAITING;
386 wakeup((caddr_t) chan);
388 nnpfs_select_wakeup(chan);
390 return 0;
393 #if defined(SWEXIT)
394 #define NNPFS_P_EXIT SWEXIT
395 #elif defined(P_WEXIT)
396 #define NNPFS_P_EXIT P_WEXIT
397 #elif defined(__APPLE__)
398 /* don't need it */
399 #else
400 #error what is your exit named ?
401 #endif
403 #if defined(HAVE_STRUCT_PROC_P_SIGMASK) || defined(HAVE_STRUCT_PROC_P_SIGCTX) || defined(HAVE_STRUCT_PROC_P_SIGWAITMASK) || defined(HAVE_FREEBSD_THREAD)
404 static void
405 nnpfs_block_sigset (sigset_t *sigset)
408 #if defined(__sigaddset)
409 #define nnpfs_sig_block(ss,signo) __sigaddset((ss), (signo))
410 #elif defined(SIGADDSET)
411 #define nnpfs_sig_block(ss,signo) SIGADDSET(*(ss), (signo))
412 #else
413 #define nnpfs_sig_block(ss,signo) *(ss) |= sigmask(signo)
414 #endif
416 nnpfs_sig_block(sigset, SIGIO);
417 nnpfs_sig_block(sigset, SIGALRM);
418 nnpfs_sig_block(sigset, SIGVTALRM);
419 nnpfs_sig_block(sigset, SIGCHLD);
420 #ifdef SIGINFO
421 nnpfs_sig_block(sigset, SIGINFO);
422 #endif
423 #undef nnpfs_sig_block
425 #endif
428 * Send a message to user space and wait for reply.
431 static int
432 nnpfs_message_rpc_int(struct nnpfs *chan,
433 struct nnpfs_message_header *message, u_int size,
434 d_thread_t *proc, int async)
436 int ret;
437 struct nnpfs_link *this_message;
438 struct nnpfs_link *this_process;
439 struct nnpfs_message_header *msg;
440 #if defined(HAVE_STRUCT_PROC_P_SIGMASK) || defined(HAVE_STRUCT_PROC_P_SIGCTX) || defined(HAVE_FREEBSD_THREAD)
441 sigset_t oldsigmask;
442 #endif
443 int catch;
445 NNPFSDEB(XDEBMSG, ("nnpfs_message_rpc opcode = %d\n", message->opcode));
447 if (!(chan->status & CHANNEL_OPENED)) /* No receiver? */
448 return ENODEV;
450 if (size < sizeof(struct nnpfs_message_wakeup)) {
451 printf("NNPFS PANIC Error: Message to small to receive wakeup, opcode = %d\n", message->opcode);
452 return ENOMEM;
455 if (!async) {
456 if (proc == NULL)
457 proc = nnpfs_curproc();
459 #ifdef HAVE_FREEBSD_THREAD
460 if (chan->proc != NULL && chan->proc->td_proc != NULL &&
461 proc->td_proc != NULL &&
462 proc->td_proc->p_pid == chan->proc->td_proc->p_pid) {
463 printf("nnpfs_message_rpc: deadlock avoided "
464 "pid = %u == %u\n", proc->td_proc->p_pid, chan->proc->td_proc->p_pid);
465 #if 0
466 psignal (proc, SIGABRT);
467 #endif
468 return EDEADLK;
471 #else /* !HAVE_FREEBSD_THREAD */
473 if (chan->proc != NULL && proc == chan->proc) {
474 printf("nnpfs_message_rpc: deadlock avoided\n");
475 #if 0
476 psignal (proc, SIGABRT);
477 #endif
478 return EDEADLK;
480 #endif /* !HAVE_FREEBSD_THREAD */
483 this_message = nnpfs_alloc(sizeof(*this_message), M_NNPFS_LINK);
485 if (async) {
486 struct async_link *t;
487 t = nnpfs_alloc(sizeof(t->this_link) + size, M_NNPFS_LINK);
489 this_process = &t->this_link;
490 msg = &t->msg;
491 this_process->error_or_size = sizeof(t->this_link) + size;
492 this_message->error_or_size = sizeof(*this_message);
493 } else {
494 this_process = nnpfs_alloc(sizeof(struct nnpfs_link), M_NNPFS_LINK);
495 msg = nnpfs_alloc(size, M_NNPFS_MSG);
496 this_process->error_or_size = 0;
497 this_message->error_or_size = 0;
500 bcopy(message, msg, size);
501 msg->size = size;
502 msg->sequence_num = chan->nsequence++;
504 this_message->message = msg;
505 this_process->message = msg;
506 NNPQUEUE_INSERT_TAIL(&chan->messageq, this_message, qentry);
507 NNPQUEUE_INSERT_TAIL(&chan->sleepq, this_process, qentry);
510 * Wakeup daemon that might be blocking select()/poll().
513 nnpfs_select_wakeup(chan);
516 * Wakeup blocking read in nnpfs_devread
519 if (chan->status & CHANNEL_WAITING) {
520 chan->status &= ~CHANNEL_WAITING;
521 wakeup((caddr_t) chan);
524 if (async) {
525 NNPFSDEB(XDEBMSG, ("nnpfs_message_rpc_async done\n"));
526 return 0;
530 * Remove signals from the sigmask so no IO will wake us up from
531 * tsleep(). We don't want to wake up from since program (emacs,
532 * bash & co can't handle them.
535 #ifdef __DragonFly__
536 if (proc->td_proc != NULL) {
537 oldsigmask = proc->td_proc->p_sigmask;
538 nnpfs_block_sigset (&proc->td_proc->p_sigmask);
540 #elif defined(HAVE_FREEBSD_THREAD)
541 /* FreeBSD 5.1 */
542 oldsigmask = proc->td_sigmask;
543 nnpfs_block_sigset (&proc->td_sigmask);
544 #elif HAVE_STRUCT_PROC_P_SIGMASK
545 /* NetBSD 1.5, Darwin 1.3, FreeBSD 4.3, 5.0, OpenBSD 2.8 */
546 oldsigmask = proc->p_sigmask;
547 nnpfs_block_sigset (&proc->p_sigmask);
548 #elif defined(HAVE_STRUCT_PROC_P_SIGCTX)
549 #if __NetBSD_Version__ >= 399001400
550 /* NetBSD 3.99.14 */
551 oldsigmask = proc->l_proc->p_sigctx.ps_sigmask;
552 nnpfs_block_sigset (&proc->l_proc->p_sigctx.ps_sigmask);
553 #else
554 /* NetBSD 1.6 */
555 oldsigmask = proc->p_sigctx.ps_sigmask;
556 nnpfs_block_sigset (&proc->p_sigctx.ps_sigmask);
557 #endif
558 #endif
561 * if we are exiting we should not try to catch signals, since
562 * there might not be enough context left in the process to handle
563 * signal delivery, and besides, most BSD-variants ignore all
564 * signals while closing anyway.
567 catch = 0;
568 #ifdef __APPLE__
569 /* XXX */
570 if (0)
571 #elif defined(HAVE_FREEBSD_THREAD)
572 if (proc->td_proc && !(proc->td_proc->p_flag & NNPFS_P_EXIT))
573 #elif __NetBSD_Version__ >= 399001400 /* NetBSD 3.99.14 */
574 if (!(proc->l_proc->p_flag & NNPFS_P_EXIT))
575 #else
576 if (!(proc->p_flag & NNPFS_P_EXIT))
577 #endif
578 catch |= PCATCH;
581 * We have to check if we have a receiver here too because the
582 * daemon could have terminated before we sleep. This seems to
583 * happen sometimes when rebooting. */
585 if (!(chan->status & CHANNEL_OPENED)) {
586 NNPFSDEB(XDEBMSG, ("nnpfs_message_rpc: channel went away\n"));
587 this_process->error_or_size = EINTR;
588 } else {
589 ret = nnpfs_dev_msleep(chan, (caddr_t)this_process,
590 (PZERO + 1) | catch, "nnpfs");
591 if (ret != 0) {
592 NNPFSDEB(XDEBMSG, ("caught signal (%d): %ld\n", ret, nnpfs_cursig(proc)));
593 this_process->error_or_size = EINTR;
597 #ifdef __DragonFly__
598 if (proc->td_proc != NULL)
599 proc->td_proc->p_sigmask = oldsigmask;
600 #elif defined(HAVE_FREEBSD_THREAD)
601 proc->td_sigmask = oldsigmask;
602 #elif HAVE_STRUCT_PROC_P_SIGMASK
603 proc->p_sigmask = oldsigmask;
604 #elif defined(HAVE_STRUCT_PROC_P_SIGCTX)
605 #if defined(__NetBSD__) && __NetBSD_Version__ >= 399001400 /* 3.99.14 */
606 proc->l_proc->p_sigctx.ps_sigmask = oldsigmask;
607 #else
608 proc->p_sigctx.ps_sigmask = oldsigmask;
609 #endif
610 #endif
613 * Caught signal, got reply message or device was closed.
614 * Need to clean up both messageq and sleepq.
616 if (NNPQUEUE_ON(&chan->messageq, this_message, qentry))
617 NNPQUEUE_REMOVE(this_message, &chan->messageq, qentry);
619 if (NNPQUEUE_ON(&chan->sleepq, this_process, qentry))
620 NNPQUEUE_REMOVE(this_process, &chan->sleepq, qentry);
622 ret = this_process->error_or_size;
624 NNPFSDEB(XDEBMSG, ("nnpfs_message_rpc this_process->error_or_size = %d\n",
625 this_process->error_or_size));
626 NNPFSDEB(XDEBMSG, ("nnpfs_message_rpc error = %d\n",
627 ((struct nnpfs_message_wakeup *) (this_process->message))->error));
629 bcopy(msg, message, size);
631 nnpfs_free(this_message, sizeof(*this_message), M_NNPFS_LINK);
632 nnpfs_free(this_process, sizeof(*this_process), M_NNPFS_LINK);
633 nnpfs_free(msg, size, M_NNPFS_MSG);
635 return ret;
639 nnpfs_message_rpc(struct nnpfs *nnpfsp,
640 struct nnpfs_message_header *message, u_int size,
641 d_thread_t *proc)
643 return nnpfs_message_rpc_int(nnpfsp, message, size, proc, FALSE);
647 nnpfs_message_rpc_async(struct nnpfs *nnpfsp,
648 struct nnpfs_message_header *message, u_int size,
649 d_thread_t *proc)
651 return nnpfs_message_rpc_int(nnpfsp, message, size, proc, TRUE);
655 * For each message type there is a message handler
656 * that implements its action, nnpfs_message_receive
657 * invokes the correct function.
660 nnpfs_message_receive(struct nnpfs *nnpfsp,
661 struct nnpfs_message_header *message,
662 u_int size,
663 d_thread_t *p)
665 NNPFSDEB(XDEBMSG, ("nnpfs_message_receive opcode = %d\n", message->opcode));
667 /* Dispatch and coerce message type */
668 switch (message->opcode) {
669 case NNPFS_MSG_WAKEUP:
670 return nnpfs_message_wakeup(nnpfsp,
671 (struct nnpfs_message_wakeup *) message,
672 message->size,
674 case NNPFS_MSG_INSTALLROOT:
675 return nnpfs_message_installroot(nnpfsp,
676 (struct nnpfs_message_installroot *) message,
677 message->size,
679 case NNPFS_MSG_INSTALLNODE:
680 return nnpfs_message_installnode(nnpfsp,
681 (struct nnpfs_message_installnode *) message,
682 message->size,
684 case NNPFS_MSG_INSTALLATTR:
685 return nnpfs_message_installattr(nnpfsp,
686 (struct nnpfs_message_installattr *) message,
687 message->size,
689 case NNPFS_MSG_INSTALLDATA:
690 return nnpfs_message_installdata(nnpfsp,
691 (struct nnpfs_message_installdata *) message,
692 message->size,
694 case NNPFS_MSG_INVALIDNODE:
695 return nnpfs_message_invalidnode(nnpfsp,
696 (struct nnpfs_message_invalidnode *) message,
697 message->size,
699 case NNPFS_MSG_UPDATEFID:
700 return nnpfs_message_updatefid(nnpfsp,
701 (struct nnpfs_message_updatefid *)message,
702 message->size,
704 case NNPFS_MSG_GC:
705 return nnpfs_message_gc(nnpfsp,
706 (struct nnpfs_message_gc *)message,
707 message->size,
709 case NNPFS_MSG_DELETE_NODE:
710 return nnpfs_message_delete_node(nnpfsp,
711 (struct nnpfs_message_delete_node *)message,
712 message->size,
714 case NNPFS_MSG_INSTALLQUOTA:
715 return nnpfs_message_installquota(nnpfsp,
716 (struct nnpfs_message_installquota *)message,
717 message->size,
720 case NNPFS_MSG_VERSION:
721 return nnpfs_message_version(nnpfsp,
722 (struct nnpfs_message_version *)message,
723 message->size,
725 default:
726 printf("NNPFS PANIC Warning nnpfs_dev: Unknown message opcode == %d\n",
727 message->opcode);
728 return EINVAL;
733 * Transfer return value from async rpc to the affected node.
734 * This should only happen for putdata for now.
737 static void
738 async_return(struct nnpfs *chan,
739 struct nnpfs_message_header *req_header,
740 struct nnpfs_message_wakeup *reply)
742 struct nnpfs_node *node;
743 struct nnpfs_message_putdata *request;
744 int error;
746 NNPFSDEB(XDEBDEV, ("nnpfs async_return\n"));
748 nnpfs_assert(req_header->opcode == NNPFS_MSG_PUTDATA); /* for now */
750 #if 0
751 /* XXX optimization, disable for testing */
752 if (!reply->error)
753 return;
754 #endif
756 request = (struct nnpfs_message_putdata *)req_header;
757 error = nnpfs_node_find(chan, &request->handle, &node);
758 if (error) {
759 if (error == ENOENT)
760 NNPFSDEB(XDEBMSG, ("nnpfs async_return: node not found\n"));
761 else if (error == EISDIR)
762 NNPFSDEB(XDEBMSG, ("nnpfs async_return: node deleted\n"));
763 return;
766 if (!node->async_error)
767 node->async_error = reply->error;
771 nnpfs_message_wakeup(struct nnpfs *chan,
772 struct nnpfs_message_wakeup *message,
773 u_int size,
774 d_thread_t *p)
776 struct nnpfs_link *t;
778 NNPFSDEB(XDEBMSG, ("nnpfs_message_wakeup error: %d\n", message->error));
780 NNPQUEUE_FOREACH(t, &chan->sleepq, qentry) {
781 if (t->message->sequence_num == message->sleepers_sequence_num) {
782 int linksize = t->error_or_size;
783 if (linksize) {
784 /* async rpc */
785 async_return(chan, t->message, message);
786 NNPQUEUE_REMOVE(t, &chan->sleepq, qentry);
787 nnpfs_free(t, linksize, M_NNPFS_LINK);
788 break;
791 if (t->message->size < size) {
792 printf("NNPFS PANIC Error: Could not wakeup requestor with opcode = %d properly, to small receive buffer.\n", t->message->opcode);
793 t->error_or_size = ENOMEM;
794 } else {
795 bcopy(message, t->message, size);
798 wakeup((caddr_t) t);
799 break;
803 return 0;
810 nnpfs_uprintf_device(void)
812 #if 0
813 int i;
815 for (i = 0; i < NNNPFS; i++) {
816 uprintf("nnpfs_dev[%d] = {\n", i);
817 uprintf("messageq.first = %lx ", NNPQUEUE_FIRST(&nnpfs_dev[i].messageq));
818 uprintf("sleepq.first = %lx ", NNPQUEUE_FIRST(&nnpfs_dev[i].sleepq));
819 uprintf("nsequence = %d status = %d\n",
820 nnpfs_dev[i].nsequence,
821 nnpfs_dev[i].status);
822 uprintf("}\n");
824 #endif
825 return 0;