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