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
;
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 code
= afs_osi_vget((struct vcache
**)avcp
, fidp
, &treq
);
260 afs_Trace3(afs_iclSetp
, CM_TRACE_VGET
, ICL_TYPE_POINTER
, *avcp
,
261 ICL_TYPE_INT32
, treq
.uid
, ICL_TYPE_FID
, fidp
);
262 code
= afs_CheckCode(code
, &treq
, 42);
268 /* This is only called by vfs_mount when afs is going to be mounted as root.
269 * Since we don't support diskless clients we shouldn't come here.
271 int afsmountroot
= 0;
272 afs_mountroot(struct vfs
*afsp
, whymountroot_t why
)
275 AFS_STATCNT(afs_mountroot
);
281 /* afs_swapvp is called to setup swapping over the net for diskless clients.
285 afs_swapvp(struct vfs
*afsp
, struct vnode
**avpp
, char *nm
)
288 AFS_STATCNT(afs_swapvp
);
295 #if defined(AFS_SUN511_ENV)
296 /* The following list must always be NULL-terminated */
297 static const fs_operation_def_t afs_vfsops_template
[] = {
298 VFSNAME_MOUNT
, { .vfs_mount
= afs_mount
},
299 VFSNAME_UNMOUNT
, { .vfs_unmount
= afs_unmount
},
300 VFSNAME_ROOT
, { .vfs_root
= afs_root
},
301 VFSNAME_STATVFS
, { .vfs_statvfs
= afs_statvfs
},
302 VFSNAME_SYNC
, { .vfs_sync
= afs_sync
},
303 VFSNAME_VGET
, { .vfs_vget
= afs_vget
},
304 VFSNAME_MOUNTROOT
, { .vfs_mountroot
= afs_mountroot
},
305 VFSNAME_FREEVFS
, { .vfs_freevfs
= gafs_freevfs
},
308 struct vfsops
*afs_vfsopsp
;
309 #elif defined(AFS_SUN510_ENV)
310 /* The following list must always be NULL-terminated */
311 const fs_operation_def_t afs_vfsops_template
[] = {
312 VFSNAME_MOUNT
, afs_mount
,
313 VFSNAME_UNMOUNT
, afs_unmount
,
314 VFSNAME_ROOT
, afs_root
,
315 VFSNAME_STATVFS
, afs_statvfs
,
316 VFSNAME_SYNC
, afs_sync
,
317 VFSNAME_VGET
, afs_vget
,
318 VFSNAME_MOUNTROOT
, afs_mountroot
,
319 VFSNAME_FREEVFS
, gafs_freevfs
,
322 struct vfsops
*afs_vfsopsp
;
324 struct vfsops Afs_vfsops
= {
339 * afsinit - intialize VFS
341 int (*ufs_iallocp
) ();
342 void (*ufs_iupdatp
) ();
344 void (*ufs_itimes_nolockp
) ();
346 int (*afs_orig_ioctl
) (), (*afs_orig_ioctl32
) ();
347 int (*afs_orig_setgroups
) (), (*afs_orig_setgroups32
) ();
349 #ifndef AFS_SUN510_ENV
350 struct ill_s
*ill_g_headp
= 0;
355 extern struct fs_operation_def afs_vnodeops_template
[];
357 #if !defined(AFS_NONFSTRANS)
358 int (*nfs_rfsdisptab_v2
) ();
359 int (*nfs_rfsdisptab_v3
) ();
360 int (*nfs_acldisptab_v2
) ();
361 int (*nfs_acldisptab_v3
) ();
363 int (*nfs_checkauth
) ();
366 extern Afs_syscall();
369 do_mod_lookup(const char * mod
, const char * sym
)
373 ptr
= modlookup(mod
, sym
);
375 afs_warn("modlookup failed for symbol '%s' in module '%s'\n",
382 #ifdef AFS_SUN510_ENV
383 afsinit(int fstype
, char *dummy
)
385 afsinit(struct vfssw
*vfsswp
, int fstype
)
388 extern int afs_xioctl();
389 extern int afs_xsetgroups();
391 AFS_STATCNT(afsinit
);
393 afs_orig_setgroups
= sysent
[SYS_setgroups
].sy_callc
;
394 afs_orig_ioctl
= sysent
[SYS_ioctl
].sy_call
;
395 sysent
[SYS_setgroups
].sy_callc
= afs_xsetgroups
;
396 sysent
[SYS_ioctl
].sy_call
= afs_xioctl
;
398 #if defined(AFS_SUN5_64BIT_ENV)
399 afs_orig_setgroups32
= sysent32
[SYS_setgroups
].sy_callc
;
400 afs_orig_ioctl32
= sysent32
[SYS_ioctl
].sy_call
;
401 sysent32
[SYS_setgroups
].sy_callc
= afs_xsetgroups
;
402 sysent32
[SYS_ioctl
].sy_call
= afs_xioctl
;
403 #endif /* AFS_SUN5_64BIT_ENV */
405 #ifdef AFS_SUN510_ENV
406 vfs_setfsops(fstype
, afs_vfsops_template
, &afs_vfsopsp
);
408 vn_make_ops("afs", afs_vnodeops_template
, &afs_ops
);
409 #else /* !AFS_SUN510_ENV */
410 vfsswp
->vsw_vfsops
= &Afs_vfsops
;
412 #endif /* !AFS_SUN510_ENV */
415 #if !defined(AFS_NONFSTRANS)
416 nfs_rfsdisptab_v2
= (int (*)()) do_mod_lookup("nfssrv", "rfsdisptab_v2");
417 if (nfs_rfsdisptab_v2
!= NULL
) {
418 nfs_acldisptab_v2
= (int (*)()) do_mod_lookup("nfssrv", "acldisptab_v2");
419 if (nfs_acldisptab_v2
!= NULL
) {
420 afs_xlatorinit_v2(nfs_rfsdisptab_v2
, nfs_acldisptab_v2
);
423 nfs_rfsdisptab_v3
= (int (*)()) do_mod_lookup("nfssrv", "rfsdisptab_v3");
424 if (nfs_rfsdisptab_v3
!= NULL
) {
425 nfs_acldisptab_v3
= (int (*)()) do_mod_lookup("nfssrv", "acldisptab_v3");
426 if (nfs_acldisptab_v3
!= NULL
) {
427 afs_xlatorinit_v3(nfs_rfsdisptab_v3
, nfs_acldisptab_v3
);
431 nfs_checkauth
= (int (*)()) do_mod_lookup("nfssrv", "checkauth");
432 #endif /* !AFS_NONFSTRANS */
434 ufs_iallocp
= (int (*)()) do_mod_lookup("ufs", "ufs_ialloc");
435 ufs_iupdatp
= (void (*)()) do_mod_lookup("ufs", "ufs_iupdat");
436 ufs_igetp
= (int (*)()) do_mod_lookup("ufs", "ufs_iget");
437 ufs_itimes_nolockp
= (void (*)()) do_mod_lookup("ufs", "ufs_itimes_nolock");
439 if (!ufs_iallocp
|| !ufs_iupdatp
|| !ufs_itimes_nolockp
|| !ufs_igetp
) {
440 afs_warn("AFS to UFS mapping cannot be fully initialised\n");
443 #if !defined(AFS_SUN510_ENV)
444 ill_g_headp
= (struct ill_s
*) do_mod_lookup("ip", "ill_g_head");
445 #endif /* !AFS_SUN510_ENV */
452 #ifdef AFS_SUN510_ENV
453 #ifdef AFS_SUN511_ENV
454 static vfsdef_t afs_vfsdef
= {
462 static struct vfsdef_v3 afs_vfsdef
= {
470 static struct vfssw afs_vfw
= {
478 #ifndef AFS_SUN511_ENV
479 static struct sysent afssysent
= {
484 #endif /* AFS_SUN511_ENV */
487 * Info/Structs to link the afs module into the kernel
489 extern struct mod_ops mod_fsops
;
491 static struct modlfs afsmodlfs
= {
494 #ifdef AFS_SUN510_ENV
501 #ifdef AFS_SUN511_ENV
503 extern struct modldrv afs_modldrv
;
505 #else /* AFS_SUN511_ENV */
507 extern struct mod_ops mod_syscallops
;
508 static struct modlsys afsmodlsys
= {
510 "afs syscall interface",
514 /** The two structures afssysent32 and afsmodlsys32 are being added
515 * for supporting 32 bit syscalls. In Solaris 7 there are two system
516 * tables viz. sysent ans sysent32. 32 bit applications use sysent32.
517 * Since most of our user space binaries are going to be 32 bit
518 * we need to attach to sysent32 also. Note that the entry into AFS
519 * land still happens through Afs_syscall irrespective of whether we
520 * land here from sysent or sysent32
523 # if defined(AFS_SUN5_64BIT_ENV)
524 extern struct mod_ops mod_syscallops32
;
526 static struct modlsys afsmodlsys32
= {
528 "afs syscall interface(32 bit)",
532 #endif /* !AFS_SUN511_ENV */
535 static struct modlinkage afs_modlinkage
= {
538 #ifdef AFS_SUN511_ENV
539 (void *)&afs_modldrv
,
542 # ifdef AFS_SUN5_64BIT_ENV
543 (void *)&afsmodlsys32
,
545 #endif /* !AFS_SUN511_ENV */
553 sysent
[SYS_setgroups
].sy_callc
= afs_orig_setgroups
;
554 sysent
[SYS_ioctl
].sy_call
= afs_orig_ioctl
;
555 #if defined(AFS_SUN5_64BIT_ENV)
556 sysent32
[SYS_setgroups
].sy_callc
= afs_orig_setgroups32
;
557 sysent32
[SYS_ioctl
].sy_call
= afs_orig_ioctl32
;
562 /** This is the function that modload calls when loading the afs kernel
563 * extensions. The solaris modload program searches for the _init
564 * function in a module and calls it when modloading
569 char *sysn
, *mod_getsysname();
571 extern char *sysbind
;
572 extern struct bind
*sb_hashtab
[];
573 struct modctl
*mp
= 0;
578 if ((!(mp
= mod_find_by_filename("fs", "ufs"))
579 && !(mp
= mod_find_by_filename(NULL
, "/kernel/fs/ufs"))
580 && !(mp
= mod_find_by_filename(NULL
, "sys/ufs"))) || (mp
585 ("ufs module must be loaded before loading afs; use modload /kernel/fs/ufs\n");
588 #ifndef AFS_NONFSTRANS
589 if ((!(mp
= mod_find_by_filename("misc", "nfssrv"))
590 && !(mp
= mod_find_by_filename(NULL
, NFSSRV
))
591 && !(mp
= mod_find_by_filename(NULL
, NFSSRV_V9
))
592 && !(mp
= mod_find_by_filename(NULL
, NFSSRV_AMD64
))) || (mp
597 ("misc/nfssrv module must be loaded before loading afs with nfs-xlator\n");
600 #endif /* !AFS_NONFSTRANS */
603 osi_Init(); /* initialize global lock, etc */
605 code
= mod_install(&afs_modlinkage
);
607 /* we failed to load, so make sure we don't leave behind any
608 * references to our syscall handlers */
615 struct modinfo
*modp
;
619 code
= mod_info(&afs_modlinkage
, modp
);
631 code
= mod_remove(&afs_modlinkage
);