Annotation of src/lib/libpuffs/puffs.c, Revision 1.74
1.74 ! pooka 1: /* $NetBSD: puffs.c,v 1.73 2007/11/05 17:48:17 pooka Exp $ */
1.1 pooka 2:
3: /*
1.44 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>
33: #if !defined(lint)
1.74 ! pooka 34: __RCSID("$NetBSD: puffs.c,v 1.73 2007/11/05 17:48:17 pooka Exp $");
1.1 pooka 35: #endif /* !lint */
36:
37: #include <sys/param.h>
38: #include <sys/mount.h>
39:
1.9 pooka 40: #include <assert.h>
1.12 pooka 41: #include <err.h>
1.1 pooka 42: #include <errno.h>
43: #include <fcntl.h>
1.21 pooka 44: #include <mntopts.h>
1.58 pooka 45: #include <paths.h>
1.1 pooka 46: #include <puffs.h>
47: #include <stdio.h>
48: #include <stdlib.h>
49: #include <string.h>
50: #include <syslog.h>
51: #include <unistd.h>
52:
1.19 pooka 53: #include "puffs_priv.h"
54:
1.21 pooka 55: /* Most file systems want this for opts, so just give it to them */
56: const struct mntopt puffsmopts[] = {
57: MOPT_STDOPTS,
58: PUFFSMOPT_STD,
59: MOPT_NULL,
60: };
61:
1.72 pooka 62: #ifdef PUFFS_WITH_THREADS
63: #include <pthread.h>
64: pthread_mutex_t pu_lock = PTHREAD_MUTEX_INITIALIZER;
65: #endif
66:
1.10 pooka 67: #define FILLOP(lower, upper) \
68: do { \
1.13 pooka 69: if (pops->puffs_node_##lower) \
1.10 pooka 70: opmask[PUFFS_VN_##upper] = 1; \
71: } while (/*CONSTCOND*/0)
72: static void
1.13 pooka 73: fillvnopmask(struct puffs_ops *pops, uint8_t *opmask)
1.10 pooka 74: {
75:
76: memset(opmask, 0, PUFFS_VN_MAX);
77:
78: FILLOP(create, CREATE);
79: FILLOP(mknod, MKNOD);
80: FILLOP(open, OPEN);
81: FILLOP(close, CLOSE);
82: FILLOP(access, ACCESS);
83: FILLOP(getattr, GETATTR);
84: FILLOP(setattr, SETATTR);
85: FILLOP(poll, POLL); /* XXX: not ready in kernel */
1.16 pooka 86: FILLOP(mmap, MMAP);
1.10 pooka 87: FILLOP(fsync, FSYNC);
88: FILLOP(seek, SEEK);
89: FILLOP(remove, REMOVE);
90: FILLOP(link, LINK);
91: FILLOP(rename, RENAME);
92: FILLOP(mkdir, MKDIR);
93: FILLOP(rmdir, RMDIR);
94: FILLOP(symlink, SYMLINK);
95: FILLOP(readdir, READDIR);
96: FILLOP(readlink, READLINK);
97: FILLOP(reclaim, RECLAIM);
98: FILLOP(inactive, INACTIVE);
99: FILLOP(print, PRINT);
100: FILLOP(read, READ);
101: FILLOP(write, WRITE);
1.19 pooka 102: }
103: #undef FILLOP
104:
1.64 pooka 105: /*ARGSUSED*/
1.63 pooka 106: static void
107: puffs_defaulterror(struct puffs_usermount *pu, uint8_t type,
1.65 pooka 108: int error, const char *str, void *cookie)
1.63 pooka 109: {
110:
1.65 pooka 111: fprintf(stderr, "%s\n", str);
1.63 pooka 112: abort();
113: }
114:
1.19 pooka 115: int
116: puffs_getselectable(struct puffs_usermount *pu)
117: {
1.10 pooka 118:
1.60 pooka 119: return pu->pu_fd;
1.10 pooka 120: }
1.19 pooka 121:
122: int
123: puffs_setblockingmode(struct puffs_usermount *pu, int mode)
124: {
1.46 pooka 125: int rv, x;
126:
1.74 ! pooka 127: assert(puffs_getstate(pu) == PUFFS_STATE_RUNNING);
! 128:
1.46 pooka 129: if (mode != PUFFSDEV_BLOCK && mode != PUFFSDEV_NONBLOCK) {
130: errno = EINVAL;
131: return -1;
132: }
1.19 pooka 133:
134: x = mode;
1.60 pooka 135: rv = ioctl(pu->pu_fd, FIONBIO, &x);
1.46 pooka 136:
137: if (rv == 0) {
138: if (mode == PUFFSDEV_BLOCK)
139: pu->pu_state &= ~PU_ASYNCFD;
140: else
141: pu->pu_state |= PU_ASYNCFD;
142: }
143:
144: return rv;
1.19 pooka 145: }
146:
147: int
148: puffs_getstate(struct puffs_usermount *pu)
149: {
150:
1.44 pooka 151: return pu->pu_state & PU_STATEMASK;
1.19 pooka 152: }
153:
154: void
155: puffs_setstacksize(struct puffs_usermount *pu, size_t ss)
156: {
1.69 pooka 157: int stackshift;
158:
159: assert(puffs_getstate(pu) == PUFFS_STATE_BEFOREMOUNT);
160: stackshift = -1;
161: while (ss) {
162: ss >>= 1;
163: stackshift++;
164: }
165: pu->pu_cc_stackshift = stackshift;
166: assert(1<<stackshift == ss);
1.19 pooka 167: }
168:
1.24 pooka 169: struct puffs_pathobj *
170: puffs_getrootpathobj(struct puffs_usermount *pu)
1.19 pooka 171: {
172: struct puffs_node *pnr;
173:
174: pnr = pu->pu_pn_root;
175: if (pnr == NULL) {
176: errno = ENOENT;
1.24 pooka 177: return NULL;
1.19 pooka 178: }
179:
1.24 pooka 180: return &pnr->pn_po;
181: }
182:
1.35 pooka 183: void
184: puffs_setroot(struct puffs_usermount *pu, struct puffs_node *pn)
185: {
186:
187: pu->pu_pn_root = pn;
188: }
189:
190: struct puffs_node *
191: puffs_getroot(struct puffs_usermount *pu)
192: {
193:
194: return pu->pu_pn_root;
195: }
196:
1.49 pooka 197: void
198: puffs_setrootinfo(struct puffs_usermount *pu, enum vtype vt,
199: vsize_t vsize, dev_t rdev)
200: {
1.60 pooka 201: struct puffs_kargs *pargs = pu->pu_kargp;
1.49 pooka 202:
1.60 pooka 203: if (puffs_getstate(pu) != PUFFS_STATE_BEFOREMOUNT) {
1.49 pooka 204: warnx("puffs_setrootinfo: call has effect only "
205: "before mount\n");
1.60 pooka 206: return;
207: }
1.49 pooka 208:
209: pargs->pa_root_vtype = vt;
210: pargs->pa_root_vsize = vsize;
211: pargs->pa_root_rdev = rdev;
212: }
213:
1.35 pooka 214: void *
215: puffs_getspecific(struct puffs_usermount *pu)
216: {
217:
218: return pu->pu_privdata;
219: }
220:
221: size_t
222: puffs_getmaxreqlen(struct puffs_usermount *pu)
223: {
224:
1.60 pooka 225: return pu->pu_maxreqlen;
1.35 pooka 226: }
1.24 pooka 227:
228: void
1.37 pooka 229: puffs_setmaxreqlen(struct puffs_usermount *pu, size_t reqlen)
230: {
231:
1.44 pooka 232: if (puffs_getstate(pu) != PUFFS_STATE_BEFOREMOUNT)
1.37 pooka 233: warnx("puffs_setmaxreqlen: call has effect only "
234: "before mount\n");
235:
1.66 pooka 236: pu->pu_kargp->pa_maxmsglen = reqlen;
1.37 pooka 237: }
238:
239: void
1.38 pooka 240: puffs_setfhsize(struct puffs_usermount *pu, size_t fhsize, int flags)
1.37 pooka 241: {
242:
1.44 pooka 243: if (puffs_getstate(pu) != PUFFS_STATE_BEFOREMOUNT)
1.37 pooka 244: warnx("puffs_setfhsize: call has effect only before mount\n");
245:
1.60 pooka 246: pu->pu_kargp->pa_fhsize = fhsize;
247: pu->pu_kargp->pa_fhflags = flags;
1.37 pooka 248: }
249:
250: void
251: puffs_setncookiehash(struct puffs_usermount *pu, int nhash)
252: {
253:
1.44 pooka 254: if (puffs_getstate(pu) != PUFFS_STATE_BEFOREMOUNT)
1.37 pooka 255: warnx("puffs_setfhsize: call has effect only before mount\n");
256:
1.60 pooka 257: pu->pu_kargp->pa_nhashbuckets = nhash;
1.37 pooka 258: }
259:
260: void
1.24 pooka 261: puffs_set_pathbuild(struct puffs_usermount *pu, pu_pathbuild_fn fn)
262: {
263:
264: pu->pu_pathbuild = fn;
265: }
266:
267: void
268: puffs_set_pathtransform(struct puffs_usermount *pu, pu_pathtransform_fn fn)
269: {
270:
271: pu->pu_pathtransform = fn;
272: }
273:
274: void
275: puffs_set_pathcmp(struct puffs_usermount *pu, pu_pathcmp_fn fn)
276: {
277:
278: pu->pu_pathcmp = fn;
279: }
280:
281: void
282: puffs_set_pathfree(struct puffs_usermount *pu, pu_pathfree_fn fn)
283: {
1.19 pooka 284:
1.24 pooka 285: pu->pu_pathfree = fn;
1.19 pooka 286: }
287:
1.24 pooka 288: void
289: puffs_set_namemod(struct puffs_usermount *pu, pu_namemod_fn fn)
290: {
291:
292: pu->pu_namemod = fn;
293: }
1.19 pooka 294:
1.40 pooka 295: void
1.63 pooka 296: puffs_set_errnotify(struct puffs_usermount *pu, pu_errnotify_fn fn)
297: {
298:
299: pu->pu_errnotify = fn;
300: }
301:
302: void
1.46 pooka 303: puffs_ml_setloopfn(struct puffs_usermount *pu, puffs_ml_loop_fn lfn)
304: {
305:
306: pu->pu_ml_lfn = lfn;
307: }
308:
309: void
310: puffs_ml_settimeout(struct puffs_usermount *pu, struct timespec *ts)
311: {
312:
313: if (ts == NULL) {
314: pu->pu_ml_timep = NULL;
315: } else {
316: pu->pu_ml_timeout = *ts;
317: pu->pu_ml_timep = &pu->pu_ml_timeout;
318: }
319: }
320:
321: void
1.71 pooka 322: puffs_set_prepost(struct puffs_usermount *pu,
323: pu_prepost_fn pre, pu_prepost_fn pst)
324: {
325:
326: pu->pu_oppre = pre;
327: pu->pu_oppost = pst;
328: }
329:
330: void
1.40 pooka 331: puffs_setback(struct puffs_cc *pcc, int whatback)
332: {
333: struct puffs_req *preq = pcc->pcc_preq;
334:
335: assert(PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN && (
336: preq->preq_optype == PUFFS_VN_OPEN ||
337: preq->preq_optype == PUFFS_VN_MMAP ||
338: preq->preq_optype == PUFFS_VN_REMOVE ||
1.54 pooka 339: preq->preq_optype == PUFFS_VN_RMDIR ||
340: preq->preq_optype == PUFFS_VN_INACTIVE));
1.40 pooka 341:
342: preq->preq_setbacks |= whatback & PUFFS_SETBACK_MASK;
343: }
344:
1.36 pooka 345: int
1.49 pooka 346: puffs_mount(struct puffs_usermount *pu, const char *dir, int mntflags,
347: void *cookie)
1.36 pooka 348: {
1.62 pooka 349: char rp[MAXPATHLEN];
1.74 ! pooka 350: int rv, fd;
1.36 pooka 351:
352: #if 1
353: /* XXXkludgehere */
354: /* kauth doesn't provide this service any longer */
355: if (geteuid() != 0)
356: mntflags |= MNT_NOSUID | MNT_NODEV;
357: #endif
358:
1.62 pooka 359: if (realpath(dir, rp) == NULL)
360: return -1;
361:
362: if (strcmp(dir, rp) != 0) {
363: warnx("puffs_mount: \"%s\" is a relative path.", dir);
364: warnx("puffs_mount: using \"%s\" instead.", rp);
365: }
366:
1.74 ! pooka 367: fd = open(_PATH_PUFFS, O_RDONLY);
! 368: if (fd == -1) {
! 369: warnx("puffs_mount: cannot open %s", _PATH_PUFFS);
! 370: return -1;
! 371: }
! 372: if (fd <= 2)
! 373: warnx("puffs_init: device fd %d (<= 2), sure this is "
! 374: "what you want?", fd);
! 375:
! 376: pu->pu_kargp->pa_fd = pu->pu_fd = fd;
1.60 pooka 377: pu->pu_kargp->pa_root_cookie = cookie;
1.62 pooka 378: if ((rv = mount(MOUNT_PUFFS, rp, mntflags,
1.60 pooka 379: pu->pu_kargp, sizeof(struct puffs_kargs))) == -1)
380: goto out;
1.66 pooka 381: #if 0
1.60 pooka 382: if ((rv = ioctl(pu->pu_fd, PUFFSREQSIZEOP, &pu->pu_maxreqlen)) == -1)
383: goto out;
1.66 pooka 384: #endif
1.49 pooka 385: PU_SETSTATE(pu, PUFFS_STATE_RUNNING);
1.36 pooka 386:
1.60 pooka 387: out:
388: free(pu->pu_kargp);
389: pu->pu_kargp = NULL;
390:
391: return rv;
1.36 pooka 392: }
1.10 pooka 393:
1.1 pooka 394: struct puffs_usermount *
1.58 pooka 395: _puffs_init(int develv, struct puffs_ops *pops, const char *mntfromname,
396: const char *puffsname, void *priv, uint32_t pflags)
1.1 pooka 397: {
398: struct puffs_usermount *pu;
1.36 pooka 399: struct puffs_kargs *pargs;
1.74 ! pooka 400: int sverrno;
1.1 pooka 401:
1.20 pooka 402: if (develv != PUFFS_DEVEL_LIBVERSION) {
1.53 pooka 403: warnx("puffs_init: mounting with lib version %d, need %d",
1.20 pooka 404: develv, PUFFS_DEVEL_LIBVERSION);
405: errno = EINVAL;
406: return NULL;
407: }
408:
1.36 pooka 409: pu = malloc(sizeof(struct puffs_usermount));
410: if (pu == NULL)
411: goto failfree;
1.47 pooka 412: memset(pu, 0, sizeof(struct puffs_usermount));
1.1 pooka 413:
1.60 pooka 414: pargs = pu->pu_kargp = malloc(sizeof(struct puffs_kargs));
415: if (pargs == NULL)
416: goto failfree;
417: memset(pargs, 0, sizeof(struct puffs_kargs));
418:
1.36 pooka 419: pargs->pa_vers = PUFFSDEVELVERS | PUFFSVERSION;
420: pargs->pa_flags = PUFFS_FLAG_KERN(pflags);
421: fillvnopmask(pops, pargs->pa_vnopmask);
1.58 pooka 422: (void)strlcpy(pargs->pa_typename, puffsname,
423: sizeof(pargs->pa_typename));
424: (void)strlcpy(pargs->pa_mntfromname, mntfromname,
425: sizeof(pargs->pa_mntfromname));
1.1 pooka 426:
1.49 pooka 427: puffs_zerostatvfs(&pargs->pa_svfsb);
428: pargs->pa_root_cookie = NULL;
429: pargs->pa_root_vtype = VDIR;
430: pargs->pa_root_vsize = 0;
431: pargs->pa_root_rdev = 0;
1.66 pooka 432: pargs->pa_maxmsglen = 0;
1.49 pooka 433:
1.1 pooka 434: pu->pu_flags = pflags;
1.13 pooka 435: pu->pu_ops = *pops;
1.21 pooka 436: free(pops); /* XXX */
1.36 pooka 437:
1.19 pooka 438: pu->pu_privdata = priv;
1.69 pooka 439: pu->pu_cc_stackshift = PUFFS_CC_STACKSHIFT_DEFAULT;
1.1 pooka 440: LIST_INIT(&pu->pu_pnodelst);
1.44 pooka 441: LIST_INIT(&pu->pu_framectrl.fb_ios);
1.46 pooka 442: LIST_INIT(&pu->pu_ccnukelst);
1.67 pooka 443: TAILQ_INIT(&pu->pu_sched);
1.70 pooka 444: TAILQ_INIT(&pu->pu_exq);
1.1 pooka 445:
1.24 pooka 446: /* defaults for some user-settable translation functions */
447: pu->pu_cmap = NULL; /* identity translation */
448:
1.30 pooka 449: pu->pu_pathbuild = puffs_stdpath_buildpath;
450: pu->pu_pathfree = puffs_stdpath_freepath;
451: pu->pu_pathcmp = puffs_stdpath_cmppath;
1.24 pooka 452: pu->pu_pathtransform = NULL;
453: pu->pu_namemod = NULL;
454:
1.63 pooka 455: pu->pu_errnotify = puffs_defaulterror;
456:
1.44 pooka 457: PU_SETSTATE(pu, PUFFS_STATE_BEFOREMOUNT);
1.1 pooka 458:
459: return pu;
1.6 pooka 460:
1.1 pooka 461: failfree:
1.6 pooka 462: /* can't unmount() from here for obvious reasons */
1.60 pooka 463: sverrno = errno;
1.1 pooka 464: free(pu);
1.60 pooka 465: errno = sverrno;
1.1 pooka 466: return NULL;
467: }
468:
1.21 pooka 469: /*
470: * XXX: there's currently no clean way to request unmount from
471: * within the user server, so be very brutal about it.
472: */
1.36 pooka 473: /*ARGSUSED1*/
1.21 pooka 474: int
475: puffs_exit(struct puffs_usermount *pu, int force)
476: {
1.44 pooka 477: struct puffs_node *pn;
1.21 pooka 478:
479: force = 1; /* currently */
480:
1.60 pooka 481: if (pu->pu_fd)
482: close(pu->pu_fd);
1.21 pooka 483:
1.44 pooka 484: while ((pn = LIST_FIRST(&pu->pu_pnodelst)) != NULL)
1.24 pooka 485: puffs_pn_put(pn);
1.44 pooka 486:
1.46 pooka 487: puffs_framev_exit(pu);
1.68 pooka 488: if (pu->pu_state & PU_HASKQ)
1.44 pooka 489: close(pu->pu_kq);
1.21 pooka 490: free(pu);
491:
492: return 0; /* always succesful for now, WILL CHANGE */
493: }
494:
495: int
1.73 pooka 496: puffs_mainloop(struct puffs_usermount *pu)
1.1 pooka 497: {
1.44 pooka 498: struct puffs_getreq *pgr = NULL;
499: struct puffs_putreq *ppr = NULL;
500: struct puffs_framectrl *pfctrl = &pu->pu_framectrl;
501: struct puffs_fctrl_io *fio;
1.67 pooka 502: struct puffs_cc *pcc;
1.44 pooka 503: struct kevent *curev, *newevs;
504: size_t nchanges;
505: int puffsfd, sverrno;
506: int ndone;
507:
508: assert(puffs_getstate(pu) >= PUFFS_STATE_RUNNING);
1.1 pooka 509:
1.36 pooka 510: pgr = puffs_req_makeget(pu, puffs_getmaxreqlen(pu), 0);
1.19 pooka 511: if (pgr == NULL)
1.44 pooka 512: goto out;
1.18 alc 513:
1.26 pooka 514: ppr = puffs_req_makeput(pu);
1.44 pooka 515: if (ppr == NULL)
516: goto out;
517:
518: newevs = realloc(pfctrl->evs, (2*pfctrl->nfds+1)*sizeof(struct kevent));
519: if (newevs == NULL)
520: goto out;
521: pfctrl->evs = newevs;
1.19 pooka 522:
1.44 pooka 523: pu->pu_state |= PU_INLOOP;
524:
525: pu->pu_kq = kqueue();
526: if (pu->pu_kq == -1)
527: goto out;
1.68 pooka 528: pu->pu_state |= PU_HASKQ;
1.44 pooka 529:
530: curev = pfctrl->evs;
531: LIST_FOREACH(fio, &pfctrl->fb_ios, fio_entries) {
532: EV_SET(curev, fio->io_fd, EVFILT_READ, EV_ADD,
533: 0, 0, (uintptr_t)fio);
534: curev++;
535: EV_SET(curev, fio->io_fd, EVFILT_WRITE, EV_ADD | EV_DISABLE,
536: 0, 0, (uintptr_t)fio);
537: curev++;
538: }
539: puffsfd = puffs_getselectable(pu);
540: EV_SET(curev, puffsfd, EVFILT_READ, EV_ADD, 0, 0, 0);
541: if (kevent(pu->pu_kq, pfctrl->evs, 2*pfctrl->nfds+1,
542: NULL, 0, NULL) == -1)
543: goto out;
544:
545: while (puffs_getstate(pu) != PUFFS_STATE_UNMOUNTED) {
1.46 pooka 546: if (pu->pu_ml_lfn)
547: pu->pu_ml_lfn(pu);
548:
1.55 pooka 549: /*
550: * Do this here, because:
551: * a) loopfunc might generate some results
552: * b) it's still "after" event handling (except for round 1)
553: */
554: if (puffs_req_putput(ppr) == -1)
555: goto out;
556: puffs_req_resetput(ppr);
557:
1.46 pooka 558: /* micro optimization: skip kevent syscall if possible */
559: if (pfctrl->nfds == 0 && pu->pu_ml_timep == NULL
560: && (pu->pu_state & PU_ASYNCFD) == 0) {
561: if (puffs_req_handle(pgr, ppr, 0) == -1)
562: goto out;
563: continue;
564: }
1.55 pooka 565:
1.46 pooka 566: /* else: do full processing */
1.1 pooka 567:
1.44 pooka 568: /*
569: * Build list of which to enable/disable in writecheck.
570: * Don't bother worrying about O(n) for now.
571: */
572: nchanges = 0;
573: LIST_FOREACH(fio, &pfctrl->fb_ios, fio_entries) {
1.46 pooka 574: if (fio->stat & FIO_WRGONE)
575: continue;
576:
1.44 pooka 577: /*
578: * Try to write out everything to avoid the
579: * need for enabling EVFILT_WRITE. The likely
580: * case is that we can fit everything into the
581: * socket buffer.
582: */
1.56 pooka 583: if (puffs_framev_output(pu, pfctrl, fio, ppr)) {
1.46 pooka 584: /* need kernel notify? (error condition) */
585: if (puffs_req_putput(ppr) == -1)
586: goto out;
587: puffs_req_resetput(ppr);
588: }
1.19 pooka 589:
1.46 pooka 590: /* en/disable write checks for kqueue as needed */
1.44 pooka 591: assert((FIO_EN_WRITE(fio) && FIO_RM_WRITE(fio)) == 0);
592: if (FIO_EN_WRITE(fio)) {
1.46 pooka 593: EV_SET(&pfctrl->evs[nchanges], fio->io_fd,
1.44 pooka 594: EVFILT_WRITE, EV_ENABLE, 0, 0,
595: (uintptr_t)fio);
1.46 pooka 596: fio->stat |= FIO_WR;
1.44 pooka 597: nchanges++;
598: }
599: if (FIO_RM_WRITE(fio)) {
1.46 pooka 600: EV_SET(&pfctrl->evs[nchanges], fio->io_fd,
1.44 pooka 601: EVFILT_WRITE, EV_DISABLE, 0, 0,
602: (uintptr_t)fio);
1.46 pooka 603: fio->stat &= ~FIO_WR;
1.44 pooka 604: nchanges++;
605: }
1.46 pooka 606: assert(nchanges <= pfctrl->nfds);
1.19 pooka 607: }
1.44 pooka 608:
1.46 pooka 609: ndone = kevent(pu->pu_kq, pfctrl->evs, nchanges,
610: pfctrl->evs, pfctrl->nfds+1, pu->pu_ml_timep);
1.50 pooka 611:
612: if (ndone == -1) {
613: if (errno != EINTR)
614: goto out;
615: else
616: continue;
617: }
618:
619: /* uoptimize */
1.46 pooka 620: if (ndone == 0)
621: continue;
1.44 pooka 622:
623: /* iterate over the results */
624: for (curev = pfctrl->evs; ndone--; curev++) {
1.61 pooka 625: int what;
626:
1.44 pooka 627: /* get & possibly dispatch events from kernel */
628: if (curev->ident == puffsfd) {
629: if (puffs_req_handle(pgr, ppr, 0) == -1)
630: goto out;
631: continue;
632: }
633:
1.46 pooka 634: fio = (void *)curev->udata;
635: if (curev->flags & EV_ERROR) {
636: assert(curev->filter == EVFILT_WRITE);
637: fio->stat &= ~FIO_WR;
638:
639: /* XXX: how to know if it's a transient error */
640: puffs_framev_writeclose(pu, fio,
641: (int)curev->data);
1.61 pooka 642: puffs_framev_notify(fio, PUFFS_FBIO_ERROR);
1.46 pooka 643: continue;
1.44 pooka 644: }
645:
1.61 pooka 646: what = 0;
647: if (curev->filter == EVFILT_READ) {
1.56 pooka 648: puffs_framev_input(pu, pfctrl, fio, ppr);
1.61 pooka 649: what |= PUFFS_FBIO_READ;
650: }
1.56 pooka 651:
1.61 pooka 652: else if (curev->filter == EVFILT_WRITE) {
1.56 pooka 653: puffs_framev_output(pu, pfctrl, fio, ppr);
1.61 pooka 654: what |= PUFFS_FBIO_WRITE;
655: }
656: if (what)
657: puffs_framev_notify(fio, what);
1.19 pooka 658: }
1.44 pooka 659:
1.46 pooka 660: /*
1.67 pooka 661: * Schedule continuations.
662: */
663: while ((pcc = TAILQ_FIRST(&pu->pu_sched)) != NULL) {
664: TAILQ_REMOVE(&pu->pu_sched, pcc, entries);
665: puffs_goto(pcc);
666: }
667:
668: /*
1.46 pooka 669: * Really free fd's now that we don't have references
670: * to them.
671: */
672: while ((fio = LIST_FIRST(&pfctrl->fb_ios_rmlist)) != NULL) {
673: LIST_REMOVE(fio, fio_entries);
674: free(fio);
675: }
1.18 alc 676: }
1.44 pooka 677: errno = 0;
1.51 pooka 678: puffs_req_putput(ppr);
1.18 alc 679:
1.19 pooka 680: out:
1.44 pooka 681: /* store the real error for a while */
682: sverrno = errno;
683:
684: if (ppr)
685: puffs_req_destroyput(ppr);
686: if (pgr)
687: puffs_req_destroyget(pgr);
688:
689: errno = sverrno;
690: if (errno)
691: return -1;
692: else
693: return 0;
1.1 pooka 694: }
CVSweb <webmaster@jp.NetBSD.org>