Home | History | Annotate | Download | only in objfs
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27 
     28 
     29 #include <fs/fs_subr.h>
     30 
     31 #include <sys/errno.h>
     32 #include <sys/kmem.h>
     33 #include <sys/modctl.h>
     34 #include <sys/objfs.h>
     35 #include <sys/objfs_impl.h>
     36 #include <sys/vfs_opreg.h>
     37 #include <sys/systm.h>
     38 
     39 extern int last_module_id;
     40 
     41 static int objfs_root_do_lookup(vnode_t *, const char *, vnode_t **, ino64_t *,
     42     cred_t *, int, int *, pathname_t *);
     43 static int objfs_root_do_readdir(vnode_t *, void *, int *,
     44     offset_t *, offset_t *, void *, int);
     45 
     46 vnode_t *
     47 objfs_create_root(vfs_t *vfsp)
     48 {
     49 	vnode_t *vp = gfs_root_create(sizeof (objfs_rootnode_t), vfsp,
     50 	    objfs_ops_root, OBJFS_INO_ROOT, NULL, NULL, OBJFS_NAME_MAX,
     51 	    objfs_root_do_readdir, objfs_root_do_lookup);
     52 
     53 	return (vp);
     54 }
     55 
     56 /* ARGSUSED */
     57 static int
     58 objfs_root_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
     59 	caller_context_t *ct)
     60 {
     61 	vap->va_type = VDIR;
     62 	vap->va_mode = 0555;
     63 	vap->va_nodeid = gfs_file_inode(vp);
     64 	vap->va_nlink = objfs_nobjs() + 2;
     65 	vap->va_size = vap->va_nlink;
     66 	vap->va_atime.tv_sec = vp->v_vfsp->vfs_mtime;
     67 	vap->va_atime.tv_nsec = 0;
     68 	vap->va_mtime = vap->va_ctime = vap->va_atime;
     69 	return (objfs_common_getattr(vp, vap));
     70 }
     71 
     72 /* ARGSUSED */
     73 static int
     74 objfs_root_do_lookup(vnode_t *vp, const char *nm, vnode_t **vpp, ino64_t *inop,
     75     cred_t *cr, int flags, int *deflags, pathname_t *rpnp)
     76 {
     77 	int result = ENOENT;
     78 	struct modctl *mp;
     79 
     80 	/*
     81 	 * Run through all the loaded modules on the system looking for
     82 	 * a matching module name.
     83 	 */
     84 	mutex_enter(&mod_lock);
     85 	mp = &modules;
     86 	do {
     87 		if (mp->mod_loaded &&
     88 		    strcmp(nm, mp->mod_modname) == 0) {
     89 			/*
     90 			 * We drop mod_lock in order to do allocations,
     91 			 * as modctls are persistent.
     92 			 */
     93 			mutex_exit(&mod_lock);
     94 			*vpp = objfs_create_odirnode(vp, mp);
     95 			*inop = OBJFS_INO_ODIR(mp->mod_id);
     96 			mutex_enter(&mod_lock);
     97 			result = 0;
     98 			break;
     99 		}
    100 	} while ((mp = mp->mod_next) != &modules);
    101 	mutex_exit(&mod_lock);
    102 
    103 	return (result);
    104 }
    105 
    106 /* ARGSUSED */
    107 int
    108 objfs_root_do_readdir(vnode_t *vp, void *dp, int *eofp,
    109     offset_t *offp, offset_t *nextp, void *data, int flags)
    110 {
    111 	struct modctl **mpp = data;
    112 	struct modctl *mp = *mpp;
    113 	struct dirent64 *odp = dp;
    114 
    115 	ASSERT(!(flags & V_RDDIR_ENTFLAGS));
    116 
    117 	mutex_enter(&mod_lock);
    118 
    119 	/* Check for EOF */
    120 	if (*offp >= last_module_id) {
    121 		*eofp = 1;
    122 		mutex_exit(&mod_lock);
    123 		return (0);
    124 	}
    125 
    126 	/*
    127 	 * Find the appropriate modctl
    128 	 */
    129 	while (mp->mod_id < *offp) {
    130 		mp = mp->mod_next;
    131 		ASSERT(mp != &modules);
    132 	}
    133 
    134 	while (!mp->mod_loaded && mp != &modules)
    135 		mp = mp->mod_next;
    136 
    137 	if (mp == &modules && *offp != 0) {
    138 		*eofp = 1;
    139 		mutex_exit(&mod_lock);
    140 		return (0);
    141 	}
    142 
    143 	/*
    144 	 * The modctl will not change, as they are persistent.
    145 	 */
    146 	mutex_exit(&mod_lock);
    147 
    148 	(void) strncpy(odp->d_name, mp->mod_modname, OBJFS_NAME_MAX);
    149 	odp->d_ino = OBJFS_INO_ODIR(mp->mod_id);
    150 	*offp = mp->mod_id;
    151 	*nextp = mp->mod_id + 1;
    152 
    153 	return (0);
    154 }
    155 
    156 /* ARGSUSED */
    157 static int
    158 objfs_root_readdir(vnode_t *vp, uio_t *uiop, cred_t *cr, int *eofp,
    159 	caller_context_t *ct, int flags)
    160 {
    161 	struct modctl *mp = &modules;
    162 
    163 	return (gfs_dir_readdir(vp, uiop, eofp, &mp, cr, ct, flags));
    164 }
    165 
    166 const fs_operation_def_t objfs_tops_root[] = {
    167 	{ VOPNAME_OPEN,		{ .vop_open = objfs_dir_open } },
    168 	{ VOPNAME_CLOSE,	{ .vop_close = objfs_common_close } },
    169 	{ VOPNAME_IOCTL,	{ .error = fs_inval } },
    170 	{ VOPNAME_GETATTR,	{ .vop_getattr = objfs_root_getattr } },
    171 	{ VOPNAME_ACCESS,	{ .vop_access = objfs_dir_access } },
    172 	{ VOPNAME_READDIR,	{ .vop_readdir = objfs_root_readdir } },
    173 	{ VOPNAME_LOOKUP,	{ .vop_lookup = gfs_vop_lookup } },
    174 	{ VOPNAME_SEEK,		{ .vop_seek = fs_seek } },
    175 	{ VOPNAME_INACTIVE,	{ .vop_inactive = gfs_vop_inactive } },
    176 	{ NULL }
    177 };
    178