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