[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.40.4.5

1.40.4.5! jmcneill    1: /*     $NetBSD: puffs_msgif.c,v 1.51 2007/11/04 17:32:34 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.40.4.5! jmcneill   33: __KERNEL_RCSID(0, "$NetBSD: puffs_msgif.c,v 1.51 2007/11/04 17:32:34 pooka Exp $");
1.1       pooka      34:
                     35: #include <sys/param.h>
1.16      pooka      36: #include <sys/fstrans.h>
1.40.4.3  joerg      37: #include <sys/kmem.h>
1.1       pooka      38: #include <sys/malloc.h>
                     39: #include <sys/mount.h>
                     40: #include <sys/vnode.h>
                     41: #include <sys/lock.h>
1.39      ad         42: #include <sys/proc.h>
1.1       pooka      43:
                     44: #include <fs/puffs/puffs_msgif.h>
                     45: #include <fs/puffs/puffs_sys.h>
                     46:
1.22      pooka      47: /*
                     48:  * waitq data structures
                     49:  */
                     50:
                     51: /*
                     52:  * While a request is going to userspace, park the caller within the
                     53:  * kernel.  This is the kernel counterpart of "struct puffs_req".
                     54:  */
1.40.4.3  joerg      55: struct puffs_msgpark {
1.22      pooka      56:        struct puffs_req        *park_preq;     /* req followed by buf  */
                     57:
                     58:        size_t                  park_copylen;   /* userspace copylength */
                     59:        size_t                  park_maxlen;    /* max size in comeback */
1.24      pooka      60:
1.40.4.3  joerg      61:        parkdone_fn             park_done;      /* "biodone" a'la puffs */
1.24      pooka      62:        void                    *park_donearg;
1.22      pooka      63:
                     64:        int                     park_flags;
1.26      pooka      65:        int                     park_refcount;
1.22      pooka      66:
                     67:        kcondvar_t              park_cv;
1.26      pooka      68:        kmutex_t                park_mtx;
                     69:
1.40.4.3  joerg      70:        TAILQ_ENTRY(puffs_msgpark) park_entries;
1.22      pooka      71: };
                     72: #define PARKFLAG_WAITERGONE    0x01
1.26      pooka      73: #define PARKFLAG_DONE          0x02
                     74: #define PARKFLAG_ONQUEUE1      0x04
                     75: #define PARKFLAG_ONQUEUE2      0x08
                     76: #define PARKFLAG_CALL          0x10
1.31      pooka      77: #define PARKFLAG_WANTREPLY     0x20
1.22      pooka      78:
                     79: static struct pool_cache parkpc;
                     80: static struct pool parkpool;
                     81:
                     82: static int
                     83: makepark(void *arg, void *obj, int flags)
                     84: {
1.40.4.3  joerg      85:        struct puffs_msgpark *park = obj;
1.22      pooka      86:
1.26      pooka      87:        mutex_init(&park->park_mtx, MUTEX_DEFAULT, IPL_NONE);
1.22      pooka      88:        cv_init(&park->park_cv, "puffsrpl");
                     89:
                     90:        return 0;
                     91: }
                     92:
                     93: static void
                     94: nukepark(void *arg, void *obj)
                     95: {
1.40.4.3  joerg      96:        struct puffs_msgpark *park = obj;
1.22      pooka      97:
                     98:        cv_destroy(&park->park_cv);
1.26      pooka      99:        mutex_destroy(&park->park_mtx);
1.22      pooka     100: }
                    101:
                    102: void
                    103: puffs_msgif_init()
                    104: {
                    105:
1.40.4.3  joerg     106:        pool_init(&parkpool, sizeof(struct puffs_msgpark), 0, 0, 0,
1.22      pooka     107:            "puffprkl", &pool_allocator_nointr, IPL_NONE);
                    108:        pool_cache_init(&parkpc, &parkpool, makepark, nukepark, NULL);
                    109: }
                    110:
                    111: void
                    112: puffs_msgif_destroy()
                    113: {
                    114:
                    115:        pool_cache_destroy(&parkpc);
                    116:        pool_destroy(&parkpool);
                    117: }
                    118:
1.40.4.3  joerg     119: static int alloced;
                    120:
                    121: static struct puffs_msgpark *
                    122: puffs_msgpark_alloc(int waitok)
1.26      pooka     123: {
1.40.4.3  joerg     124:        struct puffs_msgpark *park;
1.26      pooka     125:
                    126:        park = pool_cache_get(&parkpc, waitok ? PR_WAITOK : PR_NOWAIT);
1.40.4.3  joerg     127:        if (park == NULL)
                    128:                return park;
                    129:
                    130:        park->park_refcount = 1;
                    131:        park->park_preq = NULL;
                    132:        park->park_flags = PARKFLAG_WANTREPLY;
1.26      pooka     133:
                    134:        return park;
                    135: }
                    136:
                    137: static void
1.40.4.3  joerg     138: puffs_msgpark_reference(struct puffs_msgpark *park)
1.22      pooka     139: {
                    140:
1.40.4.3  joerg     141:        KASSERT(mutex_owned(&park->park_mtx));
1.26      pooka     142:        park->park_refcount++;
1.22      pooka     143: }
                    144:
1.40.4.3  joerg     145: /*
                    146:  * Release reference to park structure.
                    147:  */
                    148: static void
                    149: puffs_msgpark_release1(struct puffs_msgpark *park, int howmany)
1.22      pooka     150: {
1.40.4.3  joerg     151:        struct puffs_req *preq = park->park_preq;
                    152:        int refcnt;
1.22      pooka     153:
1.26      pooka     154:        KASSERT(mutex_owned(&park->park_mtx));
1.40.4.3  joerg     155:        refcnt = park->park_refcount -= howmany;
1.26      pooka     156:        mutex_exit(&park->park_mtx);
1.40.4.3  joerg     157:
                    158:        KASSERT(refcnt >= 0);
                    159:
                    160:        if (refcnt == 0) {
                    161:                alloced--;
                    162:                if (preq)
                    163:                        kmem_free(preq, park->park_maxlen);
1.26      pooka     164:                pool_cache_put(&parkpc, park);
1.40.4.3  joerg     165:        }
1.22      pooka     166: }
1.40.4.3  joerg     167: #define puffs_msgpark_release(a) puffs_msgpark_release1(a, 1)
1.22      pooka     168:
1.26      pooka     169: #ifdef PUFFSDEBUG
                    170: static void
1.40.4.3  joerg     171: parkdump(struct puffs_msgpark *park)
1.26      pooka     172: {
                    173:
                    174:        DPRINTF(("park %p, preq %p, id %" PRIu64 "\n"
                    175:            "\tcopy %zu, max %zu - done: %p/%p\n"
                    176:            "\tflags 0x%08x, refcount %d, cv/mtx: %p/%p\n",
1.40.4.3  joerg     177:            park, park->park_preq, park->park_preq->preq_id,
1.26      pooka     178:            park->park_copylen, park->park_maxlen,
                    179:            park->park_done, park->park_donearg,
                    180:            park->park_flags, park->park_refcount,
                    181:            &park->park_cv, &park->park_mtx));
                    182: }
                    183:
                    184: static void
                    185: parkqdump(struct puffs_wq *q, int dumpall)
                    186: {
1.40.4.3  joerg     187:        struct puffs_msgpark *park;
1.26      pooka     188:        int total = 0;
                    189:
                    190:        TAILQ_FOREACH(park, q, park_entries) {
                    191:                if (dumpall)
                    192:                        parkdump(park);
                    193:                total++;
                    194:        }
1.29      pooka     195:        DPRINTF(("puffs waitqueue at %p dumped, %d total\n", q, total));
1.26      pooka     196:
                    197: }
                    198: #endif /* PUFFSDEBUG */
1.22      pooka     199:
                    200: /*
1.40.4.3  joerg     201:  * A word about locking in the park structures: the lock protects the
                    202:  * fields of the *park* structure (not preq) and acts as an interlock
                    203:  * in cv operations.  The lock is always internal to this module and
                    204:  * callers do not need to worry about it.
1.22      pooka     205:  */
1.40.4.3  joerg     206:
                    207: int
                    208: puffs_msgmem_alloc(size_t len, struct puffs_msgpark **ppark, void **mem,
                    209:        int cansleep)
1.22      pooka     210: {
1.40.4.3  joerg     211:        struct puffs_msgpark *park;
                    212:        void *m;
1.22      pooka     213:
1.40.4.3  joerg     214:        m = kmem_zalloc(len, cansleep ? KM_SLEEP : KM_NOSLEEP);
                    215:        if (m == NULL) {
                    216:                KASSERT(cansleep == 0);
                    217:                return ENOMEM;
                    218:        }
1.22      pooka     219:
1.40.4.3  joerg     220:        park = puffs_msgpark_alloc(cansleep);
                    221:        if (park == NULL) {
                    222:                KASSERT(cansleep == 0);
                    223:                kmem_free(m, len);
                    224:                return ENOMEM;
                    225:        }
1.22      pooka     226:
1.40.4.3  joerg     227:        park->park_preq = m;
                    228:        park->park_maxlen = len;
1.22      pooka     229:
1.40.4.3  joerg     230:        *ppark = park;
                    231:        *mem = m;
                    232:
                    233:        return 0;
1.22      pooka     234: }
                    235:
1.40.4.3  joerg     236: void
                    237: puffs_msgmem_release(struct puffs_msgpark *park)
                    238: {
                    239:
                    240:        if (park == NULL)
                    241:                return;
                    242:
                    243:        mutex_enter(&park->park_mtx);
                    244:        puffs_msgpark_release(park);
                    245: }
                    246:
                    247: void
                    248: puffs_msg_setfaf(struct puffs_msgpark *park)
                    249: {
                    250:
                    251:        park->park_flags &= ~PARKFLAG_WANTREPLY;
                    252: }
1.1       pooka     253:
                    254: /*
                    255:  * kernel-user-kernel waitqueues
                    256:  */
                    257:
1.40.4.3  joerg     258: static int touser(struct puffs_mount *, struct puffs_msgpark *);
1.1       pooka     259:
1.40.4.3  joerg     260: static uint64_t
                    261: puffs_getmsgid(struct puffs_mount *pmp)
1.1       pooka     262: {
1.14      pooka     263:        uint64_t rv;
1.1       pooka     264:
1.22      pooka     265:        mutex_enter(&pmp->pmp_lock);
1.40.4.3  joerg     266:        rv = pmp->pmp_nextmsgid++;
1.22      pooka     267:        mutex_exit(&pmp->pmp_lock);
1.1       pooka     268:
                    269:        return rv;
                    270: }
                    271:
                    272: /* vfs request */
                    273: int
1.40.4.3  joerg     274: puffs_msg_vfs(struct puffs_mount *pmp, struct puffs_msgpark *park, int optype)
1.1       pooka     275: {
                    276:
1.25      pooka     277:        park->park_preq->preq_opclass = PUFFSOP_VFS;
                    278:        park->park_preq->preq_optype = optype;
1.1       pooka     279:
1.40.4.3  joerg     280:        park->park_copylen = park->park_maxlen;
1.1       pooka     281:
1.40.4.3  joerg     282:        return touser(pmp, park);
1.16      pooka     283: }
                    284:
1.1       pooka     285: /*
                    286:  * vnode level request
                    287:  */
                    288: int
1.40.4.3  joerg     289: puffs_msg_vn(struct puffs_mount *pmp, struct puffs_msgpark *park,
                    290:        int optype, size_t delta, struct vnode *vp_opc, struct vnode *vp_aux)
1.1       pooka     291: {
1.35      pooka     292:        struct puffs_req *preq;
                    293:        void *cookie = VPTOPNC(vp_opc);
                    294:        struct puffs_node *pnode;
                    295:        int rv;
1.1       pooka     296:
1.25      pooka     297:        park->park_preq->preq_opclass = PUFFSOP_VN;
                    298:        park->park_preq->preq_optype = optype;
                    299:        park->park_preq->preq_cookie = cookie;
                    300:
1.40.4.3  joerg     301:        KASSERT(delta < park->park_maxlen); /* "<=" wouldn't make sense */
                    302:        park->park_copylen = park->park_maxlen - delta;
1.1       pooka     303:
1.40.4.3  joerg     304:        rv = touser(pmp, park);
1.35      pooka     305:
                    306:        /*
                    307:         * Check if the user server requests that inactive be called
                    308:         * when the time is right.
                    309:         */
                    310:        preq = park->park_preq;
                    311:        if (preq->preq_setbacks & PUFFS_SETBACK_INACT_N1) {
                    312:                pnode = vp_opc->v_data;
                    313:                pnode->pn_stat |= PNODE_DOINACT;
                    314:        }
                    315:        if (preq->preq_setbacks & PUFFS_SETBACK_INACT_N2) {
                    316:                /* if no vp_aux, just ignore */
                    317:                if (vp_aux) {
                    318:                        pnode = vp_aux->v_data;
                    319:                        pnode->pn_stat |= PNODE_DOINACT;
                    320:                }
                    321:        }
1.37      pooka     322:        if (preq->preq_setbacks & PUFFS_SETBACK_NOREF_N1) {
                    323:                pnode = vp_opc->v_data;
                    324:                pnode->pn_stat |= PNODE_NOREFS;
                    325:        }
                    326:        if (preq->preq_setbacks & PUFFS_SETBACK_NOREF_N2) {
                    327:                /* if no vp_aux, just ignore */
                    328:                if (vp_aux) {
                    329:                        pnode = vp_aux->v_data;
                    330:                        pnode->pn_stat |= PNODE_NOREFS;
                    331:                }
                    332:        }
1.35      pooka     333:
                    334:        return rv;
1.1       pooka     335: }
                    336:
1.24      pooka     337: void
1.40.4.3  joerg     338: puffs_msg_vncall(struct puffs_mount *pmp, struct puffs_msgpark *park,
                    339:        int optype, size_t delta, parkdone_fn donefn, void *donearg,
                    340:        struct vnode *vp_opc)
1.1       pooka     341: {
1.35      pooka     342:        void *cookie = VPTOPNC(vp_opc);
1.1       pooka     343:
1.25      pooka     344:        park->park_preq->preq_opclass = PUFFSOP_VN;
                    345:        park->park_preq->preq_optype = optype;
                    346:        park->park_preq->preq_cookie = cookie;
                    347:
1.40.4.3  joerg     348:        KASSERT(delta < park->park_maxlen);
                    349:        park->park_copylen = park->park_maxlen - delta;
1.25      pooka     350:        park->park_done = donefn;
                    351:        park->park_donearg = donearg;
1.40.4.3  joerg     352:        park->park_flags |= PARKFLAG_CALL;
1.4       pooka     353:
1.40.4.3  joerg     354:        (void) touser(pmp, park);
1.4       pooka     355: }
                    356:
1.40.4.3  joerg     357: int
                    358: puffs_msg_raw(struct puffs_mount *pmp, struct puffs_msgpark *park)
1.21      pooka     359: {
                    360:
1.40.4.3  joerg     361:        park->park_copylen = park->park_maxlen;
1.21      pooka     362:
1.40.4.3  joerg     363:        return touser(pmp, park);
1.21      pooka     364: }
                    365:
1.40.4.1  joerg     366: void
1.40.4.3  joerg     367: puffs_msg_errnotify(struct puffs_mount *pmp, uint8_t type, int error,
1.40.4.1  joerg     368:        const char *str, void *cookie)
                    369: {
1.40.4.3  joerg     370:        struct puffs_msgpark *park;
1.40.4.1  joerg     371:        struct puffs_error *perr;
                    372:
1.40.4.3  joerg     373:        puffs_msgmem_alloc(sizeof(struct puffs_error), &park, (void **)&perr,1);
1.40.4.1  joerg     374:
                    375:        perr->perr_error = error;
                    376:        strlcpy(perr->perr_str, str, sizeof(perr->perr_str));
                    377:
1.40.4.3  joerg     378:        park->park_preq->preq_opclass |= PUFFSOP_ERROR | PUFFSOPFLAG_FAF;
1.40.4.1  joerg     379:        park->park_preq->preq_optype = type;
                    380:        park->park_preq->preq_cookie = cookie;
                    381:
1.40.4.3  joerg     382:        park->park_copylen = park->park_maxlen;
1.40.4.1  joerg     383:
1.40.4.3  joerg     384:        (void)touser(pmp, park);
1.40.4.1  joerg     385: }
                    386:
1.4       pooka     387: /*
1.40.4.5! jmcneill  388:  * Wait for the userspace ping-pong game in calling process context,
        !           389:  * unless a FAF / async call, in which case just enqueues the request
        !           390:  * and return immediately.
1.1       pooka     391:  */
                    392: static int
1.40.4.3  joerg     393: touser(struct puffs_mount *pmp, struct puffs_msgpark *park)
1.1       pooka     394: {
1.26      pooka     395:        struct lwp *l = curlwp;
1.16      pooka     396:        struct mount *mp;
1.9       pooka     397:        struct puffs_req *preq;
1.19      pooka     398:        int rv = 0;
1.1       pooka     399:
1.16      pooka     400:        mp = PMPTOMP(pmp);
1.25      pooka     401:        preq = park->park_preq;
1.40.4.3  joerg     402:        preq->preq_buflen = park->park_maxlen;
                    403:        KASSERT(preq->preq_id == 0);
1.19      pooka     404:
1.40.4.3  joerg     405:        if ((park->park_flags & PARKFLAG_WANTREPLY) == 0)
                    406:                preq->preq_opclass |= PUFFSOPFLAG_FAF;
                    407:        else
                    408:                preq->preq_id = puffs_getmsgid(pmp);
                    409:
                    410:        /* fill in caller information */
                    411:        preq->preq_pid = l->l_proc->p_pid;
                    412:        preq->preq_lid = l->l_lid;
1.31      pooka     413:
1.19      pooka     414:        /*
1.40.4.5! jmcneill  415:         * To support cv_sig, yet another movie: check if there are signals
1.19      pooka     416:         * pending and we are issueing a non-FAF.  If so, return an error
                    417:         * directly UNLESS we are issueing INACTIVE.  In that case, convert
                    418:         * it to a FAF, fire off to the file server and return an error.
                    419:         * Yes, this is bordering disgusting.  Barfbags are on me.
                    420:         */
1.31      pooka     421:        if ((park->park_flags & PARKFLAG_WANTREPLY)
1.25      pooka     422:           && (park->park_flags & PARKFLAG_CALL) == 0
1.19      pooka     423:           && (l->l_flag & LW_PENDSIG) != 0 && sigispending(l, 0)) {
                    424:                if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN
                    425:                    && preq->preq_optype == PUFFS_VN_INACTIVE) {
1.40.4.3  joerg     426:                        park->park_preq->preq_opclass |= PUFFSOPFLAG_FAF;
                    427:                        park->park_flags &= ~PARKFLAG_WANTREPLY;
1.25      pooka     428:                        DPRINTF(("puffs touser: converted to FAF %p\n", park));
1.19      pooka     429:                        rv = EINTR;
                    430:                } else {
                    431:                        return EINTR;
                    432:                }
                    433:        }
1.16      pooka     434:
                    435:        /*
                    436:         * test for suspension lock.
                    437:         *
                    438:         * Note that we *DO NOT* keep the lock, since that might block
                    439:         * lock acquiring PLUS it would give userlandia control over
                    440:         * the lock.  The operation queue enforces a strict ordering:
                    441:         * when the fs server gets in the op stream, it knows things
                    442:         * are in order.  The kernel locks can't guarantee that for
                    443:         * userspace, in any case.
                    444:         *
                    445:         * BUT: this presents a problem for ops which have a consistency
                    446:         * clause based on more than one operation.  Unfortunately such
                    447:         * operations (read, write) do not reliably work yet.
                    448:         *
                    449:         * Ya, Ya, it's wrong wong wrong, me be fixink this someday.
1.18      pooka     450:         *
                    451:         * XXX: and there is one more problem.  We sometimes need to
                    452:         * take a lazy lock in case the fs is suspending and we are
                    453:         * executing as the fs server context.  This might happen
                    454:         * e.g. in the case that the user server triggers a reclaim
                    455:         * in the kernel while the fs is suspending.  It's not a very
                    456:         * likely event, but it needs to be fixed some day.
1.16      pooka     457:         */
1.22      pooka     458:
                    459:        /*
                    460:         * MOREXXX: once PUFFS_WCACHEINFO is enabled, we can't take
                    461:         * the mutex here, since getpages() might be called locked.
                    462:         */
1.18      pooka     463:        fstrans_start(mp, FSTRANS_NORMAL);
1.22      pooka     464:        mutex_enter(&pmp->pmp_lock);
1.16      pooka     465:        fstrans_done(mp);
                    466:
1.13      pooka     467:        if (pmp->pmp_status != PUFFSTAT_RUNNING) {
1.22      pooka     468:                mutex_exit(&pmp->pmp_lock);
1.1       pooka     469:                return ENXIO;
                    470:        }
                    471:
1.26      pooka     472: #ifdef PUFFSDEBUG
1.40.4.3  joerg     473:        parkqdump(&pmp->pmp_msg_touser, puffsdebug > 1);
                    474:        parkqdump(&pmp->pmp_msg_replywait, puffsdebug > 1);
1.26      pooka     475: #endif
                    476:
1.40.4.3  joerg     477:        mutex_enter(&park->park_mtx);
                    478:        TAILQ_INSERT_TAIL(&pmp->pmp_msg_touser, park, park_entries);
1.26      pooka     479:        park->park_flags |= PARKFLAG_ONQUEUE1;
1.34      pooka     480:        puffs_mp_reference(pmp);
1.40.4.3  joerg     481:        pmp->pmp_msg_touser_count++;
1.26      pooka     482:        mutex_exit(&pmp->pmp_lock);
1.1       pooka     483:
1.20      pooka     484:        DPRINTF(("touser: req %" PRIu64 ", preq: %p, park: %p, "
1.25      pooka     485:            "c/t: 0x%x/0x%x, f: 0x%x\n", preq->preq_id, preq, park,
                    486:            preq->preq_opclass, preq->preq_optype, park->park_flags));
1.15      pooka     487:
1.40.4.3  joerg     488:        cv_broadcast(&pmp->pmp_msg_waiter_cv);
1.1       pooka     489:        selnotify(pmp->pmp_sel, 0);
                    490:
1.31      pooka     491:        if ((park->park_flags & PARKFLAG_WANTREPLY)
1.25      pooka     492:            && (park->park_flags & PARKFLAG_CALL) == 0) {
1.19      pooka     493:                int error;
                    494:
1.26      pooka     495:                error = cv_wait_sig(&park->park_cv, &park->park_mtx);
1.40.4.3  joerg     496:                DPRINTF(("puffs_touser: waiter for %p woke up with %d\n",
                    497:                    park, error));
1.19      pooka     498:                if (error) {
1.25      pooka     499:                        park->park_flags |= PARKFLAG_WAITERGONE;
1.26      pooka     500:                        if (park->park_flags & PARKFLAG_DONE) {
1.22      pooka     501:                                rv = preq->preq_rv;
1.19      pooka     502:                        } else {
1.26      pooka     503:                                /*
                    504:                                 * ok, we marked it as going away, but
                    505:                                 * still need to do queue ops.  take locks
                    506:                                 * in correct order.
                    507:                                 *
                    508:                                 * We don't want to release our reference
                    509:                                 * if it's on replywait queue to avoid error
                    510:                                 * to file server.  putop() code will DTRT.
                    511:                                 */
                    512:                                mutex_exit(&park->park_mtx);
                    513:                                mutex_enter(&pmp->pmp_lock);
                    514:                                mutex_enter(&park->park_mtx);
1.40.4.3  joerg     515:
                    516:                                /* remove from queue1 */
1.36      pooka     517:                                if (park->park_flags & PARKFLAG_ONQUEUE1) {
1.40.4.3  joerg     518:                                        TAILQ_REMOVE(&pmp->pmp_msg_touser,
1.26      pooka     519:                                            park, park_entries);
1.40.4.3  joerg     520:                                        pmp->pmp_msg_touser_count--;
1.36      pooka     521:                                        park->park_flags &= ~PARKFLAG_ONQUEUE1;
                    522:                                }
1.40.4.3  joerg     523:
                    524:                                /*
                    525:                                 * If it's waiting for a response already,
                    526:                                 * boost reference count.  Park will get
                    527:                                 * nuked once the response arrives from
                    528:                                 * the file server.
                    529:                                 */
                    530:                                if (park->park_flags & PARKFLAG_ONQUEUE2)
                    531:                                        puffs_msgpark_reference(park);
                    532:
1.26      pooka     533:                                mutex_exit(&pmp->pmp_lock);
                    534:
1.22      pooka     535:                                rv = error;
1.19      pooka     536:                        }
1.22      pooka     537:                } else {
                    538:                        rv = preq->preq_rv;
1.19      pooka     539:                }
1.22      pooka     540:
1.16      pooka     541:                /*
                    542:                 * retake the lock and release.  This makes sure (haha,
                    543:                 * I'm humorous) that we don't process the same vnode in
                    544:                 * multiple threads due to the locks hacks we have in
                    545:                 * puffs_lock().  In reality this is well protected by
                    546:                 * the biglock, but once that's gone, well, hopefully
                    547:                 * this will be fixed for real.  (and when you read this
                    548:                 * comment in 2017 and subsequently barf, my condolences ;).
                    549:                 */
1.19      pooka     550:                if (rv == 0 && !fstrans_is_owner(mp)) {
1.17      hannken   551:                        fstrans_start(mp, FSTRANS_NORMAL);
1.16      pooka     552:                        fstrans_done(mp);
                    553:                }
1.40.4.5! jmcneill  554:
1.22      pooka     555:        } else {
1.40.4.3  joerg     556:                /*
                    557:                 * Take extra reference for FAF, i.e. don't free us
                    558:                 * immediately upon return to the caller, but rather
                    559:                 * only when the message has been transported.
                    560:                 */
                    561:                puffs_msgpark_reference(park);
1.16      pooka     562:        }
                    563:
1.40.4.3  joerg     564:        mutex_exit(&park->park_mtx);
                    565:
1.22      pooka     566:        mutex_enter(&pmp->pmp_lock);
1.34      pooka     567:        puffs_mp_release(pmp);
1.22      pooka     568:        mutex_exit(&pmp->pmp_lock);
1.16      pooka     569:
1.19      pooka     570:        return rv;
1.1       pooka     571: }
                    572:
1.9       pooka     573: /*
1.40.4.3  joerg     574:  * Get next request in the outgoing queue.  "maxsize" controls the
                    575:  * size the caller can accommodate and "nonblock" signals if this
                    576:  * should block while waiting for input.  Handles all locking internally.
1.9       pooka     577:  */
1.10      pooka     578: int
1.40.4.3  joerg     579: puffs_msgif_getout(void *this, size_t maxsize, int nonblock,
                    580:        uint8_t **data, size_t *dlen, void **parkptr)
1.1       pooka     581: {
1.40.4.3  joerg     582:        struct puffs_mount *pmp = this;
                    583:        struct puffs_msgpark *park;
1.9       pooka     584:        struct puffs_req *preq;
1.40.4.3  joerg     585:        int error;
1.1       pooka     586:
1.40.4.3  joerg     587:        error = 0;
1.22      pooka     588:        mutex_enter(&pmp->pmp_lock);
1.40.4.4  joerg     589:        puffs_mp_reference(pmp);
1.40.4.3  joerg     590:        for (;;) {
                    591:                /* RIP? */
1.9       pooka     592:                if (pmp->pmp_status != PUFFSTAT_RUNNING) {
                    593:                        error = ENXIO;
1.40.4.3  joerg     594:                        break;
1.9       pooka     595:                }
1.12      pooka     596:
1.40.4.3  joerg     597:                /* need platinum yendorian express card? */
                    598:                if (TAILQ_EMPTY(&pmp->pmp_msg_touser)) {
                    599:                        DPRINTF(("puffs_getout: no outgoing op, "));
1.12      pooka     600:                        if (nonblock) {
1.40.4.3  joerg     601:                                DPRINTF(("returning EWOULDBLOCK\n"));
1.12      pooka     602:                                error = EWOULDBLOCK;
1.40.4.3  joerg     603:                                break;
1.9       pooka     604:                        }
1.40.4.3  joerg     605:                        DPRINTF(("waiting ...\n"));
1.9       pooka     606:
1.40.4.3  joerg     607:                        error = cv_wait_sig(&pmp->pmp_msg_waiter_cv,
1.22      pooka     608:                            &pmp->pmp_lock);
1.11      pooka     609:                        if (error)
1.40.4.3  joerg     610:                                break;
1.11      pooka     611:                        else
1.40.4.3  joerg     612:                                continue;
1.9       pooka     613:                }
                    614:
1.40.4.3  joerg     615:                park = TAILQ_FIRST(&pmp->pmp_msg_touser);
1.40.4.4  joerg     616:                if (park == NULL)
                    617:                        continue;
                    618:
1.40.4.3  joerg     619:                mutex_enter(&park->park_mtx);
                    620:                puffs_msgpark_reference(park);
                    621:
                    622:                DPRINTF(("puffs_getout: found park at %p, ", park));
1.22      pooka     623:
                    624:                /* If it's a goner, don't process any furher */
                    625:                if (park->park_flags & PARKFLAG_WAITERGONE) {
1.40.4.3  joerg     626:                        DPRINTF(("waitergone!\n"));
                    627:                        puffs_msgpark_release(park);
1.22      pooka     628:                        continue;
                    629:                }
                    630:
1.40.4.3  joerg     631:                /* check size */
1.26      pooka     632:                preq = park->park_preq;
1.40.4.3  joerg     633:                if (maxsize < preq->preq_frhdr.pfr_len) {
                    634:                        DPRINTF(("buffer too small\n"));
                    635:                        puffs_msgpark_release(park);
                    636:                        error = E2BIG;
                    637:                        break;
1.26      pooka     638:                }
1.28      pooka     639:
1.40.4.3  joerg     640:                DPRINTF(("returning\n"));
                    641:
                    642:                /*
                    643:                 * Ok, we found what we came for.  Release it from the
                    644:                 * outgoing queue but do not unlock.  We will unlock
                    645:                 * only after we "releaseout" it to avoid complications:
                    646:                 * otherwise it is (theoretically) possible for userland
                    647:                 * to race us into "put" before we have a change to put
                    648:                 * this baby on the receiving queue.
                    649:                 */
                    650:                TAILQ_REMOVE(&pmp->pmp_msg_touser, park, park_entries);
1.28      pooka     651:                KASSERT(park->park_flags & PARKFLAG_ONQUEUE1);
                    652:                park->park_flags &= ~PARKFLAG_ONQUEUE1;
1.40.4.3  joerg     653:                mutex_exit(&park->park_mtx);
1.26      pooka     654:
1.40.4.3  joerg     655:                pmp->pmp_msg_touser_count--;
                    656:                KASSERT(pmp->pmp_msg_touser_count >= 0);
1.9       pooka     657:
1.40.4.3  joerg     658:                break;
                    659:        }
1.40.4.4  joerg     660:        puffs_mp_release(pmp);
1.40.4.3  joerg     661:        mutex_exit(&pmp->pmp_lock);
1.9       pooka     662:
1.40.4.3  joerg     663:        if (error == 0) {
                    664:                *data = (uint8_t *)preq;
                    665:                preq->preq_frhdr.pfr_len = park->park_copylen;
                    666:                preq->preq_frhdr.pfr_alloclen = park->park_maxlen;
                    667:                preq->preq_frhdr.pfr_type = preq->preq_opclass; /* yay! */
                    668:                *dlen = preq->preq_frhdr.pfr_len;
                    669:                *parkptr = park;
                    670:        }
1.40.4.5! jmcneill  671:
1.40.4.3  joerg     672:        return error;
                    673: }
                    674:
                    675: /*
                    676:  * Release outgoing structure.  Now, depending on the success of the
                    677:  * outgoing send, it is either going onto the result waiting queue
                    678:  * or the death chamber.
                    679:  */
                    680: void
                    681: puffs_msgif_releaseout(void *this, void *parkptr, int status)
                    682: {
                    683:        struct puffs_mount *pmp = this;
                    684:        struct puffs_msgpark *park = parkptr;
1.32      pooka     685:
1.40.4.3  joerg     686:        DPRINTF(("puffs_releaseout: returning park %p, errno %d: " ,
                    687:            park, status));
                    688:        mutex_enter(&pmp->pmp_lock);
                    689:        mutex_enter(&park->park_mtx);
                    690:        if (park->park_flags & PARKFLAG_WANTREPLY) {
                    691:                if (status == 0) {
                    692:                        DPRINTF(("enqueue replywait\n"));
                    693:                        TAILQ_INSERT_TAIL(&pmp->pmp_msg_replywait, park,
1.22      pooka     694:                            park_entries);
1.26      pooka     695:                        park->park_flags |= PARKFLAG_ONQUEUE2;
1.9       pooka     696:                } else {
1.40.4.3  joerg     697:                        DPRINTF(("error path!\n"));
                    698:                        park->park_preq->preq_rv = status;
                    699:                        park->park_flags |= PARKFLAG_DONE;
                    700:                        cv_signal(&park->park_cv);
1.1       pooka     701:                }
1.40.4.3  joerg     702:                puffs_msgpark_release(park);
                    703:        } else {
                    704:                DPRINTF(("release\n"));
                    705:                puffs_msgpark_release1(park, 2);
1.1       pooka     706:        }
1.22      pooka     707:        mutex_exit(&pmp->pmp_lock);
1.1       pooka     708: }
                    709:
1.40.4.4  joerg     710: /*
                    711:  * XXX: locking with this one?
                    712:  */
1.40.4.3  joerg     713: void
                    714: puffs_msgif_incoming(void *this, void *buf)
1.1       pooka     715: {
1.40.4.3  joerg     716:        struct puffs_mount *pmp = this;
                    717:        struct puffs_req *preq = buf;
                    718:        struct puffs_frame *pfr = &preq->preq_frhdr;
                    719:        struct puffs_msgpark *park;
                    720:        int release, wgone;
                    721:
                    722:        /* XXX */
                    723:        if (PUFFSOP_OPCLASS(preq->preq_opclass) != PUFFSOP_VN
                    724:            && PUFFSOP_OPCLASS(preq->preq_opclass) != PUFFSOP_VFS)
                    725:                return;
1.1       pooka     726:
1.22      pooka     727:        mutex_enter(&pmp->pmp_lock);
1.24      pooka     728:
1.40.4.3  joerg     729:        /* Locate waiter */
                    730:        TAILQ_FOREACH(park, &pmp->pmp_msg_replywait, park_entries) {
                    731:                if (park->park_preq->preq_id == preq->preq_id)
1.24      pooka     732:                        break;
1.40.4.3  joerg     733:        }
                    734:        if (park == NULL) {
                    735:                DPRINTF(("puffs_msgif_income: no request: %" PRIu64 "\n",
                    736:                    preq->preq_id));
                    737:                mutex_exit(&pmp->pmp_lock);
                    738:                return; /* XXX send error */
                    739:        }
1.26      pooka     740:
1.40.4.3  joerg     741:        mutex_enter(&park->park_mtx);
                    742:        puffs_msgpark_reference(park);
                    743:        if (pfr->pfr_len > park->park_maxlen) {
                    744:                DPRINTF(("puffs_msgif_income: invalid buffer length: "
                    745:                    "%zu (req %" PRIu64 ", \n", pfr->pfr_len, preq->preq_id));
                    746:                park->park_preq->preq_rv = EPROTO;
                    747:                cv_signal(&park->park_cv);
                    748:                puffs_msgpark_release(park);
1.22      pooka     749:                mutex_exit(&pmp->pmp_lock);
1.40.4.3  joerg     750:                return; /* XXX: error */
                    751:        }
                    752:        wgone = park->park_flags & PARKFLAG_WAITERGONE;
1.9       pooka     753:
1.40.4.3  joerg     754:        KASSERT(park->park_flags & PARKFLAG_ONQUEUE2);
                    755:        TAILQ_REMOVE(&pmp->pmp_msg_replywait, park, park_entries);
                    756:        park->park_flags &= ~PARKFLAG_ONQUEUE2;
                    757:        mutex_exit(&pmp->pmp_lock);
1.24      pooka     758:
1.40.4.3  joerg     759:        if (wgone) {
                    760:                DPRINTF(("puffs_putop: bad service - waiter gone for "
                    761:                    "park %p\n", park));
                    762:                release = 2;
                    763:        } else {
1.24      pooka     764:                if (park->park_flags & PARKFLAG_CALL) {
1.40.4.3  joerg     765:                        DPRINTF(("puffs_msgif_income: call for %p, arg %p\n",
1.40      pooka     766:                            park->park_preq, park->park_donearg));
1.40.4.3  joerg     767:                        park->park_done(pmp, buf, park->park_donearg);
                    768:                        release = 2;
                    769:                } else {
                    770:                        /* XXX: yes, I know */
                    771:                        memcpy(park->park_preq, buf, pfr->pfr_len);
1.26      pooka     772:                        release = 1;
1.20      pooka     773:                }
1.1       pooka     774:        }
                    775:
1.40.4.3  joerg     776:        if (!wgone) {
                    777:                DPRINTF(("puffs_putop: flagging done for "
                    778:                    "park %p\n", park));
                    779:                cv_signal(&park->park_cv);
                    780:        }
1.1       pooka     781:
1.40.4.3  joerg     782:        park->park_flags |= PARKFLAG_DONE;
                    783:        puffs_msgpark_release1(park, release);
1.1       pooka     784: }
                    785:
1.22      pooka     786: /*
                    787:  * We're dead, kaput, RIP, slightly more than merely pining for the
                    788:  * fjords, belly-up, fallen, lifeless, finished, expired, gone to meet
                    789:  * our maker, ceased to be, etcetc.  YASD.  It's a dead FS!
                    790:  *
                    791:  * Caller must hold puffs mutex.
                    792:  */
                    793: void
                    794: puffs_userdead(struct puffs_mount *pmp)
                    795: {
1.40.4.3  joerg     796:        struct puffs_msgpark *park, *park_next;
1.22      pooka     797:
                    798:        /*
                    799:         * Mark filesystem status as dying so that operations don't
                    800:         * attempt to march to userspace any longer.
                    801:         */
                    802:        pmp->pmp_status = PUFFSTAT_DYING;
                    803:
                    804:        /* signal waiters on REQUEST TO file server queue */
1.40.4.3  joerg     805:        for (park = TAILQ_FIRST(&pmp->pmp_msg_touser); park; park = park_next) {
1.24      pooka     806:                uint8_t opclass;
                    807:
1.40.4.3  joerg     808:                mutex_enter(&park->park_mtx);
                    809:                puffs_msgpark_reference(park);
1.32      pooka     810:                park_next = TAILQ_NEXT(park, park_entries);
1.26      pooka     811:
                    812:                KASSERT(park->park_flags & PARKFLAG_ONQUEUE1);
1.40.4.3  joerg     813:                TAILQ_REMOVE(&pmp->pmp_msg_touser, park, park_entries);
1.26      pooka     814:                park->park_flags &= ~PARKFLAG_ONQUEUE1;
1.40.4.3  joerg     815:                pmp->pmp_msg_touser_count--;
1.22      pooka     816:
1.31      pooka     817:                /*
1.40.4.5! jmcneill  818:                 * Even though waiters on QUEUE1 are removed in touser()
        !           819:                 * in case of WAITERGONE, it is still possible for us to
        !           820:                 * get raced here due to having to retake locks in said
        !           821:                 * touser().  In the race case simply "ignore" the item
        !           822:                 * on the queue and move on to the next one.
1.31      pooka     823:                 */
                    824:                if (park->park_flags & PARKFLAG_WAITERGONE) {
                    825:                        KASSERT((park->park_flags & PARKFLAG_CALL) == 0);
                    826:                        KASSERT(park->park_flags & PARKFLAG_WANTREPLY);
1.40.4.3  joerg     827:                        puffs_msgpark_release(park);
1.40.4.5! jmcneill  828:
1.22      pooka     829:                } else {
1.31      pooka     830:                        opclass = park->park_preq->preq_opclass;
1.23      pooka     831:                        park->park_preq->preq_rv = ENXIO;
1.31      pooka     832:
                    833:                        if (park->park_flags & PARKFLAG_CALL) {
1.40.4.1  joerg     834:                                park->park_done(pmp, park->park_preq,
1.31      pooka     835:                                    park->park_donearg);
1.40.4.3  joerg     836:                                puffs_msgpark_release1(park, 2);
1.31      pooka     837:                        } else if ((park->park_flags & PARKFLAG_WANTREPLY)==0) {
1.40.4.3  joerg     838:                                puffs_msgpark_release1(park, 2);
1.31      pooka     839:                        } else {
                    840:                                park->park_preq->preq_rv = ENXIO;
                    841:                                cv_signal(&park->park_cv);
1.40.4.3  joerg     842:                                puffs_msgpark_release(park);
1.31      pooka     843:                        }
1.22      pooka     844:                }
                    845:        }
                    846:
                    847:        /* signal waiters on RESPONSE FROM file server queue */
1.40.4.3  joerg     848:        for (park=TAILQ_FIRST(&pmp->pmp_msg_replywait); park; park=park_next) {
                    849:                mutex_enter(&park->park_mtx);
                    850:                puffs_msgpark_reference(park);
1.32      pooka     851:                park_next = TAILQ_NEXT(park, park_entries);
1.26      pooka     852:
                    853:                KASSERT(park->park_flags & PARKFLAG_ONQUEUE2);
1.31      pooka     854:                KASSERT(park->park_flags & PARKFLAG_WANTREPLY);
1.26      pooka     855:
1.40.4.3  joerg     856:                TAILQ_REMOVE(&pmp->pmp_msg_replywait, park, park_entries);
1.26      pooka     857:                park->park_flags &= ~PARKFLAG_ONQUEUE2;
                    858:
1.31      pooka     859:                if (park->park_flags & PARKFLAG_WAITERGONE) {
                    860:                        KASSERT((park->park_flags & PARKFLAG_CALL) == 0);
1.40.4.3  joerg     861:                        puffs_msgpark_release(park);
1.22      pooka     862:                } else {
1.31      pooka     863:                        park->park_preq->preq_rv = ENXIO;
                    864:                        if (park->park_flags & PARKFLAG_CALL) {
1.40.4.1  joerg     865:                                park->park_done(pmp, park->park_preq,
1.31      pooka     866:                                    park->park_donearg);
1.40.4.3  joerg     867:                                puffs_msgpark_release1(park, 2);
1.31      pooka     868:                        } else {
                    869:                                cv_signal(&park->park_cv);
1.40.4.3  joerg     870:                                puffs_msgpark_release(park);
1.31      pooka     871:                        }
1.22      pooka     872:                }
                    873:        }
1.40.4.4  joerg     874:
                    875:        cv_broadcast(&pmp->pmp_msg_waiter_cv);
1.22      pooka     876: }

CVSweb <webmaster@jp.NetBSD.org>