361d6e3bb18c288decec3dd81d3bb7f13b087972
[openafs.git] / src / afs / NBSD / osi_vfsops.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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
8  */
9
10 /*
11  * osi_vfsops.c for NetBSD
12  */
13 #include <afsconfig.h>
14 #include "afs/param.h"
15
16
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 */
20 #include <sys/types.h>
21 #include <kern/mach_param.h>
22 #include <sys/sysconfig.h>
23 #include <sys/systm.h>
24 #include <sys/resource.h>
25 #include <sys/errno.h>
26 #include <sys/conf.h>
27 #include <machine/machlimits.h>
28
29
30 struct vcache *afs_globalVp = 0;
31 struct mount *afs_globalVFS = 0;
32
33 static u_char afs_mntid;
34 int afs_vfsdev = 0;
35 udecl_simple_lock_data(, afsmntid_lock)
36 #define AFSMNTID_LOCK()         usimple_lock(&afsmntid_lock)
37 #define AFSMNTID_UNLOCK()       usimple_unlock(&afsmntid_lock)
38 #define AFSMNTID_LOCK_INIT()    usimple_lock_init(&afsmntid_lock)
39      int mp_afs_mount(struct mount *afsp, char *path, caddr_t data,
40                       struct nameidata *ndp)
41 {
42     u_int size;
43
44     fsid_t tfsid;
45     struct mount *xmp, *getvfs();
46     int code;
47
48     AFS_GLOCK();
49     AFS_STATCNT(afs_mount);
50
51     if (afs_globalVFS) {        /* Don't allow remounts. */
52         AFS_GUNLOCK();
53         return (EBUSY);
54     }
55
56     afs_globalVFS = afsp;
57     afsp->vfs_bsize = 8192;
58 /*
59  * Generate a unique afs mount i.d. ( see nfs_mount() ).
60  */
61     afsp->m_stat.f_fsid.val[0] = makedev(130, 0);
62     afsp->m_stat.f_fsid.val[1] = MOUNT_AFS;
63     AFSMNTID_LOCK();
64     if (++afs_mntid == 0)
65         ++afs_mntid;
66     AFSMNTID_UNLOCK();
67     BM(AFSMNTID_LOCK());
68     tfsid.val[0] = makedev(130, afs_mntid);
69     tfsid.val[1] = MOUNT_AFS;
70     BM(AFSMNTID_UNLOCK());
71
72     while (xmp = getvfs(&tfsid)) {
73         UNMOUNT_READ_UNLOCK(xmp);
74         tfsid.val[0]++;
75         AFSMNTID_LOCK();
76         afs_mntid++;
77         AFSMNTID_UNLOCK();
78     }
79     if (major(tfsid.val[0]) != 130) {
80         AFS_GUNLOCK();
81         return (ENOENT);
82     }
83     afsp->m_stat.f_fsid.val[0] = tfsid.val[0];
84
85     afsp->m_stat.f_mntonname = AFS_KALLOC(MNAMELEN);
86     afsp->m_stat.f_mntfromname = AFS_KALLOC(MNAMELEN);
87     if (!afsp->m_stat.f_mntonname || !afsp->m_stat.f_mntfromname)
88         panic("malloc failure in afs_mount\n");
89
90     memset(afsp->m_stat.f_mntonname, 0, MNAMELEN);
91     memset(afsp->m_stat.f_mntfromname, 0, MNAMELEN);
92     AFS_COPYINSTR(path, (caddr_t) afsp->m_stat.f_mntonname, MNAMELEN, &size,
93                   code);
94     memcpy(afsp->m_stat.f_mntfromname, "AFS", 4);
95     AFS_GUNLOCK();
96     (void)mp_afs_statfs(afsp);
97     AFS_GLOCK();
98     afs_vfsdev = afsp->m_stat.f_fsid.val[0];
99
100 #ifndef AFS_NONFSTRANS
101     /* Set up the xlator in case it wasn't done elsewhere */
102     afs_xlatorinit_v2();
103     afs_xlatorinit_v3();
104 #endif
105     AFS_GUNLOCK();
106     return 0;
107 }
108
109
110 int
111 mp_afs_unmount(struct mount *afsp, int flag)
112 {
113     AFS_GLOCK();
114     AFS_STATCNT(afs_unmount);
115     afs_globalVFS = 0;
116     afs_shutdown();
117     AFS_GUNLOCK();
118     return 0;
119 }
120
121
122 int
123 mp_afs_start(struct mount *mp, int flags)
124 {
125     return (0);
126 }
127
128 int
129 mp_afs_root(struct mount *afsp, struct vnode **avpp)
130 {
131     register afs_int32 code = 0;
132     struct vrequest treq;
133     register struct vcache *tvp = 0;
134
135     AFS_GLOCK();
136     AFS_STATCNT(afs_root);
137     if (afs_globalVp && (afs_globalVp->f.states & CStatd)) {
138         tvp = afs_globalVp;
139     } else {
140         if (afs_globalVp) {
141             afs_PutVCache(afs_globalVp);
142             afs_globalVp = NULL;
143         }
144
145         if (!(code = afs_InitReq(&treq, cred)) && !(code = afs_CheckInit())) {
146             tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
147             /* we really want this to stay around */
148             if (tvp) {
149                 afs_globalVp = tvp;
150             } else
151                 code = ENOENT;
152         }
153     }
154     if (tvp) {
155         AFS_GUNLOCK();
156         VN_HOLD((struct vnode *)tvp);
157         VN_LOCK((struct vnode *)tvp);
158         tvp->v.v_flag |= VROOT; /* No-op on Ultrix 2.2 */
159         VN_UNLOCK((struct vnode *)tvp);
160         AFS_GLOCK();
161
162         afs_globalVFS = afsp;
163         *avpp = (struct vnode *)tvp;
164     }
165
166     afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *avpp,
167                ICL_TYPE_INT32, code);
168     AFS_GUNLOCK();
169     return code;
170 }
171
172
173 mp_afs_quotactl(struct mount * mp, int cmd, uid_t uid, caddr_t arg)
174 {
175     return EOPNOTSUPP;
176 }
177
178 int
179 mp_afs_statfs(struct mount *afsp)
180 {
181     struct nstatfs *abp = &afsp->m_stat;
182
183     AFS_GLOCK();
184     AFS_STATCNT(afs_statfs);
185
186     abp->f_type = MOUNT_AFS;
187     abp->f_bsize = afsp->vfs_bsize;
188
189     /* Fake a high number below to satisfy programs that use the statfs call
190      * to make sure that there's enough space in the device partition before
191      * storing something there.
192      */
193     abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
194         abp->f_ffree = 2000000;
195     abp->f_fsize = 1024;
196
197     abp->f_fsid.val[0] = afsp->m_stat.f_fsid.val[0];
198     abp->f_fsid.val[1] = afsp->m_stat.f_fsid.val[1];
199
200     AFS_GUNLOCK();
201     return 0;
202 }
203
204
205 int
206 mp_afs_sync(struct mount *mp, int flags)
207 {
208     AFS_STATCNT(afs_sync);
209     return 0;
210 }
211
212
213 int
214 mp_afs_fhtovp(struct mount *afsp, struct fid *fidp, struct vnode **avcp)
215 {
216     struct vrequest treq;
217     register code = 0;
218
219     AFS_GLOCK();
220     AFS_STATCNT(afs_vget);
221
222     *avcp = NULL;
223
224     if ((code = afs_InitReq(&treq, cred)) == 0) {
225         code = afs_osi_vget((struct vcache **)avcp, fidp, &treq);
226     }
227
228     afs_Trace3(afs_iclSetp, CM_TRACE_VGET, ICL_TYPE_POINTER, *avcp,
229                ICL_TYPE_INT32, treq.uid, ICL_TYPE_FID, fidp);
230
231     code = afs_CheckCode(code, &treq, 42);
232     AFS_GUNLOCK();
233     return code;
234 }
235
236
237 /*
238  *  afs_vptofh
239  * 
240  * afs_vptofh can return two flavors of NFS fid, depending on if submounts are
241  * allowed. The reason for this is that we can't guarantee that we found all 
242  * the entry points any OS might use to get the fid for the NFS mountd.
243  * Hence we return a "magic" fid for all but /afs. If it goes through the
244  * translator code, it will get transformed into a SmallFid that we recognize.
245  * So, if submounts are disallowed, and an NFS client tries a submount, it will
246  * get a fid which we don't recognize and the mount will either fail or we
247  * will ignore subsequent requests for that mount.
248  *
249  * The Alpha fid is organized differently than for other platforms. Their
250  * intention was to have the data portion of the fid aligned on a 4 byte
251  * boundary. To do so, the fid is organized as:
252  * u_short reserved
253  * u_short len
254  * char data[8]
255  * The len field is the length of the entire fid, from reserved through data.
256  * This length is used by fid_copy to include copying the reserved field. 
257  * Alpha's zero the reserved field before handing us the fid, but they use
258  * it in fid_cmp. We use the reserved field to store the 16 bits of the Vnode.
259  *
260  * Note that the SmallFid only allows for 8 bits of the cell index and
261  * 16 bits of the vnode. 
262  */
263
264 #define AFS_FIDDATASIZE 8
265 #define AFS_SIZEOFSMALLFID 12   /* full size of fid, including len field */
266 extern int afs_NFSRootOnly;     /* 1 => only allow NFS mounts of /afs. */
267 int afs_fid_vnodeoverflow = 0, afs_fid_uniqueoverflow = 0;
268
269 int
270 mp_afs_vptofh(struct vnode *avn, struct fid *fidp)
271 {
272     struct SmallFid Sfid;
273     long addr[2];
274     register struct cell *tcell;
275     int rootvp = 0;
276     struct vcache *avc = VTOAFS(avn);
277
278     AFS_GLOCK();
279     AFS_STATCNT(afs_fid);
280
281     if (afs_shuttingdown) {
282         AFS_GUNLOCK();
283         return EIO;
284     }
285
286     if (afs_NFSRootOnly && (avc == afs_globalVp))
287         rootvp = 1;
288     if (!afs_NFSRootOnly || rootvp) {
289         tcell = afs_GetCell(avc->f.fid.Cell, READ_LOCK);
290         Sfid.Volume = avc->f.fid.Fid.Volume;
291         fidp->fid_reserved = avc->f.fid.Fid.Vnode;
292         Sfid.CellAndUnique =
293             ((tcell->cellIndex << 24) + (avc->f.fid.Fid.Unique & 0xffffff));
294         afs_PutCell(tcell, READ_LOCK);
295         if (avc->f.fid.Fid.Vnode > 0xffff)
296             afs_fid_vnodeoverflow++;
297         if (avc->f.fid.Fid.Unique > 0xffffff)
298             afs_fid_uniqueoverflow++;
299     } else {
300         fidp->fid_reserved = AFS_XLATOR_MAGIC;
301         addr[0] = (long)avc;
302         AFS_GUNLOCK();
303         VN_HOLD((struct vnode *)avc);
304         AFS_GLOCK();
305     }
306
307     /* Use the fid pointer passed to us. */
308     fidp->fid_len = AFS_SIZEOFSMALLFID;
309     if (afs_NFSRootOnly) {
310         if (rootvp) {
311             memcpy(fidp->fid_data, (caddr_t) & Sfid, AFS_FIDDATASIZE);
312         } else {
313             memcpy(fidp->fid_data, (caddr_t) addr, AFS_FIDDATASIZE);
314         }
315     } else {
316         memcpy(fidp->fid_data, (caddr_t) & Sfid, AFS_FIDDATASIZE);
317     }
318     AFS_GUNLOCK();
319     return 0;
320 }
321
322
323 int mp_Afs_init(void);          /* vfs_init - defined below */
324
325
326 /* This is only called by vfs_mount when afs is going to be mounted as root.
327  * Since we don't support diskless clients we shouldn't come here.
328  */
329 int afsmountroot = 0;
330 int
331 mp_afs_mountroot(struct mount *afsp, struct vnode **vp)
332 {
333     AFS_GLOCK();
334     AFS_STATCNT(afs_mountroot);
335     afsmountroot++;
336     AFS_GUNLOCK();
337     return EINVAL;
338 }
339
340
341 /* It's called to setup swapping over the net for diskless clients; again
342  * not for us.
343  */
344 int afsswapvp = 0;
345 int
346 mp_afs_swapvp(void)
347 {
348     AFS_GLOCK();
349     AFS_STATCNT(afs_swapvp);
350     afsswapvp++;
351     AFS_GUNLOCK();
352     return EINVAL;
353 }
354
355
356 struct vfsops afs_vfsops = {
357     mp_afs_mount,
358     mp_afs_start,
359     mp_afs_unmount,
360     mp_afs_root,
361     mp_afs_quotactl,
362     mp_afs_statfs,
363     mp_afs_sync,
364     mp_afs_fhtovp,              /* afs_vget */
365     mp_afs_vptofh,
366     mp_Afs_init,
367     mp_afs_mountroot,
368     mp_afs_swapvp
369 };
370
371
372 /*
373  * System Call Entry Points
374  */
375 #define NULL_FUNC          (int (*)(int))0
376
377 int (*afs_syscall_func) () = NULL_FUNC;
378 int (*afs_xsetgroups_func) () = NULL_FUNC;
379 int (*afs_xioctl_func) () = NULL_FUNC;
380
381 afssyscall(p, args, retval)
382      struct proc *p;
383      void *args;
384      long *retval;
385 {
386     int (*func) ();
387     int code;
388
389     AFS_GLOCK();
390     func = afs_syscall_func;
391     if (func == NULL_FUNC) {
392         code = nosys(p, args, retval);
393     } else {
394         code = (*func) (p, args, retval);
395     }
396     AFS_GUNLOCK();
397     return code;
398 }
399
400 afsxsetgroups(p, args, retval)
401      struct proc *p;
402      void *args;
403      long *retval;
404 {
405     int (*func) ();
406     int code;
407
408     AFS_GLOCK();
409     func = afs_xsetgroups_func;
410     if (func == NULL_FUNC) {
411         code = nosys(p, args, retval);
412     } else {
413         code = (*func) (p, args, retval);
414     }
415     AFS_GUNLOCK();
416     return code;
417 }
418
419 afsxioctl(p, args, retval)
420      struct proc *p;
421      void *args;
422      long *retval;
423 {
424     int (*func) ();
425     int code;
426
427     AFS_GLOCK();
428     func = afs_xioctl_func;
429     if (func == NULL_FUNC) {
430         code = nosys(p, args, retval);
431     } else {
432         code = (*func) (p, args, retval);
433     }
434     AFS_GUNLOCK();
435     return code;
436 }
437
438
439 /*
440  * VFS initialization and unload
441  */
442
443 afs_unconfig()
444 {
445     return EBUSY;
446 }
447
448
449 cfg_subsys_attr_t afs_attributes[] = {
450     {"", 0, 0, 0, 0, 0, 0}      /* must be the last element */
451 };
452
453 afs_configure(cfg_op_t op, caddr_t indata, size_t indata_size,
454               caddr_t outdata, size_t outdata_size)
455 {
456     cfg_attr_t *attributes;
457     int ret = ESUCCESS;
458     int i, j, size;
459     caddr_t p;
460
461     switch (op) {
462     case CFG_OP_CONFIGURE:
463         /*
464          * The indata parameter is a list of attributes to be configured, and 
465          * indata_size is the count of attributes.
466          */
467         if ((ret = vfssw_add_fsname(MOUNT_AFS, &afs_vfsops, "afs")) != 0)
468             return (ret);
469         break;
470     case CFG_OP_UNCONFIGURE:
471         if ((ret = afs_unconfig()) != 0)
472             return (ret);
473         break;
474     default:
475         ret = EINVAL;
476         break;
477     }
478     return ret;
479 }
480
481
482 int
483 mp_Afs_init(void)
484 {
485     extern int Afs_xsetgroups(), afs_xioctl(), afs3_syscall();
486
487     AFS_GLOCK();
488     sysent[AFS_SYSCALL].sy_call = afs3_syscall;
489     sysent[AFS_SYSCALL].sy_parallel = 0;
490     sysent[AFS_SYSCALL].sy_narg = 6;
491     sysent[SYS_setgroups].sy_call = Afs_xsetgroups;
492     afs_xioctl_func = afsxioctl;
493     afs_xsetgroups_func = afsxsetgroups;
494     afs_syscall_func = afssyscall;
495     AFS_GUNLOCK();
496
497     return 0;
498 }