2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * osi_vfsops.c for SOLARIS
13 #include <afsconfig.h>
14 #include "afs/param.h"
19 #include "afs/sysincludes.h" /* Standard vendor system headers */
20 #include "afsincludes.h" /* Afs-based standard headers */
21 #include "afs/afs_stats.h" /* statistics stuff */
23 #include "h/syscall.h"
28 struct vfs *afs_globalVFS = 0;
29 struct vcache *afs_globalVp = 0;
31 #if defined(AFS_SUN57_64BIT_ENV)
32 extern struct sysent sysent32[];
38 afs_mount(struct vfs *afsp, struct vnode *amvp, struct mounta *uap,
39 struct AFS_UCRED *credp)
44 AFS_STATCNT(afs_mount);
46 #if defined(AFS_SUN510_ENV)
47 if (secpolicy_fs_mount(credp, amvp, afsp) != 0) {
49 if (!afs_osi_suser(credp)) {
54 afsp->vfs_fstype = afsfstype;
56 if (afs_globalVFS) { /* Don't allow remounts. */
62 afsp->vfs_bsize = 8192;
63 afsp->vfs_fsid.val[0] = AFS_VFSMAGIC; /* magic */
64 afsp->vfs_fsid.val[1] = AFS_VFSFSID;
65 afsp->vfs_dev = AFS_VFSMAGIC;
71 #if defined(AFS_SUN58_ENV)
73 afs_unmount(struct vfs *afsp, int flag, struct AFS_UCRED *credp)
76 afs_unmount(struct vfs *afsp, struct AFS_UCRED *credp)
80 AFS_STATCNT(afs_unmount);
82 #if defined(AFS_SUN510_ENV)
83 if (secpolicy_fs_unmount(credp, afsp) != 0) {
85 if (!afs_osi_suser(credp)) {
98 afs_root(struct vfs *afsp, struct vnode **avpp)
100 register afs_int32 code = 0;
101 struct vrequest treq;
102 register struct vcache *tvp = 0;
103 struct proc *proc = ttoproc(curthread);
104 struct vnode *vp = afsp->vfs_vnodecovered;
107 /* Potential deadlock:
108 * afs_root is called with the Vnode's v_lock locked. Set VVFSLOCK
109 * and drop the v_lock if we need to make an RPC to complete this
110 * request. There used to be a deadlock on the global lock until
111 * we stopped calling iget while holding the global lock.
116 AFS_STATCNT(afs_root);
118 if (afs_globalVp && (afs_globalVp->states & CStatd)) {
121 if (MUTEX_HELD(&vp->v_lock)) {
122 vp->v_flag |= VVFSLOCK;
124 mutex_exit(&vp->v_lock);
128 afs_PutVCache(afs_globalVp);
132 if (!(code = afs_InitReq(&treq, proc->p_cred))
133 && !(code = afs_CheckInit())) {
134 tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
135 /* we really want this to stay around */
143 VN_HOLD(AFSTOV(tvp));
144 mutex_enter(&AFSTOV(tvp)->v_lock);
145 AFSTOV(tvp)->v_flag |= VROOT;
146 mutex_exit(&AFSTOV(tvp)->v_lock);
148 afs_globalVFS = afsp;
152 afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *avpp,
153 ICL_TYPE_INT32, code);
157 mutex_enter(&vp->v_lock);
158 vp->v_flag &= ~VVFSLOCK;
159 if (vp->v_flag & VVFSWAIT) {
160 vp->v_flag &= ~VVFSWAIT;
161 cv_broadcast(&vp->v_cv);
170 afs_statvfs(struct vfs *afsp, struct statvfs64 *abp)
173 afs_statvfs(struct vfs *afsp, struct statvfs *abp)
178 AFS_STATCNT(afs_statfs);
180 abp->f_frsize = 1024;
181 abp->f_favail = 9000000;
182 abp->f_bsize = afsp->vfs_bsize;
183 abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
184 abp->f_ffree = 9000000;
185 abp->f_fsid = (AFS_VFSMAGIC << 16) || AFS_VFSFSID;
192 afs_sync(struct vfs *afsp, short flags, struct AFS_UCRED *credp)
198 afs_vget(struct vfs *afsp, struct vnode **avcp, struct fid *fidp)
200 cred_t *credp = CRED();
201 struct vrequest treq;
206 AFS_STATCNT(afs_vget);
209 if (!(code = afs_InitReq(&treq, credp))) {
210 code = afs_osi_vget((struct vcache **)avcp, fidp, &treq);
213 afs_Trace3(afs_iclSetp, CM_TRACE_VGET, ICL_TYPE_POINTER, *avcp,
214 ICL_TYPE_INT32, treq.uid, ICL_TYPE_FID, fidp);
215 code = afs_CheckCode(code, &treq, 42);
221 /* This is only called by vfs_mount when afs is going to be mounted as root.
222 * Since we don't support diskless clients we shouldn't come here.
224 int afsmountroot = 0;
225 afs_mountroot(struct vfs *afsp, whymountroot_t why)
228 AFS_STATCNT(afs_mountroot);
234 /* afs_swapvp is called to setup swapping over the net for diskless clients.
238 afs_swapvp(struct vfs *afsp, struct vnode **avpp, char *nm)
241 AFS_STATCNT(afs_swapvp);
248 #ifdef AFS_SUN510_ENV
249 /* The following list must always be NULL-terminated */
250 const fs_operation_def_t afs_vfsops_template[] = {
251 VFSNAME_MOUNT, afs_mount,
252 VFSNAME_UNMOUNT, afs_unmount,
253 VFSNAME_ROOT, afs_root,
254 VFSNAME_STATVFS, afs_statvfs,
255 VFSNAME_SYNC, afs_sync,
256 VFSNAME_VGET, afs_vget,
257 VFSNAME_MOUNTROOT, afs_mountroot,
258 VFSNAME_FREEVFS, fs_freevfs,
261 struct vfsops *afs_vfsopsp;
263 struct vfsops Afs_vfsops = {
272 #if defined(AFS_SUN58_ENV)
280 * afsinit - intialize VFS
282 int (*ufs_iallocp) ();
283 void (*ufs_iupdatp) ();
285 void (*ufs_itimes_nolockp) ();
287 int (*afs_orig_ioctl) (), (*afs_orig_ioctl32) ();
288 int (*afs_orig_setgroups) (), (*afs_orig_setgroups32) ();
290 #ifndef AFS_SUN510_ENV
291 struct ill_s *ill_g_headp = 0;
296 extern struct fs_operation_def afs_vnodeops_template[];
298 #if !defined(AFS_NONFSTRANS)
299 int (*nfs_rfsdisptab_v2) ();
300 int (*nfs_rfsdisptab_v3) ();
301 int (*nfs_acldisptab_v2) ();
302 int (*nfs_acldisptab_v3) ();
304 int (*nfs_checkauth) ();
307 extern Afs_syscall();
310 do_mod_lookup(const char * mod, const char * sym)
314 ptr = modlookup(mod, sym);
316 afs_warn("modlookup failed for symbol '%s' in module '%s'\n",
323 #ifdef AFS_SUN510_ENV
324 afsinit(int fstype, char *dummy)
326 afsinit(struct vfssw *vfsswp, int fstype)
329 extern int afs_xioctl();
330 extern int afs_xsetgroups();
332 AFS_STATCNT(afsinit);
334 afs_orig_setgroups = sysent[SYS_setgroups].sy_callc;
335 afs_orig_ioctl = sysent[SYS_ioctl].sy_call;
336 sysent[SYS_setgroups].sy_callc = afs_xsetgroups;
337 sysent[SYS_ioctl].sy_call = afs_xioctl;
339 #if defined(AFS_SUN57_64BIT_ENV)
340 afs_orig_setgroups32 = sysent32[SYS_setgroups].sy_callc;
341 afs_orig_ioctl32 = sysent32[SYS_ioctl].sy_call;
342 sysent32[SYS_setgroups].sy_callc = afs_xsetgroups;
343 sysent32[SYS_ioctl].sy_call = afs_xioctl;
344 #endif /* AFS_SUN57_64BIT_ENV */
346 #ifdef AFS_SUN510_ENV
347 vfs_setfsops(fstype, afs_vfsops_template, &afs_vfsopsp);
349 vn_make_ops("afs", afs_vnodeops_template, &afs_ops);
350 #else /* !AFS_SUN510_ENV */
351 vfsswp->vsw_vfsops = &Afs_vfsops;
353 #endif /* !AFS_SUN510_ENV */
356 #if !defined(AFS_NONFSTRANS)
357 nfs_rfsdisptab_v2 = (int (*)()) do_mod_lookup("nfssrv", "rfsdisptab_v2");
358 if (nfs_rfsdisptab_v2 != NULL) {
359 nfs_acldisptab_v2 = (int (*)()) do_mod_lookup("nfssrv", "acldisptab_v2");
360 if (nfs_acldisptab_v2 != NULL) {
361 afs_xlatorinit_v2(nfs_rfsdisptab_v2, nfs_acldisptab_v2);
364 nfs_rfsdisptab_v3 = (int (*)()) do_mod_lookup("nfssrv", "rfsdisptab_v3");
365 if (nfs_rfsdisptab_v3 != NULL) {
366 nfs_acldisptab_v3 = (int (*)()) do_mod_lookup("nfssrv", "acldisptab_v3");
367 if (nfs_acldisptab_v3 != NULL) {
368 afs_xlatorinit_v3(nfs_rfsdisptab_v3, nfs_acldisptab_v3);
372 nfs_checkauth = (int (*)()) do_mod_lookup("nfssrv", "checkauth");
373 #endif /* !AFS_NONFSTRANS */
375 ufs_iallocp = (int (*)()) do_mod_lookup("ufs", "ufs_ialloc");
376 ufs_iupdatp = (void (*)()) do_mod_lookup("ufs", "ufs_iupdat");
377 ufs_igetp = (int (*)()) do_mod_lookup("ufs", "ufs_iget");
378 ufs_itimes_nolockp = (void (*)()) do_mod_lookup("ufs", "ufs_itimes_nolock");
380 if (!ufs_iallocp || !ufs_iupdatp || !ufs_itimes_nolockp || !ufs_igetp) {
381 afs_warn("AFS to UFS mapping cannot be fully initialised\n");
384 #if !defined(AFS_SUN510_ENV)
385 ill_g_headp = (struct ill_s *) do_mod_lookup("ip", "ill_g_head");
386 #endif /* !AFS_SUN510_ENV */
393 #ifdef AFS_SUN510_ENV
394 static struct vfsdef_v3 afs_vfsdef = {
401 static struct vfssw afs_vfw = {
409 static struct sysent afssysent = {
415 /* inter-module dependencies */
416 char _depends_on[] = "drv/ip drv/udp strmod/rpcmod";
419 * Info/Structs to link the afs module into the kernel
421 extern struct mod_ops mod_fsops;
422 extern struct mod_ops mod_syscallops;
424 static struct modlfs afsmodlfs = {
427 #ifdef AFS_SUN510_ENV
434 static struct modlsys afsmodlsys = {
436 "afs syscall interface",
440 /** The two structures afssysent32 and afsmodlsys32 are being added
441 * for supporting 32 bit syscalls. In Solaris 7 there are two system
442 * tables viz. sysent ans sysent32. 32 bit applications use sysent32.
443 * Since most of our user space binaries are going to be 32 bit
444 * we need to attach to sysent32 also. Note that the entry into AFS
445 * land still happens through Afs_syscall irrespective of whether we
446 * land here from sysent or sysent32
449 #if defined(AFS_SUN57_64BIT_ENV)
450 extern struct mod_ops mod_syscallops32;
452 static struct modlsys afsmodlsys32 = {
454 "afs syscall interface(32 bit)",
460 static struct modlinkage afs_modlinkage = {
463 #ifdef AFS_SUN57_64BIT_ENV
464 (void *)&afsmodlsys32,
470 /** This is the function that modload calls when loading the afs kernel
471 * extensions. The solaris modload program searches for the _init
472 * function in a module and calls it when modloading
477 char *sysn, *mod_getsysname();
479 extern char *sysbind;
480 extern struct bind *sb_hashtab[];
481 struct modctl *mp = 0;
486 if ((!(mp = mod_find_by_filename("fs", "ufs"))
487 && !(mp = mod_find_by_filename(NULL, "/kernel/fs/ufs"))
488 && !(mp = mod_find_by_filename(NULL, "sys/ufs"))) || (mp
493 ("ufs module must be loaded before loading afs; use modload /kernel/fs/ufs\n");
496 #ifndef AFS_NONFSTRANS
497 #if defined(AFS_SUN55_ENV)
498 if ((!(mp = mod_find_by_filename("misc", "nfssrv"))
499 && !(mp = mod_find_by_filename(NULL, NFSSRV))
500 && !(mp = mod_find_by_filename(NULL, NFSSRV_V9))) || (mp
505 ("misc/nfssrv module must be loaded before loading afs with nfs-xlator\n");
508 #else /* !AFS_SUN55_ENV */
509 #if defined(AFS_SUN52_ENV)
510 if ((!(mp = mod_find_by_filename("fs", "nfs"))
511 && !(mp = mod_find_by_filename(NULL, "/kernel/fs/nfs"))
512 && !(mp = mod_find_by_filename(NULL, "sys/nfs"))) || (mp
517 ("fs/nfs module must be loaded before loading afs with nfs-xlator\n");
520 #endif /* AFS_SUN52_ENV */
521 #endif /* AFS_SUN55_ENV */
522 #endif /* !AFS_NONFSTRANS */
523 #if !defined(AFS_SUN58_ENV)
525 * Re-read the /etc/name_to_sysnum file to make sure afs isn't added after
526 * reboot. Ideally we would like to call modctl_read_sysbinding_file() but
527 * unfortunately in Solaris 2.2 it became a local function so we have to do
528 * the read_binding_file() direct call with the appropriate text file and
529 * system call hashtable. make_syscallname actually copies "afs" to the
530 * proper slot entry and we also actually have to properly initialize the
531 * global sysent[AFS_SYSCALL] entry!
535 #define SYSBINDFILE "/etc/name_to_sysnum"
536 #endif /* SYSBINDFILE */
537 read_binding_file(SYSBINDFILE, sb_hashtab);
538 #else /* !AFS_SUN53_ENV */
539 read_binding_file(sysbind, sb_hashtab);
540 #endif /* AFS_SUN53_ENV */
541 make_syscallname("afs", AFS_SYSCALL);
543 if (sysent[AFS_SYSCALL].sy_call == nosys) {
544 if ((sysn = mod_getsysname(AFS_SYSCALL)) != NULL) {
545 sysent[AFS_SYSCALL].sy_lock =
546 (krwlock_t *) kobj_zalloc(sizeof(krwlock_t), KM_SLEEP);
547 rw_init(sysent[AFS_SYSCALL].sy_lock, "afs_syscall",
550 #else /* !AFS_SUN57_ENV */
551 RW_DEFAULT, DEFAULT_WT);
552 #endif /* AFS_SUN57_ENV */
555 #endif /* !AFS_SUN58_ENV */
557 osi_Init(); /* initialize global lock, etc */
559 code = mod_install(&afs_modlinkage);
564 struct modinfo *modp;
568 code = mod_info(&afs_modlinkage, modp);
580 sysent[SYS_setgroups].sy_callc = afs_orig_setgroups;
581 sysent[SYS_ioctl].sy_call = afs_orig_ioctl;
582 #if defined(AFS_SUN57_64BIT_ENV)
583 sysent32[SYS_setgroups].sy_callc = afs_orig_setgroups32;
584 sysent32[SYS_ioctl].sy_call = afs_orig_ioctl32;
587 code = mod_remove(&afs_modlinkage);