2 * Copyright (c) 1995 - 2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
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>
44 struct nnpfs nnpfs_dev
[NNNPFS
];
46 /* helper struct for sending messages without sleeping */
48 struct nnpfs_link this_link
;
49 struct nnpfs_message_header msg
;
53 * Only allow one open.
56 nnpfs_devopen_common(nnpfs_dev_t dev
)
60 if (minor(dev
) < 0 || minor(dev
) >= NNNPFS
)
63 chan
= &nnpfs_dev
[minor(dev
)];
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"));
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
);
82 chan
->status
|= CHANNEL_OPENED
;
84 nnpfs_dev_unlock(chan
);
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))
99 #define nnpfs_vfs_busy(mp, flags, lock, proc) vfs_busy((mp), (flags))
100 #define nnpfs_vfs_unbusy(mp, proc) vfs_unbusy((mp))
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
);
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
);
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
);
183 if (chan
->proc
!= NULL
)
184 proc_rele(chan
->proc
);
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
);
201 * debugging glue for CURSIG
205 nnpfs_cursig (d_thread_t
*p
)
207 #if defined(HAVE_FREEBSD_THREAD)
209 return 0; /* XXX we would like to use sig_ffs, but that isn't
212 return CURSIG(p
->td_proc
);
215 #if defined(__NetBSD__) && __NetBSD_Version__ >= 106130000
216 return 0; /* XXX CURSIG operates on a struct lwp */
217 #elif !defined(CURSIG)
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
;
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();
250 if (!NNPQUEUE_EMPTY(&chan
->messageq
)) {
251 while (!NNPQUEUE_EMPTY(&chan
->messageq
)) {
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
))
261 error
= uiomove((caddr_t
) first
->message
, first
->message
->size
,
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
);
273 chan
->status
|= CHANNEL_WAITING
;
275 ret
= nnpfs_dev_msleep(chan
, (caddr_t
) chan
,
276 (PZERO
+ 1) | PCATCH
, "nnpfsread");
279 ("caught signal nnpfs_devread\n"));
281 } else if ((chan
->status
& CHANNEL_WAITING
) == 0) {
287 nnpfs_dev_unlock(chan
);
289 NNPFSDEB(XDEBDEV
, ("nnpfs_devread done error = %d\n", 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
)];
305 struct nnpfs_message_header
*msg_buf
;
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();
321 cnt
= nnpfs_uio_resid(uiop
);
322 error
= uiomove((caddr_t
) chan
->message_buffer
, NNPFS_MAX_MSG_SIZE
, uiop
);
324 printf("nnpfs_devwrite: uiomove -> %d\n", error
);
325 nnpfs_dev_unlock(chan
);
329 cnt
-= nnpfs_uio_resid(uiop
);
332 * This thread handles the received message.
335 p
= (char *)chan
->message_buffer
;
337 msg_buf
= (struct nnpfs_message_header
*)p
;
338 if (cnt
< msg_buf
->size
) {
339 NNPFSDEB(XDEBDEV
, ("nnpfs_devwrite badly formed message\n"));
343 ret
= nnpfs_message_receive(chan
,
351 cnt
-= msg_buf
->size
;
354 nnpfs_dev_unlock(chan
);
356 NNPFSDEB(XDEBDEV
, ("nnpfs_devwrite error = %d\n", 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? */
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
);
394 #define NNPFS_P_EXIT SWEXIT
395 #elif defined(P_WEXIT)
396 #define NNPFS_P_EXIT P_WEXIT
397 #elif defined(__APPLE__)
400 #error what is your exit named ?
403 #if defined(HAVE_STRUCT_PROC_P_SIGMASK) || defined(HAVE_STRUCT_PROC_P_SIGCTX) || defined(HAVE_STRUCT_PROC_P_SIGWAITMASK) || defined(HAVE_FREEBSD_THREAD)
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))
413 #define nnpfs_sig_block(ss,signo) *(ss) |= sigmask(signo)
416 nnpfs_sig_block(sigset
, SIGIO
);
417 nnpfs_sig_block(sigset
, SIGALRM
);
418 nnpfs_sig_block(sigset
, SIGVTALRM
);
419 nnpfs_sig_block(sigset
, SIGCHLD
);
421 nnpfs_sig_block(sigset
, SIGINFO
);
423 #undef nnpfs_sig_block
428 * Send a message to user space and wait for reply.
432 nnpfs_message_rpc_int(struct nnpfs
*chan
,
433 struct nnpfs_message_header
*message
, u_int size
,
434 d_thread_t
*proc
, int async
)
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)
445 NNPFSDEB(XDEBMSG
, ("nnpfs_message_rpc opcode = %d\n", message
->opcode
));
447 if (!(chan
->status
& CHANNEL_OPENED
)) /* No receiver? */
450 if (size
< sizeof(struct nnpfs_message_wakeup
)) {
451 printf("NNPFS PANIC Error: Message to small to receive wakeup, opcode = %d\n", message
->opcode
);
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
);
466 psignal (proc
, SIGABRT
);
471 #else /* !HAVE_FREEBSD_THREAD */
473 if (chan
->proc
!= NULL
&& proc
== chan
->proc
) {
474 printf("nnpfs_message_rpc: deadlock avoided\n");
476 psignal (proc
, SIGABRT
);
480 #endif /* !HAVE_FREEBSD_THREAD */
483 this_message
= nnpfs_alloc(sizeof(*this_message
), M_NNPFS_LINK
);
486 struct async_link
*t
;
487 t
= nnpfs_alloc(sizeof(t
->this_link
) + size
, M_NNPFS_LINK
);
489 this_process
= &t
->this_link
;
491 this_process
->error_or_size
= sizeof(t
->this_link
) + size
;
492 this_message
->error_or_size
= sizeof(*this_message
);
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
);
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
);
525 NNPFSDEB(XDEBMSG
, ("nnpfs_message_rpc_async done\n"));
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.
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)
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
551 oldsigmask
= proc
->l_proc
->p_sigctx
.ps_sigmask
;
552 nnpfs_block_sigset (&proc
->l_proc
->p_sigctx
.ps_sigmask
);
555 oldsigmask
= proc
->p_sigctx
.ps_sigmask
;
556 nnpfs_block_sigset (&proc
->p_sigctx
.ps_sigmask
);
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.
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
))
576 if (!(proc
->p_flag
& NNPFS_P_EXIT
))
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
;
589 ret
= nnpfs_dev_msleep(chan
, (caddr_t
)this_process
,
590 (PZERO
+ 1) | catch, "nnpfs");
592 NNPFSDEB(XDEBMSG
, ("caught signal (%d): %ld\n", ret
, nnpfs_cursig(proc
)));
593 this_process
->error_or_size
= EINTR
;
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
;
608 proc
->p_sigctx
.ps_sigmask
= oldsigmask
;
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
);
639 nnpfs_message_rpc(struct nnpfs
*nnpfsp
,
640 struct nnpfs_message_header
*message
, u_int size
,
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
,
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
,
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
,
674 case NNPFS_MSG_INSTALLROOT
:
675 return nnpfs_message_installroot(nnpfsp
,
676 (struct nnpfs_message_installroot
*) message
,
679 case NNPFS_MSG_INSTALLNODE
:
680 return nnpfs_message_installnode(nnpfsp
,
681 (struct nnpfs_message_installnode
*) message
,
684 case NNPFS_MSG_INSTALLATTR
:
685 return nnpfs_message_installattr(nnpfsp
,
686 (struct nnpfs_message_installattr
*) message
,
689 case NNPFS_MSG_INSTALLDATA
:
690 return nnpfs_message_installdata(nnpfsp
,
691 (struct nnpfs_message_installdata
*) message
,
694 case NNPFS_MSG_INVALIDNODE
:
695 return nnpfs_message_invalidnode(nnpfsp
,
696 (struct nnpfs_message_invalidnode
*) message
,
699 case NNPFS_MSG_UPDATEFID
:
700 return nnpfs_message_updatefid(nnpfsp
,
701 (struct nnpfs_message_updatefid
*)message
,
705 return nnpfs_message_gc(nnpfsp
,
706 (struct nnpfs_message_gc
*)message
,
709 case NNPFS_MSG_DELETE_NODE
:
710 return nnpfs_message_delete_node(nnpfsp
,
711 (struct nnpfs_message_delete_node
*)message
,
714 case NNPFS_MSG_INSTALLQUOTA
:
715 return nnpfs_message_installquota(nnpfsp
,
716 (struct nnpfs_message_installquota
*)message
,
720 case NNPFS_MSG_VERSION
:
721 return nnpfs_message_version(nnpfsp
,
722 (struct nnpfs_message_version
*)message
,
726 printf("NNPFS PANIC Warning nnpfs_dev: Unknown message opcode == %d\n",
733 * Transfer return value from async rpc to the affected node.
734 * This should only happen for putdata for now.
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
;
746 NNPFSDEB(XDEBDEV
, ("nnpfs async_return\n"));
748 nnpfs_assert(req_header
->opcode
== NNPFS_MSG_PUTDATA
); /* for now */
751 /* XXX optimization, disable for testing */
756 request
= (struct nnpfs_message_putdata
*)req_header
;
757 error
= nnpfs_node_find(chan
, &request
->handle
, &node
);
760 NNPFSDEB(XDEBMSG
, ("nnpfs async_return: node not found\n"));
761 else if (error
== EISDIR
)
762 NNPFSDEB(XDEBMSG
, ("nnpfs async_return: node deleted\n"));
766 if (!node
->async_error
)
767 node
->async_error
= reply
->error
;
771 nnpfs_message_wakeup(struct nnpfs
*chan
,
772 struct nnpfs_message_wakeup
*message
,
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
;
785 async_return(chan
, t
->message
, message
);
786 NNPQUEUE_REMOVE(t
, &chan
->sleepq
, qentry
);
787 nnpfs_free(t
, linksize
, M_NNPFS_LINK
);
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
;
795 bcopy(message
, t
->message
, size
);
810 nnpfs_uprintf_device(void)
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
);