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