Annotation of src/sys/fs/puffs/puffs_subr.c, Revision 1.13.2.4
1.13.2.4! yamt 1: /* $NetBSD: puffs_subr.c,v 1.13.2.3 2007/09/03 14:40:30 yamt Exp $ */
1.13.2.2 yamt 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.13.2.4! yamt 33: __KERNEL_RCSID(0, "$NetBSD: puffs_subr.c,v 1.13.2.3 2007/09/03 14:40:30 yamt Exp $");
1.13.2.2 yamt 34:
35: #include <sys/param.h>
36: #include <sys/conf.h>
1.13.2.3 yamt 37: #include <sys/hash.h>
1.13.2.4! yamt 38: #include <sys/kauth.h>
1.13.2.2 yamt 39: #include <sys/malloc.h>
40: #include <sys/mount.h>
1.13.2.4! yamt 41: #include <sys/namei.h>
! 42: #include <sys/poll.h>
1.13.2.2 yamt 43: #include <sys/socketvar.h>
44: #include <sys/vnode.h>
1.13.2.4! yamt 45: #include <sys/proc.h>
1.13.2.2 yamt 46:
47: #include <fs/puffs/puffs_msgif.h>
48: #include <fs/puffs/puffs_sys.h>
49:
50: #include <miscfs/genfs/genfs_node.h>
51: #include <miscfs/specfs/specdev.h>
52:
1.13.2.4! yamt 53: struct pool puffs_pnpool;
1.13.2.2 yamt 54:
1.13.2.3 yamt 55: #ifdef PUFFSDEBUG
1.13.2.2 yamt 56: int puffsdebug;
57: #endif
58:
1.13.2.3 yamt 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.13.2.2 yamt 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:
75: /*
76: * Grab a vnode, intialize all the puffs-dependant stuff.
77: */
78: int
79: puffs_getvnode(struct mount *mp, void *cookie, enum vtype type,
80: voff_t vsize, dev_t rdev, struct vnode **vpp)
81: {
82: struct puffs_mount *pmp;
83: struct vnode *vp, *nvp;
84: struct puffs_node *pnode;
1.13.2.3 yamt 85: struct puffs_node_hashlist *plist;
1.13.2.2 yamt 86: int error;
87:
1.13.2.4! yamt 88: if (type <= VNON || type >= VBAD)
! 89: return EINVAL;
! 90:
1.13.2.2 yamt 91: pmp = MPTOPUFFSMP(mp);
92:
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)
108: return error;
109: vp->v_vnlock = NULL;
110: vp->v_type = type;
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;
126: }
127:
128: /* So it's not dead yet.. good.. inform new vnode of its master */
129: simple_lock(&mntvnode_slock);
1.13.2.3 yamt 130: TAILQ_INSERT_TAIL(&mp->mnt_vnodelist, vp, v_mntvnodes);
1.13.2.2 yamt 131: simple_unlock(&mntvnode_slock);
132: vp->v_mount = mp;
133:
134: /*
135: * clerical tasks & footwork
136: */
137:
1.13.2.4! yamt 138: /* default size */
! 139: uvm_vnp_setsize(vp, 0);
! 140:
1.13.2.2 yamt 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: /*
155: * found: release & unallocate aliased
156: * old (well, actually, new) node
157: */
158: vp->v_op = spec_vnodeop_p;
159: vp->v_flag &= ~VLOCKSWORK;
160: vrele(vp);
161: vgone(vp); /* cya */
162:
163: /* init "new" vnode */
164: vp = nvp;
165: vp->v_vnlock = NULL;
166: vp->v_mount = mp;
167: }
168: break;
169:
170: case VFIFO:
171: vp->v_op = puffs_fifoop_p;
172: break;
173:
174: case VREG:
175: uvm_vnp_setsize(vp, vsize);
176: break;
177:
178: case VDIR:
179: case VLNK:
180: case VSOCK:
181: break;
182: default:
183: #ifdef DIAGNOSTIC
184: panic("puffs_getvnode: invalid vtype %d", type);
185: #endif
186: break;
187: }
188:
189: pnode = pool_get(&puffs_pnpool, PR_WAITOK);
1.13.2.4! yamt 190: memset(pnode, 0, sizeof(struct puffs_node));
! 191:
1.13.2.2 yamt 192: pnode->pn_cookie = cookie;
1.13.2.4! yamt 193: pnode->pn_refcount = 1;
! 194:
! 195: mutex_init(&pnode->pn_mtx, MUTEX_DEFAULT, IPL_NONE);
! 196: SLIST_INIT(&pnode->pn_sel.sel_klist);
! 197:
1.13.2.3 yamt 198: plist = puffs_cookie2hashlist(pmp, cookie);
199: LIST_INSERT_HEAD(plist, pnode, pn_hashent);
1.13.2.2 yamt 200: vp->v_data = pnode;
201: vp->v_type = type;
202: pnode->pn_vp = vp;
1.13.2.4! yamt 203: pnode->pn_serversize = vsize;
1.13.2.2 yamt 204:
205: genfs_node_init(vp, &puffs_genfsops);
206: *vpp = vp;
207:
208: DPRINTF(("new vnode at %p, pnode %p, cookie %p\n", vp,
209: pnode, pnode->pn_cookie));
210:
211: return 0;
212: }
213:
214: /* new node creating for creative vop ops (create, symlink, mkdir, mknod) */
215: int
216: puffs_newnode(struct mount *mp, struct vnode *dvp, struct vnode **vpp,
217: void *cookie, struct componentname *cnp, enum vtype type, dev_t rdev)
218: {
219: struct puffs_mount *pmp = MPTOPUFFSMP(mp);
220: struct vnode *vp;
221: int error;
222:
223: /* userspace probably has this as a NULL op */
224: if (cookie == NULL) {
225: error = EOPNOTSUPP;
226: return error;
227: }
228:
1.13.2.3 yamt 229: /*
230: * Check for previous node with the same designation.
231: * Explicitly check the root node cookie, since it might be
232: * reclaimed from the kernel when this check is made.
233: *
234: * XXX: technically this error check should punish the fs,
235: * not the caller.
236: */
1.13.2.4! yamt 237: mutex_enter(&pmp->pmp_lock);
! 238: if (cookie == pmp->pmp_root_cookie
1.13.2.3 yamt 239: || puffs_cookie2pnode(pmp, cookie) != NULL) {
1.13.2.4! yamt 240: mutex_exit(&pmp->pmp_lock);
1.13.2.3 yamt 241: error = EEXIST;
242: return error;
243: }
1.13.2.4! yamt 244: mutex_exit(&pmp->pmp_lock);
1.13.2.3 yamt 245:
1.13.2.2 yamt 246: error = puffs_getvnode(dvp->v_mount, cookie, type, 0, rdev, &vp);
247: if (error)
248: return error;
249:
250: vp->v_type = type;
251: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
252: *vpp = vp;
253:
1.13.2.4! yamt 254: if ((cnp->cn_flags & MAKEENTRY) && PUFFS_USE_NAMECACHE(pmp))
1.13.2.2 yamt 255: cache_enter(dvp, vp, cnp);
256:
257: return 0;
258: }
259:
1.13.2.4! yamt 260: /*
! 261: * Release pnode structure which dealing with references to the
! 262: * puffs_node instead of the vnode. Can't use vref()/vrele() on
! 263: * the vnode there, since that causes the lovely VOP_INACTIVE(),
! 264: * which in turn causes the lovely deadlock when called by the one
! 265: * who is supposed to handle it.
! 266: */
! 267: void
! 268: puffs_releasenode(struct puffs_node *pn)
! 269: {
! 270:
! 271: mutex_enter(&pn->pn_mtx);
! 272: if (--pn->pn_refcount == 0) {
! 273: mutex_exit(&pn->pn_mtx);
! 274: mutex_destroy(&pn->pn_mtx);
! 275: pool_put(&puffs_pnpool, pn);
! 276: } else {
! 277: mutex_exit(&pn->pn_mtx);
! 278: }
! 279: }
! 280:
! 281: /*
! 282: * Add reference to node.
! 283: * mutex held on entry and return
! 284: */
! 285: void
! 286: puffs_referencenode(struct puffs_node *pn)
! 287: {
! 288:
! 289: KASSERT(mutex_owned(&pn->pn_mtx));
! 290: pn->pn_refcount++;
! 291: }
! 292:
1.13.2.2 yamt 293: void
294: puffs_putvnode(struct vnode *vp)
295: {
296: struct puffs_mount *pmp;
297: struct puffs_node *pnode;
298:
299: pmp = VPTOPUFFSMP(vp);
300: pnode = VPTOPP(vp);
301:
302: #ifdef DIAGNOSTIC
303: if (vp->v_tag != VT_PUFFS)
304: panic("puffs_putvnode: %p not a puffs vnode", vp);
305: #endif
306:
1.13.2.3 yamt 307: LIST_REMOVE(pnode, pn_hashent);
308: genfs_node_destroy(vp);
1.13.2.4! yamt 309: puffs_releasenode(pnode);
1.13.2.2 yamt 310: vp->v_data = NULL;
311:
312: return;
313: }
314:
1.13.2.3 yamt 315: static __inline struct puffs_node_hashlist *
316: puffs_cookie2hashlist(struct puffs_mount *pmp, void *cookie)
317: {
318: uint32_t hash;
319:
320: hash = hash32_buf(&cookie, sizeof(void *), HASH32_BUF_INIT);
321: return &pmp->pmp_pnodehash[hash % pmp->pmp_npnodehash];
322: }
323:
324: /*
325: * Translate cookie to puffs_node. Caller must hold mountpoint
326: * lock and it will be held upon return.
327: */
328: static struct puffs_node *
329: puffs_cookie2pnode(struct puffs_mount *pmp, void *cookie)
330: {
331: struct puffs_node_hashlist *plist;
332: struct puffs_node *pnode;
333:
334: plist = puffs_cookie2hashlist(pmp, cookie);
335: LIST_FOREACH(pnode, plist, pn_hashent) {
336: if (pnode->pn_cookie == cookie)
337: break;
338: }
339:
340: return pnode;
341: }
342:
1.13.2.2 yamt 343: /*
1.13.2.4! yamt 344: * Make sure root vnode exists and reference it. Does NOT lock.
! 345: */
! 346: static int
! 347: puffs_makeroot(struct puffs_mount *pmp)
! 348: {
! 349: struct vnode *vp;
! 350: int rv;
! 351:
! 352: /*
! 353: * pmp_lock must be held if vref()'ing or vrele()'ing the
! 354: * root vnode. the latter is controlled by puffs_inactive().
! 355: *
! 356: * pmp_root is set here and cleared in puffs_reclaim().
! 357: */
! 358: retry:
! 359: mutex_enter(&pmp->pmp_lock);
! 360: vp = pmp->pmp_root;
! 361: if (vp) {
! 362: simple_lock(&vp->v_interlock);
! 363: mutex_exit(&pmp->pmp_lock);
! 364: if (vget(vp, LK_INTERLOCK) == 0)
! 365: return 0;
! 366: } else
! 367: mutex_exit(&pmp->pmp_lock);
! 368:
! 369: /*
! 370: * So, didn't have the magic root vnode available.
! 371: * No matter, grab another an stuff it with the cookie.
! 372: */
! 373: if ((rv = puffs_getvnode(pmp->pmp_mp, pmp->pmp_root_cookie,
! 374: pmp->pmp_root_vtype, pmp->pmp_root_vsize, pmp->pmp_root_rdev, &vp)))
! 375: return rv;
! 376:
! 377: /*
! 378: * Someone magically managed to race us into puffs_getvnode?
! 379: * Put our previous new vnode back and retry.
! 380: */
! 381: mutex_enter(&pmp->pmp_lock);
! 382: if (pmp->pmp_root) {
! 383: mutex_exit(&pmp->pmp_lock);
! 384: puffs_putvnode(vp);
! 385: goto retry;
! 386: }
! 387:
! 388: /* store cache */
! 389: vp->v_flag = VROOT;
! 390: pmp->pmp_root = vp;
! 391: mutex_exit(&pmp->pmp_lock);
! 392:
! 393: return 0;
! 394: }
! 395:
! 396: /*
1.13.2.2 yamt 397: * Locate the in-kernel vnode based on the cookie received given
1.13.2.3 yamt 398: * from userspace. Returns a vnode, if found, NULL otherwise.
399: * The parameter "lock" control whether to lock the possible or
400: * not. Locking always might cause us to lock against ourselves
401: * in situations where we want the vnode but don't care for the
402: * vnode lock, e.g. file server issued putpages.
1.13.2.2 yamt 403: */
1.13.2.4! yamt 404: int
! 405: puffs_pnode2vnode(struct puffs_mount *pmp, void *cookie, int lock,
! 406: struct vnode **vpp)
1.13.2.2 yamt 407: {
408: struct puffs_node *pnode;
409: struct vnode *vp;
1.13.2.4! yamt 410: int vgetflags, rv;
1.13.2.3 yamt 411:
412: /*
1.13.2.4! yamt 413: * Handle root in a special manner, since we want to make sure
! 414: * pmp_root is properly set.
1.13.2.3 yamt 415: */
1.13.2.4! yamt 416: if (cookie == pmp->pmp_root_cookie) {
! 417: if ((rv = puffs_makeroot(pmp)))
! 418: return rv;
! 419: if (lock)
! 420: vn_lock(pmp->pmp_root, LK_EXCLUSIVE | LK_RETRY);
1.13.2.3 yamt 421:
1.13.2.4! yamt 422: *vpp = pmp->pmp_root;
! 423: return 0;
1.13.2.3 yamt 424: }
425:
1.13.2.4! yamt 426: mutex_enter(&pmp->pmp_lock);
1.13.2.3 yamt 427: pnode = puffs_cookie2pnode(pmp, cookie);
428:
429: if (pnode == NULL) {
1.13.2.4! yamt 430: mutex_exit(&pmp->pmp_lock);
! 431: return ENOENT;
1.13.2.2 yamt 432: }
1.13.2.3 yamt 433:
1.13.2.4! yamt 434: vp = pnode->pn_vp;
1.13.2.3 yamt 435: simple_lock(&vp->v_interlock);
1.13.2.4! yamt 436: mutex_exit(&pmp->pmp_lock);
1.13.2.3 yamt 437:
1.13.2.4! yamt 438: vgetflags = LK_INTERLOCK;
! 439: if (lock)
! 440: vgetflags |= LK_EXCLUSIVE | LK_RETRY;
! 441: if ((rv = vget(vp, vgetflags)))
! 442: return rv;
1.13.2.2 yamt 443:
1.13.2.4! yamt 444: *vpp = vp;
! 445: return 0;
1.13.2.2 yamt 446: }
447:
448: void
1.13.2.4! yamt 449: puffs_makecn(struct puffs_kcn *pkcn, struct puffs_kcred *pkcr,
! 450: struct puffs_kcid *pkcid, const struct componentname *cn, int full)
1.13.2.2 yamt 451: {
452:
453: pkcn->pkcn_nameiop = cn->cn_nameiop;
454: pkcn->pkcn_flags = cn->cn_flags;
1.13.2.4! yamt 455: puffs_cidcvt(pkcid, cn->cn_lwp);
1.13.2.2 yamt 456:
1.13.2.4! yamt 457: if (full) {
! 458: (void)strcpy(pkcn->pkcn_name, cn->cn_nameptr);
! 459: } else {
! 460: (void)memcpy(pkcn->pkcn_name, cn->cn_nameptr, cn->cn_namelen);
! 461: pkcn->pkcn_name[cn->cn_namelen] = '\0';
! 462: }
1.13.2.2 yamt 463: pkcn->pkcn_namelen = cn->cn_namelen;
1.13.2.4! yamt 464: pkcn->pkcn_consume = 0;
! 465:
! 466: puffs_credcvt(pkcr, cn->cn_cred);
1.13.2.2 yamt 467: }
468:
469: /*
1.13.2.4! yamt 470: * Convert given credentials to struct puffs_kcred for userspace.
1.13.2.2 yamt 471: */
472: void
1.13.2.4! yamt 473: puffs_credcvt(struct puffs_kcred *pkcr, const kauth_cred_t cred)
1.13.2.2 yamt 474: {
475:
1.13.2.4! yamt 476: memset(pkcr, 0, sizeof(struct puffs_kcred));
1.13.2.2 yamt 477:
478: if (cred == NOCRED || cred == FSCRED) {
1.13.2.4! yamt 479: pkcr->pkcr_type = PUFFCRED_TYPE_INTERNAL;
1.13.2.2 yamt 480: if (cred == NOCRED)
1.13.2.4! yamt 481: pkcr->pkcr_internal = PUFFCRED_CRED_NOCRED;
1.13.2.2 yamt 482: if (cred == FSCRED)
1.13.2.4! yamt 483: pkcr->pkcr_internal = PUFFCRED_CRED_FSCRED;
1.13.2.2 yamt 484: } else {
1.13.2.4! yamt 485: pkcr->pkcr_type = PUFFCRED_TYPE_UUC;
! 486: kauth_cred_to_uucred(&pkcr->pkcr_uuc, cred);
1.13.2.2 yamt 487: }
488: }
489:
1.13.2.4! yamt 490: void
! 491: puffs_cidcvt(struct puffs_kcid *pkcid, const struct lwp *l)
1.13.2.2 yamt 492: {
493:
1.13.2.4! yamt 494: if (l) {
! 495: pkcid->pkcid_type = PUFFCID_TYPE_REAL;
! 496: pkcid->pkcid_pid = l->l_proc->p_pid;
! 497: pkcid->pkcid_lwpid = l->l_lid;
! 498: } else {
! 499: pkcid->pkcid_type = PUFFCID_TYPE_FAKE;
! 500: pkcid->pkcid_pid = 0;
! 501: pkcid->pkcid_lwpid = 0;
! 502: }
1.13.2.2 yamt 503: }
504:
505: static void
506: puffs_gop_size(struct vnode *vp, off_t size, off_t *eobp,
507: int flags)
508: {
509:
510: *eobp = size;
511: }
512:
513: static void
514: puffs_gop_markupdate(struct vnode *vp, int flags)
515: {
516: int uflags = 0;
517:
518: if (flags & GOP_UPDATE_ACCESSED)
519: uflags |= PUFFS_UPDATEATIME;
520: if (flags & GOP_UPDATE_MODIFIED)
521: uflags |= PUFFS_UPDATEMTIME;
522:
523: puffs_updatenode(vp, uflags);
524: }
525:
526: void
527: puffs_updatenode(struct vnode *vp, int flags)
528: {
1.13.2.4! yamt 529: struct puffs_node *pn;
1.13.2.2 yamt 530: struct timespec ts;
531:
532: if (flags == 0)
533: return;
534:
1.13.2.4! yamt 535: pn = VPTOPP(vp);
1.13.2.2 yamt 536: nanotime(&ts);
537:
1.13.2.4! yamt 538: if (flags & PUFFS_UPDATEATIME) {
! 539: pn->pn_mc_atime = ts;
! 540: pn->pn_stat |= PNODE_METACACHE_ATIME;
! 541: }
! 542: if (flags & PUFFS_UPDATECTIME) {
! 543: pn->pn_mc_ctime = ts;
! 544: pn->pn_stat |= PNODE_METACACHE_CTIME;
! 545: }
! 546: if (flags & PUFFS_UPDATEMTIME) {
! 547: pn->pn_mc_mtime = ts;
! 548: pn->pn_stat |= PNODE_METACACHE_MTIME;
! 549: }
! 550: if (flags & PUFFS_UPDATESIZE) {
! 551: pn->pn_mc_size = vp->v_size;
! 552: pn->pn_stat |= PNODE_METACACHE_SIZE;
! 553: }
1.13.2.2 yamt 554: }
555:
556: void
557: puffs_updatevpsize(struct vnode *vp)
558: {
559: struct vattr va;
560:
561: if (VOP_GETATTR(vp, &va, FSCRED, NULL))
562: return;
563:
564: if (va.va_size != VNOVAL)
565: vp->v_size = va.va_size;
566: }
567:
568: void
1.13.2.4! yamt 569: puffs_parkdone_asyncbioread(struct puffs_req *preq, void *arg)
1.13.2.2 yamt 570: {
1.13.2.4! yamt 571: struct puffs_vnreq_read *read_argp = (void *)preq;
! 572: struct buf *bp = arg;
! 573: size_t moved;
! 574:
! 575: bp->b_error = preq->preq_rv;
! 576: if (bp->b_error == 0) {
! 577: moved = bp->b_bcount - read_argp->pvnr_resid;
! 578: bp->b_resid = read_argp->pvnr_resid;
1.13.2.2 yamt 579:
1.13.2.4! yamt 580: memcpy(bp->b_data, read_argp->pvnr_data, moved);
1.13.2.2 yamt 581: }
582:
1.13.2.4! yamt 583: biodone(bp);
! 584: free(preq, M_PUFFS);
! 585: }
! 586:
! 587: /* XXX: userspace can leak kernel resources */
! 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);
1.13.2.2 yamt 625: }
CVSweb <webmaster@jp.NetBSD.org>