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