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