dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / kernel / fs / objfs / objfs_vfs.c
blobd65c5dc6009b592062cdd1d45b798b47c2229cc3
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <sys/atomic.h>
26 #include <sys/cmn_err.h>
27 #include <sys/errno.h>
28 #include <sys/mount.h>
29 #include <sys/objfs.h>
30 #include <sys/objfs_impl.h>
31 #include <sys/vfs.h>
32 #include <sys/policy.h>
33 #include <sys/sunddi.h>
34 #include <sys/sysmacros.h>
35 #include <sys/systm.h>
38 * Kernel object filesystem.
40 * This is a pseudo filesystem which exports information about currently loaded
41 * kernel objects. The root directory contains one directory for each loaded
42 * object, indexed by module name. Within each object directory is an ELF file,
43 * 'object', that contains information about the currently loaded module.
45 * This file contains functions that interact with the VFS layer. Each
46 * filesystem element is represented by a a different node.
48 * / objfs_rootnode_t objfs_root.c
49 * /<obj> objfs_odirnode_t objfs_odir.c
50 * /<obj>/object objfs_datanode_t objfs_data.c
52 * In addition, some common routines are found in the 'objfs_common.c' file.
55 static const struct vfsops objfs_vfsops;
57 static int objfs_init(int, char *);
60 * Module linkage
62 static mntopts_t objfs_mntopts = {
64 NULL
67 static vfsdef_t vfw = {
68 VFSDEF_VERSION,
69 "objfs",
70 objfs_init,
71 VSW_HASPROTO | VSW_ZMOUNT,
72 &objfs_mntopts,
75 extern struct mod_ops mod_fsops;
77 static struct modlfs modlfs = {
78 &mod_fsops, "kernel object filesystem", &vfw
81 static struct modlinkage modlinkage = {
82 MODREV_1, (void *)&modlfs, NULL
85 int
86 _init(void)
88 return (mod_install(&modlinkage));
91 int
92 _info(struct modinfo *modinfop)
94 return (mod_info(&modlinkage, modinfop));
97 int
98 _fini(void)
101 * The object filesystem cannot be unloaded.
103 return (EBUSY);
107 * Filesystem initialization.
110 static int objfs_fstype;
111 static major_t objfs_major;
112 static minor_t objfs_minor;
114 /* ARGSUSED */
115 static int
116 objfs_init(int fstype, char *name)
118 int error;
120 objfs_fstype = fstype;
121 if (error = vfs_setfsops(fstype, &objfs_vfsops)) {
122 cmn_err(CE_WARN, "objfs_init: bad fstype");
123 return (error);
126 if ((objfs_major = getudev()) == (major_t)-1) {
127 cmn_err(CE_WARN, "objfs_init: can't get unique device number");
128 objfs_major = 0;
131 objfs_data_init();
133 return (0);
137 * VFS entry points
139 static int
140 objfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
142 objfs_vfs_t *data;
143 dev_t dev;
145 if (secpolicy_fs_mount(cr, mvp, vfsp) != 0)
146 return (EPERM);
148 if (mvp->v_type != VDIR)
149 return (ENOTDIR);
151 if ((uap->flags & MS_OVERLAY) == 0 &&
152 (mvp->v_count > 1 || (mvp->v_flag & VROOT)))
153 return (EBUSY);
155 data = kmem_alloc(sizeof (objfs_vfs_t), KM_SLEEP);
158 * Initialize vfs fields
160 vfsp->vfs_bsize = DEV_BSIZE;
161 vfsp->vfs_fstype = objfs_fstype;
162 do {
163 dev = makedevice(objfs_major,
164 atomic_inc_32_nv(&objfs_minor) & L_MAXMIN32);
165 } while (vfs_devismounted(dev));
166 vfs_make_fsid(&vfsp->vfs_fsid, dev, objfs_fstype);
167 vfsp->vfs_data = data;
168 vfsp->vfs_dev = dev;
171 * Create root
173 data->objfs_vfs_root = objfs_create_root(vfsp);
175 return (0);
178 static int
179 objfs_unmount(vfs_t *vfsp, int flag, struct cred *cr)
181 objfs_vfs_t *data;
183 if (secpolicy_fs_unmount(cr, vfsp) != 0)
184 return (EPERM);
187 * We do not currently support forced unmounts
189 if (flag & MS_FORCE)
190 return (ENOTSUP);
193 * We should never have a reference count of less than 2: one for the
194 * caller, one for the root vnode.
196 ASSERT(vfsp->vfs_count >= 2);
199 * Any active vnodes will result in a hold on the root vnode
201 data = vfsp->vfs_data;
202 if (data->objfs_vfs_root->v_count > 1)
203 return (EBUSY);
206 * Release the last hold on the root vnode
208 VN_RELE(data->objfs_vfs_root);
210 kmem_free(data, sizeof (objfs_vfs_t));
212 return (0);
215 static int
216 objfs_root(vfs_t *vfsp, vnode_t **vpp)
218 objfs_vfs_t *data = vfsp->vfs_data;
220 *vpp = data->objfs_vfs_root;
221 VN_HOLD(*vpp);
223 return (0);
226 static int
227 objfs_statvfs(vfs_t *vfsp, statvfs64_t *sp)
229 dev32_t d32;
230 int total = objfs_nobjs();
232 bzero(sp, sizeof (*sp));
233 sp->f_bsize = DEV_BSIZE;
234 sp->f_frsize = DEV_BSIZE;
235 sp->f_files = total;
236 sp->f_ffree = sp->f_favail = INT_MAX - total;
237 (void) cmpldev(&d32, vfsp->vfs_dev);
238 sp->f_fsid = d32;
239 (void) strlcpy(sp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name,
240 sizeof (sp->f_basetype));
241 sp->f_flag = vf_to_stf(vfsp->vfs_flag);
242 sp->f_namemax = OBJFS_NAME_MAX;
243 (void) strlcpy(sp->f_fstr, "object", sizeof (sp->f_fstr));
245 return (0);
248 static const struct vfsops objfs_vfsops = {
249 .vfs_mount = objfs_mount,
250 .vfs_unmount = objfs_unmount,
251 .vfs_root = objfs_root,
252 .vfs_statvfs = objfs_statvfs,