/** * \brief Allocates a new VNode, adding it to the page table and our metadata */ errval_t alloc_vnode(struct pmap_x86 *pmap, struct vnode *root, enum objtype type, uint32_t entry, struct vnode **retvnode) { errval_t err; struct vnode *newvnode = slab_alloc(&pmap->slab); if (newvnode == NULL) { return LIB_ERR_SLAB_ALLOC_FAIL; } // The VNode capability err = pmap->p.slot_alloc->alloc(pmap->p.slot_alloc, &newvnode->u.vnode.cap); if (err_is_fail(err)) { return err_push(err, LIB_ERR_SLOT_ALLOC); } err = vnode_create(newvnode->u.vnode.cap, type); if (err_is_fail(err)) { return err_push(err, LIB_ERR_VNODE_CREATE); } // XXX: need to make sure that vnode cap that we will invoke is in our cspace! if (get_croot_addr(newvnode->u.vnode.cap) != CPTR_ROOTCN) { // debug_printf("%s: creating vnode for another domain in that domain's cspace; need to copy vnode cap to our cspace to make it invokable\n", __FUNCTION__); err = slot_alloc(&newvnode->u.vnode.invokable); assert(err_is_ok(err)); err = cap_copy(newvnode->u.vnode.invokable, newvnode->u.vnode.cap); assert(err_is_ok(err)); } else { // debug_printf("vnode in our cspace: copying capref to invokable\n"); newvnode->u.vnode.invokable = newvnode->u.vnode.cap; } assert(!capref_is_null(newvnode->u.vnode.cap)); assert(!capref_is_null(newvnode->u.vnode.invokable)); err = pmap->p.slot_alloc->alloc(pmap->p.slot_alloc, &newvnode->mapping); if (err_is_fail(err)) { return err_push(err, LIB_ERR_SLOT_ALLOC); } // Map it err = vnode_map(root->u.vnode.invokable, newvnode->u.vnode.cap, entry, PTABLE_ACCESS_DEFAULT, 0, 1, newvnode->mapping); if (err_is_fail(err)) { return err_push(err, LIB_ERR_VNODE_MAP); } // The VNode meta data newvnode->is_vnode = true; newvnode->entry = entry; newvnode->next = root->u.vnode.children; root->u.vnode.children = newvnode; newvnode->u.vnode.children = NULL; *retvnode = newvnode; return SYS_ERR_OK; }
/** * \brief Allocates a new VNode, adding it to the page table and our metadata */ static errval_t alloc_vnode(struct pmap_arm *pmap_arm, struct vnode *root, enum objtype type, uint32_t entry, struct vnode **retvnode) { assert(root->is_vnode); errval_t err; struct vnode *newvnode = slab_alloc(&pmap_arm->slab); if (newvnode == NULL) { return LIB_ERR_SLAB_ALLOC_FAIL; } newvnode->is_vnode = true; // The VNode capability err = slot_alloc(&newvnode->u.vnode.cap); if (err_is_fail(err)) { return err_push(err, LIB_ERR_SLOT_ALLOC); } err = vnode_create(newvnode->u.vnode.cap, type); if (err_is_fail(err)) { return err_push(err, LIB_ERR_VNODE_CREATE); } err = vnode_map(root->u.vnode.cap, newvnode->u.vnode.cap, entry, KPI_PAGING_FLAGS_READ | KPI_PAGING_FLAGS_WRITE, 0, 1); if (err_is_fail(err)) { return err_push(err, LIB_ERR_VNODE_MAP); } // The VNode meta data newvnode->entry = entry; newvnode->next = root->u.vnode.children; root->u.vnode.children = newvnode; newvnode->u.vnode.children = NULL; if (retvnode) { *retvnode = newvnode; } return SYS_ERR_OK; }
/* assumption is that vnode has iocount on it after vnode create */ int null_getnewvnode( struct mount * mp, struct vnode * lowervp, struct vnode * dvp, struct vnode ** vpp, struct componentname * cnp, int root) { struct vnode_fsparam vnfs_param; int error = 0; enum vtype type = VDIR; struct null_node * xp = null_nodecreate(lowervp); if (xp == NULL) { return ENOMEM; } if (lowervp) { type = vnode_vtype(lowervp); } vnfs_param.vnfs_mp = mp; vnfs_param.vnfs_vtype = type; vnfs_param.vnfs_str = "nullfs"; vnfs_param.vnfs_dvp = dvp; vnfs_param.vnfs_fsnode = (void *)xp; vnfs_param.vnfs_vops = nullfs_vnodeop_p; vnfs_param.vnfs_markroot = root; vnfs_param.vnfs_marksystem = 0; vnfs_param.vnfs_rdev = 0; vnfs_param.vnfs_filesize = 0; // set this to 0 since we should only be shadowing non-regular files vnfs_param.vnfs_cnp = cnp; vnfs_param.vnfs_flags = VNFS_ADDFSREF; error = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &vnfs_param, vpp); if (error == 0) { xp->null_vnode = *vpp; xp->null_myvid = vnode_vid(*vpp); vnode_settag(*vpp, VT_NULL); } else { FREE(xp, M_TEMP); } return error; }
/** * Helper function to create XNU VFS vnode object. * * @param mp Mount data structure * @param type vnode type (directory, regular file, etc) * @param pParent Parent vnode object (NULL for VBoxVFS root vnode) * @param fIsRoot Flag that indicates if created vnode object is * VBoxVFS root vnode (TRUE for VBoxVFS root vnode, FALSE * for all aother vnodes) * @param Path within Shared Folder * @param ret Returned newly created vnode * * @return 0 on success, error code otherwise */ int vboxvfs_create_vnode_internal(struct mount *mp, enum vtype type, vnode_t pParent, int fIsRoot, PSHFLSTRING Path, vnode_t *ret) { int rc; vnode_t vnode; vboxvfs_vnode_t *pVnodeData; vboxvfs_mount_t *pMount; AssertReturn(mp, EINVAL); pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); AssertReturn(pMount, EINVAL); AssertReturn(pMount->pLockGroup, EINVAL); AssertReturn(Path, EINVAL); pVnodeData = (vboxvfs_vnode_t *)RTMemAllocZ(sizeof(vboxvfs_vnode_t)); AssertReturn(pVnodeData, ENOMEM); /* Initialize private data */ pVnodeData->pHandle = SHFL_HANDLE_NIL; pVnodeData->pPath = Path; pVnodeData->pLockAttr = lck_attr_alloc_init(); if (pVnodeData->pLockAttr) { pVnodeData->pLock = lck_rw_alloc_init(pMount->pLockGroup, pVnodeData->pLockAttr); if (pVnodeData->pLock) { struct vnode_fsparam vnode_params; vnode_params.vnfs_mp = mp; vnode_params.vnfs_vtype = type; vnode_params.vnfs_str = NULL; vnode_params.vnfs_dvp = pParent; vnode_params.vnfs_fsnode = pVnodeData; /** Private data attached per xnu's vnode object */ vnode_params.vnfs_vops = g_VBoxVFSVnodeDirOpsVector; vnode_params.vnfs_markroot = fIsRoot; vnode_params.vnfs_marksystem = FALSE; vnode_params.vnfs_rdev = 0; vnode_params.vnfs_filesize = 0; vnode_params.vnfs_cnp = NULL; vnode_params.vnfs_flags = VNFS_ADDFSREF | VNFS_NOCACHE; rc = vnode_create(VNCREATE_FLAVOR, sizeof(vnode_params), &vnode_params, &vnode); if (rc == 0) *ret = vnode; return 0; } else { PDEBUG("Unable to allocate lock"); rc = ENOMEM; } lck_attr_free(pVnodeData->pLockAttr); } else { PDEBUG("Unable to allocate lock attr"); rc = ENOMEM; } return rc; }
errno_t FSNodeGetOrCreateFileVNodeByID(vnode_t *vnPtr, uint32_t flags, struct fuse_abi_data *feo, mount_t mp, vnode_t dvp, vfs_context_t context, uint32_t *oflags) { int err; vnode_t vn = NULLVP; HNodeRef hn = NULL; struct fuse_vnode_data *fvdat = NULL; struct fuse_data *mntdata = NULL; fuse_device_t dummy_device; struct fuse_abi_data fa; enum vtype vtyp; fuse_abi_data_init(&fa, feo->fad_version, fuse_entry_out_get_attr(feo)); vtyp = IFTOVT(fuse_attr_get_mode(&fa)); if ((vtyp >= VBAD) || (vtyp == VNON)) { return EINVAL; } int markroot = (flags & FN_IS_ROOT) ? 1 : 0; uint64_t size = (flags & FN_IS_ROOT) ? 0 : fuse_attr_get_size(&fa); uint32_t rdev = (flags & FN_IS_ROOT) ? 0 : fuse_attr_get_rdev(&fa); uint64_t generation = fuse_entry_out_get_generation(feo); mntdata = fuse_get_mpdata(mp); dummy_device = mntdata->fdev; err = HNodeLookupCreatingIfNecessary(dummy_device, fuse_entry_out_get_nodeid(feo), 0 /* fork index */, &hn, &vn); if ((err == 0) && (vn == NULL)) { struct vnode_fsparam params; fvdat = (struct fuse_vnode_data *)FSNodeGenericFromHNode(hn); if (!fvdat->fInitialised) { fvdat->fInitialised = true; /* self */ fvdat->vp = NULLVP; /* hold on */ fvdat->nodeid = fuse_entry_out_get_nodeid(feo); fvdat->generation = generation; /* parent */ fvdat->parentvp = dvp; if (dvp) { fvdat->parent_nodeid = VTOI(dvp); } else { fvdat->parent_nodeid = 0; } /* I/O */ { int k; for (k = 0; k < FUFH_MAXTYPE; k++) { FUFH_USE_RESET(&(fvdat->fufh[k])); } } /* flags */ fvdat->flag = flags; fvdat->c_flag = 0; /* meta */ /* XXX: truncation */ fvdat->entry_valid.tv_sec = (time_t)fuse_entry_out_get_entry_valid(feo); fvdat->entry_valid.tv_nsec = fuse_entry_out_get_entry_valid_nsec(feo); /* XXX: truncation */ fvdat->attr_valid.tv_sec = 0; fvdat->attr_valid.tv_nsec = 0; /* XXX: truncation */ fvdat->modify_time.tv_sec = (time_t)fuse_attr_get_mtime(&fa); fvdat->modify_time.tv_nsec = fuse_attr_get_mtimensec(&fa); fvdat->filesize = size; fvdat->nlookup = 0; fvdat->vtype = vtyp; /* locking */ fvdat->createlock = lck_mtx_alloc_init(fuse_lock_group, fuse_lock_attr); fvdat->creator = current_thread(); #if M_OSXFUSE_ENABLE_TSLOCKING fvdat->nodelock = lck_rw_alloc_init(fuse_lock_group, fuse_lock_attr); fvdat->nodelockowner = NULL; fvdat->truncatelock = lck_rw_alloc_init(fuse_lock_group, fuse_lock_attr); #endif } if (err == 0) { params.vnfs_mp = mp; params.vnfs_vtype = vtyp; params.vnfs_str = NULL; params.vnfs_dvp = dvp; /* NULLVP for the root vnode */ params.vnfs_fsnode = hn; #if M_OSXFUSE_ENABLE_SPECFS if ((vtyp == VBLK) || (vtyp == VCHR)) { params.vnfs_vops = fuse_spec_operations; params.vnfs_rdev = (dev_t)rdev; #else if (0) { #endif #if M_OSXFUSE_ENABLE_FIFOFS } else if (vtyp == VFIFO) { params.vnfs_vops = fuse_fifo_operations; params.vnfs_rdev = 0; (void)rdev; #else } else if (0) { #endif } else { params.vnfs_vops = fuse_vnode_operations; params.vnfs_rdev = 0; (void)rdev; } params.vnfs_marksystem = 0; params.vnfs_cnp = NULL; params.vnfs_flags = VNFS_NOCACHE | VNFS_CANTCACHE; params.vnfs_filesize = size; params.vnfs_markroot = markroot; #if M_OSXFUSE_ENABLE_BIG_LOCK fuse_biglock_unlock(mntdata->biglock); #endif err = vnode_create(VNCREATE_FLAVOR, (uint32_t)sizeof(params), ¶ms, &vn); #if M_OSXFUSE_ENABLE_BIG_LOCK fuse_biglock_lock(mntdata->biglock); #endif } if (err == 0) { if (markroot) { fvdat->parentvp = vn; } else { fvdat->parentvp = dvp; } if (oflags) { *oflags |= MAKEENTRY; } /* Need VT_OSXFUSE from xnu */ vnode_settag(vn, VT_OTHER); cache_attrs(vn, fuse_entry_out, feo); HNodeAttachVNodeSucceeded(hn, 0 /* forkIndex */, vn); FUSE_OSAddAtomic(1, (SInt32 *)&fuse_vnodes_current); } else { if (HNodeAttachVNodeFailed(hn, 0 /* forkIndex */)) { FSNodeScrub(fvdat); HNodeScrubDone(hn); } } } if (err == 0) { if (vnode_vtype(vn) != vtyp) { IOLog("osxfuse: vnode changed type behind us (old=%d, new=%d)\n", vnode_vtype(vn), vtyp); #if M_OSXFUSE_ENABLE_BIG_LOCK fuse_biglock_unlock(mntdata->biglock); #endif fuse_internal_vnode_disappear(vn, context, REVOKE_SOFT); vnode_put(vn); #if M_OSXFUSE_ENABLE_BIG_LOCK fuse_biglock_lock(mntdata->biglock); #endif err = EIO; } else if (VTOFUD(vn)->generation != generation) { IOLog("osxfuse: vnode changed generation\n"); #if M_OSXFUSE_ENABLE_BIG_LOCK fuse_biglock_unlock(mntdata->biglock); #endif fuse_internal_vnode_disappear(vn, context, REVOKE_SOFT); vnode_put(vn); #if M_OSXFUSE_ENABLE_BIG_LOCK fuse_biglock_lock(mntdata->biglock); #endif err = ESTALE; } } if (err == 0) { *vnPtr = vn; } /* assert((err == 0) == (*vnPtr != NULL); */ return err; } int fuse_vget_i(vnode_t *vpp, uint32_t flags, struct fuse_abi_data *feo, struct componentname *cnp, vnode_t dvp, mount_t mp, vfs_context_t context) { int err = 0; if (!feo) { return EINVAL; } err = FSNodeGetOrCreateFileVNodeByID(vpp, flags, feo, mp, dvp, context, NULL); if (err) { return err; } if (!fuse_isnovncache_mp(mp) && (cnp->cn_flags & MAKEENTRY)) { fuse_vncache_enter(dvp, *vpp, cnp); } /* found: */ VTOFUD(*vpp)->nlookup++; return 0; }
/** * \brief Setup an initial cspace * * Create an initial cspace layout */ static errval_t spawn_setup_cspace(struct spawninfo *si) { errval_t err; struct capref t1; /* Create root CNode */ err = cnode_create(&si->rootcn_cap, &si->rootcn, DEFAULT_CNODE_SLOTS, NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_ROOTCN); } /* Create taskcn */ err = cnode_create(&si->taskcn_cap, &si->taskcn, DEFAULT_CNODE_SLOTS, NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_TASKCN); } // Mint into rootcn setting the guard t1.cnode = si->rootcn; t1.slot = ROOTCN_SLOT_TASKCN; err = cap_mint(t1, si->taskcn_cap, 0, GUARD_REMAINDER(2 * DEFAULT_CNODE_BITS)); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_MINT_TASKCN); } /* Create slot_alloc_cnode */ t1.cnode = si->rootcn; t1.slot = ROOTCN_SLOT_SLOT_ALLOC0; err = cnode_create_raw(t1, NULL, (1<<SLOT_ALLOC_CNODE_BITS), NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_SLOTALLOC_CNODE); } t1.cnode = si->rootcn; t1.slot = ROOTCN_SLOT_SLOT_ALLOC1; err = cnode_create_raw(t1, NULL, (1<<SLOT_ALLOC_CNODE_BITS), NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_SLOTALLOC_CNODE); } t1.cnode = si->rootcn; t1.slot = ROOTCN_SLOT_SLOT_ALLOC2; err = cnode_create_raw(t1, NULL, (1<<SLOT_ALLOC_CNODE_BITS), NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_SLOTALLOC_CNODE); } // Create DCB si->dcb.cnode = si->taskcn; si->dcb.slot = TASKCN_SLOT_DISPATCHER; err = dispatcher_create(si->dcb); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_DISPATCHER); } // Give domain endpoint to itself (in taskcn) struct capref selfep = { .cnode = si->taskcn, .slot = TASKCN_SLOT_SELFEP, }; err = cap_retype(selfep, si->dcb, ObjType_EndPoint, 0); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_SELFEP); } // Map root CNode (in taskcn) t1.cnode = si->taskcn; t1.slot = TASKCN_SLOT_ROOTCN; err = cap_mint(t1, si->rootcn_cap, 0, 0); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_MINT_ROOTCN); } #ifdef TRACING_EXISTS // Set up tracing for the child err = trace_setup_child(si->taskcn, si->handle); if (err_is_fail(err)) { printf("Warning: error setting up tracing for child domain\n"); // SYS_DEBUG(err, ...); } #endif // XXX: copy over argspg? memset(&si->argspg, 0, sizeof(si->argspg)); /* Fill up basecn */ struct capref basecn_cap; struct cnoderef basecn; // Create basecn in rootcn basecn_cap.cnode = si->rootcn; basecn_cap.slot = ROOTCN_SLOT_BASE_PAGE_CN; err = cnode_create_raw(basecn_cap, &basecn, DEFAULT_CNODE_SLOTS, NULL); if (err_is_fail(err)) { return err_push(err, LIB_ERR_CNODE_CREATE); } // Place the ram caps for (uint8_t i = 0; i < DEFAULT_CNODE_SLOTS; i++) { struct capref base = { .cnode = basecn, .slot = i }; struct capref ram; err = ram_alloc(&ram, BASE_PAGE_BITS); if (err_is_fail(err)) { return err_push(err, LIB_ERR_RAM_ALLOC); } err = cap_copy(base, ram); if (err_is_fail(err)) { return err_push(err, LIB_ERR_CAP_COPY); } err = cap_destroy(ram); if (err_is_fail(err)) { return err_push(err, LIB_ERR_CAP_DESTROY); } } return SYS_ERR_OK; } static errval_t spawn_setup_vspace(struct spawninfo *si) { errval_t err; /* Create pagecn */ si->pagecn_cap = (struct capref){.cnode = si->rootcn, .slot = ROOTCN_SLOT_PAGECN}; err = cnode_create_raw(si->pagecn_cap, &si->pagecn, PAGE_CNODE_SLOTS, NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_PAGECN); } /* Init pagecn's slot allocator */ // XXX: satisfy a peculiarity of the single_slot_alloc_init_raw API size_t bufsize = SINGLE_SLOT_ALLOC_BUFLEN(PAGE_CNODE_SLOTS); void *buf = malloc(bufsize); assert(buf != NULL); err = single_slot_alloc_init_raw(&si->pagecn_slot_alloc, si->pagecn_cap, si->pagecn, PAGE_CNODE_SLOTS, buf, bufsize); if (err_is_fail(err)) { return err_push(err, LIB_ERR_SINGLE_SLOT_ALLOC_INIT_RAW); } // Create root of pagetable err = si->pagecn_slot_alloc.a.alloc(&si->pagecn_slot_alloc.a, &si->vtree); if (err_is_fail(err)) { return err_push(err, LIB_ERR_SLOT_ALLOC); } // top-level table should always live in slot 0 of pagecn assert(si->vtree.slot == 0); switch(si->cpu_type) { case CPU_X86_64: case CPU_K1OM: err = vnode_create(si->vtree, ObjType_VNode_x86_64_pml4); break; case CPU_X86_32: case CPU_SCC: #ifdef CONFIG_PAE err = vnode_create(si->vtree, ObjType_VNode_x86_32_pdpt); #else err = vnode_create(si->vtree, ObjType_VNode_x86_32_pdir); #endif break; case CPU_ARM5: case CPU_ARM7: err = vnode_create(si->vtree, ObjType_VNode_ARM_l1); break; default: assert(!"Other architecture"); return err_push(err, SPAWN_ERR_UNKNOWN_TARGET_ARCH); } if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_VNODE); } err = spawn_vspace_init(si, si->vtree, si->cpu_type); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_VSPACE_INIT); } return SYS_ERR_OK; } #if 0 /** * \brief Lookup and map an image */ static errval_t spawn_map(const char *name, struct bootinfo *bi, lvaddr_t *binary, size_t *binary_size) { errval_t err; /* Get the module from the multiboot */ struct mem_region *module = multiboot_find_module(bi, name); if (module == NULL) { return SPAWN_ERR_FIND_MODULE; } /* Map the image */ err = spawn_map_module(module, binary_size, binary, NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_MAP_MODULE); } return SYS_ERR_OK; }
__private_extern__ int nget_9p(mount_9p *nmp, fid_9p fid, qid_9p qid, vnode_t dvp, vnode_t *vpp, struct componentname *cnp, vfs_context_t ctx) { #pragma unused(ctx) struct vnode_fsparam fsp; struct hnode_9p *nhp; node_9p *np; uint32_t vid; int e, i; TRACE(); nhp = HASH9P(nmp, qid.path); loop: lck_mtx_lock(nmp->nodelck); LIST_FOREACH (np, nhp, next) { if(np->dir.qid.path != qid.path) continue; if (ISSET(np->flags, NODE_INIT)) { SET(np->flags, NODE_WAITINIT); msleep(np, nmp->nodelck, PINOD|PDROP, "nget_9p_init", NULL); goto loop; } if (ISSET(np->flags, NODE_RECL)) { SET(np->flags, NODE_WAITRECL); msleep(np, nmp->nodelck, PINOD|PDROP, "nget_9p_reclaim", NULL); goto loop; } vid = vnode_vid(np->vp); lck_mtx_unlock(nmp->nodelck); if (vnode_getwithvid(np->vp, vid)) goto loop; nlock_9p(np, NODE_LCK_EXCLUSIVE); if (dvp && cnp && ISSET(cnp->cn_flags, MAKEENTRY) && np->dir.qid.vers!=0) { // DEBUG("caching %s", np->dir->name); cache_enter(dvp, np->vp, cnp); } else { // DEBUG("not in cache qid=%d %s", qid.vers, np->dir->name); } *vpp = np->vp; return 0; } if (fid == NOFID) return EFAULT; np = malloc_9p(sizeof(*np)); if (np == NULL) { err0: lck_mtx_unlock(nmp->nodelck); return ENOMEM; } np->lck = lck_rw_alloc_init(lck_grp_9p, LCK_ATTR_NULL); if (np->lck == NULL) { free_9p(np); goto err0; } np->nmp = nmp; np->fid = fid; np->dir.qid = qid; for (i=0; i<3; i++) np->openfid[i].fid = NOFID; SET(np->flags, NODE_INIT); LIST_INSERT_HEAD(nhp, np, next); nlock_9p(np, NODE_LCK_EXCLUSIVE); lck_mtx_unlock(nmp->nodelck); if ((e=ngetdir_9p(np))) { err1: nunlock_9p(np); lck_mtx_lock(nmp->nodelck); LIST_REMOVE(np, next); CLR(np->flags, NODE_INIT); if (ISSET(np->flags, NODE_WAITINIT)) { CLR(np->flags, NODE_WAITINIT); wakeup(np); } lck_mtx_unlock(nmp->nodelck); lck_rw_free(np->lck, lck_grp_9p); free_9p(np); return e; } fsp.vnfs_mp = nmp->mp; fsp.vnfs_str = fsname; fsp.vnfs_dvp = dvp; fsp.vnfs_fsnode = np; fsp.vnfs_vops = vnode_op_9p; fsp.vnfs_markroot = dvp==NULL? TRUE: FALSE; fsp.vnfs_marksystem = FALSE; fsp.vnfs_filesize = np->dir.length; fsp.vnfs_cnp = cnp; fsp.vnfs_flags = VNFS_ADDFSREF; dirvtype_9p(&np->dir, ISSET(nmp->flags, F_DOTU), &fsp.vnfs_vtype, &fsp.vnfs_rdev); if (!dvp || !cnp || !ISSET(cnp->cn_flags, MAKEENTRY) || qid.vers==0) SET(fsp.vnfs_flags, VNFS_NOCACHE); if ((e=vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &fsp, &np->vp))) goto err1; vnode_settag(np->vp, VT_OTHER); lck_mtx_lock(nmp->nodelck); CLR(np->flags, NODE_INIT); if (ISSET(np->flags, NODE_WAITINIT)) { CLR(np->flags, NODE_WAITINIT); wakeup(np); } lck_mtx_unlock(nmp->nodelck); *vpp = np->vp; return 0; }
/* * 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 */ struct vnode * gfs_file_create(size_t size, struct vnode *pvp, vfs_t *vfs, vnodeops_t *ops, enum vtype type, int flags) { gfs_file_t *fp; struct vnode *vp; struct vnode_fsparam vfsp; dprintf("gfs_file_create: vtype %d\n", type); /* * Allocate vnode and internal data structure */ fp = kmem_zalloc(size, KM_SLEEP); bzero(&vfsp, sizeof (vfsp)); vfsp.vnfs_str = "zfs"; vfsp.vnfs_mp = vfs; vfsp.vnfs_vtype = type; vfsp.vnfs_fsnode = fp; vfsp.vnfs_flags = VNFS_ADDFSREF; vfsp.vnfs_vops = ops; if (flags & ZFS_VNODE_SYSTEM) vfsp.vnfs_marksystem = 1; if (flags & ZFS_VNODE_ROOT) vfsp.vnfs_markroot = 1; //error = getnewvnode("zfs", vfsp, ops, &vp); ASSERT(error == 0); //vn_lock(vp, /*LK_EXCLUSIVE |*/ LK_RETRY); //vp->v_data = (caddr_t)fp; //vnode_setfsnode(vp, fp); //mutex_enter(&zfsvfs->z_vnode_create_lock); while (vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &vfsp, &vp) != 0); //mutex_exit(&zfsvfs->z_vnode_create_lock); vnode_settag(vp, VT_ZFS); dprintf("new vnode %p system %d root %d: vfs %p\n", vp, vfsp.vnfs_marksystem, vfsp.vnfs_markroot, vfs); /* * Set up various pointers */ fp->gfs_ino = vnode_vid(vp); fp->gfs_vnode = vp; fp->gfs_parent = pvp; fp->gfs_size = size; fp->gfs_type = GFS_FILE; //vp->v_vflag |= VV_FORCEINSMQ; //error = insmntque(vp, vfsp); //vp->v_vflag &= ~VV_FORCEINSMQ; //KASSERT(error == 0, ("insmntque() failed: error %d", error)); /* * Initialize vnode and hold parent. */ if (pvp) { //printf("Skipping lock of parent %p\n", pvp); VN_HOLD(pvp); dprintf("parent hold pvp %p to 0 -> %d\n", pvp, ((uint32_t *)pvp)[23]); } return (vp); }