Annotation of src/sys/fs/puffs/puffs_transport.c, Revision 1.8.10.1
1.8.10.1! reinoud 1: /* $NetBSD: puffs_transport.c,v 1.8 2007/02/16 17:23:59 hannken Exp $ */
1.1 pooka 2:
3: /*
1.3 pooka 4: * Copyright (c) 2006 Antti Kantee. All Rights Reserved.
1.1 pooka 5: *
6: * Development of this software was supported by the
1.3 pooka 7: * Ulla Tuominen Foundation.
1.1 pooka 8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. The name of the company nor the name of the author may be used to
18: * endorse or promote products derived from this software without specific
19: * prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
22: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: */
33:
1.3 pooka 34: #include <sys/cdefs.h>
1.8.10.1! reinoud 35: __KERNEL_RCSID(0, "$NetBSD: puffs_transport.c,v 1.8 2007/02/16 17:23:59 hannken Exp $");
1.3 pooka 36:
1.1 pooka 37: #include <sys/param.h>
38: #include <sys/conf.h>
39: #include <sys/file.h>
40: #include <sys/filedesc.h>
1.5 pooka 41: #include <sys/fstrans.h>
42: #include <sys/kthread.h>
1.1 pooka 43: #include <sys/malloc.h>
1.4 pooka 44: #include <sys/namei.h>
1.1 pooka 45: #include <sys/poll.h>
46: #include <sys/socketvar.h>
47:
48: #include <fs/puffs/puffs_sys.h>
49:
1.7 ad 50: #include <miscfs/syncfs/syncfs.h> /* XXX: for syncer_mutex reference */
1.1 pooka 51:
52:
53: /*
54: * puffs instance structures. these are always allocated and freed
55: * from the context of the device node / fileop code.
56: */
57: struct puffs_instance {
58: pid_t pi_pid;
59: int pi_idx;
60: int pi_fd;
61: struct puffs_mount *pi_pmp;
62: struct selinfo pi_sel;
63:
64: TAILQ_ENTRY(puffs_instance) pi_entries;
65: };
66: #define PMP_EMBRYO ((struct puffs_mount *)-1) /* before mount */
67: #define PMP_DEAD ((struct puffs_mount *)-2) /* goner */
68:
69: static TAILQ_HEAD(, puffs_instance) puffs_ilist
70: = TAILQ_HEAD_INITIALIZER(puffs_ilist);
71:
1.8.10.1! reinoud 72: static int get_pi_idx(struct puffs_instance *);
! 73:
! 74:
! 75: /*
! 76: * public init / deinit
! 77: */
! 78:
1.1 pooka 79: /* protects both the list and the contents of the list elements */
1.8.10.1! reinoud 80: static kmutex_t pi_mtx;
1.1 pooka 81:
1.8.10.1! reinoud 82: void
! 83: puffs_transport_init()
! 84: {
! 85:
! 86: mutex_init(&pi_mtx, MUTEX_DEFAULT, IPL_NONE);
! 87: }
1.1 pooka 88:
1.8.10.1! reinoud 89: void
! 90: puffs_transport_destroy()
! 91: {
! 92:
! 93: mutex_destroy(&pi_mtx);
! 94: }
1.1 pooka 95:
96: /*
97: * fd routines, for cloner
98: */
99: static int puffs_fop_read(struct file *, off_t *, struct uio *,
100: kauth_cred_t, int);
101: static int puffs_fop_write(struct file *, off_t *, struct uio *,
102: kauth_cred_t, int);
103: static int puffs_fop_ioctl(struct file*, u_long, void *, struct lwp *);
104: static int puffs_fop_poll(struct file *, int, struct lwp *);
105: static int puffs_fop_close(struct file *, struct lwp *);
106: static int puffs_fop_kqfilter(struct file *, struct knote *);
107:
108:
109: static const struct fileops puffs_fileops = {
110: puffs_fop_read,
111: puffs_fop_write,
112: puffs_fop_ioctl,
113: fnullop_fcntl,
114: puffs_fop_poll,
115: fbadop_stat,
116: puffs_fop_close,
117: puffs_fop_kqfilter
118: };
119:
120: static int
121: puffs_fop_read(struct file *fp, off_t *off, struct uio *uio,
122: kauth_cred_t cred, int flags)
123: {
124:
125: return ENODEV;
126: }
127:
128: static int
129: puffs_fop_write(struct file *fp, off_t *off, struct uio *uio,
130: kauth_cred_t cred, int flags)
131: {
132:
133: return ENODEV;
134: }
135:
136: /*
137: * Poll query interface. The question is only if an event
138: * can be read from us (and by read I mean ioctl... ugh).
139: */
140: #define PUFFPOLL_EVSET (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)
141: static int
142: puffs_fop_poll(struct file *fp, int events, struct lwp *l)
143: {
144: struct puffs_mount *pmp = FPTOPMP(fp);
145: int revents;
146:
147: if (pmp == PMP_EMBRYO || pmp == PMP_DEAD) {
148: printf("puffs_fop_ioctl: puffs %p, not mounted\n", pmp);
149: return ENOENT;
150: }
151:
152: revents = events & (POLLOUT | POLLWRNORM | POLLWRBAND);
153: if ((events & PUFFPOLL_EVSET) == 0)
154: return revents;
155:
156: /* check queue */
1.8.10.1! reinoud 157: mutex_enter(&pmp->pmp_lock);
1.1 pooka 158: if (!TAILQ_EMPTY(&pmp->pmp_req_touser))
159: revents |= PUFFPOLL_EVSET;
160: else
161: selrecord(l, pmp->pmp_sel);
1.8.10.1! reinoud 162: mutex_exit(&pmp->pmp_lock);
1.1 pooka 163:
164: return revents;
165: }
166:
167: /*
168: * device close = forced unmount.
169: *
170: * unmounting is a frightfully complex operation to avoid races
171: */
172: static int
173: puffs_fop_close(struct file *fp, struct lwp *l)
174: {
175: struct puffs_instance *pi;
176: struct puffs_mount *pmp;
177: struct mount *mp;
1.2 pooka 178: int gone, rv;
1.1 pooka 179:
180: DPRINTF(("puffs_fop_close: device closed, force filesystem unmount\n"));
181:
1.2 pooka 182: restart:
1.8.10.1! reinoud 183: mutex_enter(&pi_mtx);
1.1 pooka 184: pmp = FPTOPMP(fp);
185: /*
186: * First check if the fs was never mounted. In that case
187: * remove the instance from the list. If mount is attempted later,
188: * it will simply fail.
189: */
190: if (pmp == PMP_EMBRYO) {
191: pi = FPTOPI(fp);
192: TAILQ_REMOVE(&puffs_ilist, pi, pi_entries);
1.8.10.1! reinoud 193: mutex_exit(&pi_mtx);
1.1 pooka 194: FREE(pi, M_PUFFS);
1.2 pooka 195:
196: DPRINTF(("puffs_fop_close: pmp associated with fp %p was "
197: "embryonic\n", fp));
198:
1.1 pooka 199: return 0;
200: }
201:
202: /*
203: * Next, analyze unmount was called and the instance is dead.
204: * In this case we can just free the structure and go home, it
205: * was removed from the list by puffs_nukebypmp().
206: */
207: if (pmp == PMP_DEAD) {
208: /* would be nice, but don't have a reference to it ... */
209: /* KASSERT(pmp_status == PUFFSTAT_DYING); */
1.8.10.1! reinoud 210: mutex_exit(&pi_mtx);
1.2 pooka 211:
212: DPRINTF(("puffs_fop_close: pmp associated with fp %p was "
213: "dead\n", fp));
214:
1.3 pooka 215: goto out;
1.1 pooka 216: }
217:
218: /*
219: * So we have a reference. Proceed to unwrap the file system.
220: */
221: mp = PMPTOMP(pmp);
1.8.10.1! reinoud 222: mutex_exit(&pi_mtx);
! 223: mutex_enter(&pmp->pmp_lock);
1.1 pooka 224:
225: /*
226: * Free the waiting callers before proceeding any further.
227: * The syncer might be jogging around in this file system
228: * currently. If we allow it to go to the userspace of no
229: * return while trying to get the syncer lock, well ...
230: * synclk: I feel happy, I feel fine.
231: * lockmgr: You're not fooling anyone, you know.
232: */
233: puffs_userdead(pmp);
234:
235: /*
1.2 pooka 236: * Make sure someone from puffs_unmount() isn't currently in
237: * userspace. If we don't take this precautionary step,
238: * they might notice that the mountpoint has disappeared
239: * from under them once they return. Especially note that we
240: * cannot simply test for an unmounter before calling
241: * dounmount(), since it might be possible that that particular
242: * invocation of unmount was called without MNT_FORCE. Here we
243: * *must* make sure unmount succeeds. Also, restart is necessary
244: * since pmp isn't locked. We might end up with PMP_DEAD after
245: * restart and exit from there.
246: */
247: if (pmp->pmp_unmounting) {
1.8.10.1! reinoud 248: cv_wait(&pmp->pmp_unmounting_cv, &pmp->pmp_lock);
! 249: #if 0
1.2 pooka 250: ltsleep(&pmp->pmp_unmounting, PNORELOCK | PVFS, "puffsum",
251: 0, &pmp->pmp_lock);
1.8.10.1! reinoud 252: #endif
! 253: mutex_exit(&pmp->pmp_lock);
1.2 pooka 254: DPRINTF(("puffs_fop_close: unmount was in progress for pmp %p, "
255: "restart\n", pmp));
256: goto restart;
257: }
258:
259: /*
1.5 pooka 260: * Check that suspend isn't running. Issues here:
261: * + we cannot nuke the mountpoint while suspend is running
262: * because we risk nuking it from under us (as usual... does
263: * anyone see a pattern forming?)
264: * + we must have userdead or the suspend thread might deadlock.
265: * this has been done above
266: * + this DOES NOT solve the problem with the regular unmount path.
267: * however, it is way way way way less likely a problem.
268: * perhaps vfs_busy() in vfs_suspend() would help?
269: */
270: if (pmp->pmp_suspend) {
1.8.10.1! reinoud 271: cv_wait(&pmp->pmp_suspend_cv, &pmp->pmp_lock);
! 272: #if 0
1.5 pooka 273: ltsleep(&pmp->pmp_suspend, PNORELOCK | PVFS, "puffsusum",
274: 0, &pmp->pmp_lock);
1.8.10.1! reinoud 275: #endif
! 276: mutex_exit(&pmp->pmp_lock);
1.5 pooka 277: DPRINTF(("puffs_fop_close: suspend was in progress for pmp %p, "
278: "restart\n", pmp));
279: goto restart;
280: }
1.8.10.1! reinoud 281: mutex_exit(&pmp->pmp_lock);
1.5 pooka 282:
283: /*
1.1 pooka 284: * Detach from VFS. First do necessary XXX-dance (from
285: * sys_unmount() & other callers of dounmount()
286: *
287: * XXX Freeze syncer. Must do this before locking the
288: * mount point. See dounmount() for details.
289: *
290: * XXX2: take a reference to the mountpoint before starting to
1.7 ad 291: * wait for syncer_mutex. Otherwise the mointpoint can be
1.1 pooka 292: * wiped out while we wait.
293: */
294: simple_lock(&mp->mnt_slock);
295: mp->mnt_wcnt++;
296: simple_unlock(&mp->mnt_slock);
297:
1.7 ad 298: mutex_enter(&syncer_mutex);
1.1 pooka 299:
300: simple_lock(&mp->mnt_slock);
301: mp->mnt_wcnt--;
302: if (mp->mnt_wcnt == 0)
303: wakeup(&mp->mnt_wcnt);
304: gone = mp->mnt_iflag & IMNT_GONE;
305: simple_unlock(&mp->mnt_slock);
306: if (gone) {
1.7 ad 307: mutex_exit(&syncer_mutex);
1.3 pooka 308: goto out;
1.1 pooka 309: }
310:
311: /*
312: * microscopic race condition here (although not with the current
313: * kernel), but can't really fix it without starting a crusade
314: * against vfs_busy(), so let it be, let it be, let it be
315: */
316:
317: /*
318: * The only way vfs_busy() will fail for us is if the filesystem
319: * is already a goner.
320: * XXX: skating on the thin ice of modern calling conventions ...
321: */
322: if (vfs_busy(mp, 0, 0)) {
1.7 ad 323: mutex_exit(&syncer_mutex);
1.3 pooka 324: goto out;
1.1 pooka 325: }
326:
1.3 pooka 327: /*
328: * Once we have the mount point, unmount() can't interfere..
329: * or at least in theory it shouldn't. dounmount() reentracy
330: * might require some visiting at some point.
331: */
1.2 pooka 332: rv = dounmount(mp, MNT_FORCE, l);
1.3 pooka 333: KASSERT(rv == 0);
334:
335: out:
336: /*
337: * Finally, release the instance information. It was already
338: * removed from the list by puffs_nukebypmp() and we know it's
339: * dead, so no need to lock.
340: */
341: pi = FPTOPI(fp);
342: FREE(pi, M_PUFFS);
1.1 pooka 343:
344: return 0;
345: }
346:
347: static int
1.4 pooka 348: puffs_flush(struct puffs_mount *pmp, struct puffs_flush *pf)
349: {
350: struct vnode *vp;
351: int rv;
352:
353: /* XXX: slurry */
354: if (pf->pf_op == PUFFS_INVAL_NAMECACHE_ALL) {
355: cache_purgevfs(PMPTOMP(pmp));
356: return 0;
357: }
358:
359: rv = 0;
360:
361: /*
362: * Get vnode, don't lock it. Namecache is protected by its own lock
363: * and we have a reference to protect against premature harvesting.
364: *
365: * The node we want here might be locked and the op is in
366: * userspace waiting for us to complete ==> deadlock. Another
367: * reason we need to eventually bump locking to userspace, as we
368: * will need to lock the node if we wish to do flushes.
369: */
370: vp = puffs_pnode2vnode(pmp, pf->pf_cookie, 0);
371: if (vp == NULL)
372: return ENOENT;
373:
374: switch (pf->pf_op) {
375: #if 0
376: /* not quite ready, yet */
377: case PUFFS_INVAL_NAMECACHE_NODE:
378: struct componentname *pf_cn;
379: char *name;
380: /* get comfortab^Wcomponentname */
381: MALLOC(pf_cn, struct componentname *,
382: sizeof(struct componentname), M_PUFFS, M_WAITOK | M_ZERO);
383: memset(pf_cn, 0, sizeof(struct componentname));
384: break;
385:
386: #endif
387: case PUFFS_INVAL_NAMECACHE_DIR:
388: cache_purge1(vp, NULL, PURGE_CHILDREN);
389: break;
390:
1.8.10.1! reinoud 391: #if 0
! 392: case PUFFS_INVAL_PAGECACHE_NODE_RANGE:
! 393: simple_lock(&vp->v_uobj.vmobjlock);
! 394: /* XXX: validate args? */
! 395: rv = VOP_PUTPAGES(vp, pf->pf_start, pf->pf_end, PGO_FREE);
! 396: break;
! 397: #endif
! 398:
! 399: case PUFFS_INVAL_PAGECACHE_NODE:
! 400: simple_lock(&vp->v_uobj.vmobjlock);
! 401: rv = VOP_PUTPAGES(vp, 0, 0, PGO_FREE | PGO_ALLPAGES);
! 402: break;
! 403:
1.4 pooka 404: default:
405: rv = EINVAL;
406: }
407:
408: vrele(vp);
409:
410: return rv;
411: }
412:
1.5 pooka 413: static void
414: dosuspendresume(void *arg)
415: {
416: struct puffs_mount *pmp = arg;
417: struct mount *mp;
418: int rv;
419:
420: mp = PMPTOMP(pmp);
421: /*
422: * XXX? does this really do any good or is it just
423: * paranoid stupidity? or stupid paranoia?
424: */
425: if (mp->mnt_iflag & IMNT_UNMOUNT) {
426: printf("puffs dosuspendresume(): detected suspend on "
427: "unmounting fs\n");
428: goto out;
429: }
430:
431: /* do the dance */
432: rv = vfs_suspend(PMPTOMP(pmp), 0);
433: if (rv == 0)
434: vfs_resume(PMPTOMP(pmp));
435:
1.8.10.1! reinoud 436: mutex_enter(&pmp->pmp_lock);
1.5 pooka 437: KASSERT(pmp->pmp_suspend);
438: pmp->pmp_suspend = 0;
1.8.10.1! reinoud 439: cv_broadcast(&pmp->pmp_suspend_cv);
! 440: mutex_exit(&pmp->pmp_lock);
1.5 pooka 441:
442: out:
443: kthread_exit(0);
444: }
445:
1.4 pooka 446: static int
1.1 pooka 447: puffs_fop_ioctl(struct file *fp, u_long cmd, void *data, struct lwp *l)
448: {
1.6 pooka 449: struct puffs_mount *pmp = FPTOPMP(fp);
1.1 pooka 450: int rv;
451:
452: if (pmp == PMP_EMBRYO || pmp == PMP_DEAD) {
453: printf("puffs_fop_ioctl: puffs %p, not mounted\n", pmp);
454: return ENOENT;
455: }
456:
457: switch (cmd) {
458: case PUFFSGETOP:
459: rv = puffs_getop(pmp, data, fp->f_flag & FNONBLOCK);
460: break;
461:
462: case PUFFSPUTOP:
463: rv = puffs_putop(pmp, data);
464: break;
465:
466: #if 0 /* bitrot */
467: case PUFFSSIZEOP:
468: rv = puffssizeop(pmp, data);
469: break;
470: #endif
471:
472: case PUFFSSTARTOP:
473: rv = puffs_start2(pmp, data);
474: break;
475:
1.4 pooka 476: case PUFFSFLUSHOP:
477: rv = puffs_flush(pmp, data);
478: break;
479:
1.5 pooka 480: case PUFFSSUSPENDOP:
481: rv = 0;
1.8.10.1! reinoud 482: mutex_enter(&pmp->pmp_lock);
1.5 pooka 483: if (pmp->pmp_suspend || pmp->pmp_status != PUFFSTAT_RUNNING)
484: rv = EBUSY;
485: else
486: pmp->pmp_suspend = 1;
1.8.10.1! reinoud 487: mutex_exit(&pmp->pmp_lock);
1.5 pooka 488: if (rv)
489: break;
490: rv = kthread_create1(dosuspendresume, pmp, NULL, "puffsusp");
491: break;
492:
1.1 pooka 493: /* already done in sys_ioctl() */
494: case FIONBIO:
495: rv = 0;
496: break;
497:
498: default:
499: rv = EINVAL;
500: break;
501: }
502:
503: return rv;
504: }
505:
506: /* kqueue stuff */
507:
508: static void
509: filt_puffsdetach(struct knote *kn)
510: {
511: struct puffs_instance *pi = kn->kn_hook;
512:
1.8.10.1! reinoud 513: mutex_enter(&pi_mtx);
1.1 pooka 514: SLIST_REMOVE(&pi->pi_sel.sel_klist, kn, knote, kn_selnext);
1.8.10.1! reinoud 515: mutex_exit(&pi_mtx);
1.1 pooka 516: }
517:
518: static int
519: filt_puffsioctl(struct knote *kn, long hint)
520: {
521: struct puffs_instance *pi = kn->kn_hook;
522: struct puffs_mount *pmp;
523: int error;
524:
525: error = 0;
1.8.10.1! reinoud 526: mutex_enter(&pi_mtx);
1.1 pooka 527: pmp = pi->pi_pmp;
528: if (pmp == PMP_EMBRYO || pmp == PMP_DEAD)
529: error = 1;
1.8.10.1! reinoud 530: mutex_exit(&pi_mtx);
1.1 pooka 531: if (error)
532: return 0;
533:
1.8.10.1! reinoud 534: mutex_enter(&pmp->pmp_lock);
! 535: kn->kn_data = pmp->pmp_req_waiters;
! 536: mutex_exit(&pmp->pmp_lock);
1.1 pooka 537:
538: return kn->kn_data != 0;
539: }
540:
541: static const struct filterops puffsioctl_filtops =
542: { 1, NULL, filt_puffsdetach, filt_puffsioctl };
543:
544: static int
545: puffs_fop_kqfilter(struct file *fp, struct knote *kn)
546: {
547: struct puffs_instance *pi = fp->f_data;
548: struct klist *klist;
549:
550: if (kn->kn_filter != EVFILT_READ)
551: return 1;
552:
553: klist = &pi->pi_sel.sel_klist;
554: kn->kn_fop = &puffsioctl_filtops;
555: kn->kn_hook = pi;
556:
1.8.10.1! reinoud 557: mutex_enter(&pi_mtx);
1.1 pooka 558: SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1.8.10.1! reinoud 559: mutex_exit(&pi_mtx);
1.1 pooka 560:
561: return 0;
562: }
563:
564:
565: /*
566: * Device routines
567: */
568:
569: dev_type_open(puffscdopen);
570: dev_type_close(puffscdclose);
571: dev_type_ioctl(puffscdioctl);
572:
573: /* dev */
574: const struct cdevsw puffs_cdevsw = {
575: puffscdopen, puffscdclose, noread, nowrite,
576: noioctl, nostop, notty, nopoll,
577: nommap, nokqfilter, D_OTHER
578: };
579: int
580: puffscdopen(dev_t dev, int flags, int fmt, struct lwp *l)
581: {
582: struct puffs_instance *pi;
583: struct file *fp;
584: int error, fd, idx;
585:
586: /*
587: * XXX: decide on some security model and check permissions
588: */
589:
590: if (minor(dev) != PUFFS_CLONER)
591: return ENXIO;
592:
593: if ((error = falloc(l, &fp, &fd)) != 0)
594: return error;
595:
596: MALLOC(pi, struct puffs_instance *, sizeof(struct puffs_instance),
597: M_PUFFS, M_WAITOK | M_ZERO);
598:
1.8.10.1! reinoud 599: mutex_enter(&pi_mtx);
1.1 pooka 600: idx = get_pi_idx(pi);
601: if (idx == PUFFS_CLONER) {
1.8.10.1! reinoud 602: mutex_exit(&pi_mtx);
1.1 pooka 603: FREE(pi, M_PUFFS);
604: FILE_UNUSE(fp, l);
605: ffree(fp);
606: return EBUSY;
607: }
608:
609: pi->pi_pid = l->l_proc->p_pid;
610: pi->pi_idx = idx;
1.8.10.1! reinoud 611: mutex_exit(&pi_mtx);
1.1 pooka 612:
613: DPRINTF(("puffscdopen: registered embryonic pmp for pid: %d\n",
614: pi->pi_pid));
615:
616: return fdclone(l, fp, fd, FREAD|FWRITE, &puffs_fileops, pi);
617: }
618:
619: int
620: puffscdclose(dev_t dev, int flags, int fmt, struct lwp *l)
621: {
622:
623: panic("puffscdclose impossible\n");
624:
625: return 0;
626: }
627:
628:
629: /*
630: * Set puffs_mount -pointer. Called from puffs_mount(), which is the
631: * earliest place that knows about this.
632: *
633: * We only want to make sure that the caller had the right to open the
634: * device, we don't so much care about which context it gets in case
635: * the same process opened multiple (since they are equal at this point).
636: */
637: int
638: puffs_setpmp(pid_t pid, int fd, struct puffs_mount *pmp)
639: {
640: struct puffs_instance *pi;
641: int rv = 1;
642:
1.8.10.1! reinoud 643: mutex_enter(&pi_mtx);
1.1 pooka 644: TAILQ_FOREACH(pi, &puffs_ilist, pi_entries) {
645: if (pi->pi_pid == pid && pi->pi_pmp == PMP_EMBRYO) {
646: pi->pi_pmp = pmp;
647: pi->pi_fd = fd;
648: pmp->pmp_sel = &pi->pi_sel;
649: rv = 0;
650: break;
651: }
652: }
1.8.10.1! reinoud 653: mutex_exit(&pi_mtx);
1.1 pooka 654:
655: return rv;
656: }
657:
658: /*
659: * Remove mount point from list of instances. Called from unmount.
660: */
661: void
662: puffs_nukebypmp(struct puffs_mount *pmp)
663: {
664: struct puffs_instance *pi;
665:
1.8.10.1! reinoud 666: mutex_enter(&pi_mtx);
1.1 pooka 667: TAILQ_FOREACH(pi, &puffs_ilist, pi_entries) {
668: if (pi->pi_pmp == pmp) {
669: TAILQ_REMOVE(&puffs_ilist, pi, pi_entries);
670: break;
671: }
672: }
673: if (pi)
674: pi->pi_pmp = PMP_DEAD;
675:
676: #ifdef DIAGNOSTIC
677: else
678: panic("puffs_nukebypmp: invalid puffs_mount\n");
679: #endif /* DIAGNOSTIC */
680:
1.8.10.1! reinoud 681: mutex_exit(&pi_mtx);
1.1 pooka 682:
683: DPRINTF(("puffs_nukebypmp: nuked %p\n", pi));
684: }
685:
686: /* search sorted list of instances for free minor, sorted insert arg */
687: static int
688: get_pi_idx(struct puffs_instance *pi_i)
689: {
690: struct puffs_instance *pi;
691: int i;
692:
693: i = 0;
694: TAILQ_FOREACH(pi, &puffs_ilist, pi_entries) {
695: if (i == PUFFS_CLONER)
696: return PUFFS_CLONER;
697: if (i != pi->pi_idx)
698: break;
699: i++;
700: }
701:
702: pi_i->pi_pmp = PMP_EMBRYO;
703:
704: if (pi == NULL)
705: TAILQ_INSERT_TAIL(&puffs_ilist, pi_i, pi_entries);
706: else
707: TAILQ_INSERT_BEFORE(pi, pi_i, pi_entries);
708:
709: return i;
710: }
CVSweb <webmaster@jp.NetBSD.org>