/*
 * ctfs_create_tdirnode
 */
vnode_t *
ctfs_create_tdirnode(vnode_t *pvp)
{
	return (gfs_dir_create(sizeof (ctfs_tdirnode_t), pvp, ctfs_ops_tdir,
	    ctfs_tdir_dirents, ctfs_tdir_do_inode, CTFS_NAME_MAX,
	    ctfs_tdir_do_readdir, ctfs_tdir_do_lookup));
}
/*
 * ctfs_create_cdirnode
 *
 * If necessary, creates a cdirnode for the specified contract and
 * inserts it into the contract's list of vnodes.  Returns either the
 * existing vnode or the new one.
 */
vnode_t *
ctfs_create_cdirnode(vnode_t *pvp, contract_t *ct)
{
	vnode_t *vp;
	ctfs_cdirnode_t *cdir;

	if ((vp = contract_vnode_get(ct, pvp->v_vfsp)) != NULL)
		return (vp);

	vp = gfs_dir_create(sizeof (ctfs_cdirnode_t), pvp, ctfs_ops_cdir,
	    ctfs_ctls, ctfs_cdir_do_inode, CTFS_NAME_MAX, NULL, NULL);
	cdir = vp->v_data;

	/*
	 * We must set the inode because this is called explicitly rather than
	 * through GFS callbacks.
	 */
	gfs_file_set_inode(vp, CTFS_INO_CT_DIR(ct->ct_id));

	cdir->ctfs_cn_contract	= ct;
	contract_hold(ct);
	contract_vnode_set(ct, &cdir->ctfs_cn_linkage, vp);

	return (vp);
}
vnode_t *
zfsctl_mknode_shares(vnode_t *pvp)
{
	vnode_t *vp;
	zfsctl_node_t *sdp;

	vp = gfs_dir_create(sizeof (zfsctl_node_t), pvp,
	    zfsctl_ops_shares, NULL, NULL, MAXNAMELEN,
	    NULL, NULL);
	sdp = vp->v_data;
	sdp->zc_cmtime = ((zfsctl_node_t *)pvp->v_data)->zc_cmtime;
	return (vp);

}
Example #4
0
/*
 * gfs_root_create(): create a root vnode for a GFS filesystem
 *
 * Similar to gfs_dir_create(), this creates a root vnode for a filesystem.  The
 * only difference is that it takes a vfs_t instead of a vnode_t as its parent.
 */
vnode_t *
gfs_root_create(size_t size, vfs_t *vfsp, vnodeops_t *ops, ino64_t ino,
    gfs_dirent_t *entries, gfs_inode_cb inode_cb, int maxlen,
    gfs_readdir_cb readdir_cb, gfs_lookup_cb lookup_cb)
{
	vnode_t *vp;

	VFS_HOLD(vfsp);
	vp = gfs_dir_create(size, NULL, vfsp, ops, entries, inode_cb,
	    maxlen, readdir_cb, lookup_cb);
	/* Manually set the inode */
	((gfs_file_t *)vp->v_data)->gfs_ino = ino;
	vp->v_flag |= VROOT;

	return (vp);
}
/*
 * pvp is the '.zfs' directory (zfsctl_node_t).
 * Creates vp, which is '.zfs/snapshot' (zfsctl_snapdir_t).
 *
 * This function is the callback to create a GFS vnode for '.zfs/snapshot'
 * when a lookup is performed on .zfs for "snapshot".
 */
vnode_t *
zfsctl_mknode_snapdir(vnode_t *pvp)
{
	vnode_t *vp;
	zfsctl_snapdir_t *sdp;

	vp = gfs_dir_create(sizeof (zfsctl_snapdir_t), pvp,
	    zfsctl_ops_snapdir, NULL, NULL, MAXNAMELEN,
	    zfsctl_snapdir_readdir_cb, NULL);
	sdp = vp->v_data;
	sdp->sd_node.zc_id = ZFSCTL_INO_SNAPDIR;
	sdp->sd_node.zc_cmtime = ((zfsctl_node_t *)pvp->v_data)->zc_cmtime;
	mutex_init(&sdp->sd_lock, NULL, MUTEX_DEFAULT, NULL);
	avl_create(&sdp->sd_snaps, snapentry_compare,
	    sizeof (zfs_snapentry_t), offsetof(zfs_snapentry_t, se_node));
	return (vp);
}
Example #6
0
/*
 * gfs_root_create(): create a root vnode for a GFS filesystem
 *
 * Similar to gfs_dir_create(), this creates a root vnode for a filesystem.  The
 * only difference is that it takes a vfs_t instead of a vnode_t as its parent.
 */
vnode_t *
gfs_root_create(size_t size, vfs_t *vfsp, vnodeops_t *ops, ino64_t ino,
    gfs_dirent_t *entries, gfs_inode_cb inode_cb, int maxlen,
    gfs_readdir_cb readdir_cb, gfs_lookup_cb lookup_cb)
{
	vnode_t *vp = gfs_dir_create(size, NULL, ops, entries, inode_cb,
	    maxlen, readdir_cb, lookup_cb);

	/* Manually set the inode */
	((gfs_file_t *)vp->v_data)->gfs_ino = ino;

	VFS_HOLD(vfsp);
	VN_SET_VFS_TYPE_DEV(vp, vfsp, VDIR, 0);
	vp->v_flag |= VROOT | VNOCACHE | VNOMAP | VNOSWAP | VNOMOUNT;

	return (vp);
}
Example #7
0
File: gfs.c Project: RJVB/zfs
/*
 * gfs_root_create(): create a root vnode for a GFS filesystem
 *
 * Similar to gfs_dir_create(), this creates a root vnode for a filesystem.  The
 * only difference is that it takes a vfs_t instead of a struct vnode as its parent.
 */
struct vnode *
gfs_root_create(size_t size, vfs_t *vfsp, vnodeops_t *ops, ino64_t ino,
    gfs_dirent_t *entries, gfs_inode_cb inode_cb, int maxlen,
    gfs_readdir_cb readdir_cb, gfs_lookup_cb lookup_cb)
{
	struct vnode *vp;

	VFS_HOLD(vfsp);
	vp = gfs_dir_create(size, NULL, vfsp, ops, entries, inode_cb,
                        maxlen, readdir_cb, lookup_cb,
                        ZFS_VNODE_SYSTEM);
	/* Manually set the inode */
	((gfs_file_t *)vnode_fsnode(vp))->gfs_ino = ino;
    dprintf(".zfs created returning %p; ino %d\n", vp, ino);

    /*
     * Since we created the .zfs node as VSYSTEM, we have to manually
     * call vnode_recycle() as done in zfsctl_destroy().
     */

	return (vp);
}
Example #8
0
/*
 * Get the XATTR dir for some file or directory.
 * See vnode.c: fop_lookup()
 *
 * Note this only gets the GFS XATTR directory.  We'll get the
 * real XATTR directory later, in xattr_dir_realdir.
 */
int
xattr_dir_lookup(vnode_t *dvp, vnode_t **vpp, int flags, cred_t *cr)
{
	int error = 0;

	*vpp = NULL;

	if (dvp->v_type != VDIR && dvp->v_type != VREG)
		return (EINVAL);

	mutex_enter(&dvp->v_lock);

	/*
	 * If we're already in sysattr space, don't allow creation
	 * of another level of sysattrs.
	 */
	if (dvp->v_flag & V_SYSATTR) {
		mutex_exit(&dvp->v_lock);
		return (EINVAL);
	}

	if (dvp->v_xattrdir != NULL) {
		*vpp = dvp->v_xattrdir;
		VN_HOLD(*vpp);
	} else {
		ulong_t val;
		int xattrs_allowed = dvp->v_vfsp->vfs_flag & VFS_XATTR;
		int sysattrs_allowed = 1;

		/*
		 * We have to drop the lock on dvp.  gfs_dir_create will
		 * grab it for a VN_HOLD.
		 */
		mutex_exit(&dvp->v_lock);

		/*
		 * If dvp allows xattr creation, but not sysattr
		 * creation, return the real xattr dir vp. We can't
		 * use the vfs feature mask here because _PC_SATTR_ENABLED
		 * has vnode-level granularity (e.g. .zfs).
		 */
		error = VOP_PATHCONF(dvp, _PC_SATTR_ENABLED, &val, cr, NULL);
		if (error != 0 || val == 0)
			sysattrs_allowed = 0;

		if (!xattrs_allowed && !sysattrs_allowed)
			return (EINVAL);

		if (!sysattrs_allowed) {
			struct pathname pn;
			char *nm = "";

			error = pn_get(nm, UIO_SYSSPACE, &pn);
			if (error)
				return (error);
			error = VOP_LOOKUP(dvp, nm, vpp, &pn,
			    flags|LOOKUP_HAVE_SYSATTR_DIR, rootvp, cr, NULL,
			    NULL, NULL);
			pn_free(&pn);
			return (error);
		}

		/*
		 * Note that we act as if we were given CREATE_XATTR_DIR,
		 * but only for creation of the GFS directory.
		 */
		*vpp = gfs_dir_create(
		    sizeof (xattr_dir_t), dvp, xattr_dir_ops, xattr_dirents,
		    xattrdir_do_ino, MAXNAMELEN, NULL, xattr_lookup_cb);
		mutex_enter(&dvp->v_lock);
		if (dvp->v_xattrdir != NULL) {
			/*
			 * We lost the race to create the xattr dir.
			 * Destroy this one, use the winner.  We can't
			 * just call VN_RELE(*vpp), because the vnode
			 * is only partially initialized.
			 */
			gfs_dir_t *dp = (*vpp)->v_data;

			ASSERT((*vpp)->v_count == 1);
			vn_free(*vpp);

			mutex_destroy(&dp->gfsd_lock);
			kmem_free(dp->gfsd_static,
			    dp->gfsd_nstatic * sizeof (gfs_dirent_t));
			kmem_free(dp, dp->gfsd_file.gfs_size);

			/*
			 * There is an implied VN_HOLD(dvp) here.  We should
			 * be doing a VN_RELE(dvp) to clean up the reference
			 * from *vpp, and then a VN_HOLD(dvp) for the new
			 * reference.  Instead, we just leave the count alone.
			 */

			*vpp = dvp->v_xattrdir;
			VN_HOLD(*vpp);
		} else {
			(*vpp)->v_flag |= (V_XATTRDIR|V_SYSATTR);
			dvp->v_xattrdir = *vpp;
		}
	}
	mutex_exit(&dvp->v_lock);

	return (error);
}