示例#1
0
文件: gfs.c 项目: pcd1193182/openzfs
/*
 * gfs_file_create(): create a new GFS file
 *
 *   size	- size of private data structure (v_data)
 *   pvp	- parent vnode (GFS directory)
 *   ops	- vnode operations vector
 *
 * In order to use this interface, the parent vnode must have been created by
 * gfs_dir_create(), and the private data stored in v_data must have a
 * 'gfs_file_t' as its first field.
 *
 * Given these constraints, this routine will automatically:
 *
 * 	- Allocate v_data for the vnode
 * 	- Initialize necessary fields in the vnode
 * 	- Hold the parent
 */
vnode_t *
gfs_file_create(size_t size, vnode_t *pvp, vnodeops_t *ops)
{
	gfs_file_t *fp;
	vnode_t *vp;

	/*
	 * Allocate vnode and internal data structure
	 */
	fp = kmem_zalloc(size, KM_SLEEP);
	vp = vn_alloc(KM_SLEEP);

	/*
	 * Set up various pointers
	 */
	fp->gfs_vnode = vp;
	fp->gfs_parent = pvp;
	vp->v_data = fp;
	fp->gfs_size = size;
	fp->gfs_type = GFS_FILE;

	/*
	 * Initialize vnode and hold parent.
	 */
	vn_setops(vp, ops);
	if (pvp) {
		VN_SET_VFS_TYPE_DEV(vp, pvp->v_vfsp, VREG, 0);
		VN_HOLD(pvp);
	}

	return (vp);
}
示例#2
0
/*
 * Return a looped back vnode for the given vnode.
 * If no lnode exists for this vnode create one and put it
 * in a table hashed by vnode.  If the lnode for
 * this vnode is already in the table return it (ref count is
 * incremented by lfind).  The lnode will be flushed from the
 * table when lo_inactive calls freelonode.  The creation of
 * a new lnode can be forced via the LOF_FORCE flag even if
 * the vnode exists in the table.  This is used in the creation
 * of a terminating lnode when looping is detected.  A unique
 * lnode is required for the correct evaluation of the current
 * working directory.
 * NOTE: vp is assumed to be a held vnode.
 */
struct vnode *
makelonode(struct vnode *vp, struct loinfo *li, int flag)
{
    lnode_t *lp, *tlp;
    struct vfs *vfsp;
    vnode_t *nvp;

    lp = NULL;
    TABLE_LOCK_ENTER(vp, li);
    if (flag != LOF_FORCE)
        lp = lfind(vp, li);
    if ((flag == LOF_FORCE) || (lp == NULL)) {
        /*
         * Optimistically assume that we won't need to sleep.
         */
        lp = kmem_cache_alloc(lnode_cache, KM_NOSLEEP);
        nvp = vn_alloc(KM_NOSLEEP);
        if (lp == NULL || nvp == NULL) {
            TABLE_LOCK_EXIT(vp, li);
            /* The lnode allocation may have succeeded, save it */
            tlp = lp;
            if (tlp == NULL) {
                tlp = kmem_cache_alloc(lnode_cache, KM_SLEEP);
            }
            if (nvp == NULL) {
                nvp = vn_alloc(KM_SLEEP);
            }
            lp = NULL;
            TABLE_LOCK_ENTER(vp, li);
            if (flag != LOF_FORCE)
                lp = lfind(vp, li);
            if (lp != NULL) {
                kmem_cache_free(lnode_cache, tlp);
                vn_free(nvp);
                VN_RELE(vp);
                goto found_lnode;
            }
            lp = tlp;
        }
        atomic_inc_32(&li->li_refct);
        vfsp = makelfsnode(vp->v_vfsp, li);
        lp->lo_vnode = nvp;
        VN_SET_VFS_TYPE_DEV(nvp, vfsp, vp->v_type, vp->v_rdev);
        nvp->v_flag |= (vp->v_flag & (VNOMOUNT|VNOMAP|VDIROPEN));
        vn_setops(nvp, lo_vnodeops);
        nvp->v_data = (caddr_t)lp;
        lp->lo_vp = vp;
        lp->lo_looping = 0;
        lsave(lp, li);
        vn_exists(vp);
    } else {
        VN_RELE(vp);
    }

found_lnode:
    TABLE_LOCK_EXIT(vp, li);
    return (ltov(lp));
}
示例#3
0
文件: gfs.c 项目: RJVB/zfs
/*
 * gfs_root_create_file(): create a root vnode for a GFS file as a filesystem
 *
 * Similar to gfs_root_create(), this creates a root vnode for a file to
 * be the pseudo-filesystem.
 */
struct vnode *
gfs_root_create_file(size_t size, vfs_t *vfsp, vnodeops_t *ops, ino64_t ino)
{
	struct vnode	*vp = gfs_file_create(size, NULL, ops, VREG);

	((gfs_file_t *)vnode_fsnode(vp))->gfs_ino = ino;

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

	return (vp);
}
示例#4
0
文件: gfs.c 项目: pcd1193182/openzfs
/*
 * 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);
}
示例#5
0
void
lzfs_zfsctl_create(vfs_t *vfsp)
{
	vnode_t *vp_zfsctl_dir = NULL, *vp_snap_dir = NULL;
	struct dentry *zfsctl_dir_dentry = NULL, *snap_dir_dentry = NULL;
	struct inode *inode_ctldir = NULL, *inode_snapdir = NULL;
	timestruc_t now;

	inode_ctldir = iget_locked(vfsp->vfs_super, LZFS_ZFSCTL_INO_ROOT);
	ASSERT(inode_ctldir != NULL);
	vp_zfsctl_dir = LZFS_ITOV(inode_ctldir);
	gethrestime(&now);
	ASSERT(inode_ctldir->i_state & I_NEW);
	mutex_enter(&vp_zfsctl_dir->v_lock);
	vp_zfsctl_dir->v_count = 1;
	VN_SET_VFS_TYPE_DEV(vp_zfsctl_dir, vfsp, VDIR, 0);
	bcopy(&now, &(vp_zfsctl_dir->v_inode.i_ctime), 
			sizeof (timestruc_t));
	bcopy(&now, &(vp_zfsctl_dir->v_inode.i_atime),
	      sizeof (timestruc_t));
	bcopy(&now,&(vp_zfsctl_dir->v_inode.i_mtime),sizeof (timestruc_t));
#ifdef HAVE_CRED_STRUCT
	inode_ctldir->i_uid = current->cred->uid;
	inode_ctldir->i_gid = current->cred->gid;
#else
	inode_ctldir->i_uid = current->uid;
	inode_ctldir->i_gid = current->gid;
#endif
	inode_ctldir->i_version = 1;
	inode_ctldir->i_mode |= (S_IFDIR | S_IRWXU);
	inode_ctldir->i_op = &zfsctl_dir_inode_operations;
	inode_ctldir->i_fop = &zfsctl_dir_file_operations;
	ASSERT(vfsp);
	inode_ctldir->i_sb = vfsp->vfs_super;
	ASSERT(vfsp->vfs_super);
	ASSERT(vfsp->vfs_super->s_root);
	unlock_new_inode(inode_ctldir);
	zfsctl_dir_dentry = d_alloc_name(vfsp->vfs_super->s_root, 
					 ZFS_CTLDIR_NAME);
	if (zfsctl_dir_dentry) {
	  d_add(zfsctl_dir_dentry, LZFS_VTOI(vp_zfsctl_dir));
	  vfsp->zfsctl_dir_dentry = zfsctl_dir_dentry;
	} else {
		goto dentry_out;
	}
	set_zfsvfs_ctldir(vfsp->vfs_data, vp_zfsctl_dir);
	mutex_exit(&vp_zfsctl_dir->v_lock);
	inode_snapdir = iget_locked(vfsp->vfs_super, LZFS_ZFSCTL_INO_SNAPDIR);
	ASSERT(inode_snapdir != NULL);
	ASSERT(inode_snapdir->i_state & I_NEW);
	vp_snap_dir = LZFS_ITOV(inode_snapdir);
	gethrestime(&now);
	vfsp->vfs_snap_dir = vp_snap_dir;
	mutex_enter(&vp_snap_dir->v_lock);
	vp_snap_dir->v_count = 1;
	VN_SET_VFS_TYPE_DEV(vp_snap_dir, vfsp, VDIR, 0);
	bcopy(&now,&(vp_snap_dir->v_inode.i_ctime),sizeof (timestruc_t));
	bcopy(&now,&(vp_snap_dir->v_inode.i_atime),sizeof (timestruc_t));
	bcopy(&now,&(vp_snap_dir->v_inode.i_mtime),sizeof (timestruc_t));
#ifdef HAVE_CRED_STRUCT
	inode_snapdir->i_uid = current->cred->uid;
	inode_snapdir->i_gid = current->cred->gid;
#else
	inode_snapdir->i_uid = current->uid;
	inode_snapdir->i_gid = current->gid;
#endif
	inode_snapdir->i_version = 1;
	inode_snapdir->i_mode |= (S_IFDIR | S_IRWXU);
	inode_snapdir->i_op = &snap_dir_inode_operations;
	inode_snapdir->i_fop = &snap_dir_file_operations;
	inode_snapdir->i_sb = vfsp->vfs_super;
	unlock_new_inode(inode_snapdir);
	ASSERT(zfsctl_dir_dentry);
	snap_dir_dentry = d_alloc_name(zfsctl_dir_dentry, ZFS_SNAPDIR_NAME);
	if (snap_dir_dentry) {
		d_add(snap_dir_dentry, LZFS_VTOI(vp_snap_dir));
		vfsp->snap_dir_dentry = snap_dir_dentry;
		mutex_exit(&vp_snap_dir->v_lock);
	} else {
		goto dentry_out;
	}
	return;
dentry_out:
	// free vnode
	vn_free(vp_zfsctl_dir);
	ASSERT(0 && "TODO");
}