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