5 #include <afs/sysincludes.h> /* Standard vendor system headers */
6 #include <afsincludes.h> /* Afs-based standard headers */
7 #include <afs/afs_stats.h> /* statistics */
8 #include <sys/malloc.h>
11 #include <sys/module.h>
12 #include <sys/sysproto.h>
13 #include <sys/syscall.h>
14 #include <sys/sysent.h>
16 struct vcache *afs_globalVp = NULL;
17 struct mount *afs_globalVFS = NULL;
18 int afs_pbuf_freecnt = -1;
20 extern int Afs_xsetgroups();
21 extern int afs_xioctl();
23 static struct syscall_helper_data afs_syscalls[] = {
25 .syscall_no = AFS_SYSCALL,
28 .sy_call = (sy_call_t *)afs3_syscall,
29 .sy_auevent = AUE_NULL,
36 afs_init(struct vfsconf *vfc)
39 #if defined(FBSD_SYSCALL_REGISTER_TAKES_FLAGS)
40 code = syscall_helper_register(afs_syscalls, 0);
42 code = syscall_helper_register(afs_syscalls);
45 printf("AFS_SYSCALL in use, error %i. aborting\n", code);
49 afs_pbuf_freecnt = nswbuf / 2 + 1;
54 afs_uninit(struct vfsconf *vfc)
59 return syscall_helper_unregister(afs_syscalls);
63 afs_statfs(struct mount *mp, struct statfs *abp)
66 AFS_STATCNT(afs_statfs);
68 abp->f_bsize = mp->vfs_bsize;
69 abp->f_iosize = mp->vfs_bsize;
71 abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
72 abp->f_ffree = AFS_VFS_FAKEFREE;
74 abp->f_fsid.val[0] = mp->mnt_stat.f_fsid.val[0];
75 abp->f_fsid.val[1] = mp->mnt_stat.f_fsid.val[1];
76 if (abp != &mp->mnt_stat) {
77 abp->f_type = mp->mnt_vfc->vfc_typenum;
78 memcpy((caddr_t) & abp->f_mntonname[0],
79 (caddr_t) mp->mnt_stat.f_mntonname, MNAMELEN);
80 memcpy((caddr_t) & abp->f_mntfromname[0],
81 (caddr_t) mp->mnt_stat.f_mntfromname, MNAMELEN);
89 afs_omount(struct mount *mp, char *path, caddr_t data)
91 /* ndp contains the mounted-from device. Just ignore it.
92 * we also don't care about our thread struct. */
95 if (mp->mnt_flag & MNT_UPDATE)
99 AFS_STATCNT(afs_mount);
101 if (afs_globalVFS) { /* Don't allow remounts. */
107 mp->vfs_bsize = 8192;
110 * This is kind of ugly, as the interlock has grown to encompass
111 * more fields over time and there's not a good way to group the
112 * code without duplication.
115 mp->mnt_flag &= ~MNT_LOCAL;
116 #if __FreeBSD_version < 1000021
117 mp->mnt_kern_flag |= MNTK_MPSAFE; /* solid steel */
120 * XXX mnt_stat "is considered stable as long as a ref is held".
121 * We should check that we hold the only ref.
123 mp->mnt_stat.f_iosize = 8192;
126 copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
128 bcopy("/afs", mp->mnt_stat.f_mntonname, size = 4);
129 memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
130 memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
131 strcpy(mp->mnt_stat.f_mntfromname, "AFS");
132 /* null terminated string "AFS" will fit, just leave it be. */
133 strcpy(mp->mnt_stat.f_fstypename, "afs");
136 afs_statfs(mp, &mp->mnt_stat);
142 afs_mount(struct mount *mp)
144 return afs_omount(mp, NULL, NULL);
148 #if __FreeBSD_version >= 1000004
149 afs_cmount(struct mntarg *ma, void *data, uint64_t flags)
151 afs_cmount(struct mntarg *ma, void *data, int flags)
154 return kernel_mount(ma, flags);
158 afs_unmount(struct mount *mp, int flags)
164 ((flags & MNT_FORCE) || !VREFCOUNT_GT(afs_globalVp, 1))) {
165 /* Put back afs_root's ref */
166 struct vcache *gvp = afs_globalVp;
176 * Release any remaining vnodes on this mount point. The second
177 * argument is how many refs we hold on the root vnode. Since we
178 * released our reference to the root vnode up above, give 0.
180 error = vflush(mp, 0, (flags & MNT_FORCE) ? FORCECLOSE : 0, curthread);
185 AFS_STATCNT(afs_unmount);
195 afs_root(struct mount *mp, int flags, struct vnode **vpp)
198 struct vrequest treq;
199 struct vcache *tvp = 0;
201 struct thread *td = curthread;
202 struct ucred *cr = osi_curcred();
205 AFS_STATCNT(afs_root);
208 if (afs_globalVp && (afs_globalVp->f.states & CStatd)) {
212 if (!(error = afs_InitReq(&treq, cr)) && !(error = afs_CheckInit())) {
213 tvp = afs_GetVCache(&afs_rootFid, &treq);
214 /* we really want this to stay around */
220 if (tvp != afs_globalVp) {
221 /* someone raced us and won */
231 struct vnode *vp = AFSTOV(tvp);
233 ASSERT_VI_UNLOCKED(vp, "afs_root");
235 error = vget(vp, LK_EXCLUSIVE | LK_RETRY, td);
237 /* we dropped the glock, so re-check everything it had serialized */
238 if (!afs_globalVp || !(afs_globalVp->f.states & CStatd) ||
239 tvp != afs_globalVp) {
247 * I'm uncomfortable about this. Shouldn't this happen at a
248 * higher level, and shouldn't we busy the top-level directory
249 * to prevent recycling?
251 vp->v_vflag |= VV_ROOT;
257 afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, tvp ? AFSTOV(tvp) : NULL,
258 ICL_TYPE_INT32, error);
265 afs_sync(struct mount *mp, int waitfor)
270 struct vfsops afs_vfsops = {
271 .vfs_init = afs_init,
272 .vfs_mount = afs_mount,
273 .vfs_cmount = afs_cmount,
274 .vfs_root = afs_root,
275 .vfs_statfs = afs_statfs,
276 .vfs_sync = afs_sync,
277 .vfs_uninit = afs_uninit,
278 .vfs_unmount = afs_unmount,
279 .vfs_sysctl = vfs_stdsysctl,