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]
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <sys/atomic.h>
27 #include <sys/cmn_err.h>
28 #include <sys/errno.h>
29 #include <sys/mount.h>
30 #include <sharefs/sharefs.h>
31 #include <sys/vfs_opreg.h>
32 #include <sys/policy.h>
33 #include <sys/sunddi.h>
34 #include <sys/sysmacros.h>
35 #include <sys/systm.h>
37 #include <sys/mntent.h>
41 * Kernel sharetab filesystem.
43 * This is a pseudo filesystem which exports information about shares currently
44 * in kernel memory. The only element of the pseudo filesystem is a file.
46 * This file contains functions that interact with the VFS layer.
48 * sharetab sharefs_datanode_t sharefs.c
52 vnodeops_t
*sharefs_ops_data
;
54 static const fs_operation_def_t sharefs_vfstops
[];
55 static gfs_opsvec_t sharefs_opsvec
[];
57 static int sharefs_init(int, char *);
60 * The sharefs system call.
62 static struct sysent sharefs_sysent
= {
64 SE_32RVAL1
| SE_ARGC
| SE_NOUNLOAD
,
68 static struct modlsys modlsys
= {
74 #ifdef _SYSCALL32_IMPL
75 static struct modlsys modlsys32
= {
77 "sharefs syscall (32-bit)",
80 #endif /* _SYSCALL32_IMPL */
85 static mntopts_t sharefs_mntopts
= {
90 static vfsdef_t vfw
= {
94 VSW_HASPROTO
| VSW_ZMOUNT
,
98 extern struct mod_ops mod_fsops
;
100 static struct modlfs modlfs
= {
102 "sharetab filesystem",
106 static struct modlinkage modlinkage
= {
110 #ifdef _SYSCALL32_IMPL
119 return (mod_install(&modlinkage
));
123 _info(struct modinfo
*modinfop
)
125 return (mod_info(&modlinkage
, modinfop
));
132 * The sharetab filesystem cannot be unloaded.
138 * Filesystem initialization.
141 static int sharefs_fstype
;
142 static major_t sharefs_major
;
143 static minor_t sharefs_minor
;
145 static gfs_opsvec_t sharefs_opsvec
[] = {
146 { "sharefs sharetab file", sharefs_tops_data
, &sharefs_ops_data
},
152 sharefs_init(int fstype
, char *name
)
157 sharefs_fstype
= fstype
;
158 if (error
= vfs_setfsops(fstype
, sharefs_vfstops
, &vfsops
)) {
159 cmn_err(CE_WARN
, "sharefs_init: bad vfs ops template");
163 if (error
= gfs_make_opsvec(sharefs_opsvec
)) {
164 (void) vfs_freevfsops(vfsops
);
168 if ((sharefs_major
= getudev()) == (major_t
)-1) {
170 "sharefs_init: can't get unique device number");
174 sharefs_sharetab_init();
183 sharefs_mount(vfs_t
*vfsp
, vnode_t
*mvp
, struct mounta
*uap
, cred_t
*cr
)
188 if (secpolicy_fs_mount(cr
, mvp
, vfsp
) != 0)
191 if ((uap
->flags
& MS_OVERLAY
) == 0 &&
192 (mvp
->v_count
> 1 || (mvp
->v_flag
& VROOT
)))
195 data
= kmem_alloc(sizeof (sharefs_vfs_t
), KM_SLEEP
);
198 * Initialize vfs fields
200 vfsp
->vfs_bsize
= DEV_BSIZE
;
201 vfsp
->vfs_fstype
= sharefs_fstype
;
203 dev
= makedevice(sharefs_major
,
204 atomic_inc_32_nv(&sharefs_minor
) & L_MAXMIN32
);
205 } while (vfs_devismounted(dev
));
206 vfs_make_fsid(&vfsp
->vfs_fsid
, dev
, sharefs_fstype
);
207 vfsp
->vfs_data
= data
;
213 data
->sharefs_vfs_root
= sharefs_create_root_file(vfsp
);
219 sharefs_unmount(vfs_t
*vfsp
, int flag
, struct cred
*cr
)
223 if (secpolicy_fs_unmount(cr
, vfsp
) != 0)
227 * We do not currently support forced unmounts
233 * We should never have a reference count of less than 2: one for the
234 * caller, one for the root vnode.
236 ASSERT(vfsp
->vfs_count
>= 2);
239 * Any active vnodes will result in a hold on the root vnode
241 data
= vfsp
->vfs_data
;
242 if (data
->sharefs_vfs_root
->v_count
> 1)
246 * Only allow an unmount iff there are no entries in memory.
248 rw_enter(&sharetab_lock
, RW_READER
);
249 if (sharetab_size
!= 0) {
250 rw_exit(&sharetab_lock
);
253 rw_exit(&sharetab_lock
);
256 * Release the last hold on the root vnode
258 VN_RELE(data
->sharefs_vfs_root
);
260 kmem_free(data
, sizeof (sharefs_vfs_t
));
266 sharefs_root(vfs_t
*vfsp
, vnode_t
**vpp
)
268 sharefs_vfs_t
*data
= vfsp
->vfs_data
;
270 *vpp
= data
->sharefs_vfs_root
;
277 sharefs_statvfs(vfs_t
*vfsp
, statvfs64_t
*sp
)
282 bzero(sp
, sizeof (*sp
));
283 sp
->f_bsize
= DEV_BSIZE
;
284 sp
->f_frsize
= DEV_BSIZE
;
286 sp
->f_ffree
= sp
->f_favail
= INT_MAX
- total
;
287 (void) cmpldev(&d32
, vfsp
->vfs_dev
);
289 (void) strlcpy(sp
->f_basetype
, vfssw
[vfsp
->vfs_fstype
].vsw_name
,
290 sizeof (sp
->f_basetype
));
291 sp
->f_flag
= vf_to_stf(vfsp
->vfs_flag
);
292 sp
->f_namemax
= SHAREFS_NAME_MAX
;
293 (void) strlcpy(sp
->f_fstr
, "sharefs", sizeof (sp
->f_fstr
));
298 static const fs_operation_def_t sharefs_vfstops
[] = {
299 { VFSNAME_MOUNT
, { .vfs_mount
= sharefs_mount
} },
300 { VFSNAME_UNMOUNT
, { .vfs_unmount
= sharefs_unmount
} },
301 { VFSNAME_ROOT
, { .vfs_root
= sharefs_root
} },
302 { VFSNAME_STATVFS
, { .vfs_statvfs
= sharefs_statvfs
} },