17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5facf4a8dSllai1 * Common Development and Distribution License (the "License"). 6facf4a8dSllai1 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22134a1f4eSCasper H.S. Dik * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 267c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * This file supports the vfs operations for the NAMEFS file system. 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include <sys/types.h> 347c478bd9Sstevel@tonic-gate #include <sys/param.h> 357c478bd9Sstevel@tonic-gate #include <sys/systm.h> 367c478bd9Sstevel@tonic-gate #include <sys/debug.h> 377c478bd9Sstevel@tonic-gate #include <sys/errno.h> 387c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 397c478bd9Sstevel@tonic-gate #include <sys/inline.h> 407c478bd9Sstevel@tonic-gate #include <sys/file.h> 417c478bd9Sstevel@tonic-gate #include <sys/proc.h> 427c478bd9Sstevel@tonic-gate #include <sys/stat.h> 437c478bd9Sstevel@tonic-gate #include <sys/statvfs.h> 447c478bd9Sstevel@tonic-gate #include <sys/mount.h> 457c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 467c478bd9Sstevel@tonic-gate #include <sys/var.h> 477c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 48aa59c4cbSrsb #include <sys/vfs_opreg.h> 497c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 507c478bd9Sstevel@tonic-gate #include <sys/mode.h> 517c478bd9Sstevel@tonic-gate #include <sys/pcb.h> 527c478bd9Sstevel@tonic-gate #include <sys/signal.h> 537c478bd9Sstevel@tonic-gate #include <sys/user.h> 547c478bd9Sstevel@tonic-gate #include <sys/uio.h> 557c478bd9Sstevel@tonic-gate #include <sys/cred.h> 567c478bd9Sstevel@tonic-gate #include <sys/fs/namenode.h> 577c478bd9Sstevel@tonic-gate #include <sys/stream.h> 587c478bd9Sstevel@tonic-gate #include <sys/strsubr.h> 597c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 607c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 617c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h> 627c478bd9Sstevel@tonic-gate #include <sys/policy.h> 637c478bd9Sstevel@tonic-gate #include <sys/vmem.h> 64facf4a8dSllai1 #include <sys/fs/sdev_impl.h> 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate #define NM_INOQUANT (64 * 1024) 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate /* 697c478bd9Sstevel@tonic-gate * Define global data structures. 707c478bd9Sstevel@tonic-gate */ 717c478bd9Sstevel@tonic-gate dev_t namedev; 727c478bd9Sstevel@tonic-gate int namefstype; 737c478bd9Sstevel@tonic-gate struct namenode *nm_filevp_hash[NM_FILEVP_HASH_SIZE]; 747c478bd9Sstevel@tonic-gate struct vfs namevfs; 757c478bd9Sstevel@tonic-gate kmutex_t ntable_lock; 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate static vmem_t *nm_inoarena; /* vmem arena to allocate inode no's from */ 787c478bd9Sstevel@tonic-gate static kmutex_t nm_inolock; 797c478bd9Sstevel@tonic-gate 808c819381Spf199842 vfsops_t *namefs_vfsops; 817c478bd9Sstevel@tonic-gate /* 827c478bd9Sstevel@tonic-gate * Functions to allocate node id's starting from 1. Based on vmem routines. 837c478bd9Sstevel@tonic-gate * The vmem arena is extended in NM_INOQUANT chunks. 847c478bd9Sstevel@tonic-gate */ 857c478bd9Sstevel@tonic-gate uint64_t 867c478bd9Sstevel@tonic-gate namenodeno_alloc(void) 877c478bd9Sstevel@tonic-gate { 887c478bd9Sstevel@tonic-gate uint64_t nno; 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate mutex_enter(&nm_inolock); 917c478bd9Sstevel@tonic-gate nno = (uint64_t)(uintptr_t) 927c478bd9Sstevel@tonic-gate vmem_alloc(nm_inoarena, 1, VM_NOSLEEP + VM_FIRSTFIT); 937c478bd9Sstevel@tonic-gate if (nno == 0) { 947c478bd9Sstevel@tonic-gate (void) vmem_add(nm_inoarena, (void *)(vmem_size(nm_inoarena, 957c478bd9Sstevel@tonic-gate VMEM_ALLOC | VMEM_FREE) + 1), NM_INOQUANT, VM_SLEEP); 967c478bd9Sstevel@tonic-gate nno = (uint64_t)(uintptr_t) 977c478bd9Sstevel@tonic-gate vmem_alloc(nm_inoarena, 1, VM_SLEEP + VM_FIRSTFIT); 987c478bd9Sstevel@tonic-gate ASSERT(nno != 0); 997c478bd9Sstevel@tonic-gate } 1007c478bd9Sstevel@tonic-gate mutex_exit(&nm_inolock); 1017c478bd9Sstevel@tonic-gate ASSERT32(nno <= ULONG_MAX); 1027c478bd9Sstevel@tonic-gate return (nno); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate static void 1067c478bd9Sstevel@tonic-gate namenodeno_init(void) 1077c478bd9Sstevel@tonic-gate { 1087c478bd9Sstevel@tonic-gate nm_inoarena = vmem_create("namefs_inodes", (void *)1, NM_INOQUANT, 1, 1097c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 1, VM_SLEEP); 1107c478bd9Sstevel@tonic-gate mutex_init(&nm_inolock, NULL, MUTEX_DEFAULT, NULL); 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate void 1147c478bd9Sstevel@tonic-gate namenodeno_free(uint64_t nn) 1157c478bd9Sstevel@tonic-gate { 1167c478bd9Sstevel@tonic-gate void *vaddr = (void *)(uintptr_t)nn; 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate ASSERT32((uint64_t)(uintptr_t)vaddr == nn); 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate mutex_enter(&nm_inolock); 1217c478bd9Sstevel@tonic-gate vmem_free(nm_inoarena, vaddr, 1); 1227c478bd9Sstevel@tonic-gate mutex_exit(&nm_inolock); 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate /* 1267c478bd9Sstevel@tonic-gate * Insert a namenode into the nm_filevp_hash table. 1277c478bd9Sstevel@tonic-gate * 1287c478bd9Sstevel@tonic-gate * Each link has a unique namenode with a unique nm_mountvp field. 1297c478bd9Sstevel@tonic-gate * The nm_filevp field of the namenode need not be unique, since a 1307c478bd9Sstevel@tonic-gate * file descriptor may be mounted to multiple nodes at the same time. 1317c478bd9Sstevel@tonic-gate * We hash on nm_filevp since that's what discriminates the searches 1327c478bd9Sstevel@tonic-gate * in namefind() and nm_unmountall(). 1337c478bd9Sstevel@tonic-gate */ 1347c478bd9Sstevel@tonic-gate void 1357c478bd9Sstevel@tonic-gate nameinsert(struct namenode *nodep) 1367c478bd9Sstevel@tonic-gate { 1377c478bd9Sstevel@tonic-gate struct namenode **bucket; 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ntable_lock)); 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate bucket = NM_FILEVP_HASH(nodep->nm_filevp); 1427c478bd9Sstevel@tonic-gate nodep->nm_nextp = *bucket; 1437c478bd9Sstevel@tonic-gate *bucket = nodep; 1447c478bd9Sstevel@tonic-gate } 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate /* 1477c478bd9Sstevel@tonic-gate * Remove a namenode from the hash table, if present. 1487c478bd9Sstevel@tonic-gate */ 1497c478bd9Sstevel@tonic-gate void 1507c478bd9Sstevel@tonic-gate nameremove(struct namenode *nodep) 1517c478bd9Sstevel@tonic-gate { 1527c478bd9Sstevel@tonic-gate struct namenode *np, **npp; 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ntable_lock)); 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate for (npp = NM_FILEVP_HASH(nodep->nm_filevp); (np = *npp) != NULL; 1577c478bd9Sstevel@tonic-gate npp = &np->nm_nextp) { 1587c478bd9Sstevel@tonic-gate if (np == nodep) { 1597c478bd9Sstevel@tonic-gate *npp = np->nm_nextp; 1607c478bd9Sstevel@tonic-gate return; 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate /* 1667c478bd9Sstevel@tonic-gate * Search for a namenode that has a nm_filevp == vp and nm_mountpt == mnt. 1677c478bd9Sstevel@tonic-gate * If mnt is NULL, return the first link with nm_filevp of vp. 1687c478bd9Sstevel@tonic-gate * Returns namenode pointer on success, NULL on failure. 1697c478bd9Sstevel@tonic-gate */ 1707c478bd9Sstevel@tonic-gate struct namenode * 1717c478bd9Sstevel@tonic-gate namefind(vnode_t *vp, vnode_t *mnt) 1727c478bd9Sstevel@tonic-gate { 1737c478bd9Sstevel@tonic-gate struct namenode *np; 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ntable_lock)); 1767c478bd9Sstevel@tonic-gate for (np = *NM_FILEVP_HASH(vp); np != NULL; np = np->nm_nextp) 1777c478bd9Sstevel@tonic-gate if (np->nm_filevp == vp && 1787c478bd9Sstevel@tonic-gate (mnt == NULL || np->nm_mountpt == mnt)) 1797c478bd9Sstevel@tonic-gate break; 1807c478bd9Sstevel@tonic-gate return (np); 1817c478bd9Sstevel@tonic-gate } 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate /* 1847c478bd9Sstevel@tonic-gate * Force the unmouting of a file descriptor from ALL of the nodes 1857c478bd9Sstevel@tonic-gate * that it was mounted to. 1867c478bd9Sstevel@tonic-gate * At the present time, the only usage for this routine is in the 1877c478bd9Sstevel@tonic-gate * event one end of a pipe was mounted. At the time the unmounted 1887c478bd9Sstevel@tonic-gate * end gets closed down, the mounted end is forced to be unmounted. 1897c478bd9Sstevel@tonic-gate * 1907c478bd9Sstevel@tonic-gate * This routine searches the namenode hash list for all namenodes 1917c478bd9Sstevel@tonic-gate * that have a nm_filevp field equal to vp. Each time one is found, 1927c478bd9Sstevel@tonic-gate * the dounmount() routine is called. This causes the nm_unmount() 1937c478bd9Sstevel@tonic-gate * routine to be called and thus, the file descriptor is unmounted 1947c478bd9Sstevel@tonic-gate * from the node. 1957c478bd9Sstevel@tonic-gate * 1967c478bd9Sstevel@tonic-gate * At the start of this routine, the reference count for vp is 1977c478bd9Sstevel@tonic-gate * incremented to protect the vnode from being released in the 1987c478bd9Sstevel@tonic-gate * event the mount was the only thing keeping the vnode active. 1997c478bd9Sstevel@tonic-gate * If that is the case, the VOP_CLOSE operation is applied to 2007c478bd9Sstevel@tonic-gate * the vnode, prior to it being released. 2017c478bd9Sstevel@tonic-gate */ 2027c478bd9Sstevel@tonic-gate static int 2037c478bd9Sstevel@tonic-gate nm_umountall(vnode_t *vp, cred_t *crp) 2047c478bd9Sstevel@tonic-gate { 2057c478bd9Sstevel@tonic-gate vfs_t *vfsp; 2067c478bd9Sstevel@tonic-gate struct namenode *nodep; 2077c478bd9Sstevel@tonic-gate int error = 0; 2087c478bd9Sstevel@tonic-gate int realerr = 0; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate /* 2117c478bd9Sstevel@tonic-gate * For each namenode that is associated with the file: 2127c478bd9Sstevel@tonic-gate * If the v_vfsp field is not namevfs, dounmount it. Otherwise, 2137c478bd9Sstevel@tonic-gate * it was created in nm_open() and will be released in time. 2147c478bd9Sstevel@tonic-gate * The following loop replicates some code from nm_find. That 2157c478bd9Sstevel@tonic-gate * routine can't be used as is since the list isn't strictly 2167c478bd9Sstevel@tonic-gate * consumed as it is traversed. 2177c478bd9Sstevel@tonic-gate */ 2187c478bd9Sstevel@tonic-gate mutex_enter(&ntable_lock); 2197c478bd9Sstevel@tonic-gate nodep = *NM_FILEVP_HASH(vp); 2207c478bd9Sstevel@tonic-gate while (nodep) { 2217c478bd9Sstevel@tonic-gate if (nodep->nm_filevp == vp && 2228c819381Spf199842 (vfsp = NMTOV(nodep)->v_vfsp) != NULL && 2238c819381Spf199842 vfsp != &namevfs && (NMTOV(nodep)->v_flag & VROOT)) { 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate /* 226d5dbd18dSbatschul * If the vn_vfswlock fails, skip the vfs since 2277c478bd9Sstevel@tonic-gate * somebody else may be unmounting it. 2287c478bd9Sstevel@tonic-gate */ 229d5dbd18dSbatschul if (vn_vfswlock(vfsp->vfs_vnodecovered)) { 2307c478bd9Sstevel@tonic-gate realerr = EBUSY; 2317c478bd9Sstevel@tonic-gate nodep = nodep->nm_nextp; 2327c478bd9Sstevel@tonic-gate continue; 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate /* 2367c478bd9Sstevel@tonic-gate * Can't hold ntable_lock across call to do_unmount 2377c478bd9Sstevel@tonic-gate * because nm_unmount tries to acquire it. This means 2387c478bd9Sstevel@tonic-gate * there is a window where another mount of vp can 2397c478bd9Sstevel@tonic-gate * happen so it is possible that after nm_unmountall 2407c478bd9Sstevel@tonic-gate * there are still some mounts. This situation existed 2417c478bd9Sstevel@tonic-gate * without MT locking because dounmount can sleep 2427c478bd9Sstevel@tonic-gate * so another mount could happen during that time. 2437c478bd9Sstevel@tonic-gate * This situation is unlikely and doesn't really cause 2447c478bd9Sstevel@tonic-gate * any problems. 2457c478bd9Sstevel@tonic-gate */ 2467c478bd9Sstevel@tonic-gate mutex_exit(&ntable_lock); 2477c478bd9Sstevel@tonic-gate if ((error = dounmount(vfsp, 0, crp)) != 0) 2487c478bd9Sstevel@tonic-gate realerr = error; 2497c478bd9Sstevel@tonic-gate mutex_enter(&ntable_lock); 2507c478bd9Sstevel@tonic-gate /* 2517c478bd9Sstevel@tonic-gate * Since we dropped the ntable_lock, we 2527c478bd9Sstevel@tonic-gate * have to start over from the beginning. 2537c478bd9Sstevel@tonic-gate * If for some reasons dounmount() fails, 2547c478bd9Sstevel@tonic-gate * start from beginning means that we will keep on 2557c478bd9Sstevel@tonic-gate * trying unless another thread unmounts it for us. 2567c478bd9Sstevel@tonic-gate */ 2577c478bd9Sstevel@tonic-gate nodep = *NM_FILEVP_HASH(vp); 2587c478bd9Sstevel@tonic-gate } else 2597c478bd9Sstevel@tonic-gate nodep = nodep->nm_nextp; 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate mutex_exit(&ntable_lock); 2627c478bd9Sstevel@tonic-gate return (realerr); 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate /* 2667c478bd9Sstevel@tonic-gate * Force the unmouting of a file descriptor from ALL of the nodes 2677c478bd9Sstevel@tonic-gate * that it was mounted to. XXX: fifo_close() calls this routine. 2687c478bd9Sstevel@tonic-gate * 2697c478bd9Sstevel@tonic-gate * nm_umountall() may return EBUSY. 2707c478bd9Sstevel@tonic-gate * nm_unmountall() will keep on trying until it succeeds. 2717c478bd9Sstevel@tonic-gate */ 2727c478bd9Sstevel@tonic-gate int 2737c478bd9Sstevel@tonic-gate nm_unmountall(vnode_t *vp, cred_t *crp) 2747c478bd9Sstevel@tonic-gate { 2757c478bd9Sstevel@tonic-gate int error; 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate /* 2787c478bd9Sstevel@tonic-gate * Nm_umuontall() returns only if it succeeds or 2797c478bd9Sstevel@tonic-gate * return with error EBUSY. If EBUSY, that means 2807c478bd9Sstevel@tonic-gate * it cannot acquire the lock on the covered vnode, 2817c478bd9Sstevel@tonic-gate * and we will keep on trying. 2827c478bd9Sstevel@tonic-gate */ 2837c478bd9Sstevel@tonic-gate for (;;) { 2847c478bd9Sstevel@tonic-gate error = nm_umountall(vp, crp); 2857c478bd9Sstevel@tonic-gate if (error != EBUSY) 2867c478bd9Sstevel@tonic-gate break; 2877c478bd9Sstevel@tonic-gate delay(1); /* yield cpu briefly, then try again */ 2887c478bd9Sstevel@tonic-gate } 2897c478bd9Sstevel@tonic-gate return (error); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate /* 2937c478bd9Sstevel@tonic-gate * Mount a file descriptor onto the node in the file system. 2947c478bd9Sstevel@tonic-gate * Create a new vnode, update the attributes with info from the 2957c478bd9Sstevel@tonic-gate * file descriptor and the mount point. The mask, mode, uid, gid, 2967c478bd9Sstevel@tonic-gate * atime, mtime and ctime are taken from the mountpt. Link count is 2977c478bd9Sstevel@tonic-gate * set to one, the file system id is namedev and nodeid is unique 2987c478bd9Sstevel@tonic-gate * for each mounted object. Other attributes are taken from mount point. 2997c478bd9Sstevel@tonic-gate * Make sure user is owner (or root) with write permissions on mount point. 3007c478bd9Sstevel@tonic-gate * Hash the new vnode and return 0. 3017c478bd9Sstevel@tonic-gate * Upon entry to this routine, the file descriptor is in the 3027c478bd9Sstevel@tonic-gate * fd field of a struct namefd. Copy that structure from user 3037c478bd9Sstevel@tonic-gate * space and retrieve the file descriptor. 3047c478bd9Sstevel@tonic-gate */ 3057c478bd9Sstevel@tonic-gate static int 3067c478bd9Sstevel@tonic-gate nm_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *crp) 3077c478bd9Sstevel@tonic-gate { 3087c478bd9Sstevel@tonic-gate struct namefd namefdp; 3097c478bd9Sstevel@tonic-gate struct vnode *filevp; /* file descriptor vnode */ 3107c478bd9Sstevel@tonic-gate struct file *fp; 3117c478bd9Sstevel@tonic-gate struct vnode *newvp; /* vnode representing this mount */ 3127469ad70Svikram struct vnode *rvp; /* realvp (if any) for the mountpt */ 3137c478bd9Sstevel@tonic-gate struct namenode *nodep; /* namenode for this mount */ 3147c478bd9Sstevel@tonic-gate struct vattr filevattr; /* attributes of file dec. */ 3157c478bd9Sstevel@tonic-gate struct vattr *vattrp; /* attributes of this mount */ 3167c478bd9Sstevel@tonic-gate char *resource_name; 3177c478bd9Sstevel@tonic-gate char *resource_nodetype; 3187c478bd9Sstevel@tonic-gate statvfs64_t *svfsp; 3197c478bd9Sstevel@tonic-gate int error = 0; 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate /* 3227c478bd9Sstevel@tonic-gate * Get the file descriptor from user space. 3237c478bd9Sstevel@tonic-gate * Make sure the file descriptor is valid and has an 3247c478bd9Sstevel@tonic-gate * associated file pointer. 3257c478bd9Sstevel@tonic-gate * If so, extract the vnode from the file pointer. 3267c478bd9Sstevel@tonic-gate */ 3277c478bd9Sstevel@tonic-gate if (uap->datalen != sizeof (struct namefd)) 3287c478bd9Sstevel@tonic-gate return (EINVAL); 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate if (copyin(uap->dataptr, &namefdp, uap->datalen)) 3317c478bd9Sstevel@tonic-gate return (EFAULT); 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate if ((fp = getf(namefdp.fd)) == NULL) 3347c478bd9Sstevel@tonic-gate return (EBADF); 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate /* 3377c478bd9Sstevel@tonic-gate * If the mount point already has something mounted 3387c478bd9Sstevel@tonic-gate * on it, disallow this mount. (This restriction may 3397c478bd9Sstevel@tonic-gate * be removed in a later release). 3407c478bd9Sstevel@tonic-gate * Or unmount has completed but the namefs ROOT vnode 3417c478bd9Sstevel@tonic-gate * count has not decremented to zero, disallow this mount. 3427c478bd9Sstevel@tonic-gate */ 3438c819381Spf199842 3447c478bd9Sstevel@tonic-gate mutex_enter(&mvp->v_lock); 3458c819381Spf199842 if ((mvp->v_flag & VROOT) || 3468c819381Spf199842 vfs_matchops(mvp->v_vfsp, namefs_vfsops)) { 3477c478bd9Sstevel@tonic-gate mutex_exit(&mvp->v_lock); 3487c478bd9Sstevel@tonic-gate releasef(namefdp.fd); 3497c478bd9Sstevel@tonic-gate return (EBUSY); 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate mutex_exit(&mvp->v_lock); 3527c478bd9Sstevel@tonic-gate 353facf4a8dSllai1 /* 354facf4a8dSllai1 * Cannot allow users to fattach() in /dev/pts. 355facf4a8dSllai1 * First, there is no need for doing so and secondly 356aecfc01dSrui zang - Sun Microsystems - Beijing China * we cannot allow arbitrary users to park on a node in 357aecfc01dSrui zang - Sun Microsystems - Beijing China * /dev/pts or /dev/vt. 358facf4a8dSllai1 */ 3597469ad70Svikram rvp = NULLVP; 3607469ad70Svikram if (vn_matchops(mvp, spec_getvnodeops()) && 361da6c28aaSamw VOP_REALVP(mvp, &rvp, NULL) == 0 && rvp && 362aecfc01dSrui zang - Sun Microsystems - Beijing China (vn_matchops(rvp, devpts_getvnodeops()) || 363aecfc01dSrui zang - Sun Microsystems - Beijing China vn_matchops(rvp, devvt_getvnodeops()))) { 364facf4a8dSllai1 releasef(namefdp.fd); 365facf4a8dSllai1 return (ENOTSUP); 366facf4a8dSllai1 } 367facf4a8dSllai1 3687c478bd9Sstevel@tonic-gate filevp = fp->f_vnode; 3697c478bd9Sstevel@tonic-gate if (filevp->v_type == VDIR || filevp->v_type == VPORT) { 3707c478bd9Sstevel@tonic-gate releasef(namefdp.fd); 3717c478bd9Sstevel@tonic-gate return (EINVAL); 3727c478bd9Sstevel@tonic-gate } 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate /* 3757c478bd9Sstevel@tonic-gate * If the fd being mounted refers to neither a door nor a stream, 3767c478bd9Sstevel@tonic-gate * make sure the caller is privileged. 3777c478bd9Sstevel@tonic-gate */ 3787c478bd9Sstevel@tonic-gate if (filevp->v_type != VDOOR && filevp->v_stream == NULL) { 3797c478bd9Sstevel@tonic-gate if (secpolicy_fs_mount(crp, filevp, vfsp) != 0) { 3807c478bd9Sstevel@tonic-gate /* fd is neither a stream nor a door */ 3817c478bd9Sstevel@tonic-gate releasef(namefdp.fd); 3827c478bd9Sstevel@tonic-gate return (EINVAL); 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate /* 3877c478bd9Sstevel@tonic-gate * Make sure the file descriptor is not the root of some 3887c478bd9Sstevel@tonic-gate * file system. 3897c478bd9Sstevel@tonic-gate * If it's not, create a reference and allocate a namenode 3907c478bd9Sstevel@tonic-gate * to represent this mount request. 3917c478bd9Sstevel@tonic-gate */ 3927c478bd9Sstevel@tonic-gate if (filevp->v_flag & VROOT) { 3937c478bd9Sstevel@tonic-gate releasef(namefdp.fd); 3947c478bd9Sstevel@tonic-gate return (EBUSY); 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate nodep = kmem_zalloc(sizeof (struct namenode), KM_SLEEP); 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate mutex_init(&nodep->nm_lock, NULL, MUTEX_DEFAULT, NULL); 4007c478bd9Sstevel@tonic-gate vattrp = &nodep->nm_vattr; 4017c478bd9Sstevel@tonic-gate vattrp->va_mask = AT_ALL; 402da6c28aaSamw if (error = VOP_GETATTR(mvp, vattrp, 0, crp, NULL)) 4037c478bd9Sstevel@tonic-gate goto out; 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate filevattr.va_mask = AT_ALL; 406da6c28aaSamw if (error = VOP_GETATTR(filevp, &filevattr, 0, crp, NULL)) 4077c478bd9Sstevel@tonic-gate goto out; 4087c478bd9Sstevel@tonic-gate /* 4097c478bd9Sstevel@tonic-gate * Make sure the user is the owner of the mount point 4107c478bd9Sstevel@tonic-gate * or has sufficient privileges. 4117c478bd9Sstevel@tonic-gate */ 4127c478bd9Sstevel@tonic-gate if (error = secpolicy_vnode_owner(crp, vattrp->va_uid)) 4137c478bd9Sstevel@tonic-gate goto out; 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate /* 4167c478bd9Sstevel@tonic-gate * Make sure the user has write permissions on the 4177c478bd9Sstevel@tonic-gate * mount point (or has sufficient privileges). 4187c478bd9Sstevel@tonic-gate */ 419134a1f4eSCasper H.S. Dik if (secpolicy_vnode_access2(crp, mvp, vattrp->va_uid, vattrp->va_mode, 420134a1f4eSCasper H.S. Dik VWRITE) != 0) { 4217c478bd9Sstevel@tonic-gate error = EACCES; 4227c478bd9Sstevel@tonic-gate goto out; 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate /* 4267c478bd9Sstevel@tonic-gate * If the file descriptor has file/record locking, don't 4277c478bd9Sstevel@tonic-gate * allow the mount to succeed. 4287c478bd9Sstevel@tonic-gate */ 4297c478bd9Sstevel@tonic-gate if (vn_has_flocks(filevp)) { 4307c478bd9Sstevel@tonic-gate error = EACCES; 4317c478bd9Sstevel@tonic-gate goto out; 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate /* 4357c478bd9Sstevel@tonic-gate * Initialize the namenode. 4367c478bd9Sstevel@tonic-gate */ 4377c478bd9Sstevel@tonic-gate if (filevp->v_stream) { 4387c478bd9Sstevel@tonic-gate struct stdata *stp = filevp->v_stream; 4397c478bd9Sstevel@tonic-gate mutex_enter(&stp->sd_lock); 4407c478bd9Sstevel@tonic-gate stp->sd_flag |= STRMOUNT; 4417c478bd9Sstevel@tonic-gate mutex_exit(&stp->sd_lock); 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate nodep->nm_filevp = filevp; 4447c478bd9Sstevel@tonic-gate mutex_enter(&fp->f_tlock); 4457c478bd9Sstevel@tonic-gate fp->f_count++; 4467c478bd9Sstevel@tonic-gate mutex_exit(&fp->f_tlock); 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate releasef(namefdp.fd); 4497c478bd9Sstevel@tonic-gate nodep->nm_filep = fp; 4507c478bd9Sstevel@tonic-gate nodep->nm_mountpt = mvp; 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate /* 4537c478bd9Sstevel@tonic-gate * The attributes for the mounted file descriptor were initialized 4547c478bd9Sstevel@tonic-gate * above by applying VOP_GETATTR to the mount point. Some of 4557c478bd9Sstevel@tonic-gate * the fields of the attributes structure will be overwritten 4567c478bd9Sstevel@tonic-gate * by the attributes from the file descriptor. 4577c478bd9Sstevel@tonic-gate */ 4587c478bd9Sstevel@tonic-gate vattrp->va_type = filevattr.va_type; 4597c478bd9Sstevel@tonic-gate vattrp->va_fsid = namedev; 4607c478bd9Sstevel@tonic-gate vattrp->va_nodeid = namenodeno_alloc(); 4617c478bd9Sstevel@tonic-gate vattrp->va_nlink = 1; 4627c478bd9Sstevel@tonic-gate vattrp->va_size = filevattr.va_size; 4637c478bd9Sstevel@tonic-gate vattrp->va_rdev = filevattr.va_rdev; 4647c478bd9Sstevel@tonic-gate vattrp->va_blksize = filevattr.va_blksize; 4657c478bd9Sstevel@tonic-gate vattrp->va_nblocks = filevattr.va_nblocks; 4667c478bd9Sstevel@tonic-gate vattrp->va_seq = 0; 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate /* 4697c478bd9Sstevel@tonic-gate * Initialize new vnode structure for the mounted file descriptor. 4707c478bd9Sstevel@tonic-gate */ 4717c478bd9Sstevel@tonic-gate nodep->nm_vnode = vn_alloc(KM_SLEEP); 4727c478bd9Sstevel@tonic-gate newvp = NMTOV(nodep); 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate newvp->v_flag = filevp->v_flag | VROOT | VNOMAP | VNOSWAP; 4757c478bd9Sstevel@tonic-gate vn_setops(newvp, nm_vnodeops); 4767c478bd9Sstevel@tonic-gate newvp->v_vfsp = vfsp; 4777c478bd9Sstevel@tonic-gate newvp->v_stream = filevp->v_stream; 4787c478bd9Sstevel@tonic-gate newvp->v_type = filevp->v_type; 4797c478bd9Sstevel@tonic-gate newvp->v_rdev = filevp->v_rdev; 4807c478bd9Sstevel@tonic-gate newvp->v_data = (caddr_t)nodep; 4818c819381Spf199842 VFS_HOLD(vfsp); 4827c478bd9Sstevel@tonic-gate vn_exists(newvp); 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate /* 4857c478bd9Sstevel@tonic-gate * Initialize the vfs structure. 4867c478bd9Sstevel@tonic-gate */ 4877c478bd9Sstevel@tonic-gate vfsp->vfs_vnodecovered = NULL; 4887c478bd9Sstevel@tonic-gate vfsp->vfs_flag |= VFS_UNLINKABLE; 4897c478bd9Sstevel@tonic-gate vfsp->vfs_bsize = 1024; 4907c478bd9Sstevel@tonic-gate vfsp->vfs_fstype = namefstype; 4917c478bd9Sstevel@tonic-gate vfs_make_fsid(&vfsp->vfs_fsid, namedev, namefstype); 4927c478bd9Sstevel@tonic-gate vfsp->vfs_data = (caddr_t)nodep; 4937c478bd9Sstevel@tonic-gate vfsp->vfs_dev = namedev; 4947c478bd9Sstevel@tonic-gate vfsp->vfs_bcount = 0; 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate /* 4977c478bd9Sstevel@tonic-gate * Set the name we mounted from. 4987c478bd9Sstevel@tonic-gate */ 4997c478bd9Sstevel@tonic-gate switch (filevp->v_type) { 5007c478bd9Sstevel@tonic-gate case VPROC: /* VOP_GETATTR() translates this to VREG */ 5017c478bd9Sstevel@tonic-gate case VREG: resource_nodetype = "file"; break; 5027c478bd9Sstevel@tonic-gate case VDIR: resource_nodetype = "directory"; break; 5037c478bd9Sstevel@tonic-gate case VBLK: resource_nodetype = "device"; break; 5047c478bd9Sstevel@tonic-gate case VCHR: resource_nodetype = "device"; break; 5057c478bd9Sstevel@tonic-gate case VLNK: resource_nodetype = "link"; break; 5067c478bd9Sstevel@tonic-gate case VFIFO: resource_nodetype = "fifo"; break; 5077c478bd9Sstevel@tonic-gate case VDOOR: resource_nodetype = "door"; break; 5087c478bd9Sstevel@tonic-gate case VSOCK: resource_nodetype = "socket"; break; 5097c478bd9Sstevel@tonic-gate default: resource_nodetype = "resource"; break; 5107c478bd9Sstevel@tonic-gate } 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate #define RESOURCE_NAME_SZ 128 /* Maximum length of the resource name */ 5137c478bd9Sstevel@tonic-gate resource_name = kmem_alloc(RESOURCE_NAME_SZ, KM_SLEEP); 5147c478bd9Sstevel@tonic-gate svfsp = kmem_alloc(sizeof (statvfs64_t), KM_SLEEP); 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate error = VFS_STATVFS(filevp->v_vfsp, svfsp); 5177c478bd9Sstevel@tonic-gate if (error == 0) { 5187c478bd9Sstevel@tonic-gate (void) snprintf(resource_name, RESOURCE_NAME_SZ, 5197c478bd9Sstevel@tonic-gate "unspecified_%s_%s", svfsp->f_basetype, resource_nodetype); 5207c478bd9Sstevel@tonic-gate } else { 5217c478bd9Sstevel@tonic-gate (void) snprintf(resource_name, RESOURCE_NAME_SZ, 5227c478bd9Sstevel@tonic-gate "unspecified_%s", resource_nodetype); 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 525*d7de0ceaSRobert Harris vfs_setresource(vfsp, resource_name, 0); 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate kmem_free(svfsp, sizeof (statvfs64_t)); 5287c478bd9Sstevel@tonic-gate kmem_free(resource_name, RESOURCE_NAME_SZ); 5297c478bd9Sstevel@tonic-gate #undef RESOURCE_NAME_SZ 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate /* 5327c478bd9Sstevel@tonic-gate * Insert the namenode. 5337c478bd9Sstevel@tonic-gate */ 5347c478bd9Sstevel@tonic-gate mutex_enter(&ntable_lock); 5357c478bd9Sstevel@tonic-gate nameinsert(nodep); 5367c478bd9Sstevel@tonic-gate mutex_exit(&ntable_lock); 5377c478bd9Sstevel@tonic-gate return (0); 5387c478bd9Sstevel@tonic-gate out: 5397c478bd9Sstevel@tonic-gate releasef(namefdp.fd); 5407c478bd9Sstevel@tonic-gate kmem_free(nodep, sizeof (struct namenode)); 5417c478bd9Sstevel@tonic-gate return (error); 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate /* 5457c478bd9Sstevel@tonic-gate * Unmount a file descriptor from a node in the file system. 5467c478bd9Sstevel@tonic-gate * If the user is not the owner of the file and is not privileged, 5477c478bd9Sstevel@tonic-gate * the request is denied. 5487c478bd9Sstevel@tonic-gate * Otherwise, remove the namenode from the hash list. 5497c478bd9Sstevel@tonic-gate * If the mounted file descriptor was that of a stream and this 5507c478bd9Sstevel@tonic-gate * was the last mount of the stream, turn off the STRMOUNT flag. 5517c478bd9Sstevel@tonic-gate * If the rootvp is referenced other than through the mount, 5527c478bd9Sstevel@tonic-gate * nm_inactive will clean up. 5537c478bd9Sstevel@tonic-gate */ 5547c478bd9Sstevel@tonic-gate static int 5557c478bd9Sstevel@tonic-gate nm_unmount(vfs_t *vfsp, int flag, cred_t *crp) 5567c478bd9Sstevel@tonic-gate { 5577c478bd9Sstevel@tonic-gate struct namenode *nodep = (struct namenode *)vfsp->vfs_data; 5587c478bd9Sstevel@tonic-gate vnode_t *vp, *thisvp; 5597c478bd9Sstevel@tonic-gate struct file *fp = NULL; 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate ASSERT((nodep->nm_flag & NMNMNT) == 0); 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate /* 5647c478bd9Sstevel@tonic-gate * forced unmount is not supported by this file system 5657c478bd9Sstevel@tonic-gate * and thus, ENOTSUP, is being returned. 5667c478bd9Sstevel@tonic-gate */ 5677c478bd9Sstevel@tonic-gate if (flag & MS_FORCE) { 5687c478bd9Sstevel@tonic-gate return (ENOTSUP); 5697c478bd9Sstevel@tonic-gate } 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate vp = nodep->nm_filevp; 5727c478bd9Sstevel@tonic-gate mutex_enter(&nodep->nm_lock); 5737c478bd9Sstevel@tonic-gate if (secpolicy_vnode_owner(crp, nodep->nm_vattr.va_uid) != 0) { 5747c478bd9Sstevel@tonic-gate mutex_exit(&nodep->nm_lock); 5757c478bd9Sstevel@tonic-gate return (EPERM); 5767c478bd9Sstevel@tonic-gate } 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate mutex_exit(&nodep->nm_lock); 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate mutex_enter(&ntable_lock); 5817c478bd9Sstevel@tonic-gate nameremove(nodep); 5827c478bd9Sstevel@tonic-gate thisvp = NMTOV(nodep); 5837c478bd9Sstevel@tonic-gate mutex_enter(&thisvp->v_lock); 5847c478bd9Sstevel@tonic-gate if (thisvp->v_count-- == 1) { 5857c478bd9Sstevel@tonic-gate fp = nodep->nm_filep; 5867c478bd9Sstevel@tonic-gate mutex_exit(&thisvp->v_lock); 5877c478bd9Sstevel@tonic-gate vn_invalid(thisvp); 5887c478bd9Sstevel@tonic-gate vn_free(thisvp); 5898c819381Spf199842 VFS_RELE(vfsp); 5907c478bd9Sstevel@tonic-gate namenodeno_free(nodep->nm_vattr.va_nodeid); 5917c478bd9Sstevel@tonic-gate kmem_free(nodep, sizeof (struct namenode)); 5927c478bd9Sstevel@tonic-gate } else { 5937c478bd9Sstevel@tonic-gate thisvp->v_flag &= ~VROOT; 5947c478bd9Sstevel@tonic-gate mutex_exit(&thisvp->v_lock); 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate if (namefind(vp, NULLVP) == NULL && vp->v_stream) { 5977c478bd9Sstevel@tonic-gate struct stdata *stp = vp->v_stream; 5987c478bd9Sstevel@tonic-gate mutex_enter(&stp->sd_lock); 5997c478bd9Sstevel@tonic-gate stp->sd_flag &= ~STRMOUNT; 6007c478bd9Sstevel@tonic-gate mutex_exit(&stp->sd_lock); 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate mutex_exit(&ntable_lock); 6037c478bd9Sstevel@tonic-gate if (fp != NULL) 6047c478bd9Sstevel@tonic-gate (void) closef(fp); 6057c478bd9Sstevel@tonic-gate return (0); 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate /* 6097c478bd9Sstevel@tonic-gate * Create a reference to the root of a mounted file descriptor. 6107c478bd9Sstevel@tonic-gate * This routine is called from lookupname() in the event a path 6117c478bd9Sstevel@tonic-gate * is being searched that has a mounted file descriptor in it. 6127c478bd9Sstevel@tonic-gate */ 6137c478bd9Sstevel@tonic-gate static int 6147c478bd9Sstevel@tonic-gate nm_root(vfs_t *vfsp, vnode_t **vpp) 6157c478bd9Sstevel@tonic-gate { 6167c478bd9Sstevel@tonic-gate struct namenode *nodep = (struct namenode *)vfsp->vfs_data; 6177c478bd9Sstevel@tonic-gate struct vnode *vp = NMTOV(nodep); 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate VN_HOLD(vp); 6207c478bd9Sstevel@tonic-gate *vpp = vp; 6217c478bd9Sstevel@tonic-gate return (0); 6227c478bd9Sstevel@tonic-gate } 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate /* 6257c478bd9Sstevel@tonic-gate * Return in sp the status of this file system. 6267c478bd9Sstevel@tonic-gate */ 6277c478bd9Sstevel@tonic-gate static int 6287c478bd9Sstevel@tonic-gate nm_statvfs(vfs_t *vfsp, struct statvfs64 *sp) 6297c478bd9Sstevel@tonic-gate { 6307c478bd9Sstevel@tonic-gate dev32_t d32; 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate bzero(sp, sizeof (*sp)); 6337c478bd9Sstevel@tonic-gate sp->f_bsize = 1024; 6347c478bd9Sstevel@tonic-gate sp->f_frsize = 1024; 6357c478bd9Sstevel@tonic-gate (void) cmpldev(&d32, vfsp->vfs_dev); 6367c478bd9Sstevel@tonic-gate sp->f_fsid = d32; 6377c478bd9Sstevel@tonic-gate (void) strcpy(sp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name); 6387c478bd9Sstevel@tonic-gate sp->f_flag = vf_to_stf(vfsp->vfs_flag); 6397c478bd9Sstevel@tonic-gate return (0); 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate /* 6437c478bd9Sstevel@tonic-gate * Since this file system has no disk blocks of its own, apply 6447c478bd9Sstevel@tonic-gate * the VOP_FSYNC operation on the mounted file descriptor. 6457c478bd9Sstevel@tonic-gate */ 6467c478bd9Sstevel@tonic-gate static int 6477c478bd9Sstevel@tonic-gate nm_sync(vfs_t *vfsp, short flag, cred_t *crp) 6487c478bd9Sstevel@tonic-gate { 6497c478bd9Sstevel@tonic-gate struct namenode *nodep; 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate if (vfsp == NULL) 6527c478bd9Sstevel@tonic-gate return (0); 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate nodep = (struct namenode *)vfsp->vfs_data; 6557c478bd9Sstevel@tonic-gate if (flag & SYNC_CLOSE) 6567c478bd9Sstevel@tonic-gate return (nm_umountall(nodep->nm_filevp, crp)); 6577c478bd9Sstevel@tonic-gate 658da6c28aaSamw return (VOP_FSYNC(nodep->nm_filevp, FSYNC, crp, NULL)); 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate /* 6627c478bd9Sstevel@tonic-gate * File system initialization routine. Save the file system type, 6637c478bd9Sstevel@tonic-gate * establish a file system device number and initialize nm_filevp_hash[]. 6647c478bd9Sstevel@tonic-gate */ 6657c478bd9Sstevel@tonic-gate int 6667c478bd9Sstevel@tonic-gate nameinit(int fstype, char *name) 6677c478bd9Sstevel@tonic-gate { 6687c478bd9Sstevel@tonic-gate static const fs_operation_def_t nm_vfsops_template[] = { 669aa59c4cbSrsb VFSNAME_MOUNT, { .vfs_mount = nm_mount }, 670aa59c4cbSrsb VFSNAME_UNMOUNT, { .vfs_unmount = nm_unmount }, 671aa59c4cbSrsb VFSNAME_ROOT, { .vfs_root = nm_root }, 672aa59c4cbSrsb VFSNAME_STATVFS, { .vfs_statvfs = nm_statvfs }, 673aa59c4cbSrsb VFSNAME_SYNC, { .vfs_sync = nm_sync }, 6747c478bd9Sstevel@tonic-gate NULL, NULL 6757c478bd9Sstevel@tonic-gate }; 6767c478bd9Sstevel@tonic-gate static const fs_operation_def_t nm_dummy_vfsops_template[] = { 677aa59c4cbSrsb VFSNAME_STATVFS, { .vfs_statvfs = nm_statvfs }, 678aa59c4cbSrsb VFSNAME_SYNC, { .vfs_sync = nm_sync }, 6797c478bd9Sstevel@tonic-gate NULL, NULL 6807c478bd9Sstevel@tonic-gate }; 6817c478bd9Sstevel@tonic-gate int error; 6827c478bd9Sstevel@tonic-gate int dev; 6837c478bd9Sstevel@tonic-gate vfsops_t *dummy_vfsops; 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate error = vfs_setfsops(fstype, nm_vfsops_template, &namefs_vfsops); 6867c478bd9Sstevel@tonic-gate if (error != 0) { 6877c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "nameinit: bad vfs ops template"); 6887c478bd9Sstevel@tonic-gate return (error); 6897c478bd9Sstevel@tonic-gate } 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate error = vfs_makefsops(nm_dummy_vfsops_template, &dummy_vfsops); 6927c478bd9Sstevel@tonic-gate if (error != 0) { 6937c478bd9Sstevel@tonic-gate (void) vfs_freevfsops_by_type(fstype); 6947c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "nameinit: bad dummy vfs ops template"); 6957c478bd9Sstevel@tonic-gate return (error); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate error = vn_make_ops(name, nm_vnodeops_template, &nm_vnodeops); 6997c478bd9Sstevel@tonic-gate if (error != 0) { 7007c478bd9Sstevel@tonic-gate (void) vfs_freevfsops_by_type(fstype); 7017c478bd9Sstevel@tonic-gate vfs_freevfsops(dummy_vfsops); 7027c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "nameinit: bad vnode ops template"); 7037c478bd9Sstevel@tonic-gate return (error); 7047c478bd9Sstevel@tonic-gate } 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate namefstype = fstype; 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate if ((dev = getudev()) == (major_t)-1) { 7097c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "nameinit: can't get unique device"); 7107c478bd9Sstevel@tonic-gate dev = 0; 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate mutex_init(&ntable_lock, NULL, MUTEX_DEFAULT, NULL); 7137c478bd9Sstevel@tonic-gate namedev = makedevice(dev, 0); 7147c478bd9Sstevel@tonic-gate bzero(nm_filevp_hash, sizeof (nm_filevp_hash)); 7157c478bd9Sstevel@tonic-gate vfs_setops(&namevfs, dummy_vfsops); 7167c478bd9Sstevel@tonic-gate namevfs.vfs_vnodecovered = NULL; 7177c478bd9Sstevel@tonic-gate namevfs.vfs_bsize = 1024; 7187c478bd9Sstevel@tonic-gate namevfs.vfs_fstype = namefstype; 7197c478bd9Sstevel@tonic-gate vfs_make_fsid(&namevfs.vfs_fsid, namedev, namefstype); 7207c478bd9Sstevel@tonic-gate namevfs.vfs_dev = namedev; 7217c478bd9Sstevel@tonic-gate return (0); 7227c478bd9Sstevel@tonic-gate } 7237c478bd9Sstevel@tonic-gate 7247c478bd9Sstevel@tonic-gate static mntopts_t nm_mntopts = { 7257c478bd9Sstevel@tonic-gate NULL, 7267c478bd9Sstevel@tonic-gate 0 7277c478bd9Sstevel@tonic-gate }; 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate static vfsdef_t vfw = { 7307c478bd9Sstevel@tonic-gate VFSDEF_VERSION, 7317c478bd9Sstevel@tonic-gate "namefs", 7327c478bd9Sstevel@tonic-gate nameinit, 7330fbb751dSJohn Levon VSW_HASPROTO | VSW_ZMOUNT, 7347c478bd9Sstevel@tonic-gate &nm_mntopts 7357c478bd9Sstevel@tonic-gate }; 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate /* 7387c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 7397c478bd9Sstevel@tonic-gate */ 7407c478bd9Sstevel@tonic-gate static struct modlfs modlfs = { 7417c478bd9Sstevel@tonic-gate &mod_fsops, "filesystem for namefs", &vfw 7427c478bd9Sstevel@tonic-gate }; 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 7457c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modlfs, NULL 7467c478bd9Sstevel@tonic-gate }; 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate int 7497c478bd9Sstevel@tonic-gate _init(void) 7507c478bd9Sstevel@tonic-gate { 7517c478bd9Sstevel@tonic-gate namenodeno_init(); 7527c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 7537c478bd9Sstevel@tonic-gate } 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate int 7567c478bd9Sstevel@tonic-gate _fini(void) 7577c478bd9Sstevel@tonic-gate { 7587c478bd9Sstevel@tonic-gate return (EBUSY); 7597c478bd9Sstevel@tonic-gate } 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate int 7627c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 7637c478bd9Sstevel@tonic-gate { 7647c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 7657c478bd9Sstevel@tonic-gate } 766