xref: /netbsd-src/lib/libperfuse/ops.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1 /*  $NetBSD: ops.c,v 1.44 2011/11/10 16:21:09 manu Exp $ */
2 
3 /*-
4  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
5  *
6  *  Redistribution and use in source and binary forms, with or without
7  *  modification, are permitted provided that the following conditions
8  *  are met:
9  *  1. Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  *  2. Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  *  THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16  *  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17  *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  *  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19  *  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  *  POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <libgen.h>
32 #include <errno.h>
33 #include <err.h>
34 #include <sysexits.h>
35 #include <syslog.h>
36 #include <puffs.h>
37 #include <sys/socket.h>
38 #include <sys/socket.h>
39 #include <sys/extattr.h>
40 #include <machine/vmparam.h>
41 
42 #include "perfuse_priv.h"
43 #include "fuse.h"
44 
45 extern int perfuse_diagflags;
46 
47 static void set_expire(puffs_cookie_t, struct fuse_entry_out *,
48    struct fuse_attr_out *);
49 static int attr_expired(puffs_cookie_t);
50 static int entry_expired(puffs_cookie_t);
51 static int xchg_msg(struct puffs_usermount *, puffs_cookie_t,
52     perfuse_msg_t *, size_t, enum perfuse_xchg_pb_reply);
53 static int mode_access(puffs_cookie_t, const struct puffs_cred *, mode_t);
54 static int sticky_access(struct puffs_node *, const struct puffs_cred *);
55 static void fuse_attr_to_vap(struct perfuse_state *,
56     struct vattr *, struct fuse_attr *);
57 static int node_lookup_dir_nodot(struct puffs_usermount *,
58     puffs_cookie_t, char *, size_t, struct puffs_node **);
59 static int node_lookup_common(struct puffs_usermount *, puffs_cookie_t,
60     const char *, const struct puffs_cred *, struct puffs_node **);
61 static int node_mk_common(struct puffs_usermount *, puffs_cookie_t,
62     struct puffs_newinfo *, const struct puffs_cn *pcn, perfuse_msg_t *);
63 static int node_mk_common_final(struct puffs_usermount *, puffs_cookie_t,
64     struct puffs_node *, const struct puffs_cn *pcn);
65 static uint64_t readdir_last_cookie(struct fuse_dirent *, size_t);
66 static ssize_t fuse_to_dirent(struct puffs_usermount *, puffs_cookie_t,
67     struct fuse_dirent *, size_t);
68 static int readdir_buffered(puffs_cookie_t, struct dirent *, off_t *,
69     size_t *);
70 static void requeue_request(struct puffs_usermount *,
71     puffs_cookie_t opc, enum perfuse_qtype);
72 static int dequeue_requests(struct perfuse_state *,
73     puffs_cookie_t opc, enum perfuse_qtype, int);
74 #define DEQUEUE_ALL 0
75 
76 /*
77  *  From <sys/vnode>, inside #ifdef _KERNEL section
78  */
79 #define IO_SYNC		(0x40|IO_DSYNC)
80 #define IO_DSYNC	0x00200
81 #define IO_DIRECT	0x02000
82 
83 /*
84  *  From <fcntl>, inside #ifdef _KERNEL section
85  */
86 #define F_WAIT		0x010
87 #define F_FLOCK		0x020
88 #define OFLAGS(fflags)  ((fflags) - 1)
89 
90 /*
91  * Borrowed from src/sys/kern/vfs_subr.c and src/sys/sys/vnode.h
92  */
93 const enum vtype iftovt_tab[16] = {
94 	VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
95         VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,
96 };
97 const int vttoif_tab[9] = {
98 	0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK,
99         S_IFSOCK, S_IFIFO, S_IFMT,
100 };
101 
102 #define IFTOVT(mode) (iftovt_tab[((mode) & S_IFMT) >> 12])
103 #define VTTOIF(indx) (vttoif_tab[(int)(indx)])
104 
105 int
106 perfuse_node_close_common(pu, opc, mode)
107 	struct puffs_usermount *pu;
108 	puffs_cookie_t opc;
109 	int mode;
110 {
111 	struct perfuse_state *ps;
112 	perfuse_msg_t *pm;
113 	int op;
114 	uint64_t fh;
115 	struct fuse_release_in *fri;
116 	struct perfuse_node_data *pnd;
117 	struct puffs_node *pn;
118 	int error;
119 
120 	ps = puffs_getspecific(pu);
121 	pn = (struct puffs_node *)opc;
122 	pnd = PERFUSE_NODE_DATA(pn);
123 
124 	if (puffs_pn_getvap(pn)->va_type == VDIR) {
125 		op = FUSE_RELEASEDIR;
126 		mode = FREAD;
127 	} else {
128 		op = FUSE_RELEASE;
129 	}
130 
131 	/*
132 	 * Destroy the filehandle before sending the
133 	 * request to the FUSE filesystem, otherwise
134 	 * we may get a second close() while we wait
135 	 * for the reply, and we would end up closing
136 	 * the same fh twice instead of closng both.
137 	 */
138 	fh = perfuse_get_fh(opc, mode);
139 	perfuse_destroy_fh(pn, fh);
140 
141 	/*
142 	 * release_flags may be set to FUSE_RELEASE_FLUSH
143 	 * to flush locks. lock_owner must be set in that case
144 	 *
145 	 * ps_new_msg() is called with NULL creds, which will
146 	 * be interpreted as FUSE superuser. We come here from the
147 	 * inactive method, which provides no creds, but obviously
148 	 * runs with kernel privilege.
149 	 */
150 	pm = ps->ps_new_msg(pu, opc, op, sizeof(*fri), NULL);
151 	fri = GET_INPAYLOAD(ps, pm, fuse_release_in);
152 	fri->fh = fh;
153 	fri->flags = 0;
154 	fri->release_flags = 0;
155 	fri->lock_owner = pnd->pnd_lock_owner;
156 	fri->flags = (fri->lock_owner != 0) ? FUSE_RELEASE_FLUSH : 0;
157 
158 #ifdef PERFUSE_DEBUG
159 	if (perfuse_diagflags & PDF_FH)
160 		DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", fh = 0x%"PRIx64"\n",
161 			 __func__, (void *)opc, pnd->pnd_nodeid, fri->fh);
162 #endif
163 
164 	if ((error = xchg_msg(pu, opc, pm,
165 			      NO_PAYLOAD_REPLY_LEN, wait_reply)) != 0)
166 		goto out;
167 
168 	ps->ps_destroy_msg(pm);
169 
170 	error = 0;
171 
172 out:
173 	if (error != 0)
174 		DERRX(EX_SOFTWARE, "%s: freed fh = 0x%"PRIx64" but filesystem "
175 		      "returned error = %d", __func__, fh, error);
176 
177 	return error;
178 }
179 
180 /* ARGSUSED1 */
181 static int
182 xchg_msg(pu, opc, pm, len, wait)
183 	struct puffs_usermount *pu;
184 	puffs_cookie_t opc;
185 	perfuse_msg_t *pm;
186 	size_t len;
187      	enum perfuse_xchg_pb_reply wait;
188 {
189 	struct perfuse_state *ps;
190 	struct perfuse_node_data *pnd;
191 	int error;
192 
193 	ps = puffs_getspecific(pu);
194 	pnd = NULL;
195 	if ((struct puffs_node *)opc != NULL)
196 		pnd = PERFUSE_NODE_DATA(opc);
197 
198 #ifdef PERFUSE_DEBUG
199 	if ((perfuse_diagflags & PDF_FILENAME) && (opc != 0))
200 		DPRINTF("file = \"%s\", ino = %"PRIu64" flags = 0x%x\n",
201 			perfuse_node_path(opc),
202 			((struct puffs_node *)opc)->pn_va.va_fileid,
203 			PERFUSE_NODE_DATA(opc)->pnd_flags);
204 #endif
205 	if (pnd)
206 		pnd->pnd_flags |= PND_INXCHG;
207 
208 	error = ps->ps_xchg_msg(pu, pm, len, wait);
209 
210 	if (pnd) {
211 		pnd->pnd_flags &= ~PND_INXCHG;
212 		(void)dequeue_requests(ps, opc, PCQ_AFTERXCHG, DEQUEUE_ALL);
213 	}
214 
215 	return error;
216 }
217 
218 static int
219 mode_access(opc, pcr, mode)
220 	puffs_cookie_t opc;
221 	const struct puffs_cred *pcr;
222 	mode_t mode;
223 {
224 	struct puffs_node *pn;
225 	struct vattr *va;
226 
227 	/*
228 	 * pcr is NULL for self open through fsync or readdir.
229 	 * In both case, access control is useless, as it was
230 	 * done before, at open time.
231 	 */
232 	if (pcr == NULL)
233 		return 0;
234 
235 	pn = (struct puffs_node *)opc;
236 	va = puffs_pn_getvap(pn);
237 	return puffs_access(va->va_type, va->va_mode,
238 			    va->va_uid, va->va_gid,
239 			    mode, pcr);
240 }
241 
242 static int
243 sticky_access(targ, pcr)
244 	struct puffs_node *targ;
245 	const struct puffs_cred *pcr;
246 {
247 	uid_t uid;
248 	struct puffs_node *tdir;
249 	int sticky, owner;
250 
251 	tdir = PERFUSE_NODE_DATA(targ)->pnd_parent;
252 
253 	/*
254 	 * This covers the case where the kernel requests a DELETE
255 	 * or RENAME on its own, and where puffs_cred_getuid would
256 	 * return -1. While such a situation should not happen,
257 	 * we allow it here.
258 	 *
259 	 * This also allows root to tamper with other users' files
260 	 * that have the sticky bit.
261 	 */
262 	if (puffs_cred_isjuggernaut(pcr))
263 		return 0;
264 
265 	if (puffs_cred_getuid(pcr, &uid) != 0)
266 		DERRX(EX_SOFTWARE, "puffs_cred_getuid fails in %s", __func__);
267 
268 	sticky = puffs_pn_getvap(tdir)->va_mode & S_ISTXT;
269 	owner = puffs_pn_getvap(targ)->va_uid == uid;
270 
271 	if (sticky && !owner)
272 		return EACCES;
273 
274 	return 0;
275 }
276 
277 
278 static void
279 fuse_attr_to_vap(ps, vap, fa)
280 	struct perfuse_state *ps;
281 	struct vattr *vap;
282 	struct fuse_attr *fa;
283 {
284 	vap->va_type = IFTOVT(fa->mode);
285 	vap->va_mode = fa->mode & ALLPERMS;
286 	vap->va_nlink = fa->nlink;
287 	vap->va_uid = fa->uid;
288 	vap->va_gid = fa->gid;
289 	vap->va_fsid = (long)ps->ps_fsid;
290 	vap->va_fileid = fa->ino;
291 	vap->va_size = fa->size;
292 	vap->va_blocksize = fa->blksize;
293 	vap->va_atime.tv_sec = (time_t)fa->atime;
294 	vap->va_atime.tv_nsec = (long) fa->atimensec;
295 	vap->va_mtime.tv_sec = (time_t)fa->mtime;
296 	vap->va_mtime.tv_nsec = (long)fa->mtimensec;
297 	vap->va_ctime.tv_sec = (time_t)fa->ctime;
298 	vap->va_ctime.tv_nsec = (long)fa->ctimensec;
299 	vap->va_birthtime.tv_sec = 0;
300 	vap->va_birthtime.tv_nsec = 0;
301 	vap->va_gen = 0;
302 	vap->va_flags = 0;
303 	vap->va_rdev = fa->rdev;
304 	vap->va_bytes = fa->size;
305 	vap->va_filerev = (u_quad_t)PUFFS_VNOVAL;
306 	vap->va_vaflags = 0;
307 
308 	if (vap->va_blocksize == 0)
309 		vap->va_blocksize = DEV_BSIZE;
310 
311 	if (vap->va_size == (size_t)PUFFS_VNOVAL) /* XXX */
312 		vap->va_size = 0;
313 
314 	return;
315 }
316 
317 static void
318 set_expire(opc, feo, fao)
319 	puffs_cookie_t opc;
320 	struct fuse_entry_out *feo;
321 	struct fuse_attr_out *fao;
322 {
323 	struct perfuse_node_data *pnd = PERFUSE_NODE_DATA(opc);
324 	struct timespec entry_ts;
325 	struct timespec attr_ts;
326 	struct timespec now;
327 
328 	if ((feo == NULL) && (fao == NULL))
329 		DERRX(EX_SOFTWARE, "%s: feo and fao NULL", __func__);
330 
331 	if ((feo != NULL) && (fao != NULL))
332 		DERRX(EX_SOFTWARE, "%s: feo and fao != NULL", __func__);
333 
334 	if (clock_gettime(CLOCK_REALTIME, &now) != 0)
335 		DERR(EX_OSERR, "clock_gettime failed");
336 
337 	if (feo != NULL) {
338 		entry_ts.tv_sec = (time_t)feo->entry_valid;
339 		entry_ts.tv_nsec = (long)feo->entry_valid_nsec;
340 
341 		timespecadd(&now, &entry_ts, &pnd->pnd_entry_expire);
342 
343 		attr_ts.tv_sec = (time_t)feo->attr_valid;
344 		attr_ts.tv_nsec = (long)feo->attr_valid_nsec;
345 
346 		timespecadd(&now, &attr_ts, &pnd->pnd_attr_expire);
347 	}
348 
349 	if (fao != NULL) {
350 		attr_ts.tv_sec = (time_t)fao->attr_valid;
351 		attr_ts.tv_nsec = (long)fao->attr_valid_nsec;
352 
353 		timespecadd(&now, &attr_ts, &pnd->pnd_attr_expire);
354 	}
355 
356 	return;
357 }
358 
359 static int
360 attr_expired(opc)
361 	puffs_cookie_t opc;
362 {
363 	struct perfuse_node_data *pnd = PERFUSE_NODE_DATA(opc);
364 	struct timespec now;
365 
366 	if (clock_gettime(CLOCK_REALTIME, &now) != 0)
367 		DERR(EX_OSERR, "clock_gettime failed");
368 
369 	return timespeccmp(&pnd->pnd_attr_expire, &now, <);
370 }
371 
372 static int
373 entry_expired(opc)
374 	puffs_cookie_t opc;
375 {
376 	struct perfuse_node_data *pnd = PERFUSE_NODE_DATA(opc);
377 	struct timespec now;
378 
379 	if (clock_gettime(CLOCK_REALTIME, &now) != 0)
380 		DERR(EX_OSERR, "clock_gettime failed");
381 
382 	return timespeccmp(&pnd->pnd_entry_expire, &now, <);
383 }
384 
385 
386 /*
387  * Lookup name in directory opc
388  * We take special care of name being . or ..
389  * These are returned by readdir and deserve tweaks.
390  */
391 static int
392 node_lookup_dir_nodot(pu, opc, name, namelen, pnp)
393 	struct puffs_usermount *pu;
394 	puffs_cookie_t opc;
395 	char *name;
396 	size_t namelen;
397 	struct puffs_node **pnp;
398 {
399 	/*
400 	 * "dot" is easy as we already know it
401 	 */
402 	if (strncmp(name, ".", namelen) == 0) {
403 		*pnp = (struct puffs_node *)opc;
404 		return 0;
405 	}
406 
407 	/*
408 	 * "dotdot" is also known
409 	 */
410 	if (strncmp(name, "..", namelen) == 0) {
411 		*pnp = PERFUSE_NODE_DATA(opc)->pnd_parent;
412 		return 0;
413 	}
414 
415 	return node_lookup_common(pu, opc, name, NULL, pnp);
416 }
417 
418 static int
419 node_lookup_common(pu, opc, path, pcr, pnp)
420 	struct puffs_usermount *pu;
421 	puffs_cookie_t opc;
422 	const char *path;
423 	const struct puffs_cred *pcr;
424 	struct puffs_node **pnp;
425 {
426 	struct perfuse_state *ps;
427 	struct perfuse_node_data *oldpnd;
428 	perfuse_msg_t *pm;
429 	struct fuse_entry_out *feo;
430 	struct puffs_node *pn;
431 	size_t len;
432 	int error;
433 
434 	if (pnp == NULL)
435 		DERRX(EX_SOFTWARE, "pnp must be != NULL");
436 
437 	ps = puffs_getspecific(pu);
438 
439 #ifdef PERFUSE_DEBUG
440 	if (perfuse_diagflags & PDF_FILENAME)
441 		DPRINTF("%s: opc = %p, file = \"%s\" looking up \"%s\"\n",
442 			__func__, (void *)opc, perfuse_node_path(opc), path);
443 #endif
444 	/*
445 	 * Is the node already known?
446 	 */
447 	TAILQ_FOREACH(oldpnd, &PERFUSE_NODE_DATA(opc)->pnd_children, pnd_next) {
448 		if ((oldpnd->pnd_flags & PND_REMOVED) ||
449 		    (strcmp(oldpnd->pnd_name, path) != 0))
450 			continue;
451 
452 #ifdef PERFUSE_DEBUG
453 		if (perfuse_diagflags & PDF_FILENAME)
454 			DPRINTF("%s: opc = %p, file = \"%s\" found "
455 				"cookie = %p, nodeid = 0x%"PRIx64" for \"%s\"\n",
456 				__func__, (void *)opc, perfuse_node_path(opc),
457 				(void *)oldpnd->pnd_pn, oldpnd->pnd_nodeid,
458 				path);
459 #endif
460 		break;
461 	}
462 
463 	/*
464 	 * Check for cached name
465 	 */
466 	if ((oldpnd != NULL) && !entry_expired(oldpnd->pnd_pn)) {
467 		*pnp = oldpnd->pnd_pn;
468 		return 0;
469 	}
470 
471 	len = strlen(path) + 1;
472 
473 	pm = ps->ps_new_msg(pu, opc, FUSE_LOOKUP, len, pcr);
474 	(void)strlcpy(_GET_INPAYLOAD(ps, pm, char *), path, len);
475 
476 	error = xchg_msg(pu, opc, pm, sizeof(*feo), wait_reply);
477 
478 	switch (error) {
479 	case 0:
480 		break;
481 	case ENOENT:
482 		if (oldpnd != NULL) {
483 			oldpnd->pnd_flags |= PND_REMOVED;
484 #ifdef PERFUSE_DEBUG
485 			if (perfuse_diagflags & PDF_FILENAME)
486 				DPRINTF("%s: opc = %p nodeid = 0x%"PRIx64" "
487 					"file = \"%s\" removed\n", __func__,
488 					oldpnd->pnd_pn, oldpnd->pnd_nodeid,
489 					oldpnd->pnd_name);
490 #endif
491 		}
492 		/* FALLTHROUGH */
493 	default:
494 		goto out;
495 		/* NOTREACHED */
496 		break;
497 	}
498 
499 	feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out);
500 
501 	if (oldpnd != NULL) {
502 		if (oldpnd->pnd_nodeid == feo->nodeid) {
503 			oldpnd->pnd_nlookup++;
504 			*pnp = oldpnd->pnd_pn;
505 			goto out;
506 		} else {
507 			oldpnd->pnd_flags |= PND_REMOVED;
508 #ifdef PERFUSE_DEBUG
509 			if (perfuse_diagflags & PDF_FILENAME)
510 				DPRINTF("%s: opc = %p nodeid = 0x%"PRIx64" "
511 					"file = \"%s\" replaced\n", __func__,
512 					oldpnd->pnd_pn, oldpnd->pnd_nodeid,
513 					oldpnd->pnd_name);
514 #endif
515 		}
516 	}
517 
518 	pn = perfuse_new_pn(pu, path, opc);
519 	PERFUSE_NODE_DATA(pn)->pnd_nodeid = feo->nodeid;
520 
521 	fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr);
522 	pn->pn_va.va_gen = (u_long)(feo->generation);
523 	set_expire((puffs_cookie_t)pn, feo, NULL);
524 
525 	*pnp = pn;
526 
527 #ifdef PERFUSE_DEBUG
528 	if (perfuse_diagflags & PDF_FILENAME)
529 		DPRINTF("%s: opc = %p, looked up opc = %p, "
530 			"nodeid = 0x%"PRIx64" file = \"%s\"\n", __func__,
531 			(void *)opc, pn, feo->nodeid, path);
532 #endif
533 
534 out:
535 	ps->ps_destroy_msg(pm);
536 
537 	return error;
538 }
539 
540 
541 /*
542  * Common code for methods that create objects:
543  * perfuse_node_mkdir
544  * perfuse_node_mknod
545  * perfuse_node_symlink
546  */
547 static int
548 node_mk_common(pu, opc, pni, pcn, pm)
549 	struct puffs_usermount *pu;
550 	puffs_cookie_t opc;
551 	struct puffs_newinfo *pni;
552 	const struct puffs_cn *pcn;
553 	perfuse_msg_t *pm;
554 {
555 	struct perfuse_state *ps;
556 	struct puffs_node *pn;
557 	struct fuse_entry_out *feo;
558 	int error;
559 
560 	ps =  puffs_getspecific(pu);
561 
562 	if ((error = xchg_msg(pu, opc, pm, sizeof(*feo), wait_reply)) != 0)
563 		goto out;
564 
565 	feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out);
566 	if (feo->nodeid == PERFUSE_UNKNOWN_NODEID)
567 		DERRX(EX_SOFTWARE, "%s: no nodeid", __func__);
568 
569 	pn = perfuse_new_pn(pu, pcn->pcn_name, opc);
570 	PERFUSE_NODE_DATA(pn)->pnd_nodeid = feo->nodeid;
571 
572 	fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr);
573 	pn->pn_va.va_gen = (u_long)(feo->generation);
574 	set_expire((puffs_cookie_t)pn, feo, NULL);
575 
576 	puffs_newinfo_setcookie(pni, pn);
577 
578 #ifdef PERFUSE_DEBUG
579 	if (perfuse_diagflags & PDF_FILENAME)
580 		DPRINTF("%s: opc = %p, file = \"%s\", flags = 0x%x "
581 			"nodeid = 0x%"PRIx64"\n",
582 			__func__, (void *)pn, pcn->pcn_name,
583 			PERFUSE_NODE_DATA(pn)->pnd_flags, feo->nodeid);
584 #endif
585 	ps->ps_destroy_msg(pm);
586 
587 	return node_mk_common_final(pu, opc, pn, pcn);
588 
589 out:
590 	ps->ps_destroy_msg(pm);
591 
592 	return error;
593 }
594 
595 /*
596  * Common final code for methods that create objects:
597  * perfuse_node_mkdir via node_mk_common
598  * perfuse_node_mknod via node_mk_common
599  * perfuse_node_symlink via node_mk_common
600  * perfuse_node_create
601  */
602 static int
603 node_mk_common_final(pu, opc, pn, pcn)
604 	struct puffs_usermount *pu;
605 	puffs_cookie_t opc;
606 	struct puffs_node *pn;
607 	const struct puffs_cn *pcn;
608 {
609 	struct perfuse_state *ps;
610 	perfuse_msg_t *pm;
611 	struct fuse_setattr_in *fsi;
612 	struct fuse_attr_out *fao;
613 	int error;
614 
615 	ps =  puffs_getspecific(pu);
616 
617 	/*
618 	 * Set owner and group. The kernel cannot create a file
619 	 * on its own (puffs_cred_getuid would return -1), right?
620 	 */
621 	if (puffs_cred_getuid(pcn->pcn_cred, &pn->pn_va.va_uid) != 0)
622 		DERRX(EX_SOFTWARE, "puffs_cred_getuid fails in %s", __func__);
623 	if (puffs_cred_getgid(pcn->pcn_cred, &pn->pn_va.va_gid) != 0)
624 		DERRX(EX_SOFTWARE, "puffs_cred_getgid fails in %s", __func__);
625 
626 	pm = ps->ps_new_msg(pu, (puffs_cookie_t)pn,
627 			    FUSE_SETATTR, sizeof(*fsi), pcn->pcn_cred);
628 	fsi = GET_INPAYLOAD(ps, pm, fuse_setattr_in);
629 	fsi->uid = pn->pn_va.va_uid;
630 	fsi->gid = pn->pn_va.va_gid;
631 	fsi->valid = FUSE_FATTR_UID|FUSE_FATTR_GID;
632 
633 	if ((error = xchg_msg(pu, (puffs_cookie_t)pn, pm,
634 			      sizeof(*fao), wait_reply)) != 0)
635 		goto out;
636 
637 	fao = GET_OUTPAYLOAD(ps, pm, fuse_attr_out);
638 	fuse_attr_to_vap(ps, &pn->pn_va, &fao->attr);
639 	set_expire((puffs_cookie_t)pn, NULL, fao);
640 
641 	/*
642 	 * The parent directory needs a sync
643 	 */
644 	PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY;
645 
646 out:
647 	if (pm != NULL)
648 		ps->ps_destroy_msg(pm);
649 
650 	return error;
651 }
652 
653 static uint64_t
654 readdir_last_cookie(fd, fd_len)
655 	struct fuse_dirent *fd;
656 	size_t fd_len;
657 {
658 	size_t len;
659 	size_t seen = 0;
660 	char *ndp;
661 
662 	do {
663 		len = FUSE_DIRENT_ALIGN(sizeof(*fd) + fd->namelen);
664 		seen += len;
665 
666 		if (seen >= fd_len)
667 			break;
668 
669 		ndp = (char *)(void *)fd + (size_t)len;
670 		fd = (struct fuse_dirent *)(void *)ndp;
671 	} while (1 /* CONSTCOND */);
672 
673 	return fd->off;
674 }
675 
676 static ssize_t
677 fuse_to_dirent(pu, opc, fd, fd_len)
678 	struct puffs_usermount *pu;
679 	puffs_cookie_t opc;
680 	struct fuse_dirent *fd;
681 	size_t fd_len;
682 {
683 	struct dirent *dents;
684 	size_t dents_len;
685 	ssize_t written;
686 	uint64_t fd_offset;
687 	struct fuse_dirent *fd_base;
688 	size_t len;
689 
690 	fd_base = fd;
691 	fd_offset = 0;
692 	written = 0;
693 	dents = PERFUSE_NODE_DATA(opc)->pnd_dirent;
694 	dents_len = (size_t)PERFUSE_NODE_DATA(opc)->pnd_dirent_len;
695 
696 	do {
697 		char *ndp;
698 		size_t reclen;
699 
700 		reclen = _DIRENT_RECLEN(dents, fd->namelen);
701 
702 		/*
703 		 * Check we do not overflow the output buffer
704 		 * struct fuse_dirent is bigger than struct dirent,
705 		 * so we should always use fd_len and never reallocate
706 		 * later.
707 		 * If we have to reallocate,try to double the buffer
708 		 * each time so that we do not have to do it too often.
709 		 */
710 		if (written + reclen > dents_len) {
711 			if (dents_len == 0)
712 				dents_len = fd_len;
713 			else
714 				dents_len =
715 				   MAX(2 * dents_len, written + reclen);
716 
717 			dents = PERFUSE_NODE_DATA(opc)->pnd_dirent;
718 			if ((dents = realloc(dents, dents_len)) == NULL)
719 				DERR(EX_OSERR, "%s: malloc failed", __func__);
720 
721 			PERFUSE_NODE_DATA(opc)->pnd_dirent = dents;
722 			PERFUSE_NODE_DATA(opc)->pnd_dirent_len = dents_len;
723 
724 			/*
725 			 * (void *) for delint
726 			 */
727 			ndp = (char *)(void *)dents + written;
728 			dents = (struct dirent *)(void *)ndp;
729 		}
730 
731 		/*
732 		 * Filesystem was mounted without -o use_ino
733 		 * Perform a lookup to find it.
734 		 */
735 		if (fd->ino == PERFUSE_UNKNOWN_INO) {
736 			struct puffs_node *pn;
737 
738 			if (node_lookup_dir_nodot(pu, opc, fd->name,
739 						  fd->namelen, &pn) != 0) {
740 				DWARNX("node_lookup_dir_nodot failed");
741 			} else {
742 				fd->ino = pn->pn_va.va_fileid;
743 			}
744 		}
745 
746 		dents->d_fileno = fd->ino;
747 		dents->d_reclen = (unsigned short)reclen;
748 		dents->d_namlen = fd->namelen;
749 		dents->d_type = fd->type;
750 		strlcpy(dents->d_name, fd->name, fd->namelen + 1);
751 
752 #ifdef PERFUSE_DEBUG
753 		if (perfuse_diagflags & PDF_READDIR)
754 			DPRINTF("%s: translated \"%s\" ino = %"PRIu64"\n",
755 				__func__, dents->d_name, dents->d_fileno);
756 #endif
757 
758 		dents = _DIRENT_NEXT(dents);
759 		written += reclen;
760 
761 		/*
762 		 * Move to the next record.
763 		 * fd->off is not the offset, it is an opaque cookie
764 		 * given by the filesystem to keep state across multiple
765 		 * readdir() operation.
766 		 * Use record alignement instead.
767 		 */
768 		len = FUSE_DIRENT_ALIGN(sizeof(*fd) + fd->namelen);
769 #ifdef PERFUSE_DEBUG
770 		if (perfuse_diagflags & PDF_READDIR)
771 			DPRINTF("%s: record at %"PRId64"/0x%"PRIx64" "
772 				"length = %zd/0x%zx. "
773 				"next record at %"PRId64"/0x%"PRIx64" "
774 				"max %zd/0x%zx\n",
775 				__func__, fd_offset, fd_offset, len, len,
776 				fd_offset + len, fd_offset + len,
777 				fd_len, fd_len);
778 #endif
779 		fd_offset += len;
780 
781 		/*
782 		 * Check if next record is still within the packet
783 		 * If it is not, we reached the end of the buffer.
784 		 */
785 		if (fd_offset >= fd_len)
786 			break;
787 
788 		/*
789 		 * (void *) for delint
790 		 */
791 		ndp = (char *)(void *)fd_base + (size_t)fd_offset;
792 		fd = (struct fuse_dirent *)(void *)ndp;
793 
794 	} while (1 /* CONSTCOND */);
795 
796 	/*
797 	 * Adjust the dirent output length
798 	 */
799 	if (written != -1)
800 		PERFUSE_NODE_DATA(opc)->pnd_dirent_len = written;
801 
802 	return written;
803 }
804 
805 static int
806 readdir_buffered(opc, dent, readoff, reslen)
807 	puffs_cookie_t opc;
808 	struct dirent *dent;
809 	off_t *readoff;
810 	size_t *reslen;
811 {
812 	struct dirent *fromdent;
813 	struct perfuse_node_data *pnd;
814 	char *ndp;
815 
816 	pnd = PERFUSE_NODE_DATA(opc);
817 
818 	while (*readoff < pnd->pnd_dirent_len) {
819 		/*
820 		 * (void *) for delint
821 		 */
822 		ndp = (char *)(void *)pnd->pnd_dirent + (size_t)*readoff;
823 		fromdent = (struct dirent *)(void *)ndp;
824 
825 		if (*reslen < _DIRENT_SIZE(fromdent))
826 			break;
827 
828 		memcpy(dent, fromdent, _DIRENT_SIZE(fromdent));
829 		*readoff += _DIRENT_SIZE(fromdent);
830 		*reslen -= _DIRENT_SIZE(fromdent);
831 
832 		dent = _DIRENT_NEXT(dent);
833 	}
834 
835 #ifdef PERFUSE_DEBUG
836 	if (perfuse_diagflags & PDF_READDIR)
837 		DPRINTF("%s: readoff = %"PRId64",  "
838 			"pnd->pnd_dirent_len = %"PRId64"\n",
839 			__func__, *readoff, pnd->pnd_dirent_len);
840 #endif
841 	if (*readoff >=  pnd->pnd_dirent_len) {
842 		free(pnd->pnd_dirent);
843 		pnd->pnd_dirent = NULL;
844 		pnd->pnd_dirent_len = 0;
845 	}
846 
847 	return 0;
848 }
849 
850 static void
851 requeue_request(pu, opc, type)
852 	struct puffs_usermount *pu;
853 	puffs_cookie_t opc;
854 	enum perfuse_qtype type;
855 {
856 	struct perfuse_cc_queue pcq;
857 	struct perfuse_node_data *pnd;
858 #ifdef PERFUSE_DEBUG
859 	struct perfuse_state *ps;
860 
861 	ps = perfuse_getspecific(pu);
862 #endif
863 
864 	pnd = PERFUSE_NODE_DATA(opc);
865 	pcq.pcq_type = type;
866 	pcq.pcq_cc = puffs_cc_getcc(pu);
867 	TAILQ_INSERT_TAIL(&pnd->pnd_pcq, &pcq, pcq_next);
868 
869 #ifdef PERFUSE_DEBUG
870 	if (perfuse_diagflags & PDF_REQUEUE)
871 		DPRINTF("%s: REQUEUE opc = %p, pcc = %p (%s)\n",
872 		        __func__, (void *)opc, pcq.pcq_cc,
873 			perfuse_qtypestr[type]);
874 #endif
875 
876 	puffs_cc_yield(pcq.pcq_cc);
877 	TAILQ_REMOVE(&pnd->pnd_pcq, &pcq, pcq_next);
878 
879 #ifdef PERFUSE_DEBUG
880 	if (perfuse_diagflags & PDF_REQUEUE)
881 		DPRINTF("%s: RESUME opc = %p, pcc = %p (%s)\n",
882 		        __func__, (void *)opc, pcq.pcq_cc,
883 			perfuse_qtypestr[type]);
884 #endif
885 
886 	return;
887 }
888 
889 /* ARGSUSED0 */
890 static int
891 dequeue_requests(ps, opc, type, max)
892 	struct perfuse_state *ps;
893 	puffs_cookie_t opc;
894 	enum perfuse_qtype type;
895 	int max;
896 {
897 	struct perfuse_cc_queue *pcq;
898 	struct perfuse_node_data *pnd;
899 	int dequeued;
900 
901 	pnd = PERFUSE_NODE_DATA(opc);
902 	dequeued = 0;
903 	TAILQ_FOREACH(pcq, &pnd->pnd_pcq, pcq_next) {
904 		if (pcq->pcq_type != type)
905 			continue;
906 
907 #ifdef PERFUSE_DEBUG
908 		if (perfuse_diagflags & PDF_REQUEUE)
909 			DPRINTF("%s: SCHEDULE opc = %p, pcc = %p (%s)\n",
910 				__func__, (void *)opc, pcq->pcq_cc,
911 				 perfuse_qtypestr[type]);
912 #endif
913 		puffs_cc_schedule(pcq->pcq_cc);
914 
915 		if (++dequeued == max)
916 			break;
917 	}
918 
919 #ifdef PERFUSE_DEBUG
920 	if (perfuse_diagflags & PDF_REQUEUE)
921 		DPRINTF("%s: DONE  opc = %p\n", __func__, (void *)opc);
922 #endif
923 
924 	return dequeued;
925 }
926 
927 void
928 perfuse_fs_init(pu)
929 	struct puffs_usermount *pu;
930 {
931 	struct perfuse_state *ps;
932 	perfuse_msg_t *pm;
933 	struct fuse_init_in *fii;
934 	struct fuse_init_out *fio;
935 	int error;
936 
937 	ps = puffs_getspecific(pu);
938 
939         if (puffs_mount(pu, ps->ps_target, ps->ps_mountflags, ps->ps_root) != 0)
940                 DERR(EX_OSERR, "%s: puffs_mount failed", __func__);
941 
942 	/*
943 	 * Linux 2.6.34.1 sends theses flags:
944 	 * FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC
945 	 * FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK
946 	 *
947 	 * Linux also sets max_readahead at 32 pages (128 kB)
948 	 *
949 	 * ps_new_msg() is called with NULL creds, which will
950 	 * be interpreted as FUSE superuser.
951 	 */
952 	pm = ps->ps_new_msg(pu, 0, FUSE_INIT, sizeof(*fii), NULL);
953 	fii = GET_INPAYLOAD(ps, pm, fuse_init_in);
954 	fii->major = FUSE_KERNEL_VERSION;
955 	fii->minor = FUSE_KERNEL_MINOR_VERSION;
956 	fii->max_readahead = (unsigned int)(32 * sysconf(_SC_PAGESIZE));
957 	fii->flags = (FUSE_ASYNC_READ|FUSE_POSIX_LOCKS|FUSE_ATOMIC_O_TRUNC);
958 
959 	if ((error = xchg_msg(pu, 0, pm, sizeof(*fio), wait_reply)) != 0)
960 		DERRX(EX_SOFTWARE, "init message exchange failed (%d)", error);
961 
962 	fio = GET_OUTPAYLOAD(ps, pm, fuse_init_out);
963 	ps->ps_max_readahead = fio->max_readahead;
964 	ps->ps_max_write = fio->max_write;
965 
966 	ps->ps_destroy_msg(pm);
967 
968 	return;
969 }
970 
971 int
972 perfuse_fs_unmount(pu, flags)
973 	struct puffs_usermount *pu;
974 	int flags;
975 {
976 	perfuse_msg_t *pm;
977 	struct perfuse_state *ps;
978 	puffs_cookie_t opc;
979 	int error;
980 
981 	ps = puffs_getspecific(pu);
982 	opc = (puffs_cookie_t)puffs_getroot(pu);
983 
984 	/*
985 	 * ps_new_msg() is called with NULL creds, which will
986 	 * be interpreted as FUSE superuser.
987 	 */
988 	pm = ps->ps_new_msg(pu, opc, FUSE_DESTROY, 0, NULL);
989 
990 	if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0){
991 		DWARN("unmount %s", ps->ps_target);
992 		if (!(flags & MNT_FORCE))
993 			goto out;
994 	}
995 
996 	ps->ps_umount(pu);
997 
998 	if (perfuse_diagflags & PDF_MISC)
999 		DPRINTF("%s unmounted, exit\n", ps->ps_target);
1000 
1001 	return 0;
1002 out:
1003 	ps->ps_destroy_msg(pm);
1004 
1005 	return error;
1006 }
1007 
1008 int
1009 perfuse_fs_statvfs(pu, svfsb)
1010 	struct puffs_usermount *pu;
1011 	struct statvfs *svfsb;
1012 {
1013 	struct perfuse_state *ps;
1014 	perfuse_msg_t *pm;
1015 	puffs_cookie_t opc;
1016 	struct fuse_statfs_out *fso;
1017 	int error;
1018 
1019 	ps = puffs_getspecific(pu);
1020 	opc = (puffs_cookie_t)puffs_getroot(pu);
1021 
1022 	/*
1023 	 * ps_new_msg() is called with NULL creds, which will
1024 	 * be interpreted as FUSE superuser.
1025 	 */
1026 	pm = ps->ps_new_msg(pu, opc, FUSE_STATFS, 0, NULL);
1027 
1028 	if ((error = xchg_msg(pu, opc, pm, sizeof(*fso), wait_reply)) != 0)
1029 		goto out;
1030 
1031 	fso = GET_OUTPAYLOAD(ps, pm, fuse_statfs_out);
1032 	svfsb->f_flag = ps->ps_mountflags;
1033 	svfsb->f_bsize = fso->st.bsize;
1034 	svfsb->f_frsize = fso->st.frsize;
1035 	svfsb->f_iosize = ((struct puffs_node *)opc)->pn_va.va_blocksize;
1036 	svfsb->f_blocks = fso->st.blocks;
1037 	svfsb->f_bfree = fso->st.bfree;
1038 	svfsb->f_bavail = fso->st.bavail;
1039 	svfsb->f_bresvd = fso->st.bfree - fso->st.bavail;
1040 	svfsb->f_files = fso->st.files;
1041 	svfsb->f_ffree = fso->st.ffree;
1042 	svfsb->f_favail = fso->st.ffree;/* files not reserved for root */
1043 	svfsb->f_fresvd = 0;		/* files reserved for root */
1044 
1045 	svfsb->f_syncreads = ps->ps_syncreads;
1046 	svfsb->f_syncwrites = ps->ps_syncwrites;
1047 
1048 	svfsb->f_asyncreads = ps->ps_asyncreads;
1049 	svfsb->f_asyncwrites = ps->ps_asyncwrites;
1050 
1051 	(void)memcpy(&svfsb->f_fsidx, &ps->ps_fsid, sizeof(ps->ps_fsid));
1052 	svfsb->f_fsid = (unsigned long)ps->ps_fsid;
1053 	svfsb->f_namemax = MAXPATHLEN;	/* XXX */
1054 	svfsb->f_owner = ps->ps_owner_uid;
1055 
1056 	(void)strlcpy(svfsb->f_mntonname, ps->ps_target, _VFS_NAMELEN);
1057 
1058 	if (ps->ps_filesystemtype != NULL)
1059 		(void)strlcpy(svfsb->f_fstypename,
1060 			      ps->ps_filesystemtype, _VFS_NAMELEN);
1061 	else
1062 		(void)strlcpy(svfsb->f_fstypename, "fuse", _VFS_NAMELEN);
1063 
1064 	if (ps->ps_source != NULL)
1065 		strlcpy(svfsb->f_mntfromname, ps->ps_source, _VFS_NAMELEN);
1066 	else
1067 		strlcpy(svfsb->f_mntfromname, _PATH_FUSE, _VFS_NAMELEN);
1068 out:
1069 	ps->ps_destroy_msg(pm);
1070 
1071 	return error;
1072 }
1073 
1074 int
1075 perfuse_fs_sync(pu, waitfor, pcr)
1076 	struct puffs_usermount *pu;
1077 	int waitfor;
1078 	const struct puffs_cred *pcr;
1079 {
1080 	/*
1081 	 * FUSE does not seem to have a FS sync callback.
1082 	 * Maybe do not even register this callback
1083 	 */
1084 	return puffs_fsnop_sync(pu, waitfor, pcr);
1085 }
1086 
1087 /* ARGSUSED0 */
1088 int
1089 perfuse_fs_fhtonode(pu, fid, fidsize, pni)
1090 	struct puffs_usermount *pu;
1091 	void *fid;
1092 	size_t fidsize;
1093 	struct puffs_newinfo *pni;
1094 {
1095 	DERRX(EX_SOFTWARE, "%s: UNIMPLEMENTED (FATAL)", __func__);
1096 	return 0;
1097 }
1098 
1099 /* ARGSUSED0 */
1100 int
1101 perfuse_fs_nodetofh(pu, cookie, fid, fidsize)
1102 	struct puffs_usermount *pu;
1103 	puffs_cookie_t cookie;
1104 	void *fid;
1105 	size_t *fidsize;
1106 {
1107 	DERRX(EX_SOFTWARE, "%s: UNIMPLEMENTED (FATAL)", __func__);
1108 	return 0;
1109 }
1110 
1111 #if 0
1112 /* ARGSUSED0 */
1113 void
1114 perfuse_fs_extattrctl(pu, cmd, cookie, flags, namespace, attrname)
1115 	struct puffs_usermount *pu;
1116 	int cmd,
1117 	puffs_cookie_t *cookie;
1118 	int flags;
1119 	int namespace;
1120 	const char *attrname;
1121 {
1122 	DERRX(EX_SOFTWARE, "%s: UNIMPLEMENTED (FATAL)", __func__);
1123 	return 0;
1124 }
1125 #endif /* 0 */
1126 
1127 /* ARGSUSED0 */
1128 void
1129 perfuse_fs_suspend(pu, status)
1130 	struct puffs_usermount *pu;
1131 	int status;
1132 {
1133 	return;
1134 }
1135 
1136 
1137 
1138 int
1139 perfuse_node_lookup(pu, opc, pni, pcn)
1140 	struct puffs_usermount *pu;
1141 	puffs_cookie_t opc;
1142 	struct puffs_newinfo *pni;
1143 	const struct puffs_cn *pcn;
1144 {
1145 	struct puffs_node *pn;
1146 	mode_t mode;
1147 	int error;
1148 
1149 	/*
1150 	 * Check permissions
1151 	 */
1152 	switch(pcn->pcn_nameiop) {
1153 	case NAMEI_DELETE: /* FALLTHROUGH */
1154 	case NAMEI_RENAME: /* FALLTHROUGH */
1155 	case NAMEI_CREATE:
1156 		if (pcn->pcn_flags & NAMEI_ISLASTCN)
1157 			mode = PUFFS_VEXEC|PUFFS_VWRITE;
1158 		else
1159 			mode = PUFFS_VEXEC;
1160 		break;
1161 	case NAMEI_LOOKUP: /* FALLTHROUGH */
1162 	default:
1163 		mode = PUFFS_VEXEC;
1164 		break;
1165 	}
1166 
1167 	if ((error = mode_access(opc, pcn->pcn_cred, mode)) != 0)
1168 		return error;
1169 
1170 	/*
1171 	 * Special case for ..
1172 	 */
1173 	if (strcmp(pcn->pcn_name, "..") == 0)
1174 		pn = PERFUSE_NODE_DATA(opc)->pnd_parent;
1175 	else
1176 		error = node_lookup_common(pu, (puffs_cookie_t)opc,
1177 					   pcn->pcn_name, pcn->pcn_cred, &pn);
1178 	if (error != 0)
1179 		return error;
1180 
1181 	/*
1182 	 * Removed node
1183 	 */
1184 	if (PERFUSE_NODE_DATA(pn)->pnd_flags & PND_REMOVED)
1185 		return ENOENT;
1186 
1187 	/*
1188 	 * Check for sticky bit. Unfortunately there is no way to
1189 	 * do this before creating the puffs_node, since we require
1190 	 * this operation to get the node owner.
1191 	 */
1192 	switch (pcn->pcn_nameiop) {
1193 	case NAMEI_DELETE: /* FALLTHROUGH */
1194 	case NAMEI_RENAME:
1195 		error = sticky_access(pn, pcn->pcn_cred);
1196 		if (error != 0) {
1197 			/*
1198 			 * kernel will never know about it and will
1199 			 * not reclaim it. The filesystem needs to
1200 			 * clean it up anyway, therefore mimick a forget.
1201 			 */
1202 			PERFUSE_NODE_DATA(pn)->pnd_flags |= PND_RECLAIMED;
1203 			(void)perfuse_node_reclaim(pu, (puffs_cookie_t)pn);
1204 			return error;
1205 		}
1206 		break;
1207 	default:
1208 		break;
1209 	}
1210 
1211 	/*
1212 	 * If that node had a pending reclaim, wipe it out.
1213 	 */
1214 	PERFUSE_NODE_DATA(pn)->pnd_flags &= ~PND_RECLAIMED;
1215 
1216 	puffs_newinfo_setcookie(pni, pn);
1217 	puffs_newinfo_setvtype(pni, pn->pn_va.va_type);
1218 	puffs_newinfo_setsize(pni, (voff_t)pn->pn_va.va_size);
1219 	puffs_newinfo_setrdev(pni, pn->pn_va.va_rdev);
1220 
1221 	return error;
1222 }
1223 
1224 int
1225 perfuse_node_create(pu, opc, pni, pcn, vap)
1226 	struct puffs_usermount *pu;
1227 	puffs_cookie_t opc;
1228 	struct puffs_newinfo *pni;
1229 	const struct puffs_cn *pcn;
1230 	const struct vattr *vap;
1231 {
1232 	perfuse_msg_t *pm;
1233 	struct perfuse_state *ps;
1234 	struct fuse_create_in *fci;
1235 	struct fuse_entry_out *feo;
1236 	struct fuse_open_out *foo;
1237 	struct puffs_node *pn;
1238 	const char *name;
1239 	size_t namelen;
1240 	size_t len;
1241 	int error;
1242 
1243 	if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED)
1244 		return ENOENT;
1245 
1246 	/*
1247 	 * If create is unimplemented: Check that it does not
1248 	 * already exists, and if not, do mknod and open
1249 	 */
1250 	ps = puffs_getspecific(pu);
1251 	if (ps->ps_flags & PS_NO_CREAT) {
1252 		error = node_lookup_common(pu, opc, pcn->pcn_name,
1253 					   pcn->pcn_cred, &pn);
1254 		if (error == 0)
1255 			return EEXIST;
1256 
1257 		error = perfuse_node_mknod(pu, opc, pni, pcn, vap);
1258 		if (error != 0)
1259 			return error;
1260 
1261 		error = node_lookup_common(pu, opc, pcn->pcn_name,
1262 					   pcn->pcn_cred, &pn);
1263 		if (error != 0)
1264 			return error;
1265 
1266 		/*
1267 		 * FUSE does the open at create time, while
1268 		 * NetBSD will open in a subsequent operation.
1269 		 * We need to open now, in order to retain FUSE
1270 		 * semantics. The calling process will not get
1271 		 * a file descriptor before the kernel sends
1272 		 * the open operation.
1273 		 */
1274 		opc = (puffs_cookie_t)pn;
1275 		error = perfuse_node_open(pu, opc, FWRITE, pcn->pcn_cred);
1276 		if (error != 0)
1277 			return error;
1278 
1279 		return 0;
1280 	}
1281 
1282 	name = pcn->pcn_name;
1283 	namelen = pcn->pcn_namelen + 1;
1284 	len = sizeof(*fci) + namelen;
1285 
1286 	/*
1287 	 * flags should use O_WRONLY instead of O_RDWR, but it
1288 	 * breaks when the caller tries to read from file.
1289 	 *
1290 	 * mode must contain file type (ie: S_IFREG), use VTTOIF(vap->va_type)
1291 	 */
1292 	pm = ps->ps_new_msg(pu, opc, FUSE_CREATE, len, pcn->pcn_cred);
1293 	fci = GET_INPAYLOAD(ps, pm, fuse_create_in);
1294 	fci->flags = O_CREAT | O_TRUNC | O_RDWR;
1295 	fci->mode = vap->va_mode | VTTOIF(vap->va_type);
1296 	fci->umask = 0; 	/* Seems unused by libfuse */
1297 	(void)strlcpy((char*)(void *)(fci + 1), name, namelen);
1298 
1299 	len = sizeof(*feo) + sizeof(*foo);
1300 	if ((error = xchg_msg(pu, opc, pm, len, wait_reply)) != 0)
1301 		goto out;
1302 
1303 	feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out);
1304 	foo = (struct fuse_open_out *)(void *)(feo + 1);
1305 	if (feo->nodeid == PERFUSE_UNKNOWN_NODEID)
1306 		DERRX(EX_SOFTWARE, "%s: no nodeid", __func__);
1307 
1308 	/*
1309 	 * Save the file handle and inode in node private data
1310 	 * so that we can reuse it later
1311 	 */
1312 	pn = perfuse_new_pn(pu, name, opc);
1313 	perfuse_new_fh((puffs_cookie_t)pn, foo->fh, FWRITE);
1314 	PERFUSE_NODE_DATA(pn)->pnd_nodeid = feo->nodeid;
1315 
1316 	fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr);
1317 	pn->pn_va.va_gen = (u_long)(feo->generation);
1318 	set_expire((puffs_cookie_t)pn, feo, NULL);
1319 
1320 	puffs_newinfo_setcookie(pni, pn);
1321 
1322 #ifdef PERFUSE_DEBUG
1323 	if (perfuse_diagflags & (PDF_FH|PDF_FILENAME))
1324 		DPRINTF("%s: opc = %p, file = \"%s\", flags = 0x%x "
1325 			"nodeid = 0x%"PRIx64", wfh = 0x%"PRIx64"\n",
1326 			__func__, (void *)pn, pcn->pcn_name,
1327 			PERFUSE_NODE_DATA(pn)->pnd_flags, feo->nodeid,
1328 			foo->fh);
1329 #endif
1330 
1331 	ps->ps_destroy_msg(pm);
1332 
1333 	return node_mk_common_final(pu, opc, pn, pcn);
1334 
1335 out:
1336 	ps->ps_destroy_msg(pm);
1337 
1338 	/*
1339 	 * create is unimplmented, remember it for later,
1340 	 * and start over using mknod and open instead.
1341 	 */
1342 	if (error == ENOSYS) {
1343 		ps->ps_flags |= PS_NO_CREAT;
1344 		return perfuse_node_create(pu, opc, pni, pcn, vap);
1345 	}
1346 
1347 	return error;
1348 }
1349 
1350 
1351 int
1352 perfuse_node_mknod(pu, opc, pni, pcn, vap)
1353 	struct puffs_usermount *pu;
1354 	puffs_cookie_t opc;
1355 	struct puffs_newinfo *pni;
1356 	const struct puffs_cn *pcn;
1357 	const struct vattr *vap;
1358 {
1359 	struct perfuse_state *ps;
1360 	perfuse_msg_t *pm;
1361 	struct fuse_mknod_in *fmi;
1362 	const char* path;
1363 	size_t len;
1364 
1365 	if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED)
1366 		return ENOENT;
1367 
1368 	/*
1369 	 * Only superuser can mknod objects other than
1370 	 * directories, files, socks, fifo and links.
1371 	 *
1372 	 * Create an object require -WX permission in the parent directory
1373 	 */
1374 	switch (vap->va_type) {
1375 	case VDIR:	/* FALLTHROUGH */
1376 	case VREG:	/* FALLTHROUGH */
1377 	case VFIFO:	/* FALLTHROUGH */
1378 	case VSOCK:
1379 		break;
1380 	default:	/* VNON, VBLK, VCHR, VBAD */
1381 		if (!puffs_cred_isjuggernaut(pcn->pcn_cred))
1382 			return EACCES;
1383 		break;
1384 	}
1385 
1386 
1387 	ps = puffs_getspecific(pu);
1388 	path = pcn->pcn_name;
1389 	len = sizeof(*fmi) + pcn->pcn_namelen + 1;
1390 
1391 	/*
1392 	 * mode must contain file type (ie: S_IFREG), use VTTOIF(vap->va_type)
1393 	 */
1394 	pm = ps->ps_new_msg(pu, opc, FUSE_MKNOD, len, pcn->pcn_cred);
1395 	fmi = GET_INPAYLOAD(ps, pm, fuse_mknod_in);
1396 	fmi->mode = vap->va_mode | VTTOIF(vap->va_type);
1397 	fmi->rdev = (uint32_t)vap->va_rdev;
1398 	fmi->umask = 0; 	/* Seems unused bu libfuse */
1399 	(void)strlcpy((char *)(void *)(fmi + 1), path, len - sizeof(*fmi));
1400 
1401 	return node_mk_common(pu, opc, pni, pcn, pm);
1402 }
1403 
1404 
1405 int
1406 perfuse_node_open(pu, opc, mode, pcr)
1407 	struct puffs_usermount *pu;
1408 	puffs_cookie_t opc;
1409 	int mode;
1410 	const struct puffs_cred *pcr;
1411 {
1412 	struct perfuse_state *ps;
1413 	struct perfuse_node_data *pnd;
1414 	perfuse_msg_t *pm;
1415 	mode_t fmode;
1416 	int op;
1417 	struct fuse_open_in *foi;
1418 	struct fuse_open_out *foo;
1419 	struct puffs_node *pn;
1420 	int error;
1421 
1422 	ps = puffs_getspecific(pu);
1423 	pn = (struct puffs_node *)opc;
1424 	pnd = PERFUSE_NODE_DATA(opc);
1425 	pm = NULL;
1426 	error = 0;
1427 
1428 	if (pnd->pnd_flags & PND_REMOVED)
1429 		return ENOENT;
1430 
1431 	if (puffs_pn_getvap(pn)->va_type == VDIR)
1432 		op = FUSE_OPENDIR;
1433 	else
1434 		op = FUSE_OPEN;
1435 
1436 	/*
1437 	 * libfuse docs says
1438 	 * - O_CREAT and O_EXCL should never be set.
1439 	 * - O_TRUNC may be used if mount option atomic_o_trunc is used XXX
1440 	 *
1441 	 * O_APPEND makes no sense since FUSE always sends
1442 	 * the file offset for write operations. If the
1443 	 * filesystem uses pwrite(), O_APPEND would cause
1444 	 * the offset to be ignored and cause file corruption.
1445 	 */
1446 	mode &= ~(O_CREAT|O_EXCL|O_APPEND);
1447 
1448 	/*
1449 	 * Do not open twice, and do not reopen for reading
1450 	 * if we already have write handle.
1451 	 */
1452 	if (((mode & FREAD) && (pnd->pnd_flags & PND_RFH)) ||
1453 	    ((mode & FREAD) && (pnd->pnd_flags & PND_WFH)) ||
1454 	    ((mode & FWRITE) && (pnd->pnd_flags & PND_WFH))) {
1455 		error = 0;
1456 		goto out;
1457 	}
1458 
1459 	/*
1460 	 * Queue open on a node so that we do not open
1461 	 * twice. This would be better with read and
1462 	 * write distinguished.
1463 	 */
1464 	while (pnd->pnd_flags & PND_INOPEN)
1465 		requeue_request(pu, opc, PCQ_OPEN);
1466 	pnd->pnd_flags |= PND_INOPEN;
1467 
1468 	/*
1469 	 * Convert PUFFS mode to FUSE mode: convert FREAD/FWRITE
1470 	 * to O_RDONLY/O_WRONLY while perserving the other options.
1471 	 */
1472 	fmode = mode & ~(FREAD|FWRITE);
1473 	fmode |= (mode & FWRITE) ? O_RDWR : O_RDONLY;
1474 
1475 	pm = ps->ps_new_msg(pu, opc, op, sizeof(*foi), pcr);
1476 	foi = GET_INPAYLOAD(ps, pm, fuse_open_in);
1477 	foi->flags = fmode;
1478 	foi->unused = 0;
1479 
1480 	if ((error = xchg_msg(pu, opc, pm, sizeof(*foo), wait_reply)) != 0)
1481 		goto out;
1482 
1483 	foo = GET_OUTPAYLOAD(ps, pm, fuse_open_out);
1484 
1485 	/*
1486 	 * Save the file handle in node private data
1487 	 * so that we can reuse it later
1488 	 */
1489 	perfuse_new_fh(opc, foo->fh, mode);
1490 
1491 #ifdef PERFUSE_DEBUG
1492 	if (perfuse_diagflags & (PDF_FH|PDF_FILENAME))
1493 		DPRINTF("%s: opc = %p, file = \"%s\", "
1494 			"nodeid = 0x%"PRIx64", %s%sfh = 0x%"PRIx64"\n",
1495 			__func__, (void *)opc, perfuse_node_path(opc),
1496 			pnd->pnd_nodeid, mode & FREAD ? "r" : "",
1497 			mode & FWRITE ? "w" : "", foo->fh);
1498 #endif
1499 
1500 out:
1501 	if (pm != NULL)
1502 		ps->ps_destroy_msg(pm);
1503 
1504 	pnd->pnd_flags &= ~PND_INOPEN;
1505 	(void)dequeue_requests(ps, opc, PCQ_OPEN, DEQUEUE_ALL);
1506 
1507 	return error;
1508 }
1509 
1510 /* ARGSUSED0 */
1511 int
1512 perfuse_node_close(pu, opc, flags, pcr)
1513 	struct puffs_usermount *pu;
1514 	puffs_cookie_t opc;
1515 	int flags;
1516 	const struct puffs_cred *pcr;
1517 {
1518 	struct perfuse_node_data *pnd;
1519 
1520 	pnd = PERFUSE_NODE_DATA(opc);
1521 
1522 	if (!(pnd->pnd_flags & PND_OPEN))
1523 		return EBADF;
1524 
1525 	/*
1526 	 * Actual close is postponed at inactive time.
1527 	 */
1528 	return 0;
1529 }
1530 
1531 int
1532 perfuse_node_access(pu, opc, mode, pcr)
1533 	struct puffs_usermount *pu;
1534 	puffs_cookie_t opc;
1535 	int mode;
1536 	const struct puffs_cred *pcr;
1537 {
1538 	perfuse_msg_t *pm;
1539 	struct perfuse_state *ps;
1540 	struct fuse_access_in *fai;
1541 	int error;
1542 
1543 	if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED)
1544 		return ENOENT;
1545 
1546 	/*
1547 	 * If we previously detected the filesystem does not
1548 	 * implement access(), short-circuit the call and skip
1549 	 * to libpuffs access() emulation.
1550 	 */
1551 	ps = puffs_getspecific(pu);
1552 	if (ps->ps_flags & PS_NO_ACCESS) {
1553 		const struct vattr *vap;
1554 
1555 		vap = puffs_pn_getvap((struct puffs_node *)opc);
1556 
1557 		error = puffs_access(IFTOVT(vap->va_mode),
1558 				     vap->va_mode & ACCESSPERMS,
1559 				     vap->va_uid, vap->va_gid,
1560 				     (mode_t)mode, pcr);
1561 		return error;
1562 	}
1563 
1564 	/*
1565 	 * Plain access call
1566 	 */
1567 	pm = ps->ps_new_msg(pu, opc, FUSE_ACCESS, sizeof(*fai), pcr);
1568 	fai = GET_INPAYLOAD(ps, pm, fuse_access_in);
1569 	fai->mask = 0;
1570 	fai->mask |= (mode & PUFFS_VREAD) ? R_OK : 0;
1571 	fai->mask |= (mode & PUFFS_VWRITE) ? W_OK : 0;
1572 	fai->mask |= (mode & PUFFS_VEXEC) ? X_OK : 0;
1573 
1574 	error = xchg_msg(pu, opc, pm, NO_PAYLOAD_REPLY_LEN, wait_reply);
1575 
1576 	ps->ps_destroy_msg(pm);
1577 
1578 	/*
1579 	 * If unimplemented, start over with emulation
1580 	 */
1581 	if (error == ENOSYS) {
1582 		ps->ps_flags |= PS_NO_ACCESS;
1583 		return perfuse_node_access(pu, opc, mode, pcr);
1584 	}
1585 
1586 	return error;
1587 }
1588 
1589 int
1590 perfuse_node_getattr(pu, opc, vap, pcr)
1591 	struct puffs_usermount *pu;
1592 	puffs_cookie_t opc;
1593 	struct vattr *vap;
1594 	const struct puffs_cred *pcr;
1595 {
1596 	perfuse_msg_t *pm = NULL;
1597 	struct perfuse_state *ps;
1598 	struct perfuse_node_data *pnd = PERFUSE_NODE_DATA(opc);
1599 	struct fuse_getattr_in *fgi;
1600 	struct fuse_attr_out *fao;
1601 	int error = 0;
1602 
1603 	if (pnd->pnd_flags & PND_REMOVED)
1604 		return ENOENT;
1605 
1606 	/*
1607 	 * Serialize size access, see comment in perfuse_node_setattr().
1608 	 */
1609 	while (pnd->pnd_flags & PND_INRESIZE)
1610 		requeue_request(pu, opc, PCQ_RESIZE);
1611 	pnd->pnd_flags |= PND_INRESIZE;
1612 
1613 	ps = puffs_getspecific(pu);
1614 
1615 	/*
1616 	 * Check for cached attributes
1617 	 * This still require serialized access to size.
1618 	 */
1619 	if (!attr_expired(opc)) {
1620 		(void)memcpy(vap, puffs_pn_getvap((struct puffs_node *)opc),
1621 			     sizeof(*vap));
1622 		goto out;
1623 	}
1624 
1625 	/*
1626 	 * FUSE_GETATTR_FH must be set in fgi->flags
1627 	 * if we use for fgi->fh
1628 	 */
1629 	pm = ps->ps_new_msg(pu, opc, FUSE_GETATTR, sizeof(*fgi), pcr);
1630 	fgi = GET_INPAYLOAD(ps, pm, fuse_getattr_in);
1631 	fgi->getattr_flags = 0;
1632 	fgi->dummy = 0;
1633 	fgi->fh = 0;
1634 
1635 	if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_OPEN) {
1636 		fgi->fh = perfuse_get_fh(opc, FREAD);
1637 		fgi->getattr_flags |= FUSE_GETATTR_FH;
1638 	}
1639 
1640 #ifdef PERFUSE_DEBUG
1641 	if (perfuse_diagflags & PDF_RESIZE)
1642 		DPRINTF(">> %s %p %" PRIu64 "\n", __func__, (void *)opc,
1643 		    vap->va_size);
1644 #endif
1645 
1646 	if ((error = xchg_msg(pu, opc, pm, sizeof(*fao), wait_reply)) != 0)
1647 		goto out;
1648 
1649 	fao = GET_OUTPAYLOAD(ps, pm, fuse_attr_out);
1650 
1651 #ifdef PERFUSE_DEBUG
1652 	if (perfuse_diagflags & PDF_RESIZE)
1653 		DPRINTF("<< %s %p %" PRIu64 " -> %" PRIu64 "\n", __func__,
1654 		    (void *)opc, vap->va_size, fao->attr.size);
1655 #endif
1656 
1657 	/*
1658 	 * We set birthtime, flags, filerev,vaflags to 0.
1659 	 * This seems the best bet, since the information is
1660 	 * not available from filesystem.
1661 	 */
1662 	fuse_attr_to_vap(ps, vap, &fao->attr);
1663 	set_expire(opc, NULL, fao);
1664 
1665 out:
1666 	if (pm != NULL)
1667 		ps->ps_destroy_msg(pm);
1668 
1669 	pnd->pnd_flags &= ~PND_INRESIZE;
1670 	(void)dequeue_requests(ps, opc, PCQ_RESIZE, DEQUEUE_ALL);
1671 
1672 	return error;
1673 }
1674 
1675 int
1676 perfuse_node_setattr(pu, opc, vap, pcr)
1677 	struct puffs_usermount *pu;
1678 	puffs_cookie_t opc;
1679 	const struct vattr *vap;
1680 	const struct puffs_cred *pcr;
1681 {
1682 	perfuse_msg_t *pm;
1683 	uint64_t fh;
1684 	struct perfuse_state *ps;
1685 	struct perfuse_node_data *pnd;
1686 	struct fuse_setattr_in *fsi;
1687 	struct fuse_attr_out *fao;
1688 	struct vattr *old_va;
1689 	int error;
1690 #ifdef PERFUSE_DEBUG
1691 	struct vattr *old_vap;
1692 	int resize_debug = 0;
1693 #endif
1694 
1695 	ps = puffs_getspecific(pu);
1696 	pnd = PERFUSE_NODE_DATA(opc);
1697 	pm = NULL;
1698 
1699 	/*
1700 	 * The only operation we can do once the file is removed
1701 	 * is to resize it, and we can do it only if it is open.
1702 	 * Do not even send the operation to the filesystem: the
1703 	 * file is not there anymore.
1704 	 */
1705 	if (pnd->pnd_flags & PND_REMOVED) {
1706 		if (!(pnd->pnd_flags & PND_OPEN))
1707 			return ENOENT;
1708 
1709 		error = 0;
1710 		goto out;
1711 	}
1712 
1713 	old_va = puffs_pn_getvap((struct puffs_node *)opc);
1714 
1715 	/*
1716 	 * Check for permission to change size
1717 	 */
1718 	if ((vap->va_size != (u_quad_t)PUFFS_VNOVAL) &&
1719 	    (error = mode_access(opc, pcr, PUFFS_VWRITE)) != 0)
1720 		return error;
1721 
1722 	/*
1723 	 * Check for permission to change dates
1724 	 */
1725 	if (((vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL) ||
1726 	     (vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL)) &&
1727 	    (puffs_access_times(old_va->va_uid, old_va->va_gid,
1728 				old_va->va_mode, 0, pcr) != 0))
1729 		return EACCES;
1730 
1731 	/*
1732 	 * Check for permission to change owner and group
1733 	 */
1734 	if (((vap->va_uid != (uid_t)PUFFS_VNOVAL) ||
1735 	     (vap->va_gid != (gid_t)PUFFS_VNOVAL)) &&
1736 	    (puffs_access_chown(old_va->va_uid, old_va->va_gid,
1737 				vap->va_uid, vap->va_gid, pcr)) != 0)
1738 		return EACCES;
1739 
1740 	/*
1741 	 * Check for permission to change permissions
1742 	 */
1743 	if ((vap->va_mode != (mode_t)PUFFS_VNOVAL) &&
1744 	    (puffs_access_chmod(old_va->va_uid, old_va->va_gid,
1745 				old_va->va_type, vap->va_mode, pcr)) != 0)
1746 		return EACCES;
1747 
1748 	pm = ps->ps_new_msg(pu, opc, FUSE_SETATTR, sizeof(*fsi), pcr);
1749 	fsi = GET_INPAYLOAD(ps, pm, fuse_setattr_in);
1750 	fsi->valid = 0;
1751 
1752 	/*
1753 	 * Get a fh if the node is open for writing
1754 	 */
1755 	if (pnd->pnd_flags & PND_WFH) {
1756 		fh = perfuse_get_fh(opc, FWRITE);
1757 		fsi->fh = fh;
1758 		fsi->valid |= FUSE_FATTR_FH;
1759 	}
1760 
1761 	if (vap->va_size != (u_quad_t)PUFFS_VNOVAL) {
1762 		fsi->size = vap->va_size;
1763 		fsi->valid |= FUSE_FATTR_SIZE;
1764 
1765 		/*
1766 		 * Serialize anything that can touch file size
1767 		 * to avoid reordered GETATTR and SETATTR.
1768 		 * Out of order SETATTR can report stale size,
1769 		 * which will cause the kernel to truncate the file.
1770 		 */
1771 		while (pnd->pnd_flags & PND_INRESIZE)
1772 			requeue_request(pu, opc, PCQ_RESIZE);
1773 		pnd->pnd_flags |= PND_INRESIZE;
1774 	}
1775 
1776 	/*
1777  	 * Setting mtime without atime or vice versa leads to
1778 	 * dates being reset to Epoch on glusterfs. If one
1779 	 * is missing, use the old value.
1780  	 */
1781 	if ((vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL) ||
1782 	    (vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL)) {
1783 
1784 		if (vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL) {
1785 			fsi->atime = vap->va_atime.tv_sec;
1786 			fsi->atimensec = (uint32_t)vap->va_atime.tv_nsec;
1787 		} else {
1788 			fsi->atime = old_va->va_atime.tv_sec;
1789 			fsi->atimensec = (uint32_t)old_va->va_atime.tv_nsec;
1790 		}
1791 
1792 		if (vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL) {
1793 			fsi->mtime = vap->va_mtime.tv_sec;
1794 			fsi->mtimensec = (uint32_t)vap->va_mtime.tv_nsec;
1795 		} else {
1796 			fsi->mtime = old_va->va_mtime.tv_sec;
1797 			fsi->mtimensec = (uint32_t)old_va->va_mtime.tv_nsec;
1798 		}
1799 
1800 		fsi->valid |= (FUSE_FATTR_MTIME|FUSE_FATTR_ATIME);
1801 	}
1802 
1803 	if (vap->va_mode != (mode_t)PUFFS_VNOVAL) {
1804 		fsi->mode = vap->va_mode;
1805 		fsi->valid |= FUSE_FATTR_MODE;
1806 	}
1807 
1808 	if (vap->va_uid != (uid_t)PUFFS_VNOVAL) {
1809 		fsi->uid = vap->va_uid;
1810 		fsi->valid |= FUSE_FATTR_UID;
1811 	}
1812 
1813 	if (vap->va_gid != (gid_t)PUFFS_VNOVAL) {
1814 		fsi->gid = vap->va_gid;
1815 		fsi->valid |= FUSE_FATTR_GID;
1816 	}
1817 
1818 	if (pnd->pnd_lock_owner != 0) {
1819 		fsi->lock_owner = pnd->pnd_lock_owner;
1820 		fsi->valid |= FUSE_FATTR_LOCKOWNER;
1821 	}
1822 
1823 	/*
1824 	 * ftruncate() sends only va_size, and metadata cache
1825 	 * flush adds va_atime and va_mtime. Some FUSE
1826 	 * filesystems will attempt to detect ftruncate by
1827 	 * checking for FATTR_SIZE being set without
1828 	 * FATTR_UID|FATTR_GID|FATTR_ATIME|FATTR_MTIME|FATTR_MODE
1829 	 *
1830 	 * Try to adapt and remove FATTR_ATIME|FATTR_MTIME
1831 	 * if we suspect a ftruncate().
1832 	 */
1833 	if ((vap->va_size != (u_quad_t)PUFFS_VNOVAL) &&
1834 	    ((vap->va_mode == (mode_t)PUFFS_VNOVAL) &&
1835 	     (vap->va_uid == (uid_t)PUFFS_VNOVAL) &&
1836 	     (vap->va_gid == (gid_t)PUFFS_VNOVAL))) {
1837 		fsi->atime = 0;
1838 		fsi->atimensec = 0;
1839 		fsi->mtime = 0;
1840 		fsi->mtimensec = 0;
1841 		fsi->valid &= ~(FUSE_FATTR_ATIME|FUSE_FATTR_MTIME);
1842 	}
1843 
1844 	/*
1845 	 * If nothing remain, discard the operation.
1846 	 */
1847 	if (!(fsi->valid & (FUSE_FATTR_SIZE|FUSE_FATTR_ATIME|FUSE_FATTR_MTIME|
1848 			    FUSE_FATTR_MODE|FUSE_FATTR_UID|FUSE_FATTR_GID))) {
1849 		error = 0;
1850 		goto out;
1851 	}
1852 
1853 #ifdef PERFUSE_DEBUG
1854 	old_vap = puffs_pn_getvap((struct puffs_node *)opc);
1855 
1856 	if ((perfuse_diagflags & PDF_RESIZE) &&
1857 	    (old_vap->va_size != (u_quad_t)PUFFS_VNOVAL)) {
1858 		resize_debug = 1;
1859 
1860 		DPRINTF(">> %s %p %" PRIu64 " -> %" PRIu64 "\n", __func__,
1861 		    (void *)opc,
1862 		    puffs_pn_getvap((struct puffs_node *)opc)->va_size,
1863 		    fsi->size);
1864 	}
1865 #endif
1866 
1867 	if ((error = xchg_msg(pu, opc, pm, sizeof(*fao), wait_reply)) != 0)
1868 		goto out;
1869 
1870 	/*
1871 	 * Copy back the new values
1872 	 */
1873 	fao = GET_OUTPAYLOAD(ps, pm, fuse_attr_out);
1874 
1875 #ifdef PERFUSE_DEBUG
1876 	if (resize_debug)
1877 		DPRINTF("<< %s %p %" PRIu64 " -> %" PRIu64 "\n", __func__,
1878 		    (void *)opc, old_vap->va_size, fao->attr.size);
1879 #endif
1880 
1881 	fuse_attr_to_vap(ps, old_va, &fao->attr);
1882 	set_expire(opc, NULL, fao);
1883 
1884 out:
1885 	if (pm != NULL)
1886 		ps->ps_destroy_msg(pm);
1887 
1888 	if (pnd->pnd_flags & PND_INRESIZE) {
1889 		pnd->pnd_flags &= ~PND_INRESIZE;
1890 		(void)dequeue_requests(ps, opc, PCQ_RESIZE, DEQUEUE_ALL);
1891 	}
1892 
1893 	return error;
1894 }
1895 
1896 int
1897 perfuse_node_poll(pu, opc, events)
1898 	struct puffs_usermount *pu;
1899 	puffs_cookie_t opc;
1900 	int *events;
1901 {
1902 	struct perfuse_state *ps;
1903 	perfuse_msg_t *pm;
1904 	struct fuse_poll_in *fpi;
1905 	struct fuse_poll_out *fpo;
1906 	int error;
1907 
1908 	ps = puffs_getspecific(pu);
1909 	/*
1910 	 * kh is set if FUSE_POLL_SCHEDULE_NOTIFY is set.
1911 	 *
1912 	 * XXX ps_new_msg() is called with NULL creds, which will
1913 	 * be interpreted as FUSE superuser. We have no way to
1914 	 * know the requesting process' credential, but since poll
1915 	 * is supposed to operate on a file that has been open,
1916 	 * permission should have already been checked at open time.
1917 	 * That still may breaks on filesystems that provides odd
1918 	 * semantics.
1919  	 */
1920 	pm = ps->ps_new_msg(pu, opc, FUSE_POLL, sizeof(*fpi), NULL);
1921 	fpi = GET_INPAYLOAD(ps, pm, fuse_poll_in);
1922 	fpi->fh = perfuse_get_fh(opc, FREAD);
1923 	fpi->kh = 0;
1924 	fpi->flags = 0;
1925 
1926 #ifdef PERFUSE_DEBUG
1927 	if (perfuse_diagflags & PDF_FH)
1928 		DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", fh = 0x%"PRIx64"\n",
1929 			__func__, (void *)opc,
1930 			PERFUSE_NODE_DATA(opc)->pnd_nodeid, fpi->fh);
1931 #endif
1932 	if ((error = xchg_msg(pu, opc, pm, sizeof(*fpo), wait_reply)) != 0)
1933 		goto out;
1934 
1935 	fpo = GET_OUTPAYLOAD(ps, pm, fuse_poll_out);
1936 	*events = fpo->revents;
1937 out:
1938 	ps->ps_destroy_msg(pm);
1939 
1940 	return error;
1941 }
1942 
1943 /* ARGSUSED0 */
1944 int
1945 perfuse_node_mmap(pu, opc, flags, pcr)
1946 	struct puffs_usermount *pu;
1947 	puffs_cookie_t opc;
1948 	int flags;
1949 	const struct puffs_cred *pcr;
1950 {
1951 	/*
1952 	 * Not implemented anymore in libfuse
1953 	 */
1954 	return ENOSYS;
1955 }
1956 
1957 /* ARGSUSED2 */
1958 int
1959 perfuse_node_fsync(pu, opc, pcr, flags, offlo, offhi)
1960 	struct puffs_usermount *pu;
1961 	puffs_cookie_t opc;
1962 	const struct puffs_cred *pcr;
1963 	int flags;
1964 	off_t offlo;
1965 	off_t offhi;
1966 {
1967 	int op;
1968 	perfuse_msg_t *pm;
1969 	struct perfuse_state *ps;
1970 	struct perfuse_node_data *pnd;
1971 	struct fuse_fsync_in *ffi;
1972 	uint64_t fh;
1973 	int error;
1974 
1975 	pm = NULL;
1976 	ps = puffs_getspecific(pu);
1977 	pnd = PERFUSE_NODE_DATA(opc);
1978 
1979 	/*
1980 	 * No need to sync a removed node
1981 	 */
1982 	if (pnd->pnd_flags & PND_REMOVED)
1983 		return 0;
1984 
1985 	/*
1986 	 * We do not sync closed files. They have been
1987 	 * sync at inactive time already.
1988 	 */
1989 	if (!(pnd->pnd_flags & PND_OPEN))
1990 		return 0;
1991 
1992 	if (puffs_pn_getvap((struct puffs_node *)opc)->va_type == VDIR)
1993 		op = FUSE_FSYNCDIR;
1994 	else 		/* VREG but also other types such as VLNK */
1995 		op = FUSE_FSYNC;
1996 
1997 	/*
1998 	 * Do not sync if there are no change to sync
1999 	 * XXX remove that test on files if we implement mmap
2000 	 */
2001 #ifdef PERFUSE_DEBUG
2002 	if (perfuse_diagflags & PDF_SYNC)
2003 		DPRINTF("%s: TEST opc = %p, file = \"%s\" is %sdirty\n",
2004 			__func__, (void*)opc, perfuse_node_path(opc),
2005 			pnd->pnd_flags & PND_DIRTY ? "" : "not ");
2006 #endif
2007 	if (!(pnd->pnd_flags & PND_DIRTY))
2008 		return 0;
2009 
2010 	/*
2011 	 * It seems NetBSD can call fsync without open first
2012 	 * glusterfs complain in such a situation:
2013 	 * "FSYNC() ERR => -1 (Invalid argument)"
2014 	 * The file will be closed at inactive time.
2015 	 *
2016 	 * We open the directory for reading in order to sync.
2017 	 * This sounds rather counterintuitive, but it works.
2018 	 */
2019 	if (!(pnd->pnd_flags & PND_WFH)) {
2020 		if ((error = perfuse_node_open(pu, opc, FREAD, pcr)) != 0)
2021 			goto out;
2022 	}
2023 
2024 	if (op == FUSE_FSYNCDIR)
2025 		fh = perfuse_get_fh(opc, FREAD);
2026 	else
2027 		fh = perfuse_get_fh(opc, FWRITE);
2028 
2029 	/*
2030 	 * If fsync_flags  is set, meta data should not be flushed.
2031 	 */
2032 	pm = ps->ps_new_msg(pu, opc, op, sizeof(*ffi), pcr);
2033 	ffi = GET_INPAYLOAD(ps, pm, fuse_fsync_in);
2034 	ffi->fh = fh;
2035 	ffi->fsync_flags = (flags & FFILESYNC) ? 0 : 1;
2036 
2037 #ifdef PERFUSE_DEBUG
2038 	if (perfuse_diagflags & PDF_FH)
2039 		DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", fh = 0x%"PRIx64"\n",
2040 			__func__, (void *)opc,
2041 			PERFUSE_NODE_DATA(opc)->pnd_nodeid, ffi->fh);
2042 #endif
2043 
2044 	if ((error = xchg_msg(pu, opc, pm,
2045 			      NO_PAYLOAD_REPLY_LEN, wait_reply)) != 0)
2046 		goto out;
2047 
2048 	/*
2049 	 * No reply beyond fuse_out_header: nothing to do on success
2050 	 * just clear the dirty flag
2051 	 */
2052 	pnd->pnd_flags &= ~PND_DIRTY;
2053 
2054 #ifdef PERFUSE_DEBUG
2055 	if (perfuse_diagflags & PDF_SYNC)
2056 		DPRINTF("%s: CLEAR opc = %p, file = \"%s\"\n",
2057 			__func__, (void*)opc, perfuse_node_path(opc));
2058 #endif
2059 
2060 out:
2061 	/*
2062 	 * ENOSYS is not returned to kernel,
2063 	 */
2064 	if (error == ENOSYS)
2065 		error = 0;
2066 
2067 	if (pm != NULL)
2068 		ps->ps_destroy_msg(pm);
2069 
2070 	return error;
2071 }
2072 
2073 /* ARGSUSED0 */
2074 int
2075 perfuse_node_seek(pu, opc, oldoff, newoff,  pcr)
2076 	struct puffs_usermount *pu;
2077 	puffs_cookie_t opc;
2078 	off_t oldoff;
2079 	off_t newoff;
2080 	const struct puffs_cred *pcr;
2081 {
2082 	return 0;
2083 }
2084 
2085 int
2086 perfuse_node_remove(pu, opc, targ, pcn)
2087 	struct puffs_usermount *pu;
2088 	puffs_cookie_t opc;
2089 	puffs_cookie_t targ;
2090 	const struct puffs_cn *pcn;
2091 {
2092 	struct perfuse_state *ps;
2093 	struct perfuse_node_data *pnd;
2094 	perfuse_msg_t *pm;
2095 	char *path;
2096 	const char *name;
2097 	size_t len;
2098 	int error;
2099 
2100 	pnd = PERFUSE_NODE_DATA(opc);
2101 
2102 	if ((pnd->pnd_flags & PND_REMOVED) ||
2103 	    (PERFUSE_NODE_DATA(targ)->pnd_flags & PND_REMOVED))
2104 		return ENOENT;
2105 
2106 #ifdef PERFUSE_DEBUG
2107 	if (targ == NULL)
2108 		DERRX(EX_SOFTWARE, "%s: targ is NULL", __func__);
2109 
2110 	if (perfuse_diagflags & (PDF_FH|PDF_FILENAME))
2111 		DPRINTF("%s: opc = %p, remove opc = %p, file = \"%s\"\n",
2112 			__func__, (void *)opc, (void *)targ, pcn->pcn_name);
2113 #endif
2114 	/*
2115 	 * Await for all operations on the deleted node to drain,
2116 	 * as the filesystem may be confused to have it deleted
2117 	 * during a getattr
2118 	 */
2119 	while (PERFUSE_NODE_DATA(targ)->pnd_flags & PND_INXCHG)
2120 		requeue_request(pu, targ, PCQ_AFTERXCHG);
2121 
2122 	ps = puffs_getspecific(pu);
2123 	pnd = PERFUSE_NODE_DATA(opc);
2124 	name = pcn->pcn_name;
2125 	len = pcn->pcn_namelen + 1;
2126 
2127 	pm = ps->ps_new_msg(pu, opc, FUSE_UNLINK, len, pcn->pcn_cred);
2128 	path = _GET_INPAYLOAD(ps, pm, char *);
2129 	(void)strlcpy(path, name, len);
2130 
2131 	if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0)
2132 		goto out;
2133 
2134 	PERFUSE_NODE_DATA(targ)->pnd_flags |= PND_REMOVED;
2135 	if (!(PERFUSE_NODE_DATA(targ)->pnd_flags & PND_OPEN))
2136 		puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2);
2137 
2138 	/*
2139 	 * The parent directory needs a sync
2140 	 */
2141 	PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY;
2142 
2143 #ifdef PERFUSE_DEBUG
2144 	if (perfuse_diagflags & PDF_FILENAME)
2145 		DPRINTF("%s: remove nodeid = 0x%"PRIx64" file = \"%s\"\n",
2146 			__func__, PERFUSE_NODE_DATA(targ)->pnd_nodeid,
2147 			pcn->pcn_name);
2148 #endif
2149 out:
2150 	ps->ps_destroy_msg(pm);
2151 
2152 	return error;
2153 }
2154 
2155 int
2156 perfuse_node_link(pu, opc, targ, pcn)
2157 	struct puffs_usermount *pu;
2158 	puffs_cookie_t opc;
2159 	puffs_cookie_t targ;
2160 	const struct puffs_cn *pcn;
2161 {
2162 	struct perfuse_state *ps;
2163 	perfuse_msg_t *pm;
2164 	const char *name;
2165 	size_t len;
2166 	struct puffs_node *pn;
2167 	struct fuse_link_in *fli;
2168 	int error;
2169 
2170 	if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED)
2171 		return ENOENT;
2172 
2173 	ps = puffs_getspecific(pu);
2174 	pn = (struct puffs_node *)targ;
2175 	name = pcn->pcn_name;
2176 	len =  sizeof(*fli) + pcn->pcn_namelen + 1;
2177 
2178 	pm = ps->ps_new_msg(pu, opc, FUSE_LINK, len, pcn->pcn_cred);
2179 	fli = GET_INPAYLOAD(ps, pm, fuse_link_in);
2180 	fli->oldnodeid = PERFUSE_NODE_DATA(pn)->pnd_nodeid;
2181 	(void)strlcpy((char *)(void *)(fli + 1), name, len - sizeof(*fli));
2182 
2183 	error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply);
2184 
2185 	ps->ps_destroy_msg(pm);
2186 
2187 	return error;
2188 }
2189 
2190 int
2191 perfuse_node_rename(pu, opc, src, pcn_src, targ_dir, targ, pcn_targ)
2192 	struct puffs_usermount *pu;
2193 	puffs_cookie_t opc;
2194 	puffs_cookie_t src;
2195 	const struct puffs_cn *pcn_src;
2196 	puffs_cookie_t targ_dir;
2197 	puffs_cookie_t targ;
2198 	const struct puffs_cn *pcn_targ;
2199 {
2200 	struct perfuse_state *ps;
2201 	perfuse_msg_t *pm;
2202 	struct fuse_rename_in *fri;
2203 	const char *newname;
2204 	const char *oldname;
2205 	char *np;
2206 	int error;
2207 	size_t len;
2208 	size_t newname_len;
2209 	size_t oldname_len;
2210 
2211 	if ((PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED) ||
2212 	    (PERFUSE_NODE_DATA(src)->pnd_flags & PND_REMOVED) ||
2213 	    (PERFUSE_NODE_DATA(targ_dir)->pnd_flags & PND_REMOVED))
2214 		return ENOENT;
2215 
2216 	/*
2217 	 * Await for all operations on the deleted node to drain,
2218 	 * as the filesystem may be confused to have it deleted
2219 	 * during a getattr
2220 	 */
2221 	if ((struct puffs_node *)targ != NULL) {
2222 		while (PERFUSE_NODE_DATA(targ)->pnd_flags & PND_INXCHG)
2223 			requeue_request(pu, targ, PCQ_AFTERXCHG);
2224 	} else {
2225 		while (PERFUSE_NODE_DATA(src)->pnd_flags & PND_INXCHG)
2226 			requeue_request(pu, src, PCQ_AFTERXCHG);
2227 	}
2228 
2229 	ps = puffs_getspecific(pu);
2230 	newname =  pcn_targ->pcn_name;
2231 	newname_len = pcn_targ->pcn_namelen + 1;
2232 	oldname =  pcn_src->pcn_name;
2233 	oldname_len = pcn_src->pcn_namelen + 1;
2234 
2235 	len = sizeof(*fri) + oldname_len + newname_len;
2236 	pm = ps->ps_new_msg(pu, opc, FUSE_RENAME, len, pcn_targ->pcn_cred);
2237 	fri = GET_INPAYLOAD(ps, pm, fuse_rename_in);
2238 	fri->newdir = PERFUSE_NODE_DATA(targ_dir)->pnd_nodeid;
2239 	np = (char *)(void *)(fri + 1);
2240 	(void)strlcpy(np, oldname, oldname_len);
2241 	np += oldname_len;
2242 	(void)strlcpy(np, newname, newname_len);
2243 
2244 	if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0)
2245 		goto out;
2246 
2247 	if (opc != targ_dir) {
2248 		struct perfuse_node_data *srcdir_pnd;
2249 		struct perfuse_node_data *dstdir_pnd;
2250 		struct perfuse_node_data *src_pnd;
2251 
2252 		srcdir_pnd = PERFUSE_NODE_DATA(opc);
2253 		dstdir_pnd = PERFUSE_NODE_DATA(targ_dir);
2254 		src_pnd = PERFUSE_NODE_DATA(src);
2255 
2256 		TAILQ_REMOVE(&srcdir_pnd->pnd_children, src_pnd, pnd_next);
2257 		TAILQ_INSERT_TAIL(&dstdir_pnd->pnd_children, src_pnd, pnd_next);
2258 
2259 		srcdir_pnd->pnd_childcount--;
2260 		dstdir_pnd->pnd_childcount++;
2261 
2262 		src_pnd->pnd_parent = targ_dir;
2263 
2264 		PERFUSE_NODE_DATA(targ_dir)->pnd_flags |= PND_DIRTY;
2265 	}
2266 
2267 	(void)strlcpy(PERFUSE_NODE_DATA(src)->pnd_name, newname, MAXPATHLEN);
2268 
2269 	PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY;
2270 
2271 	if ((struct puffs_node *)targ != NULL)
2272 		PERFUSE_NODE_DATA(targ)->pnd_flags |= PND_REMOVED;
2273 
2274 #ifdef PERFUSE_DEBUG
2275 	if (perfuse_diagflags & PDF_FILENAME)
2276 		DPRINTF("%s: nodeid = 0x%"PRIx64" file = \"%s\" renamed \"%s\" "
2277 			"nodeid = 0x%"PRIx64" -> nodeid = 0x%"PRIx64" \"%s\"\n",
2278 	 		__func__, PERFUSE_NODE_DATA(src)->pnd_nodeid,
2279 			pcn_src->pcn_name, pcn_targ->pcn_name,
2280 			PERFUSE_NODE_DATA(opc)->pnd_nodeid,
2281 			PERFUSE_NODE_DATA(targ_dir)->pnd_nodeid,
2282 			perfuse_node_path(targ_dir));
2283 #endif
2284 
2285 out:
2286 	if (pm != NULL)
2287 		ps->ps_destroy_msg(pm);
2288 
2289 	return error;
2290 }
2291 
2292 int
2293 perfuse_node_mkdir(pu, opc, pni, pcn, vap)
2294 	struct puffs_usermount *pu;
2295 	puffs_cookie_t opc;
2296 	struct puffs_newinfo *pni;
2297 	const struct puffs_cn *pcn;
2298 	const struct vattr *vap;
2299 {
2300 	struct perfuse_state *ps;
2301 	perfuse_msg_t *pm;
2302 	struct fuse_mkdir_in *fmi;
2303 	const char *path;
2304 	size_t len;
2305 
2306 	if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED)
2307 		return ENOENT;
2308 
2309 	ps = puffs_getspecific(pu);
2310 	path = pcn->pcn_name;
2311 	len = sizeof(*fmi) + pcn->pcn_namelen + 1;
2312 
2313 	pm = ps->ps_new_msg(pu, opc, FUSE_MKDIR, len, pcn->pcn_cred);
2314 	fmi = GET_INPAYLOAD(ps, pm, fuse_mkdir_in);
2315 	fmi->mode = vap->va_mode;
2316 	fmi->umask = 0; 	/* Seems unused by libfuse? */
2317 	(void)strlcpy((char *)(void *)(fmi + 1), path, len - sizeof(*fmi));
2318 
2319 	return node_mk_common(pu, opc, pni, pcn, pm);
2320 }
2321 
2322 
2323 int
2324 perfuse_node_rmdir(pu, opc, targ, pcn)
2325 	struct puffs_usermount *pu;
2326 	puffs_cookie_t opc;
2327 	puffs_cookie_t targ;
2328 	const struct puffs_cn *pcn;
2329 {
2330 	struct perfuse_state *ps;
2331 	struct perfuse_node_data *pnd;
2332 	perfuse_msg_t *pm;
2333 	char *path;
2334 	const char *name;
2335 	size_t len;
2336 	int error;
2337 
2338 	pnd = PERFUSE_NODE_DATA(opc);
2339 	if (pnd->pnd_flags & PND_REMOVED)
2340 		return ENOENT;
2341 
2342 	/*
2343 	 * Await for all operations on the deleted node to drain,
2344 	 * as the filesystem may be confused to have it deleted
2345 	 * during a getattr
2346 	 */
2347 	while (PERFUSE_NODE_DATA(targ)->pnd_flags & PND_INXCHG)
2348 		requeue_request(pu, targ, PCQ_AFTERXCHG);
2349 
2350 	ps = puffs_getspecific(pu);
2351 	name = pcn->pcn_name;
2352 	len = pcn->pcn_namelen + 1;
2353 
2354 	pm = ps->ps_new_msg(pu, opc, FUSE_RMDIR, len, pcn->pcn_cred);
2355 	path = _GET_INPAYLOAD(ps, pm, char *);
2356 	(void)strlcpy(path, name, len);
2357 
2358 	if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0)
2359 		goto out;
2360 
2361 	PERFUSE_NODE_DATA(targ)->pnd_flags |= PND_REMOVED;
2362 	if (!(PERFUSE_NODE_DATA(targ)->pnd_flags & PND_OPEN))
2363 		puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2);
2364 
2365 	/*
2366 	 * The parent directory needs a sync
2367 	 */
2368 	PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY;
2369 
2370 #ifdef PERFUSE_DEBUG
2371 	if (perfuse_diagflags & PDF_FILENAME)
2372 		DPRINTF("%s: remove nodeid = 0x%"PRIx64" file = \"%s\"\n",
2373 			__func__, PERFUSE_NODE_DATA(targ)->pnd_nodeid,
2374 			perfuse_node_path(targ));
2375 #endif
2376 out:
2377 	ps->ps_destroy_msg(pm);
2378 
2379 	return error;
2380 }
2381 
2382 /* vap is unused */
2383 /* ARGSUSED4 */
2384 int
2385 perfuse_node_symlink(pu, opc, pni, pcn_src, vap, link_target)
2386 	struct puffs_usermount *pu;
2387 	puffs_cookie_t opc;
2388 	struct puffs_newinfo *pni;
2389 	const struct puffs_cn *pcn_src;
2390 	const struct vattr *vap;
2391 	const char *link_target;
2392 {
2393 	struct perfuse_state *ps;
2394 	perfuse_msg_t *pm;
2395 	char *np;
2396 	const char *path;
2397 	size_t path_len;
2398 	size_t linkname_len;
2399 	size_t len;
2400 
2401 	if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED)
2402 		return ENOENT;
2403 
2404 	ps = puffs_getspecific(pu);
2405 	path = pcn_src->pcn_name;
2406 	path_len = pcn_src->pcn_namelen + 1;
2407 	linkname_len = strlen(link_target) + 1;
2408 	len = path_len + linkname_len;
2409 
2410 	pm = ps->ps_new_msg(pu, opc, FUSE_SYMLINK, len, pcn_src->pcn_cred);
2411 	np = _GET_INPAYLOAD(ps, pm, char *);
2412 	(void)strlcpy(np, path, path_len);
2413 	np += path_len;
2414 	(void)strlcpy(np, link_target, linkname_len);
2415 
2416 	return node_mk_common(pu, opc, pni, pcn_src, pm);
2417 }
2418 
2419 /* ARGSUSED4 */
2420 int
2421 perfuse_node_readdir(pu, opc, dent, readoff,
2422 		     reslen, pcr, eofflag, cookies, ncookies)
2423 	struct puffs_usermount *pu;
2424 	puffs_cookie_t opc;
2425 	struct dirent *dent;
2426 	off_t *readoff;
2427 	size_t *reslen;
2428 	const struct puffs_cred *pcr;
2429 	int *eofflag;
2430 	off_t *cookies;
2431 	size_t *ncookies;
2432 {
2433 	perfuse_msg_t *pm;
2434 	uint64_t fh;
2435 	struct perfuse_state *ps;
2436 	struct perfuse_node_data *pnd;
2437 	struct fuse_read_in *fri;
2438 	struct fuse_out_header *foh;
2439 	struct fuse_dirent *fd;
2440 	size_t foh_len;
2441 	int error;
2442 	size_t fd_maxlen;
2443 
2444 	pm = NULL;
2445 	error = 0;
2446 	ps = puffs_getspecific(pu);
2447 
2448 	/*
2449 	 * readdir state is kept at node level, and several readdir
2450 	 * requests can be issued at the same time on the same node.
2451 	 * We need to queue requests so that only one is in readdir
2452 	 * code at the same time.
2453 	 */
2454 	pnd = PERFUSE_NODE_DATA(opc);
2455 	while (pnd->pnd_flags & PND_INREADDIR)
2456 		requeue_request(pu, opc, PCQ_READDIR);
2457 	pnd->pnd_flags |= PND_INREADDIR;
2458 
2459 #ifdef PERFUSE_DEBUG
2460 	if (perfuse_diagflags & PDF_READDIR)
2461 		DPRINTF("%s: READDIR opc = %p enter critical section\n",
2462 			__func__, (void *)opc);
2463 #endif
2464 	/*
2465 	 * Re-initialize pnd->pnd_fd_cookie on the first readdir for a node
2466 	 */
2467 	if (*readoff == 0)
2468 		pnd->pnd_fd_cookie = 0;
2469 
2470 	/*
2471 	 * Do we already have the data bufered?
2472 	 */
2473 	if (pnd->pnd_dirent != NULL)
2474 		goto out;
2475 	pnd->pnd_dirent_len = 0;
2476 
2477 	/*
2478 	 * It seems NetBSD can call readdir without open first
2479 	 * libfuse will crash if it is done that way, hence open first.
2480 	 */
2481 	if (!(pnd->pnd_flags & PND_OPEN)) {
2482 		if ((error = perfuse_node_open(pu, opc, FREAD, pcr)) != 0)
2483 			goto out;
2484 	}
2485 
2486 	fh = perfuse_get_fh(opc, FREAD);
2487 
2488 #ifdef PERFUSE_DEBUG
2489 	if (perfuse_diagflags & PDF_FH)
2490 		DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", rfh = 0x%"PRIx64"\n",
2491 			__func__, (void *)opc,
2492 			PERFUSE_NODE_DATA(opc)->pnd_nodeid, fh);
2493 #endif
2494 
2495 	pnd->pnd_all_fd = NULL;
2496 	pnd->pnd_all_fd_len = 0;
2497 	fd_maxlen = ps->ps_max_readahead - sizeof(*foh);
2498 
2499 	do {
2500 		size_t fd_len;
2501 		char *afdp;
2502 
2503 		pm = ps->ps_new_msg(pu, opc, FUSE_READDIR, sizeof(*fri), pcr);
2504 
2505 		/*
2506 		 * read_flags, lock_owner and flags are unused in libfuse
2507 		 */
2508 		fri = GET_INPAYLOAD(ps, pm, fuse_read_in);
2509 		fri->fh = fh;
2510 		fri->offset = pnd->pnd_fd_cookie;
2511 		fri->size = (uint32_t)fd_maxlen;
2512 		fri->read_flags = 0;
2513 		fri->lock_owner = 0;
2514 		fri->flags = 0;
2515 
2516 		if ((error = xchg_msg(pu, opc, pm,
2517 				      UNSPEC_REPLY_LEN, wait_reply)) != 0)
2518 			goto out;
2519 
2520 		/*
2521 		 * There are many puffs_framebufs calls later,
2522 		 * therefore foh will not be valid for a long time.
2523 		 * Just get the length and forget it.
2524 		 */
2525 		foh = GET_OUTHDR(ps, pm);
2526 		foh_len = foh->len;
2527 
2528 		/*
2529 		 * Empty read: we reached the end of the buffer.
2530 		 */
2531 		if (foh_len == sizeof(*foh)) {
2532 			*eofflag = 1;
2533 			break;
2534 		}
2535 
2536 		/*
2537 		 * Check for corrupted message.
2538 		 */
2539 		if (foh_len < sizeof(*foh) + sizeof(*fd)) {
2540 			DWARNX("readdir reply too short");
2541 			error = EIO;
2542 			goto out;
2543 		}
2544 
2545 
2546 		fd = GET_OUTPAYLOAD(ps, pm, fuse_dirent);
2547 		fd_len = foh_len - sizeof(*foh);
2548 
2549 		pnd->pnd_all_fd = realloc(pnd->pnd_all_fd,
2550 					  pnd->pnd_all_fd_len + fd_len);
2551 		if (pnd->pnd_all_fd  == NULL)
2552 			DERR(EX_OSERR, "%s: malloc failed", __func__);
2553 
2554 		afdp = (char *)(void *)pnd->pnd_all_fd + pnd->pnd_all_fd_len;
2555 		(void)memcpy(afdp, fd, fd_len);
2556 
2557 		pnd->pnd_all_fd_len += fd_len;
2558 
2559 		/*
2560 		 * The fd->off field is used as a cookie for
2561 		 * resuming the next readdir() where this one was left.
2562 	 	 */
2563 		pnd->pnd_fd_cookie = readdir_last_cookie(fd, fd_len);
2564 
2565 		ps->ps_destroy_msg(pm);
2566 		pm = NULL;
2567 	} while (1 /* CONSTCOND */);
2568 
2569 	if (pnd->pnd_all_fd != NULL) {
2570 		if (fuse_to_dirent(pu, opc, pnd->pnd_all_fd,
2571 				   pnd->pnd_all_fd_len) == -1)
2572 			error = EIO;
2573 	}
2574 
2575 out:
2576 	if (pnd->pnd_all_fd != NULL) {
2577 		free(pnd->pnd_all_fd);
2578 		pnd->pnd_all_fd = NULL;
2579 		pnd->pnd_all_fd_len = 0;
2580 	}
2581 
2582 	if (pm != NULL)
2583 		ps->ps_destroy_msg(pm);
2584 
2585 	if (error == 0)
2586 		error = readdir_buffered(opc, dent, readoff, reslen);
2587 
2588 	/*
2589 	 * Schedule queued readdir requests
2590 	 */
2591 	pnd->pnd_flags &= ~PND_INREADDIR;
2592 	(void)dequeue_requests(ps, opc, PCQ_READDIR, DEQUEUE_ALL);
2593 
2594 #ifdef PERFUSE_DEBUG
2595 	if (perfuse_diagflags & PDF_READDIR)
2596 		DPRINTF("%s: READDIR opc = %p exit critical section\n",
2597 			__func__, (void *)opc);
2598 #endif
2599 
2600 	return error;
2601 }
2602 
2603 int
2604 perfuse_node_readlink(pu, opc, pcr, linkname, linklen)
2605 	struct puffs_usermount *pu;
2606 	puffs_cookie_t opc;
2607 	const struct puffs_cred *pcr;
2608 	char *linkname;
2609 	size_t *linklen;
2610 {
2611 	struct perfuse_state *ps;
2612 	perfuse_msg_t *pm;
2613 	int error;
2614 	size_t len;
2615 	struct fuse_out_header *foh;
2616 
2617 	if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED)
2618 		return ENOENT;
2619 
2620 	ps = puffs_getspecific(pu);
2621 
2622 	pm = ps->ps_new_msg(pu, opc, FUSE_READLINK, 0, pcr);
2623 
2624 	if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0)
2625 		goto out;
2626 
2627 	foh = GET_OUTHDR(ps, pm);
2628 	len = foh->len - sizeof(*foh);
2629 	if (len > *linklen)
2630 		DERRX(EX_PROTOCOL, "path len = %zd too long", len);
2631 	if (len == 0)
2632 		DERRX(EX_PROTOCOL, "path len = %zd too short", len);
2633 
2634 	/*
2635 	 * FUSE filesystems return a NUL terminated string, we
2636 	 * do not want to trailing \0
2637 	 */
2638 	*linklen = len - 1;
2639 	(void)memcpy(linkname, _GET_OUTPAYLOAD(ps, pm, char *), len);
2640 out:
2641 	ps->ps_destroy_msg(pm);
2642 
2643 	return error;
2644 }
2645 
2646 int
2647 perfuse_node_reclaim(pu, opc)
2648 	struct puffs_usermount *pu;
2649 	puffs_cookie_t opc;
2650 {
2651 	struct perfuse_state *ps;
2652 	perfuse_msg_t *pm;
2653 	struct perfuse_node_data *pnd;
2654 	struct fuse_forget_in *ffi;
2655 	struct puffs_node *pn;
2656 	struct puffs_node *pn_root;
2657 
2658 	ps = puffs_getspecific(pu);
2659 	pnd = PERFUSE_NODE_DATA(opc);
2660 
2661 	/*
2662 	 * Never forget the root.
2663 	 */
2664 	if (pnd->pnd_nodeid == FUSE_ROOT_ID)
2665 		return 0;
2666 
2667 	pnd->pnd_flags |= PND_RECLAIMED;
2668 
2669 #ifdef PERFUSE_DEBUG
2670 	if (perfuse_diagflags & PDF_RECLAIM)
2671 		DPRINTF("%s (nodeid %"PRId64") reclaimed\n",
2672 			perfuse_node_path(opc), pnd->pnd_nodeid);
2673 #endif
2674 
2675 	pn_root = puffs_getroot(pu);
2676 	pn = (struct puffs_node *)opc;
2677 	while (pn != pn_root) {
2678 		struct puffs_node *parent_pn;
2679 
2680 		pnd = PERFUSE_NODE_DATA(pn);
2681 
2682 #ifdef PERFUSE_DEBUG
2683 	if (perfuse_diagflags & PDF_RECLAIM)
2684 		DPRINTF("%s (nodeid %"PRId64") is %sreclaimed, "
2685 			"has childcount %d %s%s%s%s, pending ops:%s%s%s\n",
2686 		        perfuse_node_path((puffs_cookie_t)pn), pnd->pnd_nodeid,
2687 		        pnd->pnd_flags & PND_RECLAIMED ? "" : "not ",
2688 		        pnd->pnd_childcount,
2689 			pnd->pnd_flags & PND_OPEN ? "open " : "not open",
2690 			pnd->pnd_flags & PND_RFH ? "r" : "",
2691 			pnd->pnd_flags & PND_WFH ? "w" : "",
2692 			pnd->pnd_flags & PND_BUSY ? "" : " none",
2693 			pnd->pnd_flags & PND_INREADDIR ? " readdir" : "",
2694 			pnd->pnd_flags & PND_INWRITE ? " write" : "",
2695 			pnd->pnd_flags & PND_INOPEN ? " open" : "");
2696 #endif
2697 
2698 		if (!(pnd->pnd_flags & PND_RECLAIMED) ||
2699 		    (pnd->pnd_childcount != 0))
2700 			return 0;
2701 
2702 #ifdef PERFUSE_DEBUG
2703 		if ((pnd->pnd_flags & PND_OPEN) ||
2704 		       !TAILQ_EMPTY(&pnd->pnd_pcq))
2705 			DERRX(EX_SOFTWARE, "%s: opc = %p: still open",
2706 			      __func__, (void *)opc);
2707 
2708 		if ((pnd->pnd_flags & PND_BUSY) ||
2709 		       !TAILQ_EMPTY(&pnd->pnd_pcq))
2710 			DERRX(EX_SOFTWARE, "%s: opc = %p: ongoing operations",
2711 			      __func__, (void *)opc);
2712 #endif
2713 
2714 		/*
2715 		 * Send the FORGET message
2716 		 *
2717 		 * ps_new_msg() is called with NULL creds, which will
2718 		 * be interpreted as FUSE superuser. This is obviously
2719 		 * fine since we operate with kernel creds here.
2720 		 */
2721 		pm = ps->ps_new_msg(pu, (puffs_cookie_t)pn, FUSE_FORGET,
2722 			      sizeof(*ffi), NULL);
2723 		ffi = GET_INPAYLOAD(ps, pm, fuse_forget_in);
2724 		ffi->nlookup = pnd->pnd_nlookup;
2725 
2726 		/*
2727 		 * No reply is expected, pm is freed in xchg_msg
2728 		 */
2729 		(void)xchg_msg(pu, (puffs_cookie_t)pn,
2730 			       pm, UNSPEC_REPLY_LEN, no_reply);
2731 
2732 		parent_pn = pnd->pnd_parent;
2733 
2734 		perfuse_destroy_pn(pn);
2735 
2736 		pn = parent_pn;
2737 	}
2738 
2739 	return 0;
2740 }
2741 
2742 int
2743 perfuse_node_inactive(pu, opc)
2744 	struct puffs_usermount *pu;
2745 	puffs_cookie_t opc;
2746 {
2747 	struct perfuse_state *ps;
2748 	struct perfuse_node_data *pnd;
2749 
2750 	ps = puffs_getspecific(pu);
2751 	pnd = PERFUSE_NODE_DATA(opc);
2752 
2753 	if (!(pnd->pnd_flags & (PND_OPEN|PND_REMOVED)))
2754 		return 0;
2755 
2756 	/*
2757 	 * Make sure all operation are finished
2758 	 * There can be an ongoing write. Other
2759 	 * operation wait for all data before
2760 	 * the close/inactive.
2761 	 */
2762 	while (pnd->pnd_flags & PND_INWRITE)
2763 		requeue_request(pu, opc, PCQ_AFTERWRITE);
2764 
2765 	/*
2766 	 * The inactive operation may be cancelled.
2767 	 * If no open is in progress, set PND_INOPEN
2768 	 * so that a new open will be queued.
2769 	 */
2770 	if (pnd->pnd_flags & PND_INOPEN)
2771 		return 0;
2772 
2773 	pnd->pnd_flags |= PND_INOPEN;
2774 
2775 	/*
2776 	 * Sync data
2777 	 */
2778 	if (pnd->pnd_flags & PND_DIRTY)
2779 		(void)perfuse_node_fsync(pu, opc, NULL, 0, 0, 0);
2780 
2781 	/*
2782 	 * Close handles
2783 	 */
2784 	if (pnd->pnd_flags & PND_WFH)
2785 		(void)perfuse_node_close_common(pu, opc, FWRITE);
2786 
2787 	if (pnd->pnd_flags & PND_RFH)
2788 		(void)perfuse_node_close_common(pu, opc, FREAD);
2789 
2790 	/*
2791 	 * This will cause a reclaim to be sent
2792 	 */
2793 	if (pnd->pnd_flags & PND_REMOVED)
2794 		puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N1);
2795 
2796 	/*
2797 	 * Schedule awaiting operations
2798 	 */
2799 	pnd->pnd_flags &= ~PND_INOPEN;
2800 	(void)dequeue_requests(ps, opc, PCQ_OPEN, DEQUEUE_ALL);
2801 
2802 	return 0;
2803 }
2804 
2805 
2806 /* ARGSUSED0 */
2807 int
2808 perfuse_node_print(pu, opc)
2809 	struct puffs_usermount *pu;
2810 	puffs_cookie_t opc;
2811 {
2812 	DERRX(EX_SOFTWARE, "%s: UNIMPLEMENTED (FATAL)", __func__);
2813 	return 0;
2814 }
2815 
2816 /* ARGSUSED0 */
2817 int
2818 perfuse_node_pathconf(pu, opc, name, retval)
2819 	struct puffs_usermount *pu;
2820 	puffs_cookie_t opc;
2821 	int name;
2822 	int *retval;
2823 {
2824 	DERRX(EX_SOFTWARE, "%s: UNIMPLEMENTED (FATAL)", __func__);
2825 	return 0;
2826 }
2827 
2828 /* id is unused */
2829 /* ARGSUSED2 */
2830 int
2831 perfuse_node_advlock(pu, opc, id, op, fl, flags)
2832 	struct puffs_usermount *pu;
2833 	puffs_cookie_t opc;
2834 	void *id;
2835 	int op;
2836 	struct flock *fl;
2837 	int flags;
2838 {
2839 	struct perfuse_state *ps;
2840 	int fop;
2841 	perfuse_msg_t *pm;
2842 	struct fuse_lk_in *fli;
2843 	struct fuse_out_header *foh;
2844 	struct fuse_lk_out *flo;
2845 	uint32_t owner;
2846 	size_t len;
2847 	int error;
2848 
2849 	ps = puffs_getspecific(pu);
2850 
2851 	if (op == F_GETLK)
2852 		fop = FUSE_GETLK;
2853 	else
2854 		fop = (flags & F_WAIT) ? FUSE_SETLKW : FUSE_SETLK;
2855 
2856 	/*
2857 	 * XXX ps_new_msg() is called with NULL creds, which will
2858 	 * be interpreted as FUSE superuser. We have no way to
2859 	 * know the requesting process' credential, but since advlock()
2860 	 * is supposed to operate on a file that has been open(),
2861 	 * permission should have already been checked at open() time.
2862 	 */
2863 	pm = ps->ps_new_msg(pu, opc, fop, sizeof(*fli), NULL);
2864 	fli = GET_INPAYLOAD(ps, pm, fuse_lk_in);
2865 	fli->fh = perfuse_get_fh(opc, FWRITE);
2866 	fli->owner = fl->l_pid;
2867 	fli->lk.start = fl->l_start;
2868 	fli->lk.end = fl->l_start + fl->l_len;
2869 	fli->lk.type = fl->l_type;
2870 	fli->lk.pid = fl->l_pid;
2871 	fli->lk_flags = (flags & F_FLOCK) ? FUSE_LK_FLOCK : 0;
2872 
2873 	owner = fl->l_pid;
2874 
2875 #ifdef PERFUSE_DEBUG
2876 	if (perfuse_diagflags & PDF_FH)
2877 		DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", fh = 0x%"PRIx64"\n",
2878 			__func__, (void *)opc,
2879 			PERFUSE_NODE_DATA(opc)->pnd_nodeid, fli->fh);
2880 #endif
2881 
2882 	if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0)
2883 		goto out;
2884 
2885 	foh = GET_OUTHDR(ps, pm);
2886 	len = foh->len - sizeof(*foh);
2887 
2888 	/*
2889 	 * Save or clear the lock
2890 	 */
2891 	switch (op) {
2892 	case F_GETLK:
2893 		if (len != sizeof(*flo))
2894 			DERRX(EX_SOFTWARE,
2895 			      "%s: Unexpected lock reply len %zd",
2896 			      __func__, len);
2897 
2898 		flo = GET_OUTPAYLOAD(ps, pm, fuse_lk_out);
2899 		fl->l_start = flo->lk.start;
2900 		fl->l_len = flo->lk.end - flo->lk.start;
2901 		fl->l_pid = flo->lk.pid;
2902 		fl->l_type = flo->lk.type;
2903 		fl->l_whence = SEEK_SET;	/* libfuse hardcodes it */
2904 
2905 		PERFUSE_NODE_DATA(opc)->pnd_lock_owner = flo->lk.pid;
2906 		break;
2907 	case F_UNLCK:
2908 		owner = 0;
2909 		/* FALLTHROUGH */
2910 	case F_SETLK:
2911 		/* FALLTHROUGH */
2912 	case F_SETLKW:
2913 		if (error != 0)
2914 			PERFUSE_NODE_DATA(opc)->pnd_lock_owner = owner;
2915 
2916 		if (len != 0)
2917 			DERRX(EX_SOFTWARE,
2918 			      "%s: Unexpected unlock reply len %zd",
2919 			      __func__, len);
2920 
2921 		break;
2922 	default:
2923 		DERRX(EX_SOFTWARE, "%s: Unexpected op %d", __func__, op);
2924 		break;
2925 	}
2926 
2927 out:
2928 	ps->ps_destroy_msg(pm);
2929 
2930 	return error;
2931 }
2932 
2933 int
2934 perfuse_node_read(pu, opc, buf, offset, resid, pcr, ioflag)
2935 	struct puffs_usermount *pu;
2936 	puffs_cookie_t opc;
2937 	uint8_t *buf;
2938 	off_t offset;
2939 	size_t *resid;
2940 	const struct puffs_cred *pcr;
2941 	int ioflag;
2942 {
2943 	struct perfuse_state *ps;
2944 	struct perfuse_node_data *pnd;
2945 	const struct vattr *vap;
2946 	perfuse_msg_t *pm;
2947 	struct fuse_read_in *fri;
2948 	struct fuse_out_header *foh;
2949 	size_t readen;
2950 	int error;
2951 
2952 	ps = puffs_getspecific(pu);
2953 	pnd = PERFUSE_NODE_DATA(opc);
2954 	vap = puffs_pn_getvap((struct puffs_node *)opc);
2955 	pm = NULL;
2956 
2957 	/*
2958 	 * NetBSD turns that into a getdents(2) output
2959 	 * We just do a EISDIR as this feature is of little use.
2960 	 */
2961 	if (vap->va_type == VDIR)
2962 		return EISDIR;
2963 
2964 	if ((u_quad_t)offset + *resid > vap->va_size)
2965 		DWARNX("%s %p read %lld@%zu beyond EOF %" PRIu64 "\n",
2966 		       __func__, (void *)opc, (long long)offset,
2967 		       *resid, vap->va_size);
2968 
2969 	do {
2970 		size_t max_read;
2971 
2972 		max_read = ps->ps_max_readahead - sizeof(*foh);
2973 		/*
2974 		 * flags may be set to FUSE_READ_LOCKOWNER
2975 		 * if lock_owner is provided.
2976 		 */
2977 		pm = ps->ps_new_msg(pu, opc, FUSE_READ, sizeof(*fri), pcr);
2978 		fri = GET_INPAYLOAD(ps, pm, fuse_read_in);
2979 		fri->fh = perfuse_get_fh(opc, FREAD);
2980 		fri->offset = offset;
2981 		fri->size = (uint32_t)MIN(*resid, max_read);
2982 		fri->read_flags = 0; /* XXX Unused by libfuse? */
2983 		fri->lock_owner = pnd->pnd_lock_owner;
2984 		fri->flags = 0;
2985 		fri->flags |= (fri->lock_owner != 0) ? FUSE_READ_LOCKOWNER : 0;
2986 
2987 #ifdef PERFUSE_DEBUG
2988 	if (perfuse_diagflags & PDF_FH)
2989 		DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", fh = 0x%"PRIx64"\n",
2990 			__func__, (void *)opc, pnd->pnd_nodeid, fri->fh);
2991 #endif
2992 		error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply);
2993 
2994 		if (error  != 0)
2995 			goto out;
2996 
2997 		foh = GET_OUTHDR(ps, pm);
2998 		readen = foh->len - sizeof(*foh);
2999 
3000 #ifdef PERFUSE_DEBUG
3001 		if (readen > *resid)
3002 			DERRX(EX_SOFTWARE, "%s: Unexpected big read %zd",
3003 			      __func__, readen);
3004 #endif
3005 
3006 		(void)memcpy(buf,  _GET_OUTPAYLOAD(ps, pm, char *), readen);
3007 
3008 		buf += readen;
3009 		offset += readen;
3010 		*resid -= readen;
3011 
3012 		ps->ps_destroy_msg(pm);
3013 		pm = NULL;
3014 	} while ((*resid != 0) && (readen != 0));
3015 
3016 	if (ioflag & (IO_SYNC|IO_DSYNC))
3017 		ps->ps_syncreads++;
3018 	else
3019 		ps->ps_asyncreads++;
3020 
3021 out:
3022 	if (pm != NULL)
3023 		ps->ps_destroy_msg(pm);
3024 
3025 	return error;
3026 }
3027 
3028 int
3029 perfuse_node_write(pu, opc, buf, offset, resid, pcr, ioflag)
3030 	struct puffs_usermount *pu;
3031 	puffs_cookie_t opc;
3032 	uint8_t *buf;
3033 	off_t offset;
3034 	size_t *resid;
3035 	const struct puffs_cred *pcr;
3036 	int ioflag;
3037 {
3038 	struct perfuse_state *ps;
3039 	struct perfuse_node_data *pnd;
3040 	struct vattr *vap;
3041 	perfuse_msg_t *pm;
3042 	struct fuse_write_in *fwi;
3043 	struct fuse_write_out *fwo;
3044 	size_t data_len;
3045 	size_t payload_len;
3046 	size_t written;
3047 	int inresize;
3048 	int error;
3049 
3050 	ps = puffs_getspecific(pu);
3051 	pnd = PERFUSE_NODE_DATA(opc);
3052 	vap = puffs_pn_getvap((struct puffs_node *)opc);
3053 	written = 0;
3054 	inresize = 0;
3055 	pm = NULL;
3056 
3057 	if (vap->va_type == VDIR)
3058 		return EISDIR;
3059 
3060 	/*
3061 	 * We need to queue write requests in order to avoid
3062 	 * dequeueing PCQ_AFTERWRITE when there are pending writes.
3063 	 */
3064 	while (pnd->pnd_flags & PND_INWRITE)
3065 		requeue_request(pu, opc, PCQ_WRITE);
3066 	pnd->pnd_flags |= PND_INWRITE;
3067 
3068 	/*
3069 	 * Serialize size access, see comment in perfuse_node_setattr().
3070 	 */
3071 	if ((u_quad_t)offset + *resid > vap->va_size) {
3072 		while (pnd->pnd_flags & PND_INRESIZE)
3073 			requeue_request(pu, opc, PCQ_RESIZE);
3074 		pnd->pnd_flags |= PND_INRESIZE;
3075 		inresize = 1;
3076 	}
3077 
3078 	/*
3079 	 * append flag: re-read the file size so that
3080 	 * we get the latest value.
3081 	 */
3082 	if (ioflag & PUFFS_IO_APPEND) {
3083 		DWARNX("%s: PUFFS_IO_APPEND set, untested code", __func__);
3084 
3085 		if ((error = perfuse_node_getattr(pu, opc, vap, pcr)) != 0)
3086 			goto out;
3087 
3088 		offset = vap->va_size;
3089 	}
3090 
3091 	pm = NULL;
3092 
3093 #ifdef PERFUSE_DEBUG
3094 	if (perfuse_diagflags & PDF_RESIZE)
3095 		DPRINTF(">> %s %p %" PRIu64 "\n", __func__,
3096 			(void *)opc, vap->va_size);
3097 #endif
3098 
3099 	do {
3100 		size_t max_write;
3101 		/*
3102 		 * There is a writepage flag when data
3103 		 * is aligned to page size. Use it for
3104 		 * everything but the data after the last
3105 		 * page boundary.
3106 		 */
3107 		max_write = ps->ps_max_write - sizeof(*fwi);
3108 
3109 		data_len = MIN(*resid, max_write);
3110 		if (data_len > (size_t)sysconf(_SC_PAGESIZE))
3111 			data_len = data_len & ~(sysconf(_SC_PAGESIZE) - 1);
3112 
3113 		payload_len = data_len + sizeof(*fwi);
3114 
3115 		/*
3116 		 * flags may be set to FUSE_WRITE_CACHE (XXX usage?)
3117 		 * or FUSE_WRITE_LOCKOWNER, if lock_owner is provided.
3118 		 * write_flags is set to 1 for writepage.
3119 		 */
3120 		pm = ps->ps_new_msg(pu, opc, FUSE_WRITE, payload_len, pcr);
3121 		fwi = GET_INPAYLOAD(ps, pm, fuse_write_in);
3122 		fwi->fh = perfuse_get_fh(opc, FWRITE);
3123 		fwi->offset = offset;
3124 		fwi->size = (uint32_t)data_len;
3125 		fwi->write_flags = (fwi->size % sysconf(_SC_PAGESIZE)) ? 0 : 1;
3126 		fwi->lock_owner = pnd->pnd_lock_owner;
3127 		fwi->flags = 0;
3128 		fwi->flags |= (fwi->lock_owner != 0) ? FUSE_WRITE_LOCKOWNER : 0;
3129 		fwi->flags |= (ioflag & IO_DIRECT) ? 0 : FUSE_WRITE_CACHE;
3130 		(void)memcpy((fwi + 1), buf, data_len);
3131 
3132 
3133 #ifdef PERFUSE_DEBUG
3134 		if (perfuse_diagflags & PDF_FH)
3135 			DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", "
3136 				"fh = 0x%"PRIx64"\n", __func__,
3137 				(void *)opc, pnd->pnd_nodeid, fwi->fh);
3138 #endif
3139 		if ((error = xchg_msg(pu, opc, pm,
3140 				      sizeof(*fwo), wait_reply)) != 0)
3141 			goto out;
3142 
3143 		fwo = GET_OUTPAYLOAD(ps, pm, fuse_write_out);
3144 		written = fwo->size;
3145 #ifdef PERFUSE_DEBUG
3146 		if (written > *resid)
3147 			DERRX(EX_SOFTWARE, "%s: Unexpected big write %zd",
3148 			      __func__, written);
3149 #endif
3150 		*resid -= written;
3151 		offset += written;
3152 		buf += written;
3153 
3154 		ps->ps_destroy_msg(pm);
3155 		pm = NULL;
3156 	} while (*resid != 0);
3157 
3158 	/*
3159 	 * puffs_ops(3) says
3160 	 *  "everything must be written or an error will be generated"
3161 	 */
3162 	if (*resid != 0)
3163 		error = EFBIG;
3164 
3165 #ifdef PERFUSE_DEBUG
3166 	if (perfuse_diagflags & PDF_RESIZE) {
3167 		if (offset > (off_t)vap->va_size)
3168 			DPRINTF("<< %s %p %" PRIu64 " -> %lld\n", __func__,
3169 				(void *)opc, vap->va_size, (long long)offset);
3170 		else
3171 			DPRINTF("<< %s %p \n", __func__, (void *)opc);
3172 	}
3173 #endif
3174 
3175 	/*
3176 	 * Update file size if we wrote beyond the end
3177 	 */
3178 	if (offset > (off_t)vap->va_size)
3179 		vap->va_size = offset;
3180 
3181 	if (inresize) {
3182 #ifdef PERFUSE_DEBUG
3183 		if (!(pnd->pnd_flags & PND_INRESIZE))
3184 			DERRX(EX_SOFTWARE, "file write grow without resize");
3185 #endif
3186 		pnd->pnd_flags &= ~PND_INRESIZE;
3187 		(void)dequeue_requests(ps, opc, PCQ_RESIZE, DEQUEUE_ALL);
3188 	}
3189 
3190 
3191 	/*
3192 	 * Statistics
3193 	 */
3194 	if (ioflag & (IO_SYNC|IO_DSYNC))
3195 		ps->ps_syncwrites++;
3196 	else
3197 		ps->ps_asyncwrites++;
3198 
3199 	/*
3200 	 * Remember to sync the file
3201 	 */
3202 	pnd->pnd_flags |= PND_DIRTY;
3203 
3204 #ifdef PERFUSE_DEBUG
3205 	if (perfuse_diagflags & PDF_SYNC)
3206 		DPRINTF("%s: DIRTY opc = %p, file = \"%s\"\n",
3207 			__func__, (void*)opc, perfuse_node_path(opc));
3208 #endif
3209 out:
3210 	if (pm != NULL)
3211 		ps->ps_destroy_msg(pm);
3212 
3213 	/*
3214 	 * If there are no more queued write, we can resume
3215 	 * an operation awaiting write completion.
3216 	 */
3217 	pnd->pnd_flags &= ~PND_INWRITE;
3218 	if (dequeue_requests(ps, opc, PCQ_WRITE, 1) == 0)
3219 		(void)dequeue_requests(ps, opc, PCQ_AFTERWRITE, DEQUEUE_ALL);
3220 
3221 	return error;
3222 }
3223 
3224 /* ARGSUSED0 */
3225 void
3226 perfuse_cache_write(pu, opc, size, runs)
3227 	struct puffs_usermount *pu;
3228 	puffs_cookie_t opc;
3229 	size_t size;
3230 	struct puffs_cacherun *runs;
3231 {
3232 	return;
3233 }
3234 
3235 /* ARGSUSED4 */
3236 int
3237 perfuse_node_getextattr(pu, opc, attrns, attrname, attrsize, attr, resid, pcr)
3238 	struct puffs_usermount *pu;
3239 	puffs_cookie_t opc;
3240 	int attrns;
3241 	const char *attrname;
3242 	size_t *attrsize;
3243 	uint8_t *attr;
3244 	size_t *resid;
3245 	const struct puffs_cred *pcr;
3246 {
3247 	struct perfuse_state *ps;
3248 	char fuse_attrname[LINUX_XATTR_NAME_MAX + 1];
3249 	perfuse_msg_t *pm;
3250 	struct fuse_getxattr_in *fgi;
3251 	struct fuse_getxattr_out *fgo;
3252 	struct fuse_out_header *foh;
3253 	size_t attrnamelen;
3254 	size_t len;
3255 	char *np;
3256 	int error;
3257 
3258 	ps = puffs_getspecific(pu);
3259 	attrname = perfuse_native_ns(attrns, attrname, fuse_attrname);
3260 	attrnamelen = strlen(attrname) + 1;
3261 	len = sizeof(*fgi) + attrnamelen;
3262 
3263 	pm = ps->ps_new_msg(pu, opc, FUSE_GETXATTR, len, pcr);
3264 	fgi = GET_INPAYLOAD(ps, pm, fuse_getxattr_in);
3265 	fgi->size = (unsigned int)((resid != NULL) ? *resid : 0);
3266 	np = (char *)(void *)(fgi + 1);
3267 	(void)strlcpy(np, attrname, attrnamelen);
3268 
3269 	if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0)
3270 		goto out;
3271 
3272 	/*
3273 	 * We just get fuse_getattr_out with list size if we requested
3274 	 * a null size.
3275 	 */
3276 	if (resid == NULL) {
3277 		fgo = GET_OUTPAYLOAD(ps, pm, fuse_getxattr_out);
3278 
3279 		if (attrsize != NULL)
3280 			*attrsize = fgo->size;
3281 
3282 		goto out;
3283 	}
3284 
3285 	/*
3286 	 * And with a non null requested size, we get the list just
3287 	 * after the header
3288 	 */
3289 	foh = GET_OUTHDR(ps, pm);
3290 	np = (char *)(void *)(foh + 1);
3291 
3292 	if (resid != NULL) {
3293 		len = MAX(foh->len - sizeof(*foh), *resid);
3294 		(void)memcpy(attr, np, len);
3295 		*resid -= len;
3296 	}
3297 
3298 out:
3299 	ps->ps_destroy_msg(pm);
3300 
3301 	return error;
3302 }
3303 
3304 int
3305 perfuse_node_setextattr(pu, opc, attrns, attrname, attr, resid, pcr)
3306 	struct puffs_usermount *pu;
3307 	puffs_cookie_t opc;
3308 	int attrns;
3309 	const char *attrname;
3310 	uint8_t *attr;
3311 	size_t *resid;
3312 	const struct puffs_cred *pcr;
3313 {
3314 	struct perfuse_state *ps;
3315 	char fuse_attrname[LINUX_XATTR_NAME_MAX + 1];
3316 	perfuse_msg_t *pm;
3317 	struct fuse_setxattr_in *fsi;
3318 	size_t attrnamelen;
3319 	size_t len;
3320 	char *np;
3321 	int error;
3322 
3323 	ps = puffs_getspecific(pu);
3324 	attrname = perfuse_native_ns(attrns, attrname, fuse_attrname);
3325 	attrnamelen = strlen(attrname) + 1;
3326 	len = sizeof(*fsi) + attrnamelen + *resid;
3327 
3328 	pm = ps->ps_new_msg(pu, opc, FUSE_SETXATTR, len, pcr);
3329 	fsi = GET_INPAYLOAD(ps, pm, fuse_setxattr_in);
3330 	fsi->size = (unsigned int)*resid;
3331 	fsi->flags = 0;
3332 	np = (char *)(void *)(fsi + 1);
3333 	(void)strlcpy(np, attrname, attrnamelen);
3334 	np += attrnamelen;
3335 	(void)memcpy(np, (char *)attr, *resid);
3336 
3337 	if ((error = xchg_msg(pu, opc, pm,
3338 			      NO_PAYLOAD_REPLY_LEN, wait_reply)) != 0)
3339 		goto out;
3340 
3341 	*resid = 0;
3342 out:
3343 	ps->ps_destroy_msg(pm);
3344 
3345 	return error;
3346 }
3347 
3348 /* ARGSUSED2 */
3349 int
3350 perfuse_node_listextattr(pu, opc, attrns, attrsize, attrs, resid, flag, pcr)
3351 	struct puffs_usermount *pu;
3352 	puffs_cookie_t opc;
3353 	int attrns;
3354 	size_t *attrsize;
3355 	uint8_t *attrs;
3356 	size_t *resid;
3357 	int flag;
3358 	const struct puffs_cred *pcr;
3359 {
3360 	struct perfuse_state *ps;
3361 	perfuse_msg_t *pm;
3362 	struct fuse_getxattr_in *fgi;
3363 	struct fuse_getxattr_out *fgo;
3364 	struct fuse_out_header *foh;
3365 	char *np;
3366 	size_t len, puffs_len;
3367 	int error;
3368 
3369 	ps = puffs_getspecific(pu);
3370 	len = sizeof(*fgi);
3371 
3372 	pm = ps->ps_new_msg(pu, opc, FUSE_LISTXATTR, len, pcr);
3373 	fgi = GET_INPAYLOAD(ps, pm, fuse_getxattr_in);
3374 	if (resid != NULL)
3375 		fgi->size = (unsigned int)*resid;
3376 	else
3377 		fgi->size = 0;
3378 
3379 	if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0)
3380 		goto out;
3381 
3382 	/*
3383 	 * We just get fuse_getattr_out with list size if we requested
3384 	 * a null size.
3385 	 */
3386 	if (resid == NULL) {
3387 		fgo = GET_OUTPAYLOAD(ps, pm, fuse_getxattr_out);
3388 
3389 		if (attrsize != NULL)
3390 			*attrsize = fgo->size;
3391 
3392 		goto out;
3393 	}
3394 
3395 	/*
3396 	 * And with a non null requested size, we get the list just
3397 	 * after the header
3398 	 */
3399 	foh = GET_OUTHDR(ps, pm);
3400 	np = (char *)(void *)(foh + 1);
3401 	puffs_len = foh->len - sizeof(*foh);
3402 
3403 	if (attrs != NULL) {
3404 #ifdef PUFFS_EXTATTR_LIST_LENPREFIX
3405 		/*
3406 		 * Convert the FUSE reply to length prefixed strings
3407 		 * if this is what the kernel wants.
3408 		 */
3409 		if (flag & PUFFS_EXTATTR_LIST_LENPREFIX) {
3410 			size_t i, attrlen;
3411 
3412 			for (i = 0; i < puffs_len; i += attrlen + 1) {
3413 				attrlen = strlen(np + i);
3414 				(void)memmove(np + i + 1, np + i, attrlen);
3415 				*(np + i) = (uint8_t)attrlen;
3416 			}
3417 		}
3418 #endif /* PUFFS_EXTATTR_LIST_LENPREFIX */
3419 		(void)memcpy(attrs, np, puffs_len);
3420 		*resid -= puffs_len;
3421 	}
3422 
3423 	if (attrsize != NULL)
3424 		*attrsize = puffs_len;
3425 
3426 out:
3427 	ps->ps_destroy_msg(pm);
3428 
3429 	return error;
3430 }
3431 
3432 int
3433 perfuse_node_deleteextattr(pu, opc, attrns, attrname, pcr)
3434 	struct puffs_usermount *pu;
3435 	puffs_cookie_t opc;
3436 	int attrns;
3437 	const char *attrname;
3438 	const struct puffs_cred *pcr;
3439 {
3440 	struct perfuse_state *ps;
3441 	char fuse_attrname[LINUX_XATTR_NAME_MAX + 1];
3442 	perfuse_msg_t *pm;
3443 	size_t attrnamelen;
3444 	char *np;
3445 	int error;
3446 
3447 	ps = puffs_getspecific(pu);
3448 	attrname = perfuse_native_ns(attrns, attrname, fuse_attrname);
3449 	attrnamelen = strlen(attrname) + 1;
3450 
3451 	pm = ps->ps_new_msg(pu, opc, FUSE_REMOVEXATTR, attrnamelen, pcr);
3452 	np = _GET_INPAYLOAD(ps, pm, char *);
3453 	(void)strlcpy(np, attrname, attrnamelen);
3454 
3455 	error = xchg_msg(pu, opc, pm, NO_PAYLOAD_REPLY_LEN, wait_reply);
3456 
3457 	ps->ps_destroy_msg(pm);
3458 
3459 	return error;
3460 }
3461