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"
17 #include "afs/sysincludes.h" /* Standard vendor system headers */
18 #include "afsincludes.h" /* Afs-based standard headers */
19 #include "afs/afs_stats.h" /* statistics stuff */
21 #include "h/syscall.h"
22 #if defined(AFS_SUN511_ENV)
23 #include <sys/vfs_opreg.h>
27 #include <sys/mount.h>
29 struct vfs
*afs_globalVFS
= 0;
30 struct vcache
*afs_globalVp
= 0;
32 #if defined(AFS_SUN5_64BIT_ENV)
33 extern struct sysent sysent32
[];
39 afs_mount(struct vfs
*afsp
, struct vnode
*amvp
, struct mounta
*uap
,
45 AFS_STATCNT(afs_mount
);
47 #if defined(AFS_SUN510_ENV)
48 if (secpolicy_fs_mount(credp
, amvp
, afsp
) != 0) {
50 if (!afs_osi_suser(credp
)) {
55 afsp
->vfs_fstype
= afsfstype
;
57 if (afs_globalVFS
) { /* Don't allow remounts. */
63 afsp
->vfs_bsize
= 8192;
64 afsp
->vfs_fsid
.val
[0] = AFS_VFSMAGIC
; /* magic */
65 afsp
->vfs_fsid
.val
[1] = AFS_VFSFSID
;
66 afsp
->vfs_dev
= AFS_VFSMAGIC
;
82 afs_unmount(struct vfs
*afsp
, int flag
, afs_ucred_t
*credp
)
84 struct vcache
*rootvp
= NULL
;
87 AFS_STATCNT(afs_unmount
);
89 #if defined(AFS_SUN510_ENV)
90 if (secpolicy_fs_unmount(credp
, afsp
) != 0) {
92 if (!afs_osi_suser(credp
)) {
98 if (flag
& MS_FORCE
) {
103 /* We should have one reference from the caller, and one reference for the
104 * root vnode; any more and someone is still referencing something */
105 if (afsp
->vfs_count
> 2) {
110 /* The root vnode should have one ref for the mount; any more, and someone
111 * else is using the root vnode */
112 if (afs_globalVp
&& VREFCOUNT_GT(afs_globalVp
, 1)) {
117 afsp
->vfs_flag
|= VFS_UNMOUNTED
;
120 /* release the root vnode, which should be the last reference to us
121 * besides the caller of afs_unmount */
122 rootvp
= afs_globalVp
;
124 AFS_RELE(AFSTOV(rootvp
));
132 gafs_freevfs(struct vfs
*afsp
)
142 afs_root(struct vfs
*afsp
, struct vnode
**avpp
)
145 struct vrequest treq
;
146 struct vcache
*tvp
= 0;
148 struct proc
*proc
= ttoproc(curthread
);
149 struct vnode
*vp
= afsp
->vfs_vnodecovered
;
152 /* Potential deadlock:
153 * afs_root is called with the Vnode's v_lock locked. Set VVFSLOCK
154 * and drop the v_lock if we need to make an RPC to complete this
155 * request. There used to be a deadlock on the global lock until
156 * we stopped calling iget while holding the global lock.
161 AFS_STATCNT(afs_root
);
164 if (afs_globalVp
&& (afs_globalVp
->f
.states
& CStatd
)) {
167 if (MUTEX_HELD(&vp
->v_lock
)) {
168 vp
->v_flag
|= VVFSLOCK
;
170 mutex_exit(&vp
->v_lock
);
179 if (!(code
= afs_InitReq(&treq
, proc
->p_cred
))
180 && !(code
= afs_CheckInit())) {
181 tvp
= afs_GetVCache(&afs_rootFid
, &treq
, NULL
, NULL
);
182 /* we really want this to stay around */
185 /* someone else got there before us! */
197 mutex_enter(&AFSTOV(tvp
)->v_lock
);
198 AFSTOV(tvp
)->v_flag
|= VROOT
;
199 mutex_exit(&AFSTOV(tvp
)->v_lock
);
201 afs_globalVFS
= afsp
;
205 afs_Trace2(afs_iclSetp
, CM_TRACE_VFSROOT
, ICL_TYPE_POINTER
, *avpp
,
206 ICL_TYPE_INT32
, code
);
210 mutex_enter(&vp
->v_lock
);
211 vp
->v_flag
&= ~VVFSLOCK
;
212 if (vp
->v_flag
& VVFSWAIT
) {
213 vp
->v_flag
&= ~VVFSWAIT
;
214 cv_broadcast(&vp
->v_cv
);
222 afs_statvfs(struct vfs
*afsp
, struct statvfs64
*abp
)
226 AFS_STATCNT(afs_statfs
);
228 abp
->f_frsize
= 1024;
229 abp
->f_bsize
= afsp
->vfs_bsize
;
230 abp
->f_blocks
= abp
->f_bfree
= abp
->f_bavail
= abp
->f_files
=
231 abp
->f_favail
= abp
->f_ffree
= AFS_VFS_FAKEFREE
;
232 abp
->f_fsid
= (AFS_VFSMAGIC
<< 16) || AFS_VFSFSID
;
239 afs_sync(struct vfs
*afsp
, short flags
, afs_ucred_t
*credp
)
245 afs_vget(struct vfs
*afsp
, struct vnode
**avcp
, struct fid
*fidp
)
247 cred_t
*credp
= CRED();
248 struct vrequest treq
;
253 AFS_STATCNT(afs_vget
);
256 if (!(code
= afs_InitReq(&treq
, credp
))) {
257 struct vcache
*tvc
= NULL
;
258 code
= afs_osi_vget(&tvc
, fidp
, &treq
);
264 afs_Trace3(afs_iclSetp
, CM_TRACE_VGET
, ICL_TYPE_POINTER
, *avcp
,
265 ICL_TYPE_INT32
, treq
.uid
, ICL_TYPE_FID
, fidp
);
266 code
= afs_CheckCode(code
, &treq
, 42);
272 /* This is only called by vfs_mount when afs is going to be mounted as root.
273 * Since we don't support diskless clients we shouldn't come here.
275 int afsmountroot
= 0;
276 afs_mountroot(struct vfs
*afsp
, whymountroot_t why
)
279 AFS_STATCNT(afs_mountroot
);
285 /* afs_swapvp is called to setup swapping over the net for diskless clients.
289 afs_swapvp(struct vfs
*afsp
, struct vnode
**avpp
, char *nm
)
292 AFS_STATCNT(afs_swapvp
);
299 #if defined(AFS_SUN511_ENV)
300 /* The following list must always be NULL-terminated */
301 static const fs_operation_def_t afs_vfsops_template
[] = {
302 VFSNAME_MOUNT
, { .vfs_mount
= afs_mount
},
303 VFSNAME_UNMOUNT
, { .vfs_unmount
= afs_unmount
},
304 VFSNAME_ROOT
, { .vfs_root
= afs_root
},
305 VFSNAME_STATVFS
, { .vfs_statvfs
= afs_statvfs
},
306 VFSNAME_SYNC
, { .vfs_sync
= afs_sync
},
307 VFSNAME_VGET
, { .vfs_vget
= afs_vget
},
308 VFSNAME_MOUNTROOT
, { .vfs_mountroot
= afs_mountroot
},
309 VFSNAME_FREEVFS
, { .vfs_freevfs
= gafs_freevfs
},
312 struct vfsops
*afs_vfsopsp
;
313 #elif defined(AFS_SUN510_ENV)
314 /* The following list must always be NULL-terminated */
315 const fs_operation_def_t afs_vfsops_template
[] = {
316 VFSNAME_MOUNT
, afs_mount
,
317 VFSNAME_UNMOUNT
, afs_unmount
,
318 VFSNAME_ROOT
, afs_root
,
319 VFSNAME_STATVFS
, afs_statvfs
,
320 VFSNAME_SYNC
, afs_sync
,
321 VFSNAME_VGET
, afs_vget
,
322 VFSNAME_MOUNTROOT
, afs_mountroot
,
323 VFSNAME_FREEVFS
, gafs_freevfs
,
326 struct vfsops
*afs_vfsopsp
;
328 struct vfsops Afs_vfsops
= {
343 * afsinit - intialize VFS
345 int (*ufs_iallocp
) ();
346 void (*ufs_iupdatp
) ();
348 void (*ufs_itimes_nolockp
) ();
350 int (*afs_orig_ioctl
) (), (*afs_orig_ioctl32
) ();
351 int (*afs_orig_setgroups
) (), (*afs_orig_setgroups32
) ();
353 #ifndef AFS_SUN510_ENV
354 struct ill_s
*ill_g_headp
= 0;
359 extern struct fs_operation_def afs_vnodeops_template
[];
361 #if !defined(AFS_NONFSTRANS)
362 int (*nfs_rfsdisptab_v2
) ();
363 int (*nfs_rfsdisptab_v3
) ();
364 int (*nfs_acldisptab_v2
) ();
365 int (*nfs_acldisptab_v3
) ();
367 int (*nfs_checkauth
) ();
370 extern Afs_syscall();
373 do_mod_lookup(const char * mod
, const char * sym
)
377 ptr
= modlookup(mod
, sym
);
379 afs_warn("modlookup failed for symbol '%s' in module '%s'\n",
386 #ifdef AFS_SUN510_ENV
387 afsinit(int fstype
, char *dummy
)
389 afsinit(struct vfssw
*vfsswp
, int fstype
)
392 extern int afs_xioctl();
393 extern int afs_xsetgroups();
395 AFS_STATCNT(afsinit
);
397 afs_orig_setgroups
= sysent
[SYS_setgroups
].sy_callc
;
398 afs_orig_ioctl
= sysent
[SYS_ioctl
].sy_call
;
399 sysent
[SYS_setgroups
].sy_callc
= afs_xsetgroups
;
400 sysent
[SYS_ioctl
].sy_call
= afs_xioctl
;
402 #if defined(AFS_SUN5_64BIT_ENV)
403 afs_orig_setgroups32
= sysent32
[SYS_setgroups
].sy_callc
;
404 afs_orig_ioctl32
= sysent32
[SYS_ioctl
].sy_call
;
405 sysent32
[SYS_setgroups
].sy_callc
= afs_xsetgroups
;
406 sysent32
[SYS_ioctl
].sy_call
= afs_xioctl
;
407 #endif /* AFS_SUN5_64BIT_ENV */
409 #ifdef AFS_SUN510_ENV
410 vfs_setfsops(fstype
, afs_vfsops_template
, &afs_vfsopsp
);
412 vn_make_ops("afs", afs_vnodeops_template
, &afs_ops
);
413 #else /* !AFS_SUN510_ENV */
414 vfsswp
->vsw_vfsops
= &Afs_vfsops
;
416 #endif /* !AFS_SUN510_ENV */
419 #if !defined(AFS_NONFSTRANS)
420 nfs_rfsdisptab_v2
= (int (*)()) do_mod_lookup("nfssrv", "rfsdisptab_v2");
421 if (nfs_rfsdisptab_v2
!= NULL
) {
422 nfs_acldisptab_v2
= (int (*)()) do_mod_lookup("nfssrv", "acldisptab_v2");
423 if (nfs_acldisptab_v2
!= NULL
) {
424 afs_xlatorinit_v2(nfs_rfsdisptab_v2
, nfs_acldisptab_v2
);
427 nfs_rfsdisptab_v3
= (int (*)()) do_mod_lookup("nfssrv", "rfsdisptab_v3");
428 if (nfs_rfsdisptab_v3
!= NULL
) {
429 nfs_acldisptab_v3
= (int (*)()) do_mod_lookup("nfssrv", "acldisptab_v3");
430 if (nfs_acldisptab_v3
!= NULL
) {
431 afs_xlatorinit_v3(nfs_rfsdisptab_v3
, nfs_acldisptab_v3
);
435 nfs_checkauth
= (int (*)()) do_mod_lookup("nfssrv", "checkauth");
436 #endif /* !AFS_NONFSTRANS */
438 ufs_iallocp
= (int (*)()) do_mod_lookup("ufs", "ufs_ialloc");
439 ufs_iupdatp
= (void (*)()) do_mod_lookup("ufs", "ufs_iupdat");
440 ufs_igetp
= (int (*)()) do_mod_lookup("ufs", "ufs_iget");
441 ufs_itimes_nolockp
= (void (*)()) do_mod_lookup("ufs", "ufs_itimes_nolock");
443 if (!ufs_iallocp
|| !ufs_iupdatp
|| !ufs_itimes_nolockp
|| !ufs_igetp
) {
444 afs_warn("AFS to UFS mapping cannot be fully initialised\n");
447 #if !defined(AFS_SUN510_ENV)
448 ill_g_headp
= (struct ill_s
*) do_mod_lookup("ip", "ill_g_head");
449 #endif /* !AFS_SUN510_ENV */
456 #ifdef AFS_SUN510_ENV
457 #ifdef AFS_SUN511_ENV
458 static vfsdef_t afs_vfsdef
= {
466 static struct vfsdef_v3 afs_vfsdef
= {
474 static struct vfssw afs_vfw
= {
482 #ifndef AFS_SUN511_ENV
483 static struct sysent afssysent
= {
488 #endif /* AFS_SUN511_ENV */
491 * Info/Structs to link the afs module into the kernel
493 extern struct mod_ops mod_fsops
;
495 static struct modlfs afsmodlfs
= {
498 #ifdef AFS_SUN510_ENV
505 #ifdef AFS_SUN511_ENV
507 extern struct modldrv afs_modldrv
;
509 #else /* AFS_SUN511_ENV */
511 extern struct mod_ops mod_syscallops
;
512 static struct modlsys afsmodlsys
= {
514 "afs syscall interface",
518 /** The two structures afssysent32 and afsmodlsys32 are being added
519 * for supporting 32 bit syscalls. In Solaris 7 there are two system
520 * tables viz. sysent ans sysent32. 32 bit applications use sysent32.
521 * Since most of our user space binaries are going to be 32 bit
522 * we need to attach to sysent32 also. Note that the entry into AFS
523 * land still happens through Afs_syscall irrespective of whether we
524 * land here from sysent or sysent32
527 # if defined(AFS_SUN5_64BIT_ENV)
528 extern struct mod_ops mod_syscallops32
;
530 static struct modlsys afsmodlsys32
= {
532 "afs syscall interface(32 bit)",
536 #endif /* !AFS_SUN511_ENV */
539 static struct modlinkage afs_modlinkage
= {
542 #ifdef AFS_SUN511_ENV
543 (void *)&afs_modldrv
,
546 # ifdef AFS_SUN5_64BIT_ENV
547 (void *)&afsmodlsys32
,
549 #endif /* !AFS_SUN511_ENV */
557 sysent
[SYS_setgroups
].sy_callc
= afs_orig_setgroups
;
558 sysent
[SYS_ioctl
].sy_call
= afs_orig_ioctl
;
559 #if defined(AFS_SUN5_64BIT_ENV)
560 sysent32
[SYS_setgroups
].sy_callc
= afs_orig_setgroups32
;
561 sysent32
[SYS_ioctl
].sy_call
= afs_orig_ioctl32
;
566 /** This is the function that modload calls when loading the afs kernel
567 * extensions. The solaris modload program searches for the _init
568 * function in a module and calls it when modloading
573 char *sysn
, *mod_getsysname();
575 extern char *sysbind
;
576 extern struct bind
*sb_hashtab
[];
577 struct modctl
*mp
= 0;
582 if ((!(mp
= mod_find_by_filename("fs", "ufs"))
583 && !(mp
= mod_find_by_filename(NULL
, "/kernel/fs/ufs"))
584 && !(mp
= mod_find_by_filename(NULL
, "sys/ufs"))) || (mp
589 ("ufs module must be loaded before loading afs; use modload /kernel/fs/ufs\n");
592 #ifndef AFS_NONFSTRANS
593 if ((!(mp
= mod_find_by_filename("misc", "nfssrv"))
594 && !(mp
= mod_find_by_filename(NULL
, NFSSRV
))
595 && !(mp
= mod_find_by_filename(NULL
, NFSSRV_V9
))
596 && !(mp
= mod_find_by_filename(NULL
, NFSSRV_AMD64
))) || (mp
601 ("misc/nfssrv module must be loaded before loading afs with nfs-xlator\n");
604 #endif /* !AFS_NONFSTRANS */
607 osi_Init(); /* initialize global lock, etc */
609 code
= mod_install(&afs_modlinkage
);
611 /* we failed to load, so make sure we don't leave behind any
612 * references to our syscall handlers */
619 struct modinfo
*modp
;
623 code
= mod_info(&afs_modlinkage
, modp
);
635 code
= mod_remove(&afs_modlinkage
);