2 * Copyright (c) 2019 Tomohiro Kusumi <tkusumi@netbsd.org>
3 * Copyright (c) 2019 The DragonFly Project
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/fcntl.h>
31 #include <sys/dirent.h>
32 #include <sys/namei.h>
34 #include <sys/mountctl.h>
35 #include <vm/vm_pager.h>
36 #include <vm/vnode_pager.h>
39 fuse_set_attr(struct fuse_node *fnp, struct fuse_attr *fat)
41 struct vattr *vap = &fnp->attr;
46 vap->va_type = IFTOVT(fat->mode);
47 vap->va_size = fat->size;
48 vap->va_bytes = fat->blocks * S_BLKSIZE;
49 vap->va_mode = fat->mode & ~S_IFMT;
50 if (!fat->nlink) /* XXX .fuse_hidden* has 0 link */
53 vap->va_nlink = fat->nlink;
54 vap->va_uid = fat->uid;
55 vap->va_gid = fat->gid;
56 vap->va_fsid = fnp->fmp->mp->mnt_stat.f_fsid.val[0];
57 vap->va_fileid = fat->ino;
58 vap->va_blocksize = FUSE_BLKSIZE;
59 vap->va_rmajor = VNOVAL;
60 vap->va_rminor = VNOVAL;
61 vap->va_atime.tv_sec = fat->atime;
62 vap->va_atime.tv_nsec = fat->atimensec;
63 vap->va_mtime.tv_sec = fat->mtime;
64 vap->va_mtime.tv_nsec = fat->mtimensec;
65 vap->va_ctime.tv_sec = fat->ctime;
66 vap->va_ctime.tv_nsec = fat->ctimensec;
71 KKASSERT(vap->va_type == fnp->type);
73 if (fnp->nlink != vap->va_nlink) {
74 fuse_dbg("ino=%ju update nlink %d -> %ju\n",
75 fnp->ino, fnp->nlink, vap->va_nlink);
76 fnp->nlink = vap->va_nlink;
79 if (fnp->vp->v_object && fnp->size != vap->va_size)
80 error = fuse_node_truncate(fnp, fnp->size, vap->va_size);
86 fuse_vop_access(struct vop_access_args *ap)
88 struct vnode *vp = ap->a_vp;
89 mode_t mode = ap->a_mode;
90 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
92 struct fuse_access_in *fai;
96 if (fuse_test_dead(fmp))
99 if (fuse_test_nosys(fmp, FUSE_ACCESS))
102 switch (vp->v_type) {
106 if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY))
126 fip = fuse_ipc_get(fmp, sizeof(*fai));
127 fai = fuse_ipc_fill(fip, FUSE_ACCESS, VTOI(vp)->ino, ap->a_cred);
130 error = fuse_ipc_tx(fip);
134 if (error == ENOTCONN && (vp->v_flag & VROOT))
145 fuse_vop_open(struct vop_open_args *ap)
147 struct vnode *vp = ap->a_vp;
148 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
149 struct fuse_node *fnp = VTOI(vp);
150 struct fuse_ipc *fip;
151 struct fuse_open_in *foi;
152 struct fuse_open_out *foo;
155 if (fuse_test_dead(fmp))
158 if (fuse_test_nosys(fmp, FUSE_OPEN))
161 if (vp->v_type == VDIR)
166 fip = fuse_ipc_get(fmp, sizeof(*foi));
167 foi = fuse_ipc_fill(fip, op, fnp->ino, ap->a_cred);
168 foi->flags = OFLAGS(ap->a_mode);
169 fuse_dbg("flags=%X\n", foi->flags);
170 if (foi->flags & O_CREAT) {
171 fuse_dbg("drop O_CREAT\n");
172 foi->flags &= ~O_CREAT;
175 error = fuse_ipc_tx(fip);
180 foo = fuse_out_data(fip);
181 if (foo->open_flags & FOPEN_DIRECT_IO)
183 else if (foo->open_flags & FOPEN_KEEP_CACHE)
185 else if (foo->open_flags & FOPEN_NONSEEKABLE)
187 else if (foo->open_flags & FOPEN_CACHE_DIR)
191 fuse_get_nfh(VTOI(vp), foo->fh);
194 fuse_get_fh(ap->a_fp, foo->fh);
196 /* see #if0'd code in fuse_vop_setattr() */
197 if (!ap->a_fp->private_data)
198 fuse_get_fh(ap->a_fp, foo->fh);
200 uint64_t *fhp = ap->a_fp->private_data;
208 return vop_stdopen(ap);
212 fuse_vop_close(struct vop_close_args *ap)
214 struct vnode *vp = ap->a_vp;
215 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
216 struct fuse_node *fnp = VTOI(vp);
217 struct fuse_ipc *fip;
218 struct fuse_release_in *fri;
221 if (fuse_test_dead(fmp))
224 if (fuse_test_nosys(fmp, FUSE_RELEASE) ||
225 fuse_test_nosys(fmp, FUSE_RELEASEDIR))
228 if (vp->v_type == VDIR)
229 op = FUSE_RELEASEDIR;
233 fip = fuse_ipc_get(fmp, sizeof(*fri));
234 fri = fuse_ipc_fill(fip, op, fnp->ino, NULL);
237 //fri->release_flags = ...;
238 //fri->lock_owner = ...;
239 fri->fh = fuse_nfh(VTOI(vp));
241 fri->fh = fuse_fh(ap->a_fp);
243 error = fuse_ipc_tx(fip);
250 fuse_put_nfh(VTOI(vp));
252 fuse_put_fh(ap->a_fp);
254 return vop_stdclose(ap);
258 fuse_vop_fsync(struct vop_fsync_args *ap)
260 struct vnode *vp = ap->a_vp;
261 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
262 struct fuse_ipc *fip;
263 struct fuse_fsync_in *fsi;
266 if (fuse_test_dead(fmp))
269 if (fuse_test_nosys(fmp, FUSE_FSYNC))
272 if (vp->v_type == VDIR)
277 fip = fuse_ipc_get(fmp, sizeof(*fsi));
278 fsi = fuse_ipc_fill(fip, op, VTOI(vp)->ino, NULL);
279 fsi->fh = fuse_nfh(VTOI(vp));
281 fsi->fh = fuse_fh(ap->a_fp);
282 fsi->fsync_flags = 1; /* datasync */
284 error = fuse_ipc_tx(fip);
289 vn_syncer_remove(vp, 1);
290 vfsync(ap->a_vp, ap->a_waitfor, 1, NULL, NULL);
297 fuse_vop_getattr(struct vop_getattr_args *ap)
299 struct vnode *vp = ap->a_vp;
300 struct vattr *vap = ap->a_vap;
301 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
302 struct fuse_node *fnp = VTOI(vp);
303 struct fuse_ipc *fip;
304 struct fuse_getattr_in *fgi;
305 struct fuse_attr_out *fao;
308 if (fuse_test_dead(fmp))
311 if (fuse_test_nosys(fmp, FUSE_GETATTR))
314 fip = fuse_ipc_get(fmp, sizeof(*fgi));
315 fgi = fuse_ipc_fill(fip, FUSE_GETATTR, fnp->ino, NULL);
317 /* this may be called before open when fh is 0 */
318 fgi->getattr_flags |= FUSE_GETATTR_FH;
319 fgi->fh = fuse_nfh(fnp);
321 fgi->fh = fuse_fh(ap->a_fp);
323 error = fuse_ipc_tx(fip);
327 if (error == ENOTCONN && (vp->v_flag & VROOT)) {
328 memset(vap, 0, sizeof(*vap));
329 vap->va_type = vp->v_type;
335 fao = fuse_out_data(fip);
336 mtx_lock(&fnp->node_lock);
337 fuse_set_attr(fnp, &fao->attr);
338 memcpy(vap, &fnp->attr, sizeof(*vap));
341 //fao->attr_valid_nsec;
342 mtx_unlock(&fnp->node_lock);
346 if (vap->va_type != vp->v_type)
353 fuse_vop_setattr(struct vop_setattr_args *ap)
355 struct vnode *vp = ap->a_vp;
356 struct vattr *vap = ap->a_vap;
357 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
358 struct fuse_node *fnp = VTOI(vp);
359 struct fuse_ipc *fip;
360 struct fuse_setattr_in *fsi, arg;
361 struct fuse_attr_out *fao;
365 if (fuse_test_dead(fmp))
368 if (fuse_test_nosys(fmp, FUSE_SETATTR))
371 if (vp->v_mount->mnt_flag & MNT_RDONLY)
374 memset(&arg, 0, sizeof(arg));
375 mtx_lock(&fnp->node_lock);
377 if (!error && (vap->va_flags != VNOVAL)) {
378 mtx_unlock(&fnp->node_lock);
379 kflags |= NOTE_ATTRIB;
380 return EOPNOTSUPP; /* XXX */
383 if (!error && (vap->va_size != VNOVAL)) {
384 if (vp->v_type == VDIR) {
385 mtx_unlock(&fnp->node_lock);
388 if (vp->v_type == VREG &&
389 (vp->v_mount->mnt_flag & MNT_RDONLY)) {
390 mtx_unlock(&fnp->node_lock);
393 arg.size = vap->va_size;
394 arg.valid |= FATTR_SIZE;
395 if (vap->va_size > fnp->size)
396 kflags |= NOTE_WRITE | NOTE_EXTEND;
398 kflags |= NOTE_WRITE;
401 if (!error && (vap->va_uid != (uid_t)VNOVAL ||
402 vap->va_gid != (gid_t)VNOVAL)) {
404 error = vop_helper_chown(vp, vap->va_uid, vap->va_gid,
405 ap->a_cred, &arg.uid, &arg.gid, &mode);
406 arg.valid |= FATTR_UID;
407 arg.valid |= FATTR_GID;
408 kflags |= NOTE_ATTRIB;
411 if (!error && (vap->va_mode != (mode_t)VNOVAL)) {
412 error = vop_helper_chmod(vp, vap->va_mode, ap->a_cred,
413 vap->va_uid, vap->va_gid, (mode_t*)&arg.mode);
414 arg.valid |= FATTR_MODE;
415 kflags |= NOTE_ATTRIB;
418 if (!error && (vap->va_atime.tv_sec != VNOVAL &&
419 vap->va_atime.tv_nsec != VNOVAL)) {
420 arg.atime = vap->va_atime.tv_sec;
421 arg.atimensec = vap->va_atime.tv_nsec;
422 arg.valid |= FATTR_ATIME;
423 kflags |= NOTE_ATTRIB;
426 if (!error && (vap->va_mtime.tv_sec != VNOVAL &&
427 vap->va_mtime.tv_nsec != VNOVAL)) {
428 arg.mtime = vap->va_mtime.tv_sec;
429 arg.mtimensec = vap->va_mtime.tv_nsec;
430 arg.valid |= FATTR_MTIME;
431 kflags |= NOTE_ATTRIB;
434 if (!error && (vap->va_ctime.tv_sec != VNOVAL &&
435 vap->va_ctime.tv_nsec != VNOVAL)) {
436 arg.ctime = vap->va_ctime.tv_sec;
437 arg.ctimensec = vap->va_ctime.tv_nsec;
438 arg.valid |= FATTR_CTIME;
439 kflags |= NOTE_ATTRIB;
442 mtx_unlock(&fnp->node_lock);
449 fip = fuse_ipc_get(fmp, sizeof(*fsi));
450 fsi = fuse_ipc_fill(fip, FUSE_SETATTR, fnp->ino, ap->a_cred);
451 memcpy(fsi, &arg, sizeof(arg));
453 fsi->valid |= FATTR_FH;
454 fsi->fh = fuse_nfh(fnp);
456 /* vn_open() may call VOP_SETATTR_FP() prior to VOP_OPEN(). */
457 if (!ap->a_fp->private_data)
458 fuse_get_fh(ap->a_fp, 0); /* XXX */
459 fsi->fh = fuse_fh(ap->a_fp);
462 error = fuse_ipc_tx(fip);
466 fao = fuse_out_data(fip);
467 if (IFTOVT(fao->attr.mode) != vp->v_type) {
471 mtx_lock(&fnp->node_lock);
472 fuse_set_attr(fnp, &fao->attr);
475 //fao->attr_valid_nsec;
476 mtx_unlock(&fnp->node_lock);
479 fuse_knote(vp, kflags);
485 fuse_vop_nresolve(struct vop_nresolve_args *ap)
487 struct vnode *dvp = ap->a_dvp;
489 struct namecache *ncp = ap->a_nch->ncp;
490 struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount);
491 struct fuse_node *dfnp = VTOI(dvp);
492 struct fuse_ipc *fip;
493 struct fuse_entry_out *feo;
499 if (fuse_test_dead(fmp))
502 if (fuse_test_nosys(fmp, FUSE_LOOKUP))
505 fip = fuse_ipc_get(fmp, ncp->nc_nlen + 1);
506 p = fuse_ipc_fill(fip, FUSE_LOOKUP, dfnp->ino, ap->a_cred);
508 memcpy(p, ncp->nc_name, ncp->nc_nlen);
509 p[ncp->nc_nlen] = '\0';
510 strlcpy(tmp, p, sizeof(tmp));
512 error = fuse_ipc_tx(fip);
513 if (error == ENOENT) {
514 cache_setvp(ap->a_nch, NULL);
515 fuse_dbg("lookup \"%s\" ENOENT\n", tmp);
518 fuse_dbg("lookup \"%s\" error=%d\n", tmp, error);
522 feo = fuse_out_data(fip);
523 fuse_dbg("lookup \"%s\" ino=%ju/%ju\n", p, feo->nodeid, feo->attr.ino);
525 mode = feo->attr.mode;
528 else if (S_ISDIR(mode))
530 else if (S_ISBLK(mode))
532 else if (S_ISCHR(mode))
534 else if (S_ISLNK(mode))
536 else if (S_ISSOCK(mode))
538 else if (S_ISFIFO(mode))
543 error = fuse_alloc_node(dfnp, feo->nodeid, p, strlen(p), vtyp, &vp);
549 KKASSERT(vn_islocked(vp));
552 cache_setvp(ap->a_nch, vp);
559 //feo->entry_valid_nsec;
560 //feo->attr_valid_nsec;
568 fuse_vop_nlink(struct vop_nlink_args *ap)
570 struct vnode *dvp = ap->a_dvp;
571 struct vnode *vp = ap->a_vp;
572 struct namecache *ncp = ap->a_nch->ncp;
573 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
574 struct fuse_node *dfnp = VTOI(dvp);
575 struct fuse_node *fnp = VTOI(vp);
576 struct fuse_dent *fep;
577 struct fuse_ipc *fip;
578 struct fuse_link_in *fli;
579 struct fuse_entry_out *feo;
583 if (fuse_test_dead(fmp))
586 if (fuse_test_nosys(fmp, FUSE_LINK))
589 if (vp->v_type == VDIR)
591 if (dvp->v_mount != vp->v_mount)
593 if (fnp->nlink >= LINK_MAX)
596 fip = fuse_ipc_get(fmp, sizeof(fli) + ncp->nc_nlen + 1);
597 fli = fuse_ipc_fill(fip, FUSE_LINK, dfnp->ino, ap->a_cred);
598 fli->oldnodeid = fnp->ino;
600 p = (char*)(fli + 1);
601 memcpy(p, ncp->nc_name, ncp->nc_nlen);
602 p[ncp->nc_nlen] = '\0';
604 error = fuse_ipc_tx(fip);
608 feo = fuse_out_data(fip);
609 if (IFTOVT(feo->attr.mode) != vp->v_type) {
614 mtx_lock(&dfnp->node_lock);
615 mtx_lock(&fnp->node_lock);
616 fuse_dent_new(fnp, p, strlen(p), &fep);
617 fuse_dent_attach(dfnp, fep);
618 fuse_set_attr(fnp, &feo->attr);
619 mtx_unlock(&fnp->node_lock);
620 mtx_unlock(&dfnp->node_lock);
622 cache_setunresolved(ap->a_nch);
623 cache_setvp(ap->a_nch, vp);
624 fuse_knote(dvp, NOTE_WRITE);
625 fuse_knote(vp, NOTE_LINK);
632 //feo->entry_valid_nsec;
633 //feo->attr_valid_nsec;
641 fuse_vop_ncreate(struct vop_ncreate_args *ap)
643 struct vnode *dvp = ap->a_dvp;
645 struct namecache *ncp = ap->a_nch->ncp;
646 struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount);
647 struct fuse_node *dfnp = VTOI(dvp);
648 struct fuse_node *fnp;
649 struct fuse_ipc *fip;
650 struct fuse_create_in *fci;
651 struct fuse_entry_out *feo;
652 struct fuse_open_out *foo;
657 if (fuse_test_dead(fmp))
660 if (fuse_test_nosys(fmp, FUSE_CREATE))
663 fip = fuse_ipc_get(fmp, sizeof(*fci) + ncp->nc_nlen + 1);
664 fci = fuse_ipc_fill(fip, FUSE_CREATE, dfnp->ino, ap->a_cred);
665 fci->flags = OFLAGS(ap->a_vap->va_fuseflags);
666 fci->mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode);
669 fuse_dbg("flags=%X mode=%X\n", fci->flags, fci->mode);
671 p = (char*)(fci + 1);
672 memcpy(p, ncp->nc_name, ncp->nc_nlen);
673 p[ncp->nc_nlen] = '\0';
675 error = fuse_ipc_tx(fip);
679 feo = fuse_out_data(fip);
680 foo = (struct fuse_open_out*)(feo + 1);
681 vtyp = IFTOVT(feo->attr.mode);
682 if (vtyp != VREG && vtyp != VSOCK) {
687 error = fuse_alloc_node(dfnp, feo->nodeid, p, strlen(p), VREG, &vp);
693 KKASSERT(vn_islocked(vp));
696 mtx_lock(&fnp->node_lock);
697 fuse_set_attr(fnp, &feo->attr);
698 mtx_unlock(&fnp->node_lock);
700 cache_setunresolved(ap->a_nch);
701 cache_setvp(ap->a_nch, vp);
703 fuse_knote(dvp, NOTE_WRITE);
709 //feo->entry_valid_nsec;
710 //feo->attr_valid_nsec;
720 fuse_vop_nmknod(struct vop_nmknod_args *ap)
722 struct vnode *dvp = ap->a_dvp;
724 struct namecache *ncp = ap->a_nch->ncp;
725 struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount);
726 struct fuse_node *dfnp = VTOI(dvp);
727 struct fuse_node *fnp;
728 struct fuse_ipc *fip;
729 struct fuse_mknod_in *fmi;
730 struct fuse_entry_out *feo;
735 if (fuse_test_dead(fmp))
738 if (fuse_test_nosys(fmp, FUSE_MKNOD))
741 fip = fuse_ipc_get(fmp, sizeof(*fmi) + ncp->nc_nlen + 1);
742 fmi = fuse_ipc_fill(fip, FUSE_MKNOD, dfnp->ino, ap->a_cred);
743 fmi->mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode);
748 p = (char*)(fmi + 1);
749 memcpy(p, ncp->nc_name, ncp->nc_nlen);
750 p[ncp->nc_nlen] = '\0';
752 error = fuse_ipc_tx(fip);
756 feo = fuse_out_data(fip);
757 vtyp = IFTOVT(feo->attr.mode);
758 if (vtyp != VBLK && vtyp != VCHR && vtyp != VFIFO) {
763 error = fuse_alloc_node(dfnp, feo->nodeid, p, strlen(p),
764 ap->a_vap->va_type, &vp);
770 KKASSERT(vn_islocked(vp));
773 mtx_lock(&fnp->node_lock);
774 fuse_set_attr(fnp, &feo->attr);
775 mtx_unlock(&fnp->node_lock);
777 cache_setunresolved(ap->a_nch);
778 cache_setvp(ap->a_nch, vp);
780 fuse_knote(dvp, NOTE_WRITE);
786 //feo->entry_valid_nsec;
787 //feo->attr_valid_nsec;
795 fuse_vop_nremove(struct vop_nremove_args *ap)
797 struct vnode *dvp = ap->a_dvp;
799 struct namecache *ncp = ap->a_nch->ncp;
800 struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount);
801 struct fuse_node *dfnp = VTOI(dvp);
802 struct fuse_node *fnp;
803 struct fuse_dent *fep;
804 struct fuse_ipc *fip;
808 if (fuse_test_dead(fmp))
811 if (fuse_test_nosys(fmp, FUSE_UNLINK))
814 error = cache_vget(ap->a_nch, ap->a_cred, LK_SHARED, &vp);
815 KKASSERT(vp->v_mount == dvp->v_mount);
816 KKASSERT(!error); /* from tmpfs */
819 fip = fuse_ipc_get(fmp, ncp->nc_nlen + 1);
820 p = fuse_ipc_fill(fip, FUSE_UNLINK, dfnp->ino, ap->a_cred);
822 memcpy(p, ncp->nc_name, ncp->nc_nlen);
823 p[ncp->nc_nlen] = '\0';
825 error = fuse_ipc_tx(fip);
832 mtx_lock(&dfnp->node_lock);
833 mtx_lock(&fnp->node_lock);
834 error = fuse_dent_find(dfnp, p, strlen(p), &fep);
835 if (error == ENOENT) {
836 mtx_unlock(&fnp->node_lock);
837 mtx_unlock(&dfnp->node_lock);
842 fuse_dent_detach(dfnp, fep);
844 mtx_unlock(&fnp->node_lock);
845 mtx_unlock(&dfnp->node_lock);
847 cache_unlink(ap->a_nch);
848 fuse_knote(dvp, NOTE_WRITE);
849 fuse_knote(vp, NOTE_DELETE);
858 fuse_vop_nmkdir(struct vop_nmkdir_args *ap)
860 struct vnode *dvp = ap->a_dvp;
862 struct namecache *ncp = ap->a_nch->ncp;
863 struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount);
864 struct fuse_node *dfnp = VTOI(dvp);
865 struct fuse_node *fnp;
866 struct fuse_ipc *fip;
867 struct fuse_mkdir_in *fmi;
868 struct fuse_entry_out *feo;
872 if (fuse_test_dead(fmp))
875 if (fuse_test_nosys(fmp, FUSE_MKDIR))
878 fip = fuse_ipc_get(fmp, sizeof(*fmi) + ncp->nc_nlen + 1);
879 fmi = fuse_ipc_fill(fip, FUSE_MKDIR, dfnp->ino, ap->a_cred);
880 fmi->mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode);
882 p = (char*)(fmi + 1);
883 memcpy(p, ncp->nc_name, ncp->nc_nlen);
884 p[ncp->nc_nlen] = '\0';
886 error = fuse_ipc_tx(fip);
890 feo = fuse_out_data(fip);
891 if (IFTOVT(feo->attr.mode) != VDIR) {
896 error = fuse_alloc_node(dfnp, feo->nodeid, p, strlen(p), VDIR, &vp);
902 KKASSERT(vn_islocked(vp));
905 mtx_lock(&fnp->node_lock);
906 fuse_set_attr(fnp, &feo->attr);
907 mtx_unlock(&fnp->node_lock);
909 cache_setunresolved(ap->a_nch);
910 cache_setvp(ap->a_nch, vp);
912 fuse_knote(dvp, NOTE_WRITE | NOTE_LINK);
918 //feo->entry_valid_nsec;
919 //feo->attr_valid_nsec;
927 fuse_vop_nrmdir(struct vop_nrmdir_args *ap)
929 struct vnode *dvp = ap->a_dvp;
931 struct namecache *ncp = ap->a_nch->ncp;
932 struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount);
933 struct fuse_node *dfnp = VTOI(dvp);
934 struct fuse_node *fnp;
935 struct fuse_dent *fep;
936 struct fuse_ipc *fip;
940 if (fuse_test_dead(fmp))
943 if (fuse_test_nosys(fmp, FUSE_RMDIR))
946 error = cache_vget(ap->a_nch, ap->a_cred, LK_SHARED, &vp);
947 KKASSERT(vp->v_mount == dvp->v_mount);
948 KKASSERT(!error); /* from tmpfs */
951 fip = fuse_ipc_get(fmp, ncp->nc_nlen + 1);
952 p = fuse_ipc_fill(fip, FUSE_RMDIR, dfnp->ino, ap->a_cred);
954 memcpy(p, ncp->nc_name, ncp->nc_nlen);
955 p[ncp->nc_nlen] = '\0';
957 error = fuse_ipc_tx(fip);
964 mtx_lock(&dfnp->node_lock);
965 mtx_lock(&fnp->node_lock);
966 error = fuse_dent_find(dfnp, p, strlen(p), &fep);
967 if (error == ENOENT) {
968 mtx_unlock(&fnp->node_lock);
969 mtx_unlock(&dfnp->node_lock);
974 fuse_dent_detach(dfnp, fep);
976 mtx_unlock(&fnp->node_lock);
977 mtx_unlock(&dfnp->node_lock);
979 cache_unlink(ap->a_nch);
980 fuse_knote(dvp, NOTE_WRITE | NOTE_LINK);
989 fuse_vop_pathconf(struct vop_pathconf_args *ap)
991 switch (ap->a_name) {
992 case _PC_FILESIZEBITS:
999 return vop_stdpathconf(ap);
1006 fuse_vop_readdir(struct vop_readdir_args *ap)
1008 struct vnode *vp = ap->a_vp;
1009 struct uio *uio = ap->a_uio;
1010 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
1011 struct fuse_ipc *fip;
1012 struct fuse_read_in *fri;
1015 off_t cur_offset = 0;
1018 if (fuse_test_dead(fmp))
1021 if (fuse_test_nosys(fmp, FUSE_READDIR))
1024 fip = fuse_ipc_get(fmp, sizeof(*fri));
1025 fri = fuse_ipc_fill(fip, FUSE_READDIR, VTOI(vp)->ino, ap->a_cred);
1026 fri->fh = fuse_nfh(VTOI(vp));
1028 fri->fh = fuse_fh(ap->a_fp);
1031 * XXX This needs to be large enough to read all entries at once.
1032 * FUSE filesystems typically just opendir/readdir and return entries.
1034 fri->size = FUSE_BLKSIZE * 10;
1036 //fri->read_flags = ...;
1037 //fri->lock_owner = ...;
1040 error = fuse_ipc_tx(fip);
1044 buf = fuse_out_data(fip);
1045 len = fuse_out_data_size(fip);
1048 const struct fuse_dirent *fde;
1051 fuse_dbg("uio_offset=%ju uio_resid=%ju\n",
1052 uio->uio_offset, uio->uio_resid);
1054 if (len < FUSE_NAME_OFFSET) {
1059 if (uio->uio_resid < FUSE_NAME_OFFSET)
1062 fde = (const struct fuse_dirent*)buf;
1063 if (!fde->namelen) {
1067 freclen = FUSE_DIRENT_SIZE(fde);
1071 * getdirentries(2) in sys/kern/vfs_syscalls.c
1072 * readdir(3) in lib/libc/gen/readdir.c
1074 if (cur_offset >= uio->uio_offset) {
1076 if (vop_write_dirent(&error, uio, fde->ino, fde->type,
1077 fde->namelen, fde->name))
1081 fuse_dbg("ino=%ju type=%d name=%s len=%u\n",
1082 fde->ino, fde->type, fde->name, fde->namelen);
1085 cur_offset += _DIRENT_RECLEN(fde->namelen);
1095 fuse_vop_readlink(struct vop_readlink_args *ap)
1097 struct vnode *vp = ap->a_vp;
1098 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
1099 struct fuse_ipc *fip;
1102 if (fuse_test_dead(fmp))
1105 if (fuse_test_nosys(fmp, FUSE_READLINK))
1108 if (vp->v_type != VLNK)
1111 fip = fuse_ipc_get(fmp, 0);
1112 fuse_ipc_fill(fip, FUSE_READLINK, VTOI(vp)->ino, ap->a_cred);
1114 error = fuse_ipc_tx(fip);
1118 error = uiomove(fuse_out_data(fip), fuse_out_data_size(fip), ap->a_uio);
1126 fuse_vop_nrename(struct vop_nrename_args *ap)
1128 struct namecache *fncp = ap->a_fnch->ncp;
1129 struct namecache *tncp = ap->a_tnch->ncp;
1130 struct vnode *fdvp = ap->a_fdvp;
1131 struct vnode *fvp = fncp->nc_vp;
1132 struct vnode *tdvp = ap->a_tdvp;
1134 struct fuse_mount *fmp = VFSTOFUSE(fdvp->v_mount);
1135 struct fuse_node *fdfnp = VTOI(fdvp);
1136 struct fuse_node *ffnp = VTOI(fvp);
1137 struct fuse_node *tdfnp = VTOI(tdvp);
1138 struct fuse_node *tfnp;
1139 struct fuse_dent *ffep;
1140 struct fuse_dent *tfep;
1141 struct fuse_ipc *fip;
1142 struct fuse_rename_in *fri;
1143 char *p, *newname, *oldname;
1146 KKASSERT(fdvp->v_mount == fvp->v_mount);
1148 if (fuse_test_dead(fmp))
1151 if (fuse_test_nosys(fmp, FUSE_RENAME))
1154 error = cache_vget(ap->a_tnch, ap->a_cred, LK_SHARED, &tvp);
1161 /* Disallow cross-device renames.
1162 * Why isn't this done by the caller? */
1163 if (fvp->v_mount != tdvp->v_mount ||
1164 (tvp && fvp->v_mount != tvp->v_mount)) {
1173 error = fuse_dent_find(fdfnp, fncp->nc_name, fncp->nc_nlen, &ffep);
1174 if (error == ENOENT)
1176 KKASSERT(ffep->fnp == ffnp);
1180 if (ffnp->type == VDIR && tfnp->type == VDIR) {
1181 if (!RB_EMPTY(&tfnp->dent_head)) {
1185 } else if (ffnp->type == VDIR && tfnp->type != VDIR) {
1188 } else if (ffnp->type != VDIR && tfnp->type == VDIR) {
1192 KKASSERT(ffnp->type != VDIR && tfnp->type != VDIR);
1195 fip = fuse_ipc_get(fmp,
1196 sizeof(*fri) + fncp->nc_nlen + tncp->nc_nlen + 2);
1197 /* There is also fuse_rename2_in with flags. */
1198 fri = fuse_ipc_fill(fip, FUSE_RENAME, fdfnp->ino, ap->a_cred);
1199 fri->newdir = tdfnp->ino;
1201 p = (char*)(fri + 1);
1202 memcpy(p, fncp->nc_name, fncp->nc_nlen);
1203 p[fncp->nc_nlen] = '\0';
1204 memcpy(p + fncp->nc_nlen + 1, tncp->nc_name, tncp->nc_nlen);
1205 p[fncp->nc_nlen + 1 + tncp->nc_nlen] = '\0';
1207 error = fuse_ipc_tx(fip);
1212 if (fncp->nc_nlen != tncp->nc_nlen ||
1213 memcmp(fncp->nc_name, tncp->nc_name, fncp->nc_nlen)) {
1214 newname = kmalloc(tncp->nc_nlen + 1, M_TEMP, M_WAITOK | M_ZERO);
1216 memcpy(newname, tncp->nc_name, tncp->nc_nlen);
1217 newname[tncp->nc_nlen] = '\0';
1218 fuse_dbg("newname=\"%s\"\n", newname);
1222 mtx_lock(&tdfnp->node_lock);
1223 mtx_lock(&fdfnp->node_lock);
1224 mtx_lock(&ffnp->node_lock);
1226 fuse_dbg("detach from_dent=\"%s\"\n", ffep->name);
1227 fuse_dent_detach(fdfnp, ffep);
1230 oldname = ffep->name;
1231 ffep->name = newname;
1236 mtx_lock(&tfnp->node_lock);
1237 error = fuse_dent_find(tdfnp, tncp->nc_name, tncp->nc_nlen,
1240 fuse_dbg("detach/free to_dent=\"%s\"\n", tfep->name);
1241 fuse_dent_detach(tdfnp, tfep);
1242 fuse_dent_free(tfep);
1243 mtx_unlock(&tfnp->node_lock);
1244 fuse_knote(tdvp, NOTE_DELETE);
1247 fuse_dbg("attach from_dent=\"%s\"\n", ffep->name);
1248 fuse_dent_attach(tdfnp, ffep);
1250 mtx_unlock(&ffnp->node_lock);
1251 mtx_unlock(&fdfnp->node_lock);
1252 mtx_unlock(&tdfnp->node_lock);
1255 kfree(newname, M_TEMP);
1257 cache_rename(ap->a_fnch, ap->a_tnch);
1258 fuse_knote(fdvp, NOTE_WRITE);
1259 fuse_knote(tdvp, NOTE_WRITE);
1260 fuse_knote(fvp, NOTE_RENAME);
1269 fuse_vop_nsymlink(struct vop_nsymlink_args *ap)
1271 struct vnode *dvp = ap->a_dvp;
1273 struct namecache *ncp = ap->a_nch->ncp;
1274 struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount);
1275 struct fuse_node *dfnp = VTOI(dvp);
1276 struct fuse_node *fnp;
1277 struct fuse_ipc *fip;
1278 struct fuse_entry_out *feo;
1282 if (fuse_test_dead(fmp))
1285 if (fuse_test_nosys(fmp, FUSE_SYMLINK))
1288 fip = fuse_ipc_get(fmp, strlen(ap->a_target) + 1 + ncp->nc_nlen + 1);
1289 p = fuse_ipc_fill(fip, FUSE_SYMLINK, dfnp->ino, ap->a_cred);
1291 memcpy(p, ncp->nc_name, ncp->nc_nlen);
1292 p[ncp->nc_nlen] = '\0';
1293 memcpy(p + ncp->nc_nlen + 1, ap->a_target, strlen(ap->a_target) + 1);
1295 error = fuse_ipc_tx(fip);
1299 feo = fuse_out_data(fip);
1300 if (IFTOVT(feo->attr.mode) != VLNK) {
1305 error = fuse_alloc_node(dfnp, feo->nodeid, p, strlen(p), VLNK, &vp);
1311 KKASSERT(vn_islocked(vp));
1314 mtx_lock(&fnp->node_lock);
1315 fuse_set_attr(fnp, &feo->attr);
1316 mtx_unlock(&fnp->node_lock);
1318 cache_setunresolved(ap->a_nch);
1319 cache_setvp(ap->a_nch, vp);
1321 fuse_knote(vp, NOTE_WRITE);
1327 //feo->entry_valid_nsec;
1328 //feo->attr_valid_nsec;
1336 fuse_vop_read(struct vop_read_args *ap)
1338 struct vnode *vp = ap->a_vp;
1339 struct uio *uio = ap->a_uio;
1340 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
1342 fuse_dbg("ino=%ju ioflag=%x\n", VTOI(vp)->ino, ap->a_ioflag);
1344 if (fuse_test_dead(fmp))
1347 if (fuse_test_nosys(fmp, FUSE_READ))
1350 if (!uio->uio_resid)
1353 return fuse_read(ap);
1357 fuse_vop_write(struct vop_write_args *ap)
1359 struct vnode *vp = ap->a_vp;
1360 struct uio *uio = ap->a_uio;
1361 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
1363 fuse_dbg("ino=%ju ioflag=%x\n", VTOI(vp)->ino, ap->a_ioflag);
1364 return EOPNOTSUPP; /* XXX disabled */
1366 if (fuse_test_dead(fmp))
1369 if (fuse_test_nosys(fmp, FUSE_WRITE))
1372 if (!uio->uio_resid)
1375 if (ap->a_ioflag & IO_DIRECT)
1376 return fuse_dio_write(ap);
1378 return fuse_write(ap);
1382 fuse_vop_strategy(struct vop_strategy_args *ap)
1384 struct bio *bio = ap->a_bio;
1385 struct buf *bp = bio->bio_buf;
1387 fuse_dbg("ino=%ju b_cmd=%d\n", VTOI(ap->a_vp)->ino, bp->b_cmd);
1397 fuse_bmap(struct vop_bmap_args *ap)
1399 fuse_dbg("ino=%ju a_cmd=%d a_loffset=%ju\n",
1400 VTOI(ap->a_vp)->ino, ap->a_cmd, ap->a_loffset);
1406 fuse_vop_print(struct vop_print_args *ap)
1408 struct fuse_node *fnp = VTOI(ap->a_vp);
1410 fuse_print("tag VT_FUSE, node %p, ino %ju, parent ino %ju\n",
1411 fnp, VTOI(ap->a_vp)->ino, VTOI(fnp->pfnp->vp)->ino);
1417 fuse_vop_inactive(struct vop_inactive_args *ap)
1419 struct vnode *vp = ap->a_vp;
1420 struct mount *mp = vp->v_mount;
1421 struct fuse_node *fnp = VTOI(vp);
1423 lwkt_gettoken(&mp->mnt_token);
1426 lwkt_reltoken(&mp->mnt_token);
1430 fuse_dbg("ino=%ju nlink=%d\n", fnp->ino, fnp->nlink);
1431 vinvalbuf(vp, V_SAVE, 0, 0);
1432 lwkt_reltoken(&mp->mnt_token);
1438 fuse_vop_reclaim(struct vop_reclaim_args *ap)
1440 struct vnode *vp = ap->a_vp;
1441 struct mount *mp = vp->v_mount;
1442 struct fuse_node *fnp = VTOI(vp);
1444 lwkt_gettoken(&mp->mnt_token);
1446 fuse_dbg("ino=%ju\n", fnp->ino);
1447 fuse_node_free(fnp);
1450 lwkt_reltoken(&mp->mnt_token);
1456 fuse_vop_mountctl(struct vop_mountctl_args *ap)
1461 mp = ap->a_head.a_ops->head.vv_mount;
1462 lwkt_gettoken(&mp->mnt_token);
1465 //case MOUNTCTL_MOUNTFLAGS:
1469 res = vop_stdmountctl(ap);
1473 lwkt_reltoken(&mp->mnt_token);
1477 static void filt_fusedetach(struct knote*);
1478 static int filt_fuseread(struct knote*, long);
1479 static int filt_fusewrite(struct knote*, long);
1480 static int filt_fusevnode(struct knote*, long);
1482 static struct filterops fuseread_filtops =
1483 { FILTEROP_ISFD | FILTEROP_MPSAFE,
1484 NULL, filt_fusedetach, filt_fuseread };
1485 static struct filterops fusewrite_filtops =
1486 { FILTEROP_ISFD | FILTEROP_MPSAFE,
1487 NULL, filt_fusedetach, filt_fusewrite };
1488 static struct filterops fusevnode_filtops =
1489 { FILTEROP_ISFD | FILTEROP_MPSAFE,
1490 NULL, filt_fusedetach, filt_fusevnode };
1493 fuse_kqfilter(struct vop_kqfilter_args *ap)
1495 struct vnode *vp = ap->a_vp;
1496 struct knote *kn = ap->a_kn;
1498 switch (kn->kn_filter) {
1500 kn->kn_fop = &fuseread_filtops;
1503 kn->kn_fop = &fusewrite_filtops;
1506 kn->kn_fop = &fusevnode_filtops;
1512 kn->kn_hook = (caddr_t)vp;
1513 knote_insert(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn);
1519 filt_fusedetach(struct knote *kn)
1521 struct vnode *vp = (void*)kn->kn_hook;
1523 knote_remove(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn);
1527 filt_fuseread(struct knote *kn, long hint)
1529 struct vnode *vp = (void*)kn->kn_hook;
1530 struct fuse_node *fnp = VTOI(vp);
1533 if (hint == NOTE_REVOKE) {
1534 kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT);
1539 * Interlock against MP races when performing this function.
1541 mtx_lock(&fnp->node_lock);
1542 off = fnp->size - kn->kn_fp->f_offset;
1543 kn->kn_data = (off < INTPTR_MAX) ? off : INTPTR_MAX;
1544 if (kn->kn_sfflags & NOTE_OLDAPI) {
1545 mtx_unlock(&fnp->node_lock);
1549 kn->kn_data = (off < INTPTR_MAX) ? off : INTPTR_MAX;
1550 mtx_unlock(&fnp->node_lock);
1552 return kn->kn_data != 0;
1556 filt_fusewrite(struct knote *kn, long hint)
1558 if (hint == NOTE_REVOKE)
1559 kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT);
1566 filt_fusevnode(struct knote *kn, long hint)
1568 if (kn->kn_sfflags & hint)
1569 kn->kn_fflags |= hint;
1570 if (hint == NOTE_REVOKE) {
1571 kn->kn_flags |= (EV_EOF | EV_NODATA);
1575 return kn->kn_fflags != 0;
1579 fuse_vop_getpages(struct vop_getpages_args *ap)
1581 if (!ap->a_vp->v_mount)
1582 return VM_PAGER_BAD;
1584 return vnode_pager_generic_getpages(ap->a_vp, ap->a_m, ap->a_count,
1585 ap->a_reqpage, ap->a_seqaccess);
1589 fuse_vop_putpages(struct vop_putpages_args *ap)
1591 if (!ap->a_vp->v_mount)
1592 return VM_PAGER_BAD;
1594 return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count,
1595 ap->a_sync, ap->a_rtvals);
1598 struct vop_ops fuse_vnode_vops = {
1599 .vop_default = vop_defaultop,
1600 .vop_access = fuse_vop_access,
1601 .vop_open = fuse_vop_open,
1602 .vop_close = fuse_vop_close,
1603 .vop_fsync = fuse_vop_fsync,
1604 .vop_getattr = fuse_vop_getattr,
1605 .vop_setattr = fuse_vop_setattr,
1606 .vop_nresolve = fuse_vop_nresolve,
1607 //.vop_nlookupdotdot = fuse_nlookupdotdot,
1608 .vop_nlink = fuse_vop_nlink,
1609 .vop_ncreate = fuse_vop_ncreate,
1610 .vop_nmknod = fuse_vop_nmknod,
1611 .vop_nremove = fuse_vop_nremove,
1612 .vop_nmkdir = fuse_vop_nmkdir,
1613 .vop_nrmdir = fuse_vop_nrmdir,
1614 .vop_pathconf = fuse_vop_pathconf,
1615 .vop_readdir = fuse_vop_readdir,
1616 .vop_readlink = fuse_vop_readlink,
1617 .vop_nrename = fuse_vop_nrename,
1618 .vop_nsymlink = fuse_vop_nsymlink,
1619 .vop_read = fuse_vop_read,
1620 .vop_write = fuse_vop_write,
1621 .vop_strategy = fuse_vop_strategy,
1622 .vop_bmap = fuse_bmap,
1623 //.vop_advlock = fuse_advlock,
1624 .vop_print = fuse_vop_print,
1625 .vop_inactive = fuse_vop_inactive,
1626 .vop_reclaim = fuse_vop_reclaim,
1627 .vop_mountctl = fuse_vop_mountctl,
1628 .vop_kqfilter = fuse_kqfilter,
1629 .vop_getpages = fuse_vop_getpages,
1630 .vop_putpages = fuse_vop_putpages,
1633 struct vop_ops fuse_spec_vops = {
1634 .vop_default = vop_defaultop,
1635 .vop_access = fuse_vop_access,
1636 .vop_close = fuse_vop_close,
1637 .vop_fsync = fuse_vop_fsync,
1638 .vop_getattr = fuse_vop_getattr,
1639 .vop_setattr = fuse_vop_setattr,
1640 .vop_read = vop_stdnoread,
1641 .vop_write = vop_stdnowrite,
1642 //.vop_markatime = fuse_vop_markatime,
1643 .vop_print = fuse_vop_print,
1644 .vop_inactive = fuse_vop_inactive,
1645 .vop_reclaim = fuse_vop_reclaim,