[BACK]Return to xfs_dev-common.c CVS log [TXT][DIR] Up to [local] / sys / xfs

Annotation of sys/xfs/xfs_dev-common.c, Revision 1.1.1.1

1.1       nbrk        1: /*
                      2:  * Copyright (c) 1995 - 2003 Kungliga Tekniska Högskolan
                      3:  * (Royal Institute of Technology, Stockholm, Sweden).
                      4:  * All rights reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  *
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  *
                     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.
                     16:  *
                     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.
                     20:  *
                     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.
                     32:  */
                     33:
                     34:
                     35: #include <xfs/xfs_locl.h>
                     36: #include <xfs/xfs_message.h>
                     37: #include <xfs/xfs_msg_locl.h>
                     38: #include <xfs/xfs_fs.h>
                     39: #include <xfs/xfs_dev.h>
                     40: #include <xfs/xfs_deb.h>
                     41:
                     42: RCSID("$arla: xfs_dev-common.c,v 1.61 2003/07/15 16:25:42 lha Exp $");
                     43:
                     44: struct xfs_channel xfs_channel[NNNPFS];
                     45:
                     46: void
                     47: xfs_initq(struct xfs_link *q)
                     48: {
                     49:     q->next = q;
                     50:     q->prev = q;
                     51: }
                     52:
                     53: /* Is this queue empty? */
                     54: int
                     55: xfs_emptyq(const struct xfs_link *q)
                     56: {
                     57:     return q->next == q;
                     58: }
                     59:
                     60: /* Is this link on any queue? Link *must* be inited! */
                     61: int
                     62: xfs_onq(const struct xfs_link *link)
                     63: {
                     64:     return link->next != NULL || link->prev != NULL;
                     65: }
                     66:
                     67: /* Append q with p */
                     68: void
                     69: xfs_appendq(struct xfs_link *q, struct xfs_link *p)
                     70: {
                     71:     p->next = q;
                     72:     p->prev = q->prev;
                     73:     p->prev->next = p;
                     74:     q->prev = p;
                     75: }
                     76:
                     77: /* remove `p' from its queue */
                     78: void
                     79: xfs_outq(struct xfs_link *p)
                     80: {
                     81:     p->next->prev = p->prev;
                     82:     p->prev->next = p->next;
                     83:     p->next = p->prev = NULL;
                     84: }
                     85:
                     86: /*
                     87:  * Only allow one open.
                     88:  */
                     89: int
                     90: xfs_devopen_common(dev_t dev)
                     91: {
                     92:     struct xfs_channel *chan;
                     93:
                     94:     if (minor(dev) < 0 || minor(dev) >= NNNPFS)
                     95:        return ENXIO;
                     96:
                     97:     chan = &xfs_channel[minor(dev)];
                     98:
                     99:     /* Only allow one reader/writer */
                    100:     if (chan->status & CHANNEL_OPENED) {
                    101:        NNPFSDEB(XDEBDEV, ("xfs_devopen: already open\n"));
                    102:        return EBUSY;
                    103:     } else {
                    104:        chan->status |= CHANNEL_OPENED;
                    105:     }
                    106:
                    107:     chan->message_buffer = xfs_alloc(MAX_XMSG_SIZE, M_NNPFS_MSG);
                    108:
                    109:     /* initialize the queues if they have not been initialized before */
                    110:     xfs_initq(&chan->sleepq);
                    111:     xfs_initq(&chan->messageq);
                    112:
                    113:     return 0;
                    114: }
                    115:
                    116: #if defined(HAVE_TWO_ARGUMENT_VFS_BUSY)
                    117: #define xfs_vfs_busy(mp, flags, lock, proc) vfs_busy((mp), (flags))
                    118: #define xfs_vfs_unbusy(mp, proc) vfs_unbusy((mp))
                    119: #elif defined(HAVE_THREE_ARGUMENT_VFS_BUSY)
                    120: #define xfs_vfs_busy(mp, flags, lock, proc) vfs_busy((mp), (flags), (lock))
                    121: #define xfs_vfs_unbusy(mp, proc) vfs_unbusy((mp))
                    122: #elif defined(HAVE_FOUR_ARGUMENT_VFS_BUSY)
                    123: #define xfs_vfs_busy(mp, flags, lock, proc) vfs_busy((mp), (flags), (lock), (proc))
                    124: #define xfs_vfs_unbusy(mp, proc) vfs_unbusy((mp), (proc))
                    125: #elif defined(__osf__)
                    126: #define xfs_vfs_busy(mp, flags, lock, proc) (0)
                    127: #define xfs_vfs_unbusy(mp, proc) (0)
                    128: #else
                    129: #define xfs_vfs_busy(mp, flags, lock, proc) vfs_busy((mp))
                    130: #define xfs_vfs_unbusy(mp, proc) vfs_unbusy((mp))
                    131: #endif
                    132:
                    133: /*
                    134:  * Wakeup all sleepers and cleanup.
                    135:  */
                    136: int
                    137: xfs_devclose_common(dev_t dev, d_thread_t *proc)
                    138: {
                    139:     struct xfs_channel *chan = &xfs_channel[minor(dev)];
                    140:     struct xfs_link *first;
                    141:
                    142:     /* Sanity check, paranoia? */
                    143:     if (!(chan->status & CHANNEL_OPENED))
                    144:        panic("xfs_devclose never opened?");
                    145:
                    146:     chan->status &= ~CHANNEL_OPENED;
                    147:
                    148:     /* No one is going to read those messages so empty queue! */
                    149:     while (!xfs_emptyq(&chan->messageq)) {
                    150:        NNPFSDEB(XDEBDEV, ("before outq(messageq)\n"));
                    151:
                    152:        first = chan->messageq.next;
                    153:        xfs_outq(first);
                    154:        if (first->error_or_size != 0)
                    155:            xfs_free(first, first->error_or_size, M_NNPFS_LINK);
                    156:
                    157:        NNPFSDEB(XDEBDEV, ("after outq(messageq)\n"));
                    158:     }
                    159:
                    160:     /* Wakeup those waiting for replies that will never arrive. */
                    161:     while (!xfs_emptyq(&chan->sleepq)) {
                    162:        NNPFSDEB(XDEBDEV, ("before outq(sleepq)\n"));
                    163:        first = chan->sleepq.next;
                    164:        xfs_outq(first);
                    165:        first->error_or_size = ENODEV;
                    166:        wakeup((caddr_t) first);
                    167:        NNPFSDEB(XDEBDEV, ("after outq(sleepq)\n"));
                    168:     }
                    169:
                    170:     if (chan->status & CHANNEL_WAITING)
                    171:        wakeup((caddr_t) chan);
                    172:
                    173:     if (chan->message_buffer) {
                    174:        xfs_free(chan->message_buffer, MAX_XMSG_SIZE, M_NNPFS_MSG);
                    175:        chan->message_buffer = NULL;
                    176:     }
                    177:
                    178:     /*
                    179:      * Free all xfs nodes.
                    180:      */
                    181:
                    182:     if (xfs[minor(dev)].mp != NULL) {
                    183:        if (xfs_vfs_busy(xfs[minor(dev)].mp, VB_READ|VB_WAIT, NULL, proc)) {
                    184:            NNPFSDEB(XDEBNODE, ("xfs_dev_close: vfs_busy() --> BUSY\n"));
                    185:            return EBUSY;
                    186:        }
                    187:        free_all_xfs_nodes(&xfs[minor(dev)], FORCECLOSE, 0);
                    188:
                    189:        xfs_vfs_unbusy(xfs[minor(dev)].mp, proc);
                    190:     }
                    191:
                    192:     return 0;
                    193: }
                    194:
                    195: #ifdef NNPFS_DEBUG
                    196: /*
                    197:  * debugging glue for CURSIG
                    198:  */
                    199:
                    200: static long
                    201: xfs_cursig (d_thread_t *p)
                    202: {
                    203: #if defined(__osf__)
                    204:     thread_t th        = current_thread();
                    205:     struct np_uthread  *npu = thread_to_np_uthread(th);
                    206:     return CURSIG(p,npu);
                    207: #elif 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: #else
                    218:     return CURSIG(p);
                    219: #endif
                    220: #endif
                    221: }
                    222: #endif
                    223:
                    224: /*
                    225:  * Move messages from kernel to user space.
                    226:  */
                    227:
                    228: int
                    229: xfs_devread(dev_t dev, struct uio * uiop, int ioflag)
                    230: {
                    231:     struct xfs_channel *chan = &xfs_channel[minor(dev)];
                    232:     struct xfs_link *first;
                    233:     int error = 0;
                    234: #ifdef NNPFS_DEBUG
                    235:     char devname[64];
                    236: #endif
                    237:
                    238:     NNPFSDEB(XDEBDEV, ("xfs_devread dev = %s\n",
                    239:                     xfs_devtoname_r(dev, devname, sizeof(devname))));
                    240:
                    241:     NNPFSDEB(XDEBDEV, ("xfs_devread: m = %lx, m->prev = %lx, m->next = %lx\n",
                    242:                     (unsigned long)&chan->messageq,
                    243:                     (unsigned long)chan->messageq.prev,
                    244:                     (unsigned long)chan->messageq.next));
                    245:
                    246: #ifdef HAVE_FREEBSD_THREAD
                    247:     chan->proc = xfs_uio_to_thread(uiop);
                    248: #else
                    249:     chan->proc = xfs_uio_to_proc(uiop);
                    250: #endif
                    251:
                    252:  again:
                    253:
                    254:     if (!xfs_emptyq (&chan->messageq)) {
                    255:        while (!xfs_emptyq (&chan->messageq)) {
                    256:            /* Remove message */
                    257:            first = chan->messageq.next;
                    258:            NNPFSDEB(XDEBDEV, ("xfs_devread: first = %lx, "
                    259:                             "first->prev = %lx, first->next = %lx\n",
                    260:                             (unsigned long)first,
                    261:                             (unsigned long)first->prev,
                    262:                             (unsigned long)first->next));
                    263:
                    264:            NNPFSDEB(XDEBDEV, ("xfs_devread: message->size = %u\n",
                    265:                             first->message->size));
                    266:
                    267:            if (first->message->size > uiop->uio_resid)
                    268:                break;
                    269:
                    270:            error = uiomove((caddr_t) first->message, first->message->size,
                    271:                            uiop);
                    272:            if (error)
                    273:                break;
                    274:
                    275:            xfs_outq(first);
                    276:
                    277:            if (first->error_or_size != 0)
                    278:                xfs_free(first, first->error_or_size, M_NNPFS_LINK);
                    279:        }
                    280:     } else {
                    281:        chan->status |= CHANNEL_WAITING;
                    282:        if (tsleep((caddr_t) chan, (PZERO + 1) | PCATCH, "xfsread", 0)) {
                    283: #ifdef HAVE_FREEBSD_THREAD
                    284:            NNPFSDEB(XDEBMSG,
                    285:                   ("caught signal xfs_devread: %ld\n",
                    286:                    xfs_cursig(xfs_uio_to_thread(uiop))));
                    287: #else
                    288:            NNPFSDEB(XDEBMSG,
                    289:                   ("caught signal xfs_devread: %ld\n",
                    290:                    xfs_cursig(xfs_uio_to_proc(uiop))));
                    291: #endif
                    292:            error = EINTR;
                    293:        } else if ((chan->status & CHANNEL_WAITING) == 0) {
                    294:            goto again;
                    295:        } else
                    296:            error = EIO;
                    297:     }
                    298:
                    299:     NNPFSDEB(XDEBDEV, ("xfs_devread done error = %d\n", error));
                    300:
                    301:     return error;
                    302: }
                    303:
                    304: /*
                    305:  * Move messages from user space to kernel space,
                    306:  * wakeup sleepers, insert new data in VFS.
                    307:  */
                    308: int
                    309: xfs_devwrite(dev_t dev, struct uio *uiop, int ioflag)
                    310: {
                    311:     struct xfs_channel *chan = &xfs_channel[minor(dev)];
                    312:     char *p;
                    313:     int error;
                    314:     u_int cnt;
                    315:     struct xfs_message_header *msg_buf;
                    316: #ifdef NNPFS_DEBUG
                    317:     char devname[64];
                    318: #endif
                    319:
                    320:     NNPFSDEB(XDEBDEV, ("xfs_devwrite dev = %s\n",
                    321:                     xfs_devtoname_r (dev, devname, sizeof(devname))));
                    322:
                    323: #ifdef HAVE_FREEBSD_THREAD
                    324:     chan->proc = xfs_uio_to_thread(uiop);
                    325: #else
                    326:     chan->proc = xfs_uio_to_proc(uiop);
                    327: #endif
                    328:     cnt = uiop->uio_resid;
                    329:     error = uiomove((caddr_t) chan->message_buffer, MAX_XMSG_SIZE, uiop);
                    330:     if (error != 0)
                    331:        return error;
                    332:
                    333:     cnt -= uiop->uio_resid;
                    334:
                    335:     /*
                    336:      * This thread handles the received message.
                    337:      */
                    338:     for (p = (char *)chan->message_buffer;
                    339:         cnt > 0;
                    340:         p += msg_buf->size, cnt -= msg_buf->size) {
                    341: #ifdef HAVE_FREEBSD_THREAD
                    342:        d_thread_t *pp = xfs_uio_to_thread(uiop);
                    343: #else
                    344:        d_thread_t *pp = xfs_uio_to_proc(uiop);
                    345: #endif
                    346:
                    347:        msg_buf = (struct xfs_message_header *)p;
                    348:        error = xfs_message_receive (minor(dev),
                    349:                                     msg_buf,
                    350:                                     msg_buf->size,
                    351:                                     pp);
                    352:     }
                    353:     NNPFSDEB(XDEBDEV, ("xfs_devwrite error = %d\n", error));
                    354:     return error;
                    355: }
                    356:
                    357: /*
                    358:  * Send a message to user space.
                    359:  */
                    360: int
                    361: xfs_message_send(int fd, struct xfs_message_header * message, u_int size)
                    362: {
                    363:     struct xfs_channel *chan = &xfs_channel[fd];
                    364:     struct {
                    365:        struct xfs_link this_message;
                    366:        struct xfs_message_header msg;
                    367:     } *t;
                    368:
                    369:     NNPFSDEB(XDEBMSG, ("xfs_message_send opcode = %d\n", message->opcode));
                    370:
                    371:     if (!(chan->status & CHANNEL_OPENED))      /* No receiver? */
                    372:        return ENODEV;
                    373:
                    374:     /* Prepare message and copy it later */
                    375:     message->size = size;
                    376:     message->sequence_num = chan->nsequence++;
                    377:
                    378:     t = xfs_alloc(sizeof(t->this_message) + size, M_NNPFS);
                    379:     t->this_message.error_or_size = sizeof(t->this_message) + size;
                    380:     bcopy(message, &t->msg, size);
                    381:
                    382:     t->this_message.message = &t->msg;
                    383:     xfs_appendq(&chan->messageq, &t->this_message);
                    384:     if (chan->status & CHANNEL_WAITING) {
                    385:        chan->status &= ~CHANNEL_WAITING;
                    386:        wakeup((caddr_t) chan);
                    387:     }
                    388:     xfs_select_wakeup(chan);
                    389:
                    390:     return 0;
                    391: }
                    392:
                    393: #if defined(SWEXIT)
                    394: #define NNPFS_P_EXIT SWEXIT
                    395: #elif defined(P_WEXIT)
                    396: #define NNPFS_P_EXIT P_WEXIT
                    397: #else
                    398: #error what is your exit named ?
                    399: #endif
                    400:
                    401: #if defined(HAVE_STRUCT_PROC_P_SIGMASK) || defined(HAVE_STRUCT_PROC_P_SIGCTX) || defined(HAVE_STRUCT_PROC_P_SIGWAITMASK) || defined(__osf__) || defined(HAVE_FREEBSD_THREAD)
                    402: static void
                    403: xfs_block_sigset (sigset_t *sigset)
                    404: {
                    405:
                    406: #if defined(__sigaddset)
                    407: #define xfs_sig_block(ss,signo) __sigaddset((ss), (signo))
                    408: #elif defined(SIGADDSET)
                    409: #define xfs_sig_block(ss,signo) SIGADDSET(*(ss), (signo))
                    410: #else
                    411: #define xfs_sig_block(ss,signo) *(ss) |= sigmask(signo)
                    412: #endif
                    413:
                    414:     xfs_sig_block(sigset, SIGIO);
                    415:     xfs_sig_block(sigset, SIGALRM);
                    416:     xfs_sig_block(sigset, SIGVTALRM);
                    417:     xfs_sig_block(sigset, SIGCHLD);
                    418: #ifdef SIGINFO
                    419:     xfs_sig_block(sigset, SIGINFO);
                    420: #endif
                    421: #undef xfs_sig_block
                    422: }
                    423: #endif
                    424:
                    425: /*
                    426:  * Send a message to user space and wait for reply.
                    427:  */
                    428:
                    429: int
                    430: xfs_message_rpc(int fd, struct xfs_message_header * message, u_int size,
                    431:                d_thread_t *proc)
                    432: {
                    433:     int ret;
                    434:     struct xfs_channel *chan = &xfs_channel[fd];
                    435:     struct xfs_link *this_message;
                    436:     struct xfs_link *this_process;
                    437:     struct xfs_message_header *msg;
                    438: #if defined(HAVE_STRUCT_PROC_P_SIGMASK) || defined(HAVE_STRUCT_PROC_P_SIGCTX) || defined(__osf__) || defined(HAVE_FREEBSD_THREAD)
                    439:     sigset_t oldsigmask;
                    440: #endif
                    441:     int catch;
                    442:
                    443:     NNPFSDEB(XDEBMSG, ("xfs_message_rpc opcode = %d\n", message->opcode));
                    444:
                    445:     if (proc == NULL) {
                    446: #ifdef HAVE_FREEBSD_THREAD
                    447:        proc = xfs_curthread();
                    448: #else
                    449:        proc = xfs_curproc();
                    450: #endif
                    451:     }
                    452:     if (!(chan->status & CHANNEL_OPENED))      /* No receiver? */
                    453:        return ENODEV;
                    454:
                    455: #ifdef HAVE_FREEBSD_THREAD
                    456:     if (chan->proc != NULL && chan->proc->td_proc != NULL &&
                    457:       proc->td_proc->p_pid == chan->proc->td_proc->p_pid) {
                    458:        printf("xfs_message_rpc: deadlock avoided "
                    459:               "pid = %u == %u\n", proc->td_proc->p_pid, chan->proc->td_proc->p_pid);
                    460: #else
                    461:     if (chan->proc != NULL && proc->p_pid == chan->proc->p_pid) {
                    462:        printf("xfs_message_rpc: deadlock avoided "
                    463:               "pid = %u == %u\n", proc->p_pid, chan->proc->p_pid);
                    464: #endif
                    465: #if 0
                    466:        psignal (proc, SIGABRT);
                    467: #endif
                    468:        return EDEADLK;
                    469:     }
                    470:
                    471:     if (size < sizeof(struct xfs_message_wakeup)) {
                    472:        printf("NNPFS PANIC Error: Message to small to receive wakeup, opcode = %d\n", message->opcode);
                    473:        return ENOMEM;
                    474:     }
                    475:     this_message = xfs_alloc(sizeof(struct xfs_link), M_NNPFS_LINK);
                    476:     this_process = xfs_alloc(sizeof(struct xfs_link), M_NNPFS_LINK);
                    477:     msg = xfs_alloc(size, M_NNPFS_MSG);
                    478:     bcopy(message, msg, size);
                    479:
                    480:     msg->size = size;
                    481:     msg->sequence_num = chan->nsequence++;
                    482:     this_message->error_or_size = 0;
                    483:     this_message->message = msg;
                    484:     this_process->message = msg;
                    485:     xfs_appendq(&chan->messageq, this_message);
                    486:     xfs_appendq(&chan->sleepq, this_process);
                    487:     xfs_select_wakeup(chan);
                    488:     this_process->error_or_size = 0;
                    489:
                    490:     if (chan->status & CHANNEL_WAITING) {
                    491:        chan->status &= ~CHANNEL_WAITING;
                    492:        wakeup((caddr_t) chan);
                    493:     }
                    494:
                    495:     /*
                    496:      * Remove signals from the sigmask so no IO will wake us up from
                    497:      * tsleep(). We don't want to wake up from since program (emacs,
                    498:      * bash & co can't handle them.
                    499:      */
                    500:
                    501: #ifdef HAVE_FREEBSD_THREAD
                    502:     /* FreeBSD 5.1 */
                    503:     oldsigmask = proc->td_sigmask;
                    504:     xfs_block_sigset (&proc->td_sigmask);
                    505: #elif HAVE_STRUCT_PROC_P_SIGMASK
                    506:     /* NetBSD 1.5, Darwin 1.3, FreeBSD 4.3, 5.0, OpenBSD 2.8 */
                    507:     oldsigmask = proc->p_sigmask;
                    508:     xfs_block_sigset (&proc->p_sigmask);
                    509: #elif defined(HAVE_STRUCT_PROC_P_SIGCTX)
                    510:     /* NetBSD 1.6 */
                    511:     oldsigmask = proc->p_sigctx.ps_sigmask;
                    512:     xfs_block_sigset (&proc->p_sigctx.ps_sigmask);
                    513: #elif defined(HAVE_STRUCT_PROC_P_SIGWAITMASK)
                    514:     /* OSF 4.0 */
                    515:     oldsigmask = proc->p_sigwaitmask;
                    516:     xfs_block_sigset (&proc->p_sigwaitmask);
                    517: #elif defined(__osf__)
                    518:     /* OSF 5.0 */
                    519:     oldsigmask = u.u_sigmask;
                    520:     xfs_block_sigset (&u.u_sigmask);
                    521: #endif
                    522:
                    523:     /*
                    524:      * if we are exiting we should not try to catch signals, since
                    525:      * there might not be enough context left in the process to handle
                    526:      * signal delivery, and besides, most BSD-variants ignore all
                    527:      * signals while closing anyway.
                    528:      */
                    529:
                    530:     catch = 0;
                    531: #ifdef HAVE_FREEBSD_THREAD
                    532:     if (!(proc->td_proc->p_flag & NNPFS_P_EXIT))
                    533: #else
                    534:     if (!(proc->p_flag & NNPFS_P_EXIT))
                    535: #endif
                    536:        catch |= PCATCH;
                    537:
                    538:     /*
                    539:      * We have to check if we have a receiver here too because the
                    540:      * daemon could have terminated before we sleep. This seems to
                    541:      * happen sometimes when rebooting.  */
                    542:
                    543:     if (!(chan->status & CHANNEL_OPENED)) {
                    544:        NNPFSDEB(XDEBMSG, ("xfs_message_rpc: channel went away\n"));
                    545:        this_process->error_or_size = EINTR;
                    546:     } else if ((ret = tsleep((caddr_t) this_process,
                    547:                             (PZERO + 1) | catch, "xfs", 0)) != 0) {
                    548:        NNPFSDEB(XDEBMSG, ("caught signal (%d): %ld\n",
                    549:                         ret, xfs_cursig(proc)));
                    550:        this_process->error_or_size = EINTR;
                    551:     }
                    552:
                    553: #ifdef HAVE_FREEBSD_THREAD
                    554:     proc->td_sigmask = oldsigmask;
                    555: #elif HAVE_STRUCT_PROC_P_SIGMASK
                    556:     proc->p_sigmask = oldsigmask;
                    557: #elif defined(HAVE_STRUCT_PROC_P_SIGCTX)
                    558:     proc->p_sigctx.ps_sigmask = oldsigmask;
                    559: #elif defined(HAVE_STRUCT_PROC_P_SIGWAITMASK)
                    560:     proc->p_sigwaitmask = oldsigmask;
                    561: #elif defined(__osf__)
                    562:     u.u_sigmask = oldsigmask;
                    563: #endif
                    564:
                    565:     /*
                    566:      * Caught signal, got reply message or device was closed.
                    567:      * Need to clean up both messageq and sleepq.
                    568:      */
                    569:     if (xfs_onq(this_message)) {
                    570:        xfs_outq(this_message);
                    571:     }
                    572:     if (xfs_onq(this_process)) {
                    573:        xfs_outq(this_process);
                    574:     }
                    575:     ret = this_process->error_or_size;
                    576:
                    577:     NNPFSDEB(XDEBMSG, ("xfs_message_rpc this_process->error_or_size = %d\n",
                    578:                     this_process->error_or_size));
                    579:     NNPFSDEB(XDEBMSG, ("xfs_message_rpc opcode ((xfs_message_wakeup*)(this_process->message))->error = %d\n", ((struct xfs_message_wakeup *) (this_process->message))->error));
                    580:
                    581:     bcopy(msg, message, size);
                    582:
                    583:     xfs_free(this_message, sizeof(*this_message), M_NNPFS_LINK);
                    584:     xfs_free(this_process, sizeof(*this_process), M_NNPFS_LINK);
                    585:     xfs_free(msg, size, M_NNPFS_MSG);
                    586:
                    587:     return ret;
                    588: }
                    589:
                    590: /*
                    591:  * For each message type there is a message handler
                    592:  * that implements its action, xfs_message_receive
                    593:  * invokes the correct function.
                    594:  */
                    595: int
                    596: xfs_message_receive(int fd,
                    597:                    struct xfs_message_header *message,
                    598:                    u_int size,
                    599:                    d_thread_t *p)
                    600: {
                    601:     NNPFSDEB(XDEBMSG, ("xfs_message_receive opcode = %d\n", message->opcode));
                    602:
                    603:     /* Dispatch and coerce message type */
                    604:     switch (message->opcode) {
                    605:     case NNPFS_MSG_WAKEUP:
                    606:        return xfs_message_wakeup(fd,
                    607:                                  (struct xfs_message_wakeup *) message,
                    608:                                  message->size,
                    609:                                  p);
                    610:     case NNPFS_MSG_WAKEUP_DATA:
                    611:        return xfs_message_wakeup_data(fd,
                    612:                                 (struct xfs_message_wakeup_data *) message,
                    613:                                       message->size,
                    614:                                       p);
                    615:     case NNPFS_MSG_INSTALLROOT:
                    616:        return xfs_message_installroot(fd,
                    617:                                 (struct xfs_message_installroot *) message,
                    618:                                       message->size,
                    619:                                       p);
                    620:     case NNPFS_MSG_INSTALLNODE:
                    621:        return xfs_message_installnode(fd,
                    622:                                 (struct xfs_message_installnode *) message,
                    623:                                       message->size,
                    624:                                       p);
                    625:     case NNPFS_MSG_INSTALLATTR:
                    626:        return xfs_message_installattr(fd,
                    627:                                 (struct xfs_message_installattr *) message,
                    628:                                       message->size,
                    629:                                       p);
                    630:     case NNPFS_MSG_INSTALLDATA:
                    631:        return xfs_message_installdata(fd,
                    632:                                 (struct xfs_message_installdata *) message,
                    633:                                       message->size,
                    634:                                       p);
                    635:     case NNPFS_MSG_INVALIDNODE:
                    636:        return xfs_message_invalidnode(fd,
                    637:                                 (struct xfs_message_invalidnode *) message,
                    638:                                       message->size,
                    639:                                       p);
                    640:     case NNPFS_MSG_UPDATEFID:
                    641:        return xfs_message_updatefid(fd,
                    642:                                     (struct xfs_message_updatefid *)message,
                    643:                                     message->size,
                    644:                                     p);
                    645:     case NNPFS_MSG_GC_NODES:
                    646:        return xfs_message_gc_nodes(fd,
                    647:                                    (struct xfs_message_gc_nodes *)message,
                    648:                                    message->size,
                    649:                                    p);
                    650:     case NNPFS_MSG_VERSION:
                    651:        return xfs_message_version(fd,
                    652:                                   (struct xfs_message_version *)message,
                    653:                                   message->size,
                    654:                                   p);
                    655:     default:
                    656:        printf("NNPFS PANIC Warning xfs_dev: Unknown message opcode == %d\n",
                    657:               message->opcode);
                    658:        return EINVAL;
                    659:     }
                    660: }
                    661:
                    662: int
                    663: xfs_message_wakeup(int fd,
                    664:                   struct xfs_message_wakeup *message,
                    665:                   u_int size,
                    666:                   d_thread_t *p)
                    667: {
                    668:     struct xfs_channel *chan = &xfs_channel[fd];
                    669:     struct xfs_link *sleepq = &chan->sleepq;
                    670:     struct xfs_link *t = chan->sleepq.next;    /* Really first in q */
                    671:
                    672:     NNPFSDEB(XDEBMSG, ("xfs_message_wakeup error: %d\n", message->error));
                    673:
                    674:     for (; t != sleepq; t = t->next)
                    675:        if (t->message->sequence_num == message->sleepers_sequence_num) {
                    676:            if (t->message->size < size) {
                    677:                printf("NNPFS PANIC Error: Could not wakeup requestor with opcode = %d properly, to small receive buffer.\n", t->message->opcode);
                    678:                t->error_or_size = ENOMEM;
                    679:            } else
                    680:                bcopy(message, t->message, size);
                    681:
                    682:            wakeup((caddr_t) t);
                    683:            break;
                    684:        }
                    685:
                    686:     return 0;
                    687: }
                    688:
                    689: int
                    690: xfs_message_wakeup_data(int fd,
                    691:                        struct xfs_message_wakeup_data * message,
                    692:                        u_int size,
                    693:                        d_thread_t *p)
                    694: {
                    695:     struct xfs_channel *chan = &xfs_channel[fd];
                    696:     struct xfs_link *sleepq = &chan->sleepq;
                    697:     struct xfs_link *t = chan->sleepq.next;    /* Really first in q */
                    698:
                    699:     NNPFSDEB(XDEBMSG, ("xfs_message_wakeup_data error: %d\n", message->error));
                    700:
                    701:     for (; t != sleepq; t = t->next)
                    702:        if (t->message->sequence_num == message->sleepers_sequence_num) {
                    703:            if (t->message->size < size) {
                    704:                printf("NNPFS PANIC Error: Could not wakeup requestor with opcode = %d properly, to small receive buffer.\n", t->message->opcode);
                    705:                t->error_or_size = ENOMEM;
                    706:            } else
                    707:                bcopy(message, t->message, size);
                    708:            wakeup((caddr_t) t);
                    709:            break;
                    710:        }
                    711:     return 0;
                    712: }
                    713:
                    714: /*
                    715:  *
                    716:  */
                    717: int
                    718: xfs_uprintf_device(void)
                    719: {
                    720: #if 0
                    721:     int i;
                    722:
                    723:     for (i = 0; i < NNNPFS; i++) {
                    724:        uprintf("xfs_channel[%d] = {\n", i);
                    725:        uprintf("messageq.next = %lx ", xfs_channel[i].messageq.next);
                    726:        uprintf("messageq.prev = %lx ", xfs_channel[i].messageq.prev);
                    727:        uprintf("sleepq.next = %lx ", xfs_channel[i].sleepq.next);
                    728:        uprintf("sleepq.prev = %lx ", xfs_channel[i].sleepq.prev);
                    729:        uprintf("nsequence = %d status = %d\n",
                    730:                xfs_channel[i].nsequence,
                    731:                xfs_channel[i].status);
                    732:        uprintf("}\n");
                    733:     }
                    734: #endif
                    735:     return 0;
                    736: }

CVSweb