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