/* * 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); }
/* * 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)); }
/* * 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); }
/* * 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); }
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"); }