Beispiel #1
0
static int
fuse_vnode_alloc(struct mount *mp,
    struct thread *td,
    uint64_t nodeid,
    enum vtype vtyp,
    struct vnode **vpp)
{
	struct fuse_vnode_data *fvdat;
	struct vnode *vp2;
	int err = 0;

	FS_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), LK_EXCLUSIVE, td, vpp,
	    fuse_vnode_cmp, &nodeid);
	if (err)
		return (err);

	if (*vpp) {
		MPASS((*vpp)->v_type == vtyp && (*vpp)->v_data != NULL);
		FS_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);
	}
	lockmgr((*vpp)->v_vnlock, LK_EXCLUSIVE, NULL);
	fuse_vnode_init(*vpp, fvdat, nodeid, vtyp);
	err = insmntque(*vpp, mp);
	ASSERT_VOP_ELOCKED(*vpp, "fuse_vnode_alloc");
	if (err) {
		free(fvdat, M_FUSEVN);
		*vpp = NULL;
		return (err);
	}
	err = vfs_hash_insert(*vpp, fuse_vnode_hash(nodeid), LK_EXCLUSIVE,
	    td, &vp2, fuse_vnode_cmp, &nodeid);
	if (err)
		return (err);
	if (vp2 != NULL) {
		*vpp = vp2;
		return (0);
	}

	ASSERT_VOP_ELOCKED(*vpp, "fuse_vnode_alloc");

	return (0);
}
Beispiel #2
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);
}