8f97ae01bf103acb53851b410b81bc46ea67a079
[openafs.git] / src / afs / FBSD / osi_vfsops.c
1 #include <afsconfig.h>
2 #include <afs/param.h>
3
4
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>
9 #include <sys/namei.h>
10 #include <sys/conf.h>
11 #include <sys/module.h>
12 #include <sys/sysproto.h>
13 #include <sys/syscall.h>
14 #include <sys/sysent.h>
15
16 struct vcache *afs_globalVp = NULL;
17 struct mount *afs_globalVFS = NULL;
18 int afs_pbuf_freecnt = -1;
19
20 #ifdef AFS_FBSD50_ENV
21 #define THREAD_OR_PROC struct thread *p
22 #else
23 #define THREAD_OR_PROC struct proc *p
24 #endif
25
26 extern int Afs_xsetgroups();
27 extern int afs_xioctl();
28
29 static sy_call_t *old_handler;
30
31
32 int
33 afs_init(struct vfsconf *vfc)
34 {
35     if (sysent[AFS_SYSCALL].sy_call != nosys
36         && sysent[AFS_SYSCALL].sy_call != lkmnosys) {
37         printf("AFS_SYSCALL in use. aborting\n");
38         return EBUSY;
39     }
40     osi_Init();
41     afs_pbuf_freecnt = nswbuf / 2 + 1;
42 #if 0
43     sysent[SYS_setgroups].sy_call = Afs_xsetgroups;
44     sysent[SYS_ioctl].sy_call = afs_xioctl;
45 #endif
46     old_handler = sysent[AFS_SYSCALL].sy_call;
47     sysent[AFS_SYSCALL].sy_call = afs3_syscall;
48     sysent[AFS_SYSCALL].sy_narg = 5;
49     return 0;
50 }
51
52 int
53 afs_uninit(struct vfsconf *vfc)
54 {
55     if (afs_globalVFS)
56         return EBUSY;
57 #if 0
58     sysent[SYS_ioctl].sy_call = ioctl;
59     sysent[SYS_setgroups].sy_call = setgroups;
60 #endif
61     sysent[AFS_SYSCALL].sy_narg = 0;
62     sysent[AFS_SYSCALL].sy_call = old_handler;
63     return 0;
64 }
65
66 int
67 afs_start(struct mount *mp, int flags, THREAD_OR_PROC)
68 {
69     return (0);                 /* nothing to do. ? */
70 }
71
72 int
73 #ifdef AFS_FBSD53_ENV
74 afs_omount(struct mount *mp, char *path, caddr_t data, struct thread *p)
75 #else
76 afs_omount(struct mount *mp, char *path, caddr_t data, struct nameidata *ndp,
77         THREAD_OR_PROC)
78 #endif
79 {
80     /* ndp contains the mounted-from device.  Just ignore it.
81      * we also don't care about our proc struct. */
82     size_t size;
83
84     if (mp->mnt_flag & MNT_UPDATE)
85         return EINVAL;
86
87     AFS_GLOCK();
88     AFS_STATCNT(afs_mount);
89
90     if (afs_globalVFS) {        /* Don't allow remounts. */
91         AFS_GUNLOCK();
92         return EBUSY;
93     }
94
95     afs_globalVFS = mp;
96     mp->vfs_bsize = 8192;
97     vfs_getnewfsid(mp);
98 #ifdef AFS_FBSD70_ENV /* XXX 70? */
99     MNT_ILOCK(mp);
100     mp->mnt_flag &= ~MNT_LOCAL;
101     mp->mnt_kern_flag |= MNTK_MPSAFE; /* solid steel */
102 #endif
103     mp->mnt_stat.f_iosize = 8192;
104
105     if (path != NULL)
106         copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
107     else
108         bcopy("/afs", mp->mnt_stat.f_mntonname, size = 4);
109     memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
110     memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
111     strcpy(mp->mnt_stat.f_mntfromname, "AFS");
112     /* null terminated string "AFS" will fit, just leave it be. */
113     strcpy(mp->mnt_stat.f_fstypename, "afs");
114 #ifdef AFS_FBSD70_ENV
115     MNT_IUNLOCK(mp);
116 #endif
117     AFS_GUNLOCK();
118     afs_statfs(mp, &mp->mnt_stat, p);
119
120     return 0;
121 }
122
123 #ifdef AFS_FBSD53_ENV
124 int
125 afs_mount(struct mount *mp, struct thread *td)
126 {
127     return afs_omount(mp, NULL, NULL, td);
128 }
129 #endif
130
131 #ifdef AFS_FBSD60_ENV
132 static int
133 afs_cmount(struct mntarg *ma, void *data, int flags, struct thread *td)
134 {
135     return kernel_mount(ma, flags);
136 }
137 #endif
138
139 int
140 afs_unmount(struct mount *mp, int flags, THREAD_OR_PROC)
141 {
142
143     /*
144      * Release any remaining vnodes on this mount point.
145      * The `1' means that we hold one extra reference on
146      * the root vnode (this is just a guess right now).
147      * This has to be done outside the global lock.
148      */
149 #if defined(AFS_FBSD80_ENV)
150   /* do nothing */
151 #elif defined(AFS_FBSD53_ENV)
152     vflush(mp, 1, (flags & MNT_FORCE) ? FORCECLOSE : 0, p);
153 #else
154     vflush(mp, 1, (flags & MNT_FORCE) ? FORCECLOSE : 0);
155 #endif
156     AFS_GLOCK();
157     AFS_STATCNT(afs_unmount);
158     afs_globalVFS = 0;
159     afs_shutdown();
160     AFS_GUNLOCK();
161
162     return 0;
163 }
164
165 int
166 #if defined(AFS_FBSD80_ENV)
167 afs_root(struct mount *mp, int flags, struct vnode **vpp)
168 #elif defined(AFS_FBSD60_ENV)
169 afs_root(struct mount *mp, int flags, struct vnode **vpp, struct thread *td)
170 #elif defined(AFS_FBSD53_ENV)
171 afs_root(struct mount *mp, struct vnode **vpp, struct thread *td)
172 #else
173 afs_root(struct mount *mp, struct vnode **vpp)
174 #endif
175 {
176     int error;
177     struct vrequest treq;
178     register struct vcache *tvp = 0;
179 #ifdef AFS_FBSD50_ENV
180 #if !defined(AFS_FBSD53_ENV) || defined(AFS_FBSD80_ENV)
181     struct thread *td = curthread;
182 #endif
183     struct ucred *cr = osi_curcred();
184 #else
185     struct proc *p = curproc;
186     struct ucred *cr = p->p_cred->pc_ucred;
187 #endif
188
189     AFS_GLOCK();
190     AFS_STATCNT(afs_root);
191     crhold(cr);
192     if (afs_globalVp && (afs_globalVp->f.states & CStatd)) {
193         tvp = afs_globalVp;
194         error = 0;
195     } else {
196 tryagain:
197 #ifndef AFS_FBSD80_ENV
198         if (afs_globalVp) {
199             afs_PutVCache(afs_globalVp);
200             /* vrele() needed here or not? */
201             afs_globalVp = NULL;
202         }
203 #endif
204         if (!(error = afs_InitReq(&treq, cr)) && !(error = afs_CheckInit())) {
205             tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
206             /* we really want this to stay around */
207             if (tvp)
208                 afs_globalVp = tvp;
209             else
210                 error = ENOENT;
211         }
212     }
213     if (tvp) {
214         struct vnode *vp = AFSTOV(tvp);
215
216 #ifdef AFS_FBSD50_ENV
217         ASSERT_VI_UNLOCKED(vp, "afs_root");
218 #endif
219         AFS_GUNLOCK();
220         /*
221          * I'm uncomfortable about this.  Shouldn't this happen at a
222          * higher level, and shouldn't we busy the top-level directory
223          * to prevent recycling?
224          */
225 #ifdef AFS_FBSD50_ENV
226         error = vget(vp, LK_EXCLUSIVE | LK_RETRY, td);
227         vp->v_vflag |= VV_ROOT;
228 #else
229         error = vget(vp, LK_EXCLUSIVE | LK_RETRY, p);
230         vp->v_flag |= VROOT;
231 #endif
232         AFS_GLOCK();
233         if (error != 0)
234                 goto tryagain;
235
236         afs_globalVFS = mp;
237         *vpp = vp;
238     }
239
240     afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, tvp ? AFSTOV(tvp) : NULL,
241                ICL_TYPE_INT32, error);
242     AFS_GUNLOCK();
243     crfree(cr);
244     return error;
245 }
246
247 int
248 afs_statfs(struct mount *mp, struct statfs *abp, THREAD_OR_PROC)
249 {
250     AFS_GLOCK();
251     AFS_STATCNT(afs_statfs);
252
253     abp->f_bsize = mp->vfs_bsize;
254     abp->f_iosize = mp->vfs_bsize;
255
256     /* Fake a high number below to satisfy programs that use the statfs call
257      * to make sure that there's enough space in the device partition before
258      * storing something there.
259      */
260     abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
261         abp->f_ffree = 2000000;
262
263     abp->f_fsid.val[0] = mp->mnt_stat.f_fsid.val[0];
264     abp->f_fsid.val[1] = mp->mnt_stat.f_fsid.val[1];
265     if (abp != &mp->mnt_stat) {
266         abp->f_type = mp->mnt_vfc->vfc_typenum;
267         memcpy((caddr_t) & abp->f_mntonname[0],
268                (caddr_t) mp->mnt_stat.f_mntonname, MNAMELEN);
269         memcpy((caddr_t) & abp->f_mntfromname[0],
270                (caddr_t) mp->mnt_stat.f_mntfromname, MNAMELEN);
271     }
272
273     AFS_GUNLOCK();
274     return 0;
275 }
276
277 int
278 #ifdef AFS_FBSD60_ENV
279 afs_sync(struct mount *mp, int waitfor, struct thread *td)
280 #else
281 afs_sync(struct mount *mp, int waitfor, struct ucred *cred, THREAD_OR_PROC)
282 #endif
283 {
284     return 0;
285 }
286
287 #ifdef AFS_FBSD60_ENV
288 struct vfsops afs_vfsops = {
289         .vfs_init =             afs_init,
290         .vfs_mount =            afs_mount,
291         .vfs_cmount =           afs_cmount,
292         .vfs_root =             afs_root,
293         .vfs_statfs =           afs_statfs,
294         .vfs_sync =             afs_sync,
295         .vfs_uninit =           afs_uninit,
296         .vfs_unmount =          afs_unmount,
297         .vfs_sysctl =           vfs_stdsysctl,
298 };
299 #else
300 struct vfsops afs_vfsops = {
301 #ifdef AFS_FBSD53_ENV
302     afs_mount,
303 #endif
304     afs_omount,
305     afs_start,
306     afs_unmount,
307     afs_root,
308     vfs_stdquotactl,
309     afs_statfs,
310     afs_sync,
311     vfs_stdvget,
312     vfs_stdfhtovp,
313     vfs_stdcheckexp,
314     vfs_stdvptofh,
315     afs_init,
316     afs_uninit,
317     vfs_stdextattrctl,
318 #ifdef AFS_FBSD50_ENV
319     vfs_stdsysctl,
320 #endif
321 };
322 #endif