[BACK]Return to puffs_msgif.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / fs / puffs

Annotation of src/sys/fs/puffs/puffs_msgif.c, Revision 1.75

1.75    ! pooka       1: /*     $NetBSD: puffs_msgif.c,v 1.74 2009/11/05 19:42:44 pooka Exp $   */
1.1       pooka       2:
                      3: /*
1.16      pooka       4:  * Copyright (c) 2005, 2006, 2007  Antti Kantee.  All Rights Reserved.
1.1       pooka       5:  *
                      6:  * Development of this software was supported by the
                      7:  * Google Summer of Code program and the Ulla Tuominen Foundation.
                      8:  * The Google SoC project was mentored by Bill Studenmund.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
                     20:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     21:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     22:  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     25:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     29:  * SUCH DAMAGE.
                     30:  */
                     31:
                     32: #include <sys/cdefs.h>
1.75    ! pooka      33: __KERNEL_RCSID(0, "$NetBSD: puffs_msgif.c,v 1.74 2009/11/05 19:42:44 pooka Exp $");
1.1       pooka      34:
                     35: #include <sys/param.h>
1.68      tnn        36: #include <sys/atomic.h>
1.46      pooka      37: #include <sys/kmem.h>
1.53      pooka      38: #include <sys/kthread.h>
                     39: #include <sys/lock.h>
1.1       pooka      40: #include <sys/malloc.h>
                     41: #include <sys/mount.h>
1.53      pooka      42: #include <sys/namei.h>
                     43: #include <sys/proc.h>
1.1       pooka      44: #include <sys/vnode.h>
1.71      ad         45: #include <sys/atomic.h>
1.53      pooka      46:
1.55      pooka      47: #include <dev/putter/putter_sys.h>
1.1       pooka      48:
                     49: #include <fs/puffs/puffs_msgif.h>
                     50: #include <fs/puffs/puffs_sys.h>
                     51:
1.53      pooka      52: #include <miscfs/syncfs/syncfs.h> /* XXX: for syncer_mutex reference */
                     53:
1.22      pooka      54: /*
                     55:  * waitq data structures
                     56:  */
                     57:
                     58: /*
                     59:  * While a request is going to userspace, park the caller within the
                     60:  * kernel.  This is the kernel counterpart of "struct puffs_req".
                     61:  */
1.46      pooka      62: struct puffs_msgpark {
1.22      pooka      63:        struct puffs_req        *park_preq;     /* req followed by buf  */
                     64:
                     65:        size_t                  park_copylen;   /* userspace copylength */
                     66:        size_t                  park_maxlen;    /* max size in comeback */
1.24      pooka      67:
1.46      pooka      68:        parkdone_fn             park_done;      /* "biodone" a'la puffs */
1.24      pooka      69:        void                    *park_donearg;
1.22      pooka      70:
                     71:        int                     park_flags;
1.26      pooka      72:        int                     park_refcount;
1.22      pooka      73:
                     74:        kcondvar_t              park_cv;
1.26      pooka      75:        kmutex_t                park_mtx;
                     76:
1.46      pooka      77:        TAILQ_ENTRY(puffs_msgpark) park_entries;
1.22      pooka      78: };
                     79: #define PARKFLAG_WAITERGONE    0x01
1.26      pooka      80: #define PARKFLAG_DONE          0x02
                     81: #define PARKFLAG_ONQUEUE1      0x04
                     82: #define PARKFLAG_ONQUEUE2      0x08
                     83: #define PARKFLAG_CALL          0x10
1.31      pooka      84: #define PARKFLAG_WANTREPLY     0x20
1.57      pooka      85: #define        PARKFLAG_HASERROR       0x40
1.22      pooka      86:
1.52      ad         87: static pool_cache_t parkpc;
1.57      pooka      88: #ifdef PUFFSDEBUG
                     89: static int totalpark;
                     90: #endif
1.22      pooka      91:
                     92: static int
                     93: makepark(void *arg, void *obj, int flags)
                     94: {
1.46      pooka      95:        struct puffs_msgpark *park = obj;
1.22      pooka      96:
1.26      pooka      97:        mutex_init(&park->park_mtx, MUTEX_DEFAULT, IPL_NONE);
1.22      pooka      98:        cv_init(&park->park_cv, "puffsrpl");
                     99:
                    100:        return 0;
                    101: }
                    102:
                    103: static void
                    104: nukepark(void *arg, void *obj)
                    105: {
1.46      pooka     106:        struct puffs_msgpark *park = obj;
1.22      pooka     107:
                    108:        cv_destroy(&park->park_cv);
1.26      pooka     109:        mutex_destroy(&park->park_mtx);
1.22      pooka     110: }
                    111:
                    112: void
1.73      cegger    113: puffs_msgif_init(void)
1.22      pooka     114: {
                    115:
1.52      ad        116:        parkpc = pool_cache_init(sizeof(struct puffs_msgpark), 0, 0, 0,
                    117:            "puffprkl", NULL, IPL_NONE, makepark, nukepark, NULL);
1.22      pooka     118: }
                    119:
                    120: void
1.73      cegger    121: puffs_msgif_destroy(void)
1.22      pooka     122: {
                    123:
1.52      ad        124:        pool_cache_destroy(parkpc);
1.22      pooka     125: }
                    126:
1.46      pooka     127: static int alloced;
                    128:
                    129: static struct puffs_msgpark *
                    130: puffs_msgpark_alloc(int waitok)
1.26      pooka     131: {
1.46      pooka     132:        struct puffs_msgpark *park;
1.26      pooka     133:
1.52      ad        134:        park = pool_cache_get(parkpc, waitok ? PR_WAITOK : PR_NOWAIT);
1.46      pooka     135:        if (park == NULL)
                    136:                return park;
                    137:
                    138:        park->park_refcount = 1;
                    139:        park->park_preq = NULL;
                    140:        park->park_flags = PARKFLAG_WANTREPLY;
1.26      pooka     141:
1.57      pooka     142: #ifdef PUFFSDEBUG
                    143:        totalpark++;
                    144: #endif
                    145:
1.26      pooka     146:        return park;
                    147: }
                    148:
                    149: static void
1.46      pooka     150: puffs_msgpark_reference(struct puffs_msgpark *park)
1.22      pooka     151: {
                    152:
1.46      pooka     153:        KASSERT(mutex_owned(&park->park_mtx));
1.26      pooka     154:        park->park_refcount++;
1.22      pooka     155: }
                    156:
1.46      pooka     157: /*
                    158:  * Release reference to park structure.
                    159:  */
                    160: static void
                    161: puffs_msgpark_release1(struct puffs_msgpark *park, int howmany)
1.22      pooka     162: {
1.46      pooka     163:        struct puffs_req *preq = park->park_preq;
                    164:        int refcnt;
1.22      pooka     165:
1.26      pooka     166:        KASSERT(mutex_owned(&park->park_mtx));
1.46      pooka     167:        refcnt = park->park_refcount -= howmany;
                    168:        mutex_exit(&park->park_mtx);
                    169:
                    170:        KASSERT(refcnt >= 0);
1.26      pooka     171:
1.46      pooka     172:        if (refcnt == 0) {
                    173:                alloced--;
                    174:                if (preq)
                    175:                        kmem_free(preq, park->park_maxlen);
1.52      ad        176:                pool_cache_put(parkpc, park);
1.57      pooka     177:
                    178: #ifdef PUFFSDEBUG
                    179:                totalpark--;
                    180: #endif
1.46      pooka     181:        }
1.22      pooka     182: }
1.46      pooka     183: #define puffs_msgpark_release(a) puffs_msgpark_release1(a, 1)
1.22      pooka     184:
1.26      pooka     185: #ifdef PUFFSDEBUG
                    186: static void
1.46      pooka     187: parkdump(struct puffs_msgpark *park)
1.26      pooka     188: {
                    189:
                    190:        DPRINTF(("park %p, preq %p, id %" PRIu64 "\n"
                    191:            "\tcopy %zu, max %zu - done: %p/%p\n"
                    192:            "\tflags 0x%08x, refcount %d, cv/mtx: %p/%p\n",
1.46      pooka     193:            park, park->park_preq, park->park_preq->preq_id,
1.26      pooka     194:            park->park_copylen, park->park_maxlen,
                    195:            park->park_done, park->park_donearg,
                    196:            park->park_flags, park->park_refcount,
                    197:            &park->park_cv, &park->park_mtx));
                    198: }
                    199:
                    200: static void
                    201: parkqdump(struct puffs_wq *q, int dumpall)
                    202: {
1.46      pooka     203:        struct puffs_msgpark *park;
1.26      pooka     204:        int total = 0;
                    205:
                    206:        TAILQ_FOREACH(park, q, park_entries) {
                    207:                if (dumpall)
                    208:                        parkdump(park);
                    209:                total++;
                    210:        }
1.29      pooka     211:        DPRINTF(("puffs waitqueue at %p dumped, %d total\n", q, total));
1.26      pooka     212:
                    213: }
                    214: #endif /* PUFFSDEBUG */
1.22      pooka     215:
                    216: /*
1.46      pooka     217:  * A word about locking in the park structures: the lock protects the
                    218:  * fields of the *park* structure (not preq) and acts as an interlock
                    219:  * in cv operations.  The lock is always internal to this module and
                    220:  * callers do not need to worry about it.
1.22      pooka     221:  */
1.46      pooka     222:
                    223: int
                    224: puffs_msgmem_alloc(size_t len, struct puffs_msgpark **ppark, void **mem,
                    225:        int cansleep)
                    226: {
                    227:        struct puffs_msgpark *park;
                    228:        void *m;
                    229:
                    230:        m = kmem_zalloc(len, cansleep ? KM_SLEEP : KM_NOSLEEP);
                    231:        if (m == NULL) {
                    232:                KASSERT(cansleep == 0);
                    233:                return ENOMEM;
                    234:        }
                    235:
                    236:        park = puffs_msgpark_alloc(cansleep);
                    237:        if (park == NULL) {
                    238:                KASSERT(cansleep == 0);
                    239:                kmem_free(m, len);
                    240:                return ENOMEM;
                    241:        }
                    242:
                    243:        park->park_preq = m;
1.57      pooka     244:        park->park_maxlen = park->park_copylen = len;
1.46      pooka     245:
                    246:        *ppark = park;
                    247:        *mem = m;
                    248:
                    249:        return 0;
                    250: }
                    251:
                    252: void
                    253: puffs_msgmem_release(struct puffs_msgpark *park)
1.22      pooka     254: {
                    255:
1.46      pooka     256:        if (park == NULL)
                    257:                return;
1.22      pooka     258:
1.46      pooka     259:        mutex_enter(&park->park_mtx);
                    260:        puffs_msgpark_release(park);
                    261: }
1.22      pooka     262:
1.46      pooka     263: void
                    264: puffs_msg_setfaf(struct puffs_msgpark *park)
                    265: {
1.22      pooka     266:
1.57      pooka     267:        KASSERT((park->park_flags & PARKFLAG_CALL) == 0);
1.36      pooka     268:        park->park_flags &= ~PARKFLAG_WANTREPLY;
1.22      pooka     269: }
                    270:
1.57      pooka     271: void
                    272: puffs_msg_setdelta(struct puffs_msgpark *park, size_t delta)
1.1       pooka     273: {
                    274:
1.57      pooka     275:        KASSERT(delta < park->park_maxlen); /* "<=" wouldn't make sense */
                    276:        park->park_copylen = park->park_maxlen - delta;
1.1       pooka     277: }
                    278:
1.57      pooka     279: void
1.64      pooka     280: puffs_msg_setinfo(struct puffs_msgpark *park, int class, int type,
                    281:        puffs_cookie_t ck)
1.1       pooka     282: {
                    283:
1.57      pooka     284:        park->park_preq->preq_opclass = PUFFSOP_OPCLASS(class);
                    285:        park->park_preq->preq_optype = type;
1.64      pooka     286:        park->park_preq->preq_cookie = ck;
1.1       pooka     287: }
                    288:
1.24      pooka     289: void
1.57      pooka     290: puffs_msg_setcall(struct puffs_msgpark *park, parkdone_fn donefn, void *donearg)
1.1       pooka     291: {
1.25      pooka     292:
1.57      pooka     293:        KASSERT(park->park_flags & PARKFLAG_WANTREPLY);
1.25      pooka     294:        park->park_done = donefn;
                    295:        park->park_donearg = donearg;
1.46      pooka     296:        park->park_flags |= PARKFLAG_CALL;
1.20      pooka     297: }
                    298:
1.57      pooka     299: /*
                    300:  * kernel-user-kernel waitqueues
                    301:  */
1.4       pooka     302:
1.57      pooka     303: static uint64_t
                    304: puffs_getmsgid(struct puffs_mount *pmp)
1.41      pooka     305: {
1.57      pooka     306:        uint64_t rv;
1.41      pooka     307:
1.57      pooka     308:        mutex_enter(&pmp->pmp_lock);
                    309:        rv = pmp->pmp_nextmsgid++;
                    310:        mutex_exit(&pmp->pmp_lock);
1.41      pooka     311:
1.57      pooka     312:        return rv;
1.41      pooka     313: }
                    314:
1.4       pooka     315: /*
1.57      pooka     316:  * A word about reference counting of parks.  A reference must be taken
                    317:  * when accessing a park and additionally when it is on a queue.  So
                    318:  * when taking it off a queue and releasing the access reference, the
                    319:  * reference count is generally decremented by 2.
1.1       pooka     320:  */
1.57      pooka     321:
                    322: void
                    323: puffs_msg_enqueue(struct puffs_mount *pmp, struct puffs_msgpark *park)
1.1       pooka     324: {
1.26      pooka     325:        struct lwp *l = curlwp;
1.16      pooka     326:        struct mount *mp;
1.9       pooka     327:        struct puffs_req *preq;
1.1       pooka     328:
1.16      pooka     329:        mp = PMPTOMP(pmp);
1.25      pooka     330:        preq = park->park_preq;
1.46      pooka     331:        preq->preq_buflen = park->park_maxlen;
1.61      pooka     332:        KASSERT(preq->preq_id == 0
                    333:            || (preq->preq_opclass & PUFFSOPFLAG_ISRESPONSE));
1.46      pooka     334:
                    335:        if ((park->park_flags & PARKFLAG_WANTREPLY) == 0)
                    336:                preq->preq_opclass |= PUFFSOPFLAG_FAF;
                    337:        else
                    338:                preq->preq_id = puffs_getmsgid(pmp);
1.31      pooka     339:
1.49      pooka     340:        /* fill in caller information */
                    341:        preq->preq_pid = l->l_proc->p_pid;
                    342:        preq->preq_lid = l->l_lid;
                    343:
1.19      pooka     344:        /*
1.51      pooka     345:         * To support cv_sig, yet another movie: check if there are signals
1.19      pooka     346:         * pending and we are issueing a non-FAF.  If so, return an error
1.57      pooka     347:         * directly UNLESS we are issueing INACTIVE/RECLAIM.  In that case,
                    348:         * convert it to a FAF, fire off to the file server and return
                    349:         * an error.  Yes, this is bordering disgusting.  Barfbags are on me.
1.19      pooka     350:         */
1.57      pooka     351:        if (__predict_false((park->park_flags & PARKFLAG_WANTREPLY)
1.25      pooka     352:           && (park->park_flags & PARKFLAG_CALL) == 0
1.57      pooka     353:           && (l->l_flag & LW_PENDSIG) != 0 && sigispending(l, 0))) {
                    354:                park->park_flags |= PARKFLAG_HASERROR;
                    355:                preq->preq_rv = EINTR;
1.19      pooka     356:                if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN
1.57      pooka     357:                    && (preq->preq_optype == PUFFS_VN_INACTIVE
                    358:                     || preq->preq_optype == PUFFS_VN_RECLAIM)) {
1.46      pooka     359:                        park->park_preq->preq_opclass |= PUFFSOPFLAG_FAF;
                    360:                        park->park_flags &= ~PARKFLAG_WANTREPLY;
1.57      pooka     361:                        DPRINTF(("puffs_msg_enqueue: converted to FAF %p\n",
                    362:                            park));
1.19      pooka     363:                } else {
1.57      pooka     364:                        return;
1.19      pooka     365:                }
                    366:        }
1.16      pooka     367:
1.22      pooka     368:        mutex_enter(&pmp->pmp_lock);
1.13      pooka     369:        if (pmp->pmp_status != PUFFSTAT_RUNNING) {
1.22      pooka     370:                mutex_exit(&pmp->pmp_lock);
1.57      pooka     371:                park->park_flags |= PARKFLAG_HASERROR;
                    372:                preq->preq_rv = ENXIO;
                    373:                return;
1.1       pooka     374:        }
                    375:
1.26      pooka     376: #ifdef PUFFSDEBUG
1.46      pooka     377:        parkqdump(&pmp->pmp_msg_touser, puffsdebug > 1);
                    378:        parkqdump(&pmp->pmp_msg_replywait, puffsdebug > 1);
1.26      pooka     379: #endif
                    380:
1.57      pooka     381:        /*
                    382:         * Note: we don't need to lock park since we have the only
                    383:         * reference to it at this point.
                    384:         */
1.46      pooka     385:        TAILQ_INSERT_TAIL(&pmp->pmp_msg_touser, park, park_entries);
1.26      pooka     386:        park->park_flags |= PARKFLAG_ONQUEUE1;
1.46      pooka     387:        pmp->pmp_msg_touser_count++;
1.57      pooka     388:        park->park_refcount++;
1.26      pooka     389:        mutex_exit(&pmp->pmp_lock);
1.1       pooka     390:
1.57      pooka     391:        cv_broadcast(&pmp->pmp_msg_waiter_cv);
                    392:        putter_notify(pmp->pmp_pi);
                    393:
1.20      pooka     394:        DPRINTF(("touser: req %" PRIu64 ", preq: %p, park: %p, "
1.25      pooka     395:            "c/t: 0x%x/0x%x, f: 0x%x\n", preq->preq_id, preq, park,
                    396:            preq->preq_opclass, preq->preq_optype, park->park_flags));
1.57      pooka     397: }
1.15      pooka     398:
1.57      pooka     399: int
                    400: puffs_msg_wait(struct puffs_mount *pmp, struct puffs_msgpark *park)
                    401: {
                    402:        struct puffs_req *preq = park->park_preq; /* XXX: hmmm */
                    403:        int error = 0;
                    404:        int rv;
1.1       pooka     405:
1.57      pooka     406:        mutex_enter(&pmp->pmp_lock);
                    407:        puffs_mp_reference(pmp);
                    408:        mutex_exit(&pmp->pmp_lock);
1.46      pooka     409:
1.57      pooka     410:        mutex_enter(&park->park_mtx);
                    411:        if ((park->park_flags & PARKFLAG_WANTREPLY) == 0
                    412:            || (park->park_flags & PARKFLAG_CALL)) {
                    413:                mutex_exit(&park->park_mtx);
                    414:                rv = 0;
                    415:                goto skipwait;
                    416:        }
1.46      pooka     417:
1.57      pooka     418:        /* did the response beat us to the wait? */
                    419:        if (__predict_false((park->park_flags & PARKFLAG_DONE)
                    420:            || (park->park_flags & PARKFLAG_HASERROR))) {
                    421:                rv = park->park_preq->preq_rv;
                    422:                mutex_exit(&park->park_mtx);
                    423:                goto skipwait;
                    424:        }
1.26      pooka     425:
1.57      pooka     426:        error = cv_wait_sig(&park->park_cv, &park->park_mtx);
                    427:        DPRINTF(("puffs_touser: waiter for %p woke up with %d\n",
                    428:            park, error));
                    429:        if (error) {
                    430:                park->park_flags |= PARKFLAG_WAITERGONE;
                    431:                if (park->park_flags & PARKFLAG_DONE) {
                    432:                        rv = preq->preq_rv;
                    433:                        mutex_exit(&park->park_mtx);
                    434:                } else {
                    435:                        /*
                    436:                         * ok, we marked it as going away, but
                    437:                         * still need to do queue ops.  take locks
                    438:                         * in correct order.
                    439:                         *
                    440:                         * We don't want to release our reference
                    441:                         * if it's on replywait queue to avoid error
                    442:                         * to file server.  putop() code will DTRT.
                    443:                         */
                    444:                        mutex_exit(&park->park_mtx);
                    445:                        mutex_enter(&pmp->pmp_lock);
                    446:                        mutex_enter(&park->park_mtx);
                    447:
                    448:                        /*
                    449:                         * Still on queue1?  We can safely remove it
                    450:                         * without any consequences since the file
                    451:                         * server hasn't seen it.  "else" we need to
                    452:                         * wait for the response and just ignore it
                    453:                         * to avoid signalling an incorrect error to
                    454:                         * the file server.
                    455:                         */
                    456:                        if (park->park_flags & PARKFLAG_ONQUEUE1) {
                    457:                                TAILQ_REMOVE(&pmp->pmp_msg_touser,
                    458:                                    park, park_entries);
                    459:                                puffs_msgpark_release(park);
                    460:                                pmp->pmp_msg_touser_count--;
                    461:                                park->park_flags &= ~PARKFLAG_ONQUEUE1;
                    462:                        } else {
                    463:                                mutex_exit(&park->park_mtx);
1.19      pooka     464:                        }
1.57      pooka     465:                        mutex_exit(&pmp->pmp_lock);
1.22      pooka     466:
1.60      pooka     467:                        rv = EINTR;
1.16      pooka     468:                }
1.22      pooka     469:        } else {
1.57      pooka     470:                rv = preq->preq_rv;
                    471:                mutex_exit(&park->park_mtx);
1.16      pooka     472:        }
                    473:
1.57      pooka     474:  skipwait:
1.22      pooka     475:        mutex_enter(&pmp->pmp_lock);
1.34      pooka     476:        puffs_mp_release(pmp);
1.22      pooka     477:        mutex_exit(&pmp->pmp_lock);
1.16      pooka     478:
1.19      pooka     479:        return rv;
1.1       pooka     480: }
                    481:
1.9       pooka     482: /*
1.57      pooka     483:  * XXX: this suuuucks.  Hopefully I'll get rid of this lossage once
                    484:  * the whole setback-nonsense gets fixed.
                    485:  */
                    486: int
                    487: puffs_msg_wait2(struct puffs_mount *pmp, struct puffs_msgpark *park,
                    488:        struct puffs_node *pn1, struct puffs_node *pn2)
                    489: {
                    490:        struct puffs_req *preq;
                    491:        int rv;
                    492:
                    493:        rv = puffs_msg_wait(pmp, park);
                    494:
                    495:        preq = park->park_preq;
                    496:        if (pn1 && preq->preq_setbacks & PUFFS_SETBACK_INACT_N1)
                    497:                pn1->pn_stat |= PNODE_DOINACT;
                    498:        if (pn2 && preq->preq_setbacks & PUFFS_SETBACK_INACT_N2)
                    499:                pn2->pn_stat |= PNODE_DOINACT;
                    500:
                    501:        if (pn1 && preq->preq_setbacks & PUFFS_SETBACK_NOREF_N1)
                    502:                pn1->pn_stat |= PNODE_NOREFS;
                    503:        if (pn2 && preq->preq_setbacks & PUFFS_SETBACK_NOREF_N2)
                    504:                pn2->pn_stat |= PNODE_NOREFS;
                    505:
                    506:        return rv;
                    507:
                    508: }
                    509:
                    510: /*
1.61      pooka     511:  * XXX: lazy bum.  please, for the love of foie gras, fix me.
                    512:  * This should *NOT* depend on setfaf.  Also "memcpy" could
                    513:  * be done more nicely.
                    514:  */
                    515: void
                    516: puffs_msg_sendresp(struct puffs_mount *pmp, struct puffs_req *origpreq, int rv)
                    517: {
                    518:        struct puffs_msgpark *park;
                    519:        struct puffs_req *preq;
                    520:
1.63      pooka     521:        puffs_msgmem_alloc(sizeof(struct puffs_req), &park, (void *)&preq, 1);
1.61      pooka     522:        puffs_msg_setfaf(park); /* XXXXXX: avoids reqid override */
                    523:
                    524:        memcpy(preq, origpreq, sizeof(struct puffs_req));
                    525:        preq->preq_rv = rv;
                    526:        preq->preq_opclass |= PUFFSOPFLAG_ISRESPONSE;
                    527:
                    528:        puffs_msg_enqueue(pmp, park);
                    529:        puffs_msgmem_release(park);
                    530: }
                    531:
                    532: /*
1.46      pooka     533:  * Get next request in the outgoing queue.  "maxsize" controls the
                    534:  * size the caller can accommodate and "nonblock" signals if this
                    535:  * should block while waiting for input.  Handles all locking internally.
1.9       pooka     536:  */
1.10      pooka     537: int
1.46      pooka     538: puffs_msgif_getout(void *this, size_t maxsize, int nonblock,
                    539:        uint8_t **data, size_t *dlen, void **parkptr)
1.1       pooka     540: {
1.46      pooka     541:        struct puffs_mount *pmp = this;
                    542:        struct puffs_msgpark *park;
1.9       pooka     543:        struct puffs_req *preq;
1.46      pooka     544:        int error;
1.1       pooka     545:
1.46      pooka     546:        error = 0;
1.22      pooka     547:        mutex_enter(&pmp->pmp_lock);
1.50      pooka     548:        puffs_mp_reference(pmp);
1.46      pooka     549:        for (;;) {
                    550:                /* RIP? */
1.9       pooka     551:                if (pmp->pmp_status != PUFFSTAT_RUNNING) {
                    552:                        error = ENXIO;
1.46      pooka     553:                        break;
1.9       pooka     554:                }
1.12      pooka     555:
1.46      pooka     556:                /* need platinum yendorian express card? */
                    557:                if (TAILQ_EMPTY(&pmp->pmp_msg_touser)) {
                    558:                        DPRINTF(("puffs_getout: no outgoing op, "));
1.12      pooka     559:                        if (nonblock) {
1.46      pooka     560:                                DPRINTF(("returning EWOULDBLOCK\n"));
1.12      pooka     561:                                error = EWOULDBLOCK;
1.46      pooka     562:                                break;
1.9       pooka     563:                        }
1.46      pooka     564:                        DPRINTF(("waiting ...\n"));
1.9       pooka     565:
1.46      pooka     566:                        error = cv_wait_sig(&pmp->pmp_msg_waiter_cv,
1.22      pooka     567:                            &pmp->pmp_lock);
1.11      pooka     568:                        if (error)
1.46      pooka     569:                                break;
1.11      pooka     570:                        else
1.46      pooka     571:                                continue;
1.9       pooka     572:                }
                    573:
1.46      pooka     574:                park = TAILQ_FIRST(&pmp->pmp_msg_touser);
1.50      pooka     575:                if (park == NULL)
                    576:                        continue;
                    577:
1.46      pooka     578:                mutex_enter(&park->park_mtx);
                    579:                puffs_msgpark_reference(park);
                    580:
                    581:                DPRINTF(("puffs_getout: found park at %p, ", park));
1.22      pooka     582:
                    583:                /* If it's a goner, don't process any furher */
                    584:                if (park->park_flags & PARKFLAG_WAITERGONE) {
1.46      pooka     585:                        DPRINTF(("waitergone!\n"));
                    586:                        puffs_msgpark_release(park);
1.22      pooka     587:                        continue;
                    588:                }
1.55      pooka     589:                preq = park->park_preq;
1.22      pooka     590:
1.55      pooka     591: #if 0
1.46      pooka     592:                /* check size */
1.55      pooka     593:                /*
                    594:                 * XXX: this check is not valid for now, we don't know
                    595:                 * the size of the caller's input buffer.  i.e. this
                    596:                 * will most likely go away
                    597:                 */
1.46      pooka     598:                if (maxsize < preq->preq_frhdr.pfr_len) {
                    599:                        DPRINTF(("buffer too small\n"));
                    600:                        puffs_msgpark_release(park);
                    601:                        error = E2BIG;
                    602:                        break;
1.26      pooka     603:                }
1.55      pooka     604: #endif
1.28      pooka     605:
1.46      pooka     606:                DPRINTF(("returning\n"));
                    607:
                    608:                /*
                    609:                 * Ok, we found what we came for.  Release it from the
                    610:                 * outgoing queue but do not unlock.  We will unlock
                    611:                 * only after we "releaseout" it to avoid complications:
                    612:                 * otherwise it is (theoretically) possible for userland
                    613:                 * to race us into "put" before we have a change to put
                    614:                 * this baby on the receiving queue.
                    615:                 */
                    616:                TAILQ_REMOVE(&pmp->pmp_msg_touser, park, park_entries);
1.28      pooka     617:                KASSERT(park->park_flags & PARKFLAG_ONQUEUE1);
                    618:                park->park_flags &= ~PARKFLAG_ONQUEUE1;
1.46      pooka     619:                mutex_exit(&park->park_mtx);
                    620:
                    621:                pmp->pmp_msg_touser_count--;
                    622:                KASSERT(pmp->pmp_msg_touser_count >= 0);
1.26      pooka     623:
1.46      pooka     624:                break;
                    625:        }
1.50      pooka     626:        puffs_mp_release(pmp);
1.46      pooka     627:        mutex_exit(&pmp->pmp_lock);
1.9       pooka     628:
1.46      pooka     629:        if (error == 0) {
                    630:                *data = (uint8_t *)preq;
1.55      pooka     631:                preq->preq_pth.pth_framelen = park->park_copylen;
                    632:                *dlen = preq->preq_pth.pth_framelen;
1.46      pooka     633:                *parkptr = park;
                    634:        }
1.51      pooka     635:
1.46      pooka     636:        return error;
                    637: }
1.9       pooka     638:
1.46      pooka     639: /*
                    640:  * Release outgoing structure.  Now, depending on the success of the
                    641:  * outgoing send, it is either going onto the result waiting queue
                    642:  * or the death chamber.
                    643:  */
                    644: void
                    645: puffs_msgif_releaseout(void *this, void *parkptr, int status)
                    646: {
                    647:        struct puffs_mount *pmp = this;
                    648:        struct puffs_msgpark *park = parkptr;
1.32      pooka     649:
1.46      pooka     650:        DPRINTF(("puffs_releaseout: returning park %p, errno %d: " ,
                    651:            park, status));
                    652:        mutex_enter(&pmp->pmp_lock);
                    653:        mutex_enter(&park->park_mtx);
                    654:        if (park->park_flags & PARKFLAG_WANTREPLY) {
                    655:                if (status == 0) {
                    656:                        DPRINTF(("enqueue replywait\n"));
                    657:                        TAILQ_INSERT_TAIL(&pmp->pmp_msg_replywait, park,
1.22      pooka     658:                            park_entries);
1.26      pooka     659:                        park->park_flags |= PARKFLAG_ONQUEUE2;
1.9       pooka     660:                } else {
1.46      pooka     661:                        DPRINTF(("error path!\n"));
                    662:                        park->park_preq->preq_rv = status;
                    663:                        park->park_flags |= PARKFLAG_DONE;
                    664:                        cv_signal(&park->park_cv);
1.1       pooka     665:                }
1.46      pooka     666:                puffs_msgpark_release(park);
                    667:        } else {
                    668:                DPRINTF(("release\n"));
                    669:                puffs_msgpark_release1(park, 2);
1.1       pooka     670:        }
1.22      pooka     671:        mutex_exit(&pmp->pmp_lock);
1.1       pooka     672: }
                    673:
1.53      pooka     674: size_t
                    675: puffs_msgif_waitcount(void *this)
                    676: {
                    677:        struct puffs_mount *pmp = this;
                    678:        size_t rv;
                    679:
                    680:        mutex_enter(&pmp->pmp_lock);
                    681:        rv = pmp->pmp_msg_touser_count;
                    682:        mutex_exit(&pmp->pmp_lock);
                    683:
                    684:        return rv;
                    685: }
                    686:
1.50      pooka     687: /*
                    688:  * XXX: locking with this one?
                    689:  */
1.53      pooka     690: static void
1.56      pooka     691: puffsop_msg(void *this, struct puffs_req *preq)
1.1       pooka     692: {
1.46      pooka     693:        struct puffs_mount *pmp = this;
1.55      pooka     694:        struct putter_hdr *pth = &preq->preq_pth;
1.46      pooka     695:        struct puffs_msgpark *park;
1.57      pooka     696:        int wgone;
1.1       pooka     697:
1.22      pooka     698:        mutex_enter(&pmp->pmp_lock);
1.9       pooka     699:
1.46      pooka     700:        /* Locate waiter */
                    701:        TAILQ_FOREACH(park, &pmp->pmp_msg_replywait, park_entries) {
                    702:                if (park->park_preq->preq_id == preq->preq_id)
1.1       pooka     703:                        break;
1.46      pooka     704:        }
                    705:        if (park == NULL) {
1.58      pooka     706:                DPRINTF(("puffsop_msg: no request: %" PRIu64 "\n",
1.46      pooka     707:                    preq->preq_id));
                    708:                mutex_exit(&pmp->pmp_lock);
                    709:                return; /* XXX send error */
                    710:        }
1.26      pooka     711:
1.46      pooka     712:        mutex_enter(&park->park_mtx);
                    713:        puffs_msgpark_reference(park);
1.55      pooka     714:        if (pth->pth_framelen > park->park_maxlen) {
1.58      pooka     715:                DPRINTF(("puffsop_msg: invalid buffer length: "
1.55      pooka     716:                    "%" PRIu64 " (req %" PRIu64 ", \n", pth->pth_framelen,
                    717:                    preq->preq_id));
1.46      pooka     718:                park->park_preq->preq_rv = EPROTO;
                    719:                cv_signal(&park->park_cv);
1.57      pooka     720:                puffs_msgpark_release1(park, 2);
1.22      pooka     721:                mutex_exit(&pmp->pmp_lock);
1.46      pooka     722:                return; /* XXX: error */
                    723:        }
                    724:        wgone = park->park_flags & PARKFLAG_WAITERGONE;
1.9       pooka     725:
1.46      pooka     726:        KASSERT(park->park_flags & PARKFLAG_ONQUEUE2);
                    727:        TAILQ_REMOVE(&pmp->pmp_msg_replywait, park, park_entries);
                    728:        park->park_flags &= ~PARKFLAG_ONQUEUE2;
                    729:        mutex_exit(&pmp->pmp_lock);
1.24      pooka     730:
1.46      pooka     731:        if (wgone) {
1.58      pooka     732:                DPRINTF(("puffsop_msg: bad service - waiter gone for "
1.46      pooka     733:                    "park %p\n", park));
                    734:        } else {
1.24      pooka     735:                if (park->park_flags & PARKFLAG_CALL) {
1.58      pooka     736:                        DPRINTF(("puffsop_msg: call for %p, arg %p\n",
1.40      pooka     737:                            park->park_preq, park->park_donearg));
1.55      pooka     738:                        park->park_done(pmp, preq, park->park_donearg);
1.46      pooka     739:                } else {
                    740:                        /* XXX: yes, I know */
1.55      pooka     741:                        memcpy(park->park_preq, preq, pth->pth_framelen);
1.20      pooka     742:                }
1.46      pooka     743:        }
1.1       pooka     744:
1.46      pooka     745:        if (!wgone) {
                    746:                DPRINTF(("puffs_putop: flagging done for "
                    747:                    "park %p\n", park));
                    748:                cv_signal(&park->park_cv);
1.1       pooka     749:        }
                    750:
1.46      pooka     751:        park->park_flags |= PARKFLAG_DONE;
1.57      pooka     752:        puffs_msgpark_release1(park, 2);
1.1       pooka     753: }
                    754:
1.61      pooka     755: static void
1.53      pooka     756: puffsop_flush(struct puffs_mount *pmp, struct puffs_flush *pf)
                    757: {
                    758:        struct vnode *vp;
                    759:        voff_t offlo, offhi;
                    760:        int rv, flags = 0;
                    761:
1.61      pooka     762:        if (pf->pf_req.preq_pth.pth_framelen != sizeof(struct puffs_flush)) {
                    763:                rv = EINVAL;
                    764:                goto out;
                    765:        }
                    766:
1.53      pooka     767:        /* XXX: slurry */
                    768:        if (pf->pf_op == PUFFS_INVAL_NAMECACHE_ALL) {
                    769:                cache_purgevfs(PMPTOMP(pmp));
1.61      pooka     770:                rv = 0;
                    771:                goto out;
1.53      pooka     772:        }
                    773:
                    774:        /*
                    775:         * Get vnode, don't lock it.  Namecache is protected by its own lock
                    776:         * and we have a reference to protect against premature harvesting.
                    777:         *
                    778:         * The node we want here might be locked and the op is in
                    779:         * userspace waiting for us to complete ==> deadlock.  Another
                    780:         * reason we need to eventually bump locking to userspace, as we
                    781:         * will need to lock the node if we wish to do flushes.
                    782:         */
                    783:        rv = puffs_cookie2vnode(pmp, pf->pf_cookie, 0, 0, &vp);
                    784:        if (rv) {
                    785:                if (rv == PUFFS_NOSUCHCOOKIE)
1.61      pooka     786:                        rv = ENOENT;
                    787:                goto out;
1.53      pooka     788:        }
                    789:
                    790:        switch (pf->pf_op) {
                    791: #if 0
                    792:        /* not quite ready, yet */
                    793:        case PUFFS_INVAL_NAMECACHE_NODE:
                    794:        struct componentname *pf_cn;
                    795:        char *name;
                    796:                /* get comfortab^Wcomponentname */
1.59      pooka     797:                pf_cn = kmem_alloc(componentname);
1.53      pooka     798:                memset(pf_cn, 0, sizeof(struct componentname));
                    799:                break;
                    800:
                    801: #endif
                    802:        case PUFFS_INVAL_NAMECACHE_DIR:
                    803:                if (vp->v_type != VDIR) {
                    804:                        rv = EINVAL;
                    805:                        break;
                    806:                }
                    807:                cache_purge1(vp, NULL, PURGE_CHILDREN);
                    808:                break;
                    809:
                    810:        case PUFFS_INVAL_PAGECACHE_NODE_RANGE:
                    811:                flags = PGO_FREE;
                    812:                /*FALLTHROUGH*/
                    813:        case PUFFS_FLUSH_PAGECACHE_NODE_RANGE:
                    814:                if (flags == 0)
                    815:                        flags = PGO_CLEANIT;
                    816:
                    817:                if (pf->pf_end > vp->v_size || vp->v_type != VREG) {
                    818:                        rv = EINVAL;
                    819:                        break;
                    820:                }
                    821:
                    822:                offlo = trunc_page(pf->pf_start);
                    823:                offhi = round_page(pf->pf_end);
                    824:                if (offhi != 0 && offlo >= offhi) {
                    825:                        rv = EINVAL;
                    826:                        break;
                    827:                }
                    828:
1.62      ad        829:                mutex_enter(&vp->v_uobj.vmobjlock);
1.53      pooka     830:                rv = VOP_PUTPAGES(vp, offlo, offhi, flags);
                    831:                break;
                    832:
                    833:        default:
                    834:                rv = EINVAL;
                    835:        }
                    836:
                    837:        vrele(vp);
                    838:
1.61      pooka     839:  out:
                    840:        puffs_msg_sendresp(pmp, &pf->pf_req, rv);
1.53      pooka     841: }
                    842:
                    843: int
1.56      pooka     844: puffs_msgif_dispatch(void *this, struct putter_hdr *pth)
1.53      pooka     845: {
                    846:        struct puffs_mount *pmp = this;
1.56      pooka     847:        struct puffs_req *preq = (struct puffs_req *)pth;
1.74      pooka     848:        int rv = 0;
1.56      pooka     849:
                    850:        /* XXX: need to send error to userspace */
1.61      pooka     851:        if (pth->pth_framelen < sizeof(struct puffs_req)) {
                    852:                puffs_msg_sendresp(pmp, preq, EINVAL); /* E2SMALL */
                    853:                return 0;
                    854:        }
1.53      pooka     855:
1.55      pooka     856:        switch (PUFFSOP_OPCLASS(preq->preq_opclass)) {
1.53      pooka     857:        case PUFFSOP_VN:
                    858:        case PUFFSOP_VFS:
1.61      pooka     859:                DPRINTF(("dispatch: vn/vfs message 0x%x\n", preq->preq_optype));
1.56      pooka     860:                puffsop_msg(pmp, preq);
1.53      pooka     861:                break;
                    862:        case PUFFSOP_FLUSH:
1.61      pooka     863:                DPRINTF(("dispatch: flush 0x%x\n", preq->preq_optype));
1.56      pooka     864:                puffsop_flush(pmp, (struct puffs_flush *)preq);
1.53      pooka     865:                break;
                    866:        default:
1.61      pooka     867:                DPRINTF(("dispatch: invalid class 0x%x\n", preq->preq_opclass));
1.75    ! pooka     868:                puffs_msg_sendresp(pmp, preq, EOPNOTSUPP);
1.53      pooka     869:                break;
                    870:        }
                    871:
1.74      pooka     872:        return rv;
1.53      pooka     873: }
                    874:
                    875: int
                    876: puffs_msgif_close(void *this)
                    877: {
                    878:        struct puffs_mount *pmp = this;
                    879:        struct mount *mp = PMPTOMP(pmp);
                    880:
                    881:        mutex_enter(&pmp->pmp_lock);
                    882:        puffs_mp_reference(pmp);
                    883:
                    884:        /*
                    885:         * Free the waiting callers before proceeding any further.
                    886:         * The syncer might be jogging around in this file system
                    887:         * currently.  If we allow it to go to the userspace of no
                    888:         * return while trying to get the syncer lock, well ...
                    889:         */
                    890:        puffs_userdead(pmp);
                    891:
                    892:        /*
                    893:         * Make sure someone from puffs_unmount() isn't currently in
                    894:         * userspace.  If we don't take this precautionary step,
                    895:         * they might notice that the mountpoint has disappeared
                    896:         * from under them once they return.  Especially note that we
                    897:         * cannot simply test for an unmounter before calling
                    898:         * dounmount(), since it might be possible that that particular
                    899:         * invocation of unmount was called without MNT_FORCE.  Here we
                    900:         * *must* make sure unmount succeeds.  Also, restart is necessary
                    901:         * since pmp isn't locked.  We might end up with PUTTER_DEAD after
                    902:         * restart and exit from there.
                    903:         */
                    904:        if (pmp->pmp_unmounting) {
                    905:                cv_wait(&pmp->pmp_unmounting_cv, &pmp->pmp_lock);
                    906:                puffs_mp_release(pmp);
                    907:                mutex_exit(&pmp->pmp_lock);
                    908:                DPRINTF(("puffs_fop_close: unmount was in progress for pmp %p, "
                    909:                    "restart\n", pmp));
                    910:                return ERESTART;
                    911:        }
                    912:
                    913:        /* Won't access pmp from here anymore */
1.72      ad        914:        atomic_inc_uint((unsigned int*)&mp->mnt_refcnt);
1.53      pooka     915:        puffs_mp_release(pmp);
                    916:        mutex_exit(&pmp->pmp_lock);
                    917:
1.72      ad        918:        /* Detach from VFS. */
1.71      ad        919:        (void)dounmount(mp, MNT_FORCE, curlwp);
1.72      ad        920:        vfs_destroy(mp);
1.53      pooka     921:
                    922:        return 0;
                    923: }
                    924:
                    925: /*
1.22      pooka     926:  * We're dead, kaput, RIP, slightly more than merely pining for the
                    927:  * fjords, belly-up, fallen, lifeless, finished, expired, gone to meet
                    928:  * our maker, ceased to be, etcetc.  YASD.  It's a dead FS!
                    929:  *
                    930:  * Caller must hold puffs mutex.
                    931:  */
                    932: void
                    933: puffs_userdead(struct puffs_mount *pmp)
                    934: {
1.46      pooka     935:        struct puffs_msgpark *park, *park_next;
1.22      pooka     936:
                    937:        /*
                    938:         * Mark filesystem status as dying so that operations don't
                    939:         * attempt to march to userspace any longer.
                    940:         */
                    941:        pmp->pmp_status = PUFFSTAT_DYING;
                    942:
                    943:        /* signal waiters on REQUEST TO file server queue */
1.46      pooka     944:        for (park = TAILQ_FIRST(&pmp->pmp_msg_touser); park; park = park_next) {
1.24      pooka     945:                uint8_t opclass;
                    946:
1.46      pooka     947:                mutex_enter(&park->park_mtx);
                    948:                puffs_msgpark_reference(park);
1.32      pooka     949:                park_next = TAILQ_NEXT(park, park_entries);
1.26      pooka     950:
                    951:                KASSERT(park->park_flags & PARKFLAG_ONQUEUE1);
1.46      pooka     952:                TAILQ_REMOVE(&pmp->pmp_msg_touser, park, park_entries);
1.26      pooka     953:                park->park_flags &= ~PARKFLAG_ONQUEUE1;
1.46      pooka     954:                pmp->pmp_msg_touser_count--;
1.22      pooka     955:
1.31      pooka     956:                /*
1.51      pooka     957:                 * Even though waiters on QUEUE1 are removed in touser()
                    958:                 * in case of WAITERGONE, it is still possible for us to
                    959:                 * get raced here due to having to retake locks in said
                    960:                 * touser().  In the race case simply "ignore" the item
                    961:                 * on the queue and move on to the next one.
1.31      pooka     962:                 */
                    963:                if (park->park_flags & PARKFLAG_WAITERGONE) {
                    964:                        KASSERT((park->park_flags & PARKFLAG_CALL) == 0);
                    965:                        KASSERT(park->park_flags & PARKFLAG_WANTREPLY);
1.46      pooka     966:                        puffs_msgpark_release(park);
1.51      pooka     967:
1.22      pooka     968:                } else {
1.31      pooka     969:                        opclass = park->park_preq->preq_opclass;
1.23      pooka     970:                        park->park_preq->preq_rv = ENXIO;
1.31      pooka     971:
                    972:                        if (park->park_flags & PARKFLAG_CALL) {
1.42      pooka     973:                                park->park_done(pmp, park->park_preq,
1.31      pooka     974:                                    park->park_donearg);
1.46      pooka     975:                                puffs_msgpark_release1(park, 2);
1.31      pooka     976:                        } else if ((park->park_flags & PARKFLAG_WANTREPLY)==0) {
1.46      pooka     977:                                puffs_msgpark_release1(park, 2);
1.31      pooka     978:                        } else {
                    979:                                park->park_preq->preq_rv = ENXIO;
                    980:                                cv_signal(&park->park_cv);
1.46      pooka     981:                                puffs_msgpark_release(park);
1.31      pooka     982:                        }
1.22      pooka     983:                }
                    984:        }
                    985:
                    986:        /* signal waiters on RESPONSE FROM file server queue */
1.46      pooka     987:        for (park=TAILQ_FIRST(&pmp->pmp_msg_replywait); park; park=park_next) {
                    988:                mutex_enter(&park->park_mtx);
                    989:                puffs_msgpark_reference(park);
1.32      pooka     990:                park_next = TAILQ_NEXT(park, park_entries);
1.26      pooka     991:
                    992:                KASSERT(park->park_flags & PARKFLAG_ONQUEUE2);
1.31      pooka     993:                KASSERT(park->park_flags & PARKFLAG_WANTREPLY);
1.26      pooka     994:
1.46      pooka     995:                TAILQ_REMOVE(&pmp->pmp_msg_replywait, park, park_entries);
1.26      pooka     996:                park->park_flags &= ~PARKFLAG_ONQUEUE2;
                    997:
1.31      pooka     998:                if (park->park_flags & PARKFLAG_WAITERGONE) {
                    999:                        KASSERT((park->park_flags & PARKFLAG_CALL) == 0);
1.46      pooka    1000:                        puffs_msgpark_release(park);
1.22      pooka    1001:                } else {
1.31      pooka    1002:                        park->park_preq->preq_rv = ENXIO;
                   1003:                        if (park->park_flags & PARKFLAG_CALL) {
1.42      pooka    1004:                                park->park_done(pmp, park->park_preq,
1.31      pooka    1005:                                    park->park_donearg);
1.46      pooka    1006:                                puffs_msgpark_release1(park, 2);
1.31      pooka    1007:                        } else {
                   1008:                                cv_signal(&park->park_cv);
1.46      pooka    1009:                                puffs_msgpark_release(park);
1.31      pooka    1010:                        }
1.22      pooka    1011:                }
                   1012:        }
1.50      pooka    1013:
                   1014:        cv_broadcast(&pmp->pmp_msg_waiter_cv);
1.22      pooka    1015: }

CVSweb <webmaster@jp.NetBSD.org>