Annotation of src/sys/fs/puffs/puffs_subr.c, Revision 1.22.2.9
1.22.2.9! ad 1: /* $NetBSD: puffs_subr.c,v 1.22.2.8 2007/07/15 15:52:51 ad Exp $ */
1.1 pooka 2:
3: /*
4: * Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
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.22.2.9! ad 33: __KERNEL_RCSID(0, "$NetBSD: puffs_subr.c,v 1.22.2.8 2007/07/15 15:52:51 ad Exp $");
1.1 pooka 34:
35: #include <sys/param.h>
36: #include <sys/conf.h>
1.16 pooka 37: #include <sys/hash.h>
1.22.2.5 ad 38: #include <sys/kauth.h>
1.1 pooka 39: #include <sys/malloc.h>
40: #include <sys/mount.h>
1.22.2.5 ad 41: #include <sys/namei.h>
42: #include <sys/poll.h>
1.1 pooka 43: #include <sys/socketvar.h>
44: #include <sys/vnode.h>
1.22.2.3 ad 45: #include <sys/proc.h>
1.1 pooka 46:
47: #include <fs/puffs/puffs_msgif.h>
48: #include <fs/puffs/puffs_sys.h>
49:
1.7 pooka 50: #include <miscfs/genfs/genfs_node.h>
1.4 pooka 51: #include <miscfs/specfs/specdev.h>
52:
1.22.2.4 ad 53: struct pool puffs_pnpool;
1.1 pooka 54:
1.19 pooka 55: #ifdef PUFFSDEBUG
1.10 pooka 56: int puffsdebug;
57: #endif
58:
1.16 pooka 59: static __inline struct puffs_node_hashlist
60: *puffs_cookie2hashlist(struct puffs_mount *, void *);
61: static struct puffs_node *puffs_cookie2pnode(struct puffs_mount *, void *);
1.7 pooka 62:
63: static void puffs_gop_size(struct vnode *, off_t, off_t *, int);
64: static void puffs_gop_markupdate(struct vnode *, int);
65:
66: static const struct genfs_ops puffs_genfsops = {
67: .gop_size = puffs_gop_size,
68: .gop_write = genfs_gop_write,
69: .gop_markupdate = puffs_gop_markupdate,
70: #if 0
71: .gop_alloc, should ask userspace
72: #endif
73: };
74:
1.1 pooka 75: /*
76: * Grab a vnode, intialize all the puffs-dependant stuff.
77: */
78: int
1.4 pooka 79: puffs_getvnode(struct mount *mp, void *cookie, enum vtype type,
1.7 pooka 80: voff_t vsize, dev_t rdev, struct vnode **vpp)
1.1 pooka 81: {
82: struct puffs_mount *pmp;
1.4 pooka 83: struct vnode *vp, *nvp;
1.1 pooka 84: struct puffs_node *pnode;
1.16 pooka 85: struct puffs_node_hashlist *plist;
1.1 pooka 86: int error;
87:
1.22.2.8 ad 88: if (type <= VNON || type >= VBAD)
89: return EINVAL;
90:
1.1 pooka 91: pmp = MPTOPUFFSMP(mp);
92:
1.2 pooka 93: /*
94: * XXX: there is a deadlock condition between vfs_busy() and
95: * vnode locks. For an unmounting file system the mountpoint
96: * is frozen, but in unmount(FORCE) vflush() wants to access all
97: * of the vnodes. If we are here waiting for the mountpoint
98: * lock while holding on to a vnode lock, well, we ain't
99: * just pining for the fjords anymore. If we release the
100: * vnode lock, we will be in the situation "mount point
101: * is dying" and panic() will ensue in insmntque. So as a
102: * temporary workaround, get a vnode without putting it on
103: * the mount point list, check if mount point is still alive
104: * and kicking and only then add the vnode to the list.
105: */
106: error = getnewvnode(VT_PUFFS, NULL, puffs_vnodeop_p, &vp);
107: if (error)
1.1 pooka 108: return error;
1.2 pooka 109: vp->v_vnlock = NULL;
1.4 pooka 110: vp->v_type = type;
1.2 pooka 111:
112: /*
113: * Check what mount point isn't going away. This will work
114: * until we decide to remove biglock or make the kernel
115: * preemptive. But hopefully the real problem will be fixed
116: * by then.
117: *
118: * XXX: yes, should call vfs_busy(), but thar be rabbits with
119: * vicious streaks a mile wide ...
120: */
121: if (mp->mnt_iflag & IMNT_UNMOUNT) {
122: DPRINTF(("puffs_getvnode: mp %p unmount, unable to create "
123: "vnode for cookie %p\n", mp, cookie));
124: ungetnewvnode(vp);
125: return ENXIO;
1.1 pooka 126: }
127:
1.2 pooka 128: /* So it's not dead yet.. good.. inform new vnode of its master */
1.22.2.2 ad 129: mutex_enter(&mntvnode_lock);
1.16 pooka 130: TAILQ_INSERT_TAIL(&mp->mnt_vnodelist, vp, v_mntvnodes);
1.22.2.2 ad 131: mutex_exit(&mntvnode_lock);
1.2 pooka 132: vp->v_mount = mp;
133:
1.4 pooka 134: /*
135: * clerical tasks & footwork
136: */
137:
1.22.2.5 ad 138: /* default size */
139: uvm_vnp_setsize(vp, 0);
140:
1.4 pooka 141: /* dances based on vnode type. almost ufs_vinit(), but not quite */
142: switch (type) {
143: case VCHR:
144: case VBLK:
145: /*
146: * replace vnode operation vector with the specops vector.
147: * our user server has very little control over the node
148: * if it decides its a character or block special file
149: */
150: vp->v_op = puffs_specop_p;
151:
152: /* do the standard checkalias-dance */
153: if ((nvp = checkalias(vp, rdev, mp)) != NULL) {
154: /*
1.6 pooka 155: * found: release & unallocate aliased
1.4 pooka 156: * old (well, actually, new) node
157: */
158: vp->v_op = spec_vnodeop_p;
1.22.2.7 ad 159: mutex_enter(&vp->v_interlock);
160: vp->v_iflag &= ~VI_LOCKSWORK;
161: mutex_exit(&vp->v_interlock);
1.4 pooka 162: vrele(vp);
163: vgone(vp); /* cya */
164:
165: /* init "new" vnode */
166: vp = nvp;
167: vp->v_vnlock = NULL;
168: vp->v_mount = mp;
169: }
170: break;
1.7 pooka 171:
1.5 pooka 172: case VFIFO:
173: vp->v_op = puffs_fifoop_p;
174: break;
1.7 pooka 175:
176: case VREG:
177: uvm_vnp_setsize(vp, vsize);
178: break;
179:
1.5 pooka 180: case VDIR:
181: case VLNK:
182: case VSOCK:
183: break;
1.4 pooka 184: default:
1.5 pooka 185: #ifdef DIAGNOSTIC
186: panic("puffs_getvnode: invalid vtype %d", type);
187: #endif
1.4 pooka 188: break;
189: }
190:
1.2 pooka 191: pnode = pool_get(&puffs_pnpool, PR_WAITOK);
1.1 pooka 192: pnode->pn_cookie = cookie;
193: pnode->pn_stat = 0;
1.22.2.5 ad 194: pnode->pn_refcount = 1;
195:
196: mutex_init(&pnode->pn_mtx, MUTEX_DEFAULT, IPL_NONE);
197: SLIST_INIT(&pnode->pn_sel.sel_klist);
198: pnode->pn_revents = 0;
199:
1.16 pooka 200: plist = puffs_cookie2hashlist(pmp, cookie);
201: LIST_INSERT_HEAD(plist, pnode, pn_hashent);
1.1 pooka 202: vp->v_data = pnode;
1.4 pooka 203: vp->v_type = type;
1.1 pooka 204: pnode->pn_vp = vp;
205:
1.7 pooka 206: genfs_node_init(vp, &puffs_genfsops);
1.1 pooka 207: *vpp = vp;
208:
209: DPRINTF(("new vnode at %p, pnode %p, cookie %p\n", vp,
210: pnode, pnode->pn_cookie));
211:
212: return 0;
213: }
214:
215: /* new node creating for creative vop ops (create, symlink, mkdir, mknod) */
216: int
217: puffs_newnode(struct mount *mp, struct vnode *dvp, struct vnode **vpp,
1.4 pooka 218: void *cookie, struct componentname *cnp, enum vtype type, dev_t rdev)
1.1 pooka 219: {
1.13 pooka 220: struct puffs_mount *pmp = MPTOPUFFSMP(mp);
1.1 pooka 221: struct vnode *vp;
222: int error;
223:
224: /* userspace probably has this as a NULL op */
225: if (cookie == NULL) {
226: error = EOPNOTSUPP;
1.3 pooka 227: return error;
1.1 pooka 228: }
229:
1.15 pooka 230: /*
231: * Check for previous node with the same designation.
1.20 pooka 232: * Explicitly check the root node cookie, since it might be
233: * reclaimed from the kernel when this check is made.
1.15 pooka 234: *
235: * XXX: technically this error check should punish the fs,
236: * not the caller.
237: */
1.22.2.4 ad 238: mutex_enter(&pmp->pmp_lock);
1.22.2.5 ad 239: if (cookie == pmp->pmp_root_cookie
1.20 pooka 240: || puffs_cookie2pnode(pmp, cookie) != NULL) {
1.22.2.4 ad 241: mutex_exit(&pmp->pmp_lock);
1.15 pooka 242: error = EEXIST;
243: return error;
244: }
1.22.2.4 ad 245: mutex_exit(&pmp->pmp_lock);
1.15 pooka 246:
1.7 pooka 247: error = puffs_getvnode(dvp->v_mount, cookie, type, 0, rdev, &vp);
1.1 pooka 248: if (error)
1.3 pooka 249: return error;
1.1 pooka 250:
251: vp->v_type = type;
252: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
253: *vpp = vp;
254:
1.22.2.8 ad 255: if ((cnp->cn_flags & MAKEENTRY) && PUFFS_USE_NAMECACHE(pmp))
1.13 pooka 256: cache_enter(dvp, vp, cnp);
257:
1.3 pooka 258: return 0;
1.1 pooka 259: }
260:
1.22.2.5 ad 261: /*
262: * Release pnode structure which dealing with references to the
263: * puffs_node instead of the vnode. Can't use vref()/vrele() on
264: * the vnode there, since that causes the lovely VOP_INACTIVE(),
265: * which in turn causes the lovely deadlock when called by the one
266: * who is supposed to handle it.
267: */
268: void
269: puffs_releasenode(struct puffs_node *pn)
270: {
271:
272: mutex_enter(&pn->pn_mtx);
273: if (--pn->pn_refcount == 0) {
274: mutex_exit(&pn->pn_mtx);
275: mutex_destroy(&pn->pn_mtx);
276: pool_put(&puffs_pnpool, pn);
277: } else {
278: mutex_exit(&pn->pn_mtx);
279: }
280: }
281:
282: /*
283: * Add reference to node.
284: * mutex held on entry and return
285: */
286: void
287: puffs_referencenode(struct puffs_node *pn)
288: {
289:
290: KASSERT(mutex_owned(&pn->pn_mtx));
291: pn->pn_refcount++;
292: }
293:
1.1 pooka 294: void
295: puffs_putvnode(struct vnode *vp)
296: {
297: struct puffs_mount *pmp;
298: struct puffs_node *pnode;
299:
300: pmp = VPTOPUFFSMP(vp);
301: pnode = VPTOPP(vp);
302:
303: #ifdef DIAGNOSTIC
304: if (vp->v_tag != VT_PUFFS)
305: panic("puffs_putvnode: %p not a puffs vnode", vp);
306: #endif
307:
1.16 pooka 308: LIST_REMOVE(pnode, pn_hashent);
1.21 ad 309: genfs_node_destroy(vp);
1.22.2.5 ad 310: puffs_releasenode(pnode);
1.1 pooka 311: vp->v_data = NULL;
312:
313: return;
314: }
315:
1.16 pooka 316: static __inline struct puffs_node_hashlist *
317: puffs_cookie2hashlist(struct puffs_mount *pmp, void *cookie)
318: {
319: uint32_t hash;
320:
321: hash = hash32_buf(&cookie, sizeof(void *), HASH32_BUF_INIT);
322: return &pmp->pmp_pnodehash[hash % pmp->pmp_npnodehash];
323: }
324:
1.1 pooka 325: /*
1.15 pooka 326: * Translate cookie to puffs_node. Caller must hold mountpoint
327: * lock and it will be held upon return.
328: */
1.16 pooka 329: static struct puffs_node *
1.15 pooka 330: puffs_cookie2pnode(struct puffs_mount *pmp, void *cookie)
331: {
1.16 pooka 332: struct puffs_node_hashlist *plist;
1.15 pooka 333: struct puffs_node *pnode;
334:
1.16 pooka 335: plist = puffs_cookie2hashlist(pmp, cookie);
336: LIST_FOREACH(pnode, plist, pn_hashent) {
1.15 pooka 337: if (pnode->pn_cookie == cookie)
338: break;
339: }
340:
341: return pnode;
342: }
343:
344: /*
1.22.2.8 ad 345: * Make sure root vnode exists and reference it. Does NOT lock.
346: */
347: static int
348: puffs_makeroot(struct puffs_mount *pmp)
349: {
350: struct vnode *vp;
351: int rv;
352:
353: /*
354: * pmp_lock must be held if vref()'ing or vrele()'ing the
355: * root vnode. the latter is controlled by puffs_inactive().
356: *
357: * pmp_root is set here and cleared in puffs_reclaim().
358: */
359: retry:
360: mutex_enter(&pmp->pmp_lock);
361: vp = pmp->pmp_root;
362: if (vp) {
363: mutex_enter(&vp->v_interlock);
364: mutex_exit(&pmp->pmp_lock);
365: if (vget(vp, LK_INTERLOCK) == 0)
366: return 0;
367: } else
368: mutex_exit(&pmp->pmp_lock);
369:
370: /*
371: * So, didn't have the magic root vnode available.
372: * No matter, grab another an stuff it with the cookie.
373: */
374: if ((rv = puffs_getvnode(pmp->pmp_mp, pmp->pmp_root_cookie,
375: pmp->pmp_root_vtype, pmp->pmp_root_vsize, pmp->pmp_root_rdev, &vp)))
376: return rv;
377:
378: /*
379: * Someone magically managed to race us into puffs_getvnode?
380: * Put our previous new vnode back and retry.
381: */
382: mutex_enter(&pmp->pmp_lock);
383: if (pmp->pmp_root) {
384: mutex_exit(&pmp->pmp_lock);
385: puffs_putvnode(vp);
386: goto retry;
387: }
388:
389: /* store cache */
390: vp->v_vflag = VV_ROOT;
391: pmp->pmp_root = vp;
392: mutex_exit(&pmp->pmp_lock);
393:
394: return 0;
395: }
396:
397: /*
1.1 pooka 398: * Locate the in-kernel vnode based on the cookie received given
1.20 pooka 399: * from userspace. Returns a vnode, if found, NULL otherwise.
400: * The parameter "lock" control whether to lock the possible or
401: * not. Locking always might cause us to lock against ourselves
402: * in situations where we want the vnode but don't care for the
403: * vnode lock, e.g. file server issued putpages.
1.1 pooka 404: */
1.22.2.8 ad 405: int
406: puffs_pnode2vnode(struct puffs_mount *pmp, void *cookie, int lock,
407: struct vnode **vpp)
1.1 pooka 408: {
409: struct puffs_node *pnode;
410: struct vnode *vp;
1.22.2.8 ad 411: int vgetflags, rv;
1.1 pooka 412:
1.20 pooka 413: /*
1.22.2.8 ad 414: * Handle root in a special manner, since we want to make sure
415: * pmp_root is properly set.
1.20 pooka 416: */
1.22.2.5 ad 417: if (cookie == pmp->pmp_root_cookie) {
1.22.2.8 ad 418: if ((rv = puffs_makeroot(pmp)))
419: return rv;
420: if (lock)
421: vn_lock(pmp->pmp_root, LK_EXCLUSIVE | LK_RETRY);
1.20 pooka 422:
1.22.2.8 ad 423: *vpp = pmp->pmp_root;
424: return 0;
1.20 pooka 425: }
426:
1.22.2.4 ad 427: mutex_enter(&pmp->pmp_lock);
1.15 pooka 428: pnode = puffs_cookie2pnode(pmp, cookie);
1.14 pooka 429:
1.15 pooka 430: if (pnode == NULL) {
1.22.2.4 ad 431: mutex_exit(&pmp->pmp_lock);
1.22.2.8 ad 432: return ENOENT;
1.15 pooka 433: }
1.17 pooka 434:
1.22.2.8 ad 435: vp = pnode->pn_vp;
1.22.2.3 ad 436: mutex_enter(&vp->v_interlock);
1.22.2.4 ad 437: mutex_exit(&pmp->pmp_lock);
1.1 pooka 438:
1.22.2.8 ad 439: vgetflags = LK_INTERLOCK;
440: if (lock)
441: vgetflags |= LK_EXCLUSIVE | LK_RETRY;
442: if ((rv = vget(vp, vgetflags)))
443: return rv;
1.14 pooka 444:
1.22.2.8 ad 445: *vpp = vp;
446: return 0;
1.1 pooka 447: }
448:
449: void
1.22.2.8 ad 450: puffs_makecn(struct puffs_kcn *pkcn, struct puffs_kcred *pkcr,
451: struct puffs_kcid *pkcid, const struct componentname *cn, int full)
1.1 pooka 452: {
453:
1.12 pooka 454: pkcn->pkcn_nameiop = cn->cn_nameiop;
455: pkcn->pkcn_flags = cn->cn_flags;
1.22.2.8 ad 456: puffs_cidcvt(pkcid, cn->cn_lwp);
1.1 pooka 457:
1.22.2.8 ad 458: if (full) {
459: (void)strcpy(pkcn->pkcn_name, cn->cn_nameptr);
460: } else {
461: (void)memcpy(pkcn->pkcn_name, cn->cn_nameptr, cn->cn_namelen);
462: pkcn->pkcn_name[cn->cn_namelen] = '\0';
463: }
1.12 pooka 464: pkcn->pkcn_namelen = cn->cn_namelen;
1.22.2.8 ad 465: pkcn->pkcn_consume = 0;
466:
467: puffs_credcvt(pkcr, cn->cn_cred);
1.1 pooka 468: }
469:
470: /*
1.22.2.8 ad 471: * Convert given credentials to struct puffs_kcred for userspace.
1.1 pooka 472: */
473: void
1.22.2.8 ad 474: puffs_credcvt(struct puffs_kcred *pkcr, const kauth_cred_t cred)
1.1 pooka 475: {
476:
1.22.2.8 ad 477: memset(pkcr, 0, sizeof(struct puffs_kcred));
1.1 pooka 478:
479: if (cred == NOCRED || cred == FSCRED) {
1.22.2.8 ad 480: pkcr->pkcr_type = PUFFCRED_TYPE_INTERNAL;
1.1 pooka 481: if (cred == NOCRED)
1.22.2.8 ad 482: pkcr->pkcr_internal = PUFFCRED_CRED_NOCRED;
1.1 pooka 483: if (cred == FSCRED)
1.22.2.8 ad 484: pkcr->pkcr_internal = PUFFCRED_CRED_FSCRED;
1.1 pooka 485: } else {
1.22.2.8 ad 486: pkcr->pkcr_type = PUFFCRED_TYPE_UUC;
487: kauth_cred_to_uucred(&pkcr->pkcr_uuc, cred);
1.1 pooka 488: }
489: }
490:
1.22.2.8 ad 491: void
492: puffs_cidcvt(struct puffs_kcid *pkcid, const struct lwp *l)
1.1 pooka 493: {
494:
1.22.2.8 ad 495: if (l) {
496: pkcid->pkcid_type = PUFFCID_TYPE_REAL;
497: pkcid->pkcid_pid = l->l_proc->p_pid;
498: pkcid->pkcid_lwpid = l->l_lid;
499: } else {
500: pkcid->pkcid_type = PUFFCID_TYPE_FAKE;
501: pkcid->pkcid_pid = 0;
502: pkcid->pkcid_lwpid = 0;
503: }
1.1 pooka 504: }
1.7 pooka 505:
506: static void
1.8 christos 507: puffs_gop_size(struct vnode *vp, off_t size, off_t *eobp,
508: int flags)
1.7 pooka 509: {
510:
511: *eobp = size;
512: }
513:
514: static void
515: puffs_gop_markupdate(struct vnode *vp, int flags)
516: {
517: int uflags = 0;
518:
519: if (flags & GOP_UPDATE_ACCESSED)
520: uflags |= PUFFS_UPDATEATIME;
521: if (flags & GOP_UPDATE_MODIFIED)
522: uflags |= PUFFS_UPDATEMTIME;
523:
524: puffs_updatenode(vp, uflags);
525: }
526:
527: void
528: puffs_updatenode(struct vnode *vp, int flags)
529: {
1.22.2.4 ad 530: struct puffs_node *pn;
1.7 pooka 531: struct timespec ts;
532:
533: if (flags == 0)
534: return;
535:
1.22.2.4 ad 536: pn = VPTOPP(vp);
1.7 pooka 537: nanotime(&ts);
538:
1.22.2.4 ad 539: if (flags & PUFFS_UPDATEATIME) {
540: pn->pn_mc_atime = ts;
541: pn->pn_stat |= PNODE_METACACHE_ATIME;
542: }
543: if (flags & PUFFS_UPDATECTIME) {
544: pn->pn_mc_ctime = ts;
545: pn->pn_stat |= PNODE_METACACHE_CTIME;
546: }
547: if (flags & PUFFS_UPDATEMTIME) {
548: pn->pn_mc_mtime = ts;
549: pn->pn_stat |= PNODE_METACACHE_MTIME;
550: }
551: if (flags & PUFFS_UPDATESIZE) {
552: pn->pn_mc_size = vp->v_size;
553: pn->pn_stat |= PNODE_METACACHE_SIZE;
554: }
1.7 pooka 555: }
1.9 pooka 556:
557: void
558: puffs_updatevpsize(struct vnode *vp)
559: {
560: struct vattr va;
561:
562: if (VOP_GETATTR(vp, &va, FSCRED, NULL))
563: return;
564:
565: if (va.va_size != VNOVAL)
566: vp->v_size = va.va_size;
567: }
1.11 pooka 568:
569: void
1.22.2.4 ad 570: puffs_parkdone_asyncbioread(struct puffs_req *preq, void *arg)
1.11 pooka 571: {
1.22.2.4 ad 572: struct puffs_vnreq_read *read_argp = (void *)preq;
573: struct buf *bp = arg;
574: size_t moved;
575:
1.22.2.9! ad 576: bp->b_error = preq->preq_rv;
! 577: if (bp->b_error == 0) {
1.22.2.4 ad 578: moved = bp->b_bcount - read_argp->pvnr_resid;
1.22.2.9! ad 579: bp->b_resid = read_argp->pvnr_resid;
! 580:
1.22.2.4 ad 581: memcpy(bp->b_data, read_argp->pvnr_data, moved);
1.22.2.9! ad 582: }
1.22 pooka 583:
1.22.2.9! ad 584: biodone(bp);
1.22.2.4 ad 585: free(preq, M_PUFFS);
1.22 pooka 586: }
1.22.2.5 ad 587:
588: void
589: puffs_parkdone_poll(struct puffs_req *preq, void *arg)
590: {
591: struct puffs_vnreq_poll *poll_argp = (void *)preq;
592: struct puffs_node *pn = arg;
593: int revents;
594:
595: if (preq->preq_rv == 0)
596: revents = poll_argp->pvnr_events;
597: else
598: revents = POLLERR;
599:
600: mutex_enter(&pn->pn_mtx);
601: pn->pn_revents |= revents;
602: mutex_exit(&pn->pn_mtx);
603:
604: selnotify(&pn->pn_sel, 0);
605: free(preq, M_PUFFS);
606:
607: puffs_releasenode(pn);
608: }
609:
610: void
611: puffs_mp_reference(struct puffs_mount *pmp)
612: {
613:
614: KASSERT(mutex_owned(&pmp->pmp_lock));
615: pmp->pmp_refcount++;
616: }
617:
618: void
619: puffs_mp_release(struct puffs_mount *pmp)
620: {
621:
622: KASSERT(mutex_owned(&pmp->pmp_lock));
623: if (--pmp->pmp_refcount == 0)
624: cv_broadcast(&pmp->pmp_refcount_cv);
625: }
CVSweb <webmaster@jp.NetBSD.org>