/* struct vnop_reclaim_args { struct vnode *a_vp; struct thread *a_td; }; */ static int fuse_vnop_reclaim(struct vop_reclaim_args *ap) { struct vnode *vp = ap->a_vp; struct thread *td = ap->a_td; struct fuse_vnode_data *fvdat = VTOFUD(vp); struct fuse_filehandle *fufh = NULL; int type; if (!fvdat) { panic("FUSE: no vnode data during recycling"); } FS_DEBUG("inode=%ju\n", (uintmax_t)VTOI(vp)); for (type = 0; type < FUFH_MAXTYPE; type++) { fufh = &(fvdat->fufh[type]); if (FUFH_IS_VALID(fufh)) { printf("FUSE: vnode being reclaimed but fufh (type=%d) is valid", type); fuse_filehandle_close(vp, type, td, NULL); } } if ((!fuse_isdeadfs(vp)) && (fvdat->nlookup)) { fuse_internal_forget_send(vnode_mount(vp), td, NULL, VTOI(vp), fvdat->nlookup); } fuse_vnode_setparent(vp, NULL); cache_purge(vp); vfs_hash_remove(vp); vnode_destroy_vobject(vp); fuse_vnode_destroy(vp); return 0; }
static int fuse_vnode_alloc(struct mount *mp, struct thread *td, uint64_t nodeid, enum vtype vtyp, struct vnode **vpp) { const int lkflags = LK_EXCLUSIVE | LK_RETRY; struct fuse_vnode_data *fvdat; struct vnode *vp2; int err = 0; DEBUG("been asked for vno #%ju\n", (uintmax_t)nodeid); if (vtyp == VNON) { return EINVAL; } *vpp = NULL; err = vfs_hash_get(mp, fuse_vnode_hash(nodeid), lkflags, td, vpp, fuse_vnode_cmp, &nodeid); if (err) return (err); if (*vpp) { MPASS((*vpp)->v_type == vtyp && (*vpp)->v_data != NULL); DEBUG("vnode taken from hash\n"); return (0); } fvdat = malloc(sizeof(*fvdat), M_FUSEVN, M_WAITOK | M_ZERO); err = getnewvnode("fuse", mp, &fuse_vnops, vpp); if (err) { free(fvdat, M_FUSEVN); return (err); } vn_lock(*vpp, lkflags); err = insmntque(*vpp, mp); ASSERT_VOP_ELOCKED(*vpp, "fuse_vnode_alloc"); if (err) { VOP_UNLOCK(*vpp, 0); free(fvdat, M_FUSEVN); *vpp = NULL; return (err); } fuse_vnode_init(*vpp, fvdat, nodeid, vtyp); err = vfs_hash_insert(*vpp, fuse_vnode_hash(nodeid), lkflags, td, &vp2, fuse_vnode_cmp, &nodeid); if (err) { VOP_UNLOCK(*vpp, 0); fuse_vnode_destroy(*vpp); *vpp = NULL; return (err); } /* * XXXIP: Prevent silent vnode reuse. It may happen because several fuse * filesystems ignore inode numbers */ KASSERT(vp2 == NULL, ("vfs hash collision for node #%ju\n", (uintmax_t)nodeid)); ASSERT_VOP_ELOCKED(*vpp, "fuse_vnode_alloc"); return (0); }