namevfs.c revision d5dbd18d69de8954ab5ceb588e99d43fc9b21d46
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#pragma ident "%Z%%M% %I% %E% SMI" /* from S5R4 1.28 */
/*
* This file supports the vfs operations for the NAMEFS file system.
*/
#include <sys/sysmacros.h>
/*
* Define global data structures.
*/
int namefstype;
static kmutex_t nm_inolock;
/*
* Functions to allocate node id's starting from 1. Based on vmem routines.
* The vmem arena is extended in NM_INOQUANT chunks.
*/
namenodeno_alloc(void)
{
if (nno == 0) {
}
return (nno);
}
static void
namenodeno_init(void)
{
}
void
{
}
/*
* Insert a namenode into the nm_filevp_hash table.
*
* Each link has a unique namenode with a unique nm_mountvp field.
* The nm_filevp field of the namenode need not be unique, since a
* file descriptor may be mounted to multiple nodes at the same time.
* We hash on nm_filevp since that's what discriminates the searches
* in namefind() and nm_unmountall().
*/
void
{
}
/*
* Remove a namenode from the hash table, if present.
*/
void
{
return;
}
}
}
/*
* Search for a namenode that has a nm_filevp == vp and nm_mountpt == mnt.
* If mnt is NULL, return the first link with nm_filevp of vp.
* Returns namenode pointer on success, NULL on failure.
*/
struct namenode *
{
break;
return (np);
}
/*
* Force the unmouting of a file descriptor from ALL of the nodes
* that it was mounted to.
* At the present time, the only usage for this routine is in the
* event one end of a pipe was mounted. At the time the unmounted
* end gets closed down, the mounted end is forced to be unmounted.
*
* This routine searches the namenode hash list for all namenodes
* that have a nm_filevp field equal to vp. Each time one is found,
* the dounmount() routine is called. This causes the nm_unmount()
* routine to be called and thus, the file descriptor is unmounted
* from the node.
*
* At the start of this routine, the reference count for vp is
* incremented to protect the vnode from being released in the
* event the mount was the only thing keeping the vnode active.
* If that is the case, the VOP_CLOSE operation is applied to
* the vnode, prior to it being released.
*/
static int
{
int error = 0;
int realerr = 0;
/*
* For each namenode that is associated with the file:
* If the v_vfsp field is not namevfs, dounmount it. Otherwise,
* it was created in nm_open() and will be released in time.
* The following loop replicates some code from nm_find. That
* routine can't be used as is since the list isn't strictly
* consumed as it is traversed.
*/
while (nodep) {
/*
* If the vn_vfswlock fails, skip the vfs since
* somebody else may be unmounting it.
*/
continue;
}
/*
* Can't hold ntable_lock across call to do_unmount
* because nm_unmount tries to acquire it. This means
* there is a window where another mount of vp can
* happen so it is possible that after nm_unmountall
* there are still some mounts. This situation existed
* without MT locking because dounmount can sleep
* so another mount could happen during that time.
* This situation is unlikely and doesn't really cause
* any problems.
*/
/*
* Since we dropped the ntable_lock, we
* have to start over from the beginning.
* If for some reasons dounmount() fails,
* start from beginning means that we will keep on
* trying unless another thread unmounts it for us.
*/
} else
}
return (realerr);
}
/*
* Force the unmouting of a file descriptor from ALL of the nodes
* that it was mounted to. XXX: fifo_close() calls this routine.
*
* nm_umountall() may return EBUSY.
* nm_unmountall() will keep on trying until it succeeds.
*/
int
{
int error;
/*
* Nm_umuontall() returns only if it succeeds or
* return with error EBUSY. If EBUSY, that means
* it cannot acquire the lock on the covered vnode,
* and we will keep on trying.
*/
for (;;) {
break;
}
return (error);
}
/*
* Mount a file descriptor onto the node in the file system.
* Create a new vnode, update the attributes with info from the
* file descriptor and the mount point. The mask, mode, uid, gid,
* atime, mtime and ctime are taken from the mountpt. Link count is
* set to one, the file system id is namedev and nodeid is unique
* for each mounted object. Other attributes are taken from mount point.
* Make sure user is owner (or root) with write permissions on mount point.
* Hash the new vnode and return 0.
* Upon entry to this routine, the file descriptor is in the
* fd field of a struct namefd. Copy that structure from user
* space and retrieve the file descriptor.
*/
static int
{
char *resource_name;
char *resource_nodetype;
int error = 0;
/*
* Get the file descriptor from user space.
* Make sure the file descriptor is valid and has an
* associated file pointer.
* If so, extract the vnode from the file pointer.
*/
return (EINVAL);
return (EFAULT);
return (EBADF);
/*
* If the mount point already has something mounted
* on it, disallow this mount. (This restriction may
* be removed in a later release).
* Or unmount has completed but the namefs ROOT vnode
* count has not decremented to zero, disallow this mount.
*/
return (EBUSY);
}
return (EINVAL);
}
/*
* If the fd being mounted refers to neither a door nor a stream,
* make sure the caller is privileged.
*/
/* fd is neither a stream nor a door */
return (EINVAL);
}
}
/*
* Make sure the file descriptor is not the root of some
* file system.
* If it's not, create a reference and allocate a namenode
* to represent this mount request.
*/
return (EBUSY);
}
goto out;
goto out;
/*
* Make sure the user is the owner of the mount point
* or has sufficient privileges.
*/
goto out;
/*
* Make sure the user has write permissions on the
* mount point (or has sufficient privileges).
*/
goto out;
}
/*
* allow the mount to succeed.
*/
if (vn_has_flocks(filevp)) {
goto out;
}
/*
* Initialize the namenode.
*/
}
/*
* The attributes for the mounted file descriptor were initialized
* above by applying VOP_GETATTR to the mount point. Some of
* the fields of the attributes structure will be overwritten
* by the attributes from the file descriptor.
*/
/*
* Initialize new vnode structure for the mounted file descriptor.
*/
/*
* Initialize the vfs structure.
*/
vfsp->vfs_bcount = 0;
/*
* Set the name we mounted from.
*/
case VPROC: /* VOP_GETATTR() translates this to VREG */
default: resource_nodetype = "resource"; break;
}
if (error == 0) {
} else {
"unspecified_%s", resource_nodetype);
}
/*
* Insert the namenode.
*/
return (0);
out:
return (error);
}
/*
* Unmount a file descriptor from a node in the file system.
* If the user is not the owner of the file and is not privileged,
* the request is denied.
* Otherwise, remove the namenode from the hash list.
* If the mounted file descriptor was that of a stream and this
* was the last mount of the stream, turn off the STRMOUNT flag.
* If the rootvp is referenced other than through the mount,
* nm_inactive will clean up.
*/
static int
{
/*
* forced unmount is not supported by this file system
* and thus, ENOTSUP, is being returned.
*/
return (ENOTSUP);
}
return (EPERM);
}
} else {
}
}
return (0);
}
/*
* Create a reference to the root of a mounted file descriptor.
* This routine is called from lookupname() in the event a path
* is being searched that has a mounted file descriptor in it.
*/
static int
{
return (0);
}
/*
* Return in sp the status of this file system.
*/
static int
{
return (0);
}
/*
* Since this file system has no disk blocks of its own, apply
* the VOP_FSYNC operation on the mounted file descriptor.
*/
static int
{
return (0);
if (flag & SYNC_CLOSE)
}
/*
* File system initialization routine. Save the file system type,
* establish a file system device number and initialize nm_filevp_hash[].
*/
int
{
static const fs_operation_def_t nm_vfsops_template[] = {
};
static const fs_operation_def_t nm_dummy_vfsops_template[] = {
};
int error;
int dev;
if (error != 0) {
return (error);
}
if (error != 0) {
(void) vfs_freevfsops_by_type(fstype);
return (error);
}
if (error != 0) {
(void) vfs_freevfsops_by_type(fstype);
return (error);
}
namefstype = fstype;
dev = 0;
}
return (0);
}
static mntopts_t nm_mntopts = {
NULL,
0
};
"namefs",
};
/*
* Module linkage information for the kernel.
*/
};
static struct modlinkage modlinkage = {
};
int
_init(void)
{
return (mod_install(&modlinkage));
}
int
_fini(void)
{
return (EBUSY);
}
int
{
}