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