2 * Copyright 2000, International Business Machines Corporation and others.
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
11 * osi_vfsops.c for DUX
13 #include <afsconfig.h>
14 #include "afs/param.h"
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>
29 #include <machine/machlimits.h>
32 struct vcache *afs_globalVp = 0;
33 struct mount *afs_globalVFS = 0;
35 static u_char afs_mntid;
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)
47 struct mount *xmp, *getvfs();
51 AFS_STATCNT(afs_mount);
53 if (afs_globalVFS) { /* Don't allow remounts. */
59 afsp->vfs_bsize = 8192;
61 * Generate a unique afs mount i.d. ( see nfs_mount() ).
63 afsp->m_stat.f_fsid.val[0] = makedev(130, 0);
64 afsp->m_stat.f_fsid.val[1] = MOUNT_AFS;
70 tfsid.val[0] = makedev(130, afs_mntid);
71 tfsid.val[1] = MOUNT_AFS;
72 BM(AFSMNTID_UNLOCK());
74 while (xmp = getvfs(&tfsid)) {
75 UNMOUNT_READ_UNLOCK(xmp);
81 if (major(tfsid.val[0]) != 130) {
85 afsp->m_stat.f_fsid.val[0] = tfsid.val[0];
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");
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,
96 memcpy(afsp->m_stat.f_mntfromname, "AFS", 4);
98 (void)mp_afs_statfs(afsp);
100 afs_vfsdev = afsp->m_stat.f_fsid.val[0];
102 #ifndef AFS_NONFSTRANS
103 /* Set up the xlator in case it wasn't done elsewhere */
113 mp_afs_unmount(struct mount *afsp, int flag)
116 AFS_STATCNT(afs_unmount);
125 mp_afs_start(struct mount *mp, int flags)
131 mp_afs_root(struct mount *afsp, struct vnode **avpp)
133 register afs_int32 code = 0;
134 struct vrequest treq;
135 register struct vcache *tvp = 0;
138 AFS_STATCNT(afs_root);
139 if (afs_globalVp && (afs_globalVp->states & CStatd)) {
143 afs_PutVCache(afs_globalVp);
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 */
158 struct vnode *vp = AFSTOV(tvp);
162 vp->v_flag |= VROOT; /* No-op on Ultrix 2.2 */
166 afs_globalVFS = afsp;
170 afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *avpp,
171 ICL_TYPE_INT32, code);
177 mp_afs_quotactl(struct mount * mp, int cmd, uid_t uid, caddr_t arg)
183 mp_afs_statfs(struct mount *afsp)
185 struct nstatfs *abp = &afsp->m_stat;
188 AFS_STATCNT(afs_statfs);
190 abp->f_type = MOUNT_AFS;
191 abp->f_bsize = afsp->vfs_bsize;
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.
197 abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
198 abp->f_ffree = 2000000;
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];
210 mp_afs_sync(struct mount *mp, int flags)
212 AFS_STATCNT(afs_sync);
219 mp_afs_smoothsync(struct mount *mp, u_int age, u_int smsync_flag)
221 AFS_STATCNT(afs_sync);
227 mp_afs_fhtovp(struct mount *afsp, struct fid *fidp, struct vnode **avcp)
229 struct vrequest treq;
233 AFS_STATCNT(afs_vget);
237 if ((code = afs_InitReq(&treq, u.u_cred)) == 0) {
238 code = afs_osi_vget((struct vcache **)avcp, fidp, &treq);
241 afs_Trace3(afs_iclSetp, CM_TRACE_VGET, ICL_TYPE_POINTER, *avcp,
242 ICL_TYPE_INT32, treq.uid, ICL_TYPE_FID, fidp);
244 code = afs_CheckCode(code, &treq, 42);
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.
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:
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.
273 * Note that the SmallFid only allows for 8 bits of the cell index and
274 * 16 bits of the vnode.
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;
283 mp_afs_vptofh(struct vnode *avn, struct fid *fidp)
285 struct SmallFid Sfid;
287 register struct cell *tcell;
289 struct vcache *avc = VTOAFS(avn);
292 AFS_STATCNT(afs_fid);
294 if (afs_shuttingdown) {
299 if (afs_NFSRootOnly && (avc == afs_globalVp))
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;
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++;
313 fidp->fid_reserved = AFS_XLATOR_MAGIC;
316 VN_HOLD(AFSTOV(avc));
320 /* Use the fid pointer passed to us. */
321 fidp->fid_len = AFS_SIZEOFSMALLFID;
322 if (afs_NFSRootOnly) {
324 memcpy(fidp->fid_data, (caddr_t) & Sfid, AFS_FIDDATASIZE);
326 memcpy(fidp->fid_data, (caddr_t) addr, AFS_FIDDATASIZE);
329 memcpy(fidp->fid_data, (caddr_t) & Sfid, AFS_FIDDATASIZE);
336 int mp_Afs_init(void); /* vfs_init - defined below */
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.
342 int afsmountroot = 0;
344 mp_afs_mountroot(struct mount *afsp, struct vnode **vp)
347 AFS_STATCNT(afs_mountroot);
354 /* It's called to setup swapping over the net for diskless clients; again
362 AFS_STATCNT(afs_swapvp);
369 struct vfsops afs_vfsops = {
377 mp_afs_fhtovp, /* afs_vget */
389 * System Call Entry Points
391 #define NULL_FUNC (int (*)(int))0
393 int (*afs_syscall_func) () = NULL_FUNC;
394 int (*afs_xsetgroups_func) () = NULL_FUNC;
395 int (*afs_xioctl_func) () = NULL_FUNC;
397 afssyscall(p, args, retval)
406 func = afs_syscall_func;
407 if (func == NULL_FUNC) {
408 code = nosys(p, args, retval);
410 code = (*func) (p, args, retval);
416 afsxsetgroups(p, args, retval)
425 func = afs_xsetgroups_func;
426 if (func == NULL_FUNC) {
427 code = nosys(p, args, retval);
429 code = (*func) (p, args, retval);
435 afsxioctl(p, args, retval)
444 func = afs_xioctl_func;
445 if (func == NULL_FUNC) {
446 code = nosys(p, args, retval);
448 code = (*func) (p, args, retval);
456 * VFS initialization and unload
465 cfg_subsys_attr_t afs_attributes[] = {
466 {"", 0, 0, 0, 0, 0, 0} /* must be the last element */
469 afs_configure(cfg_op_t op, caddr_t indata, size_t indata_size,
470 caddr_t outdata, size_t outdata_size)
472 cfg_attr_t *attributes;
478 case CFG_OP_CONFIGURE:
480 * The indata parameter is a list of attributes to be configured, and
481 * indata_size is the count of attributes.
483 if ((ret = vfssw_add_fsname(MOUNT_AFS, &afs_vfsops, "afs")) != 0)
486 case CFG_OP_UNCONFIGURE:
487 if ((ret = afs_unconfig()) != 0)
501 extern int Afs_xsetgroups(), afs_xioctl(), afs3_syscall();
504 ((struct sysent *)(&sysent[AFS_SYSCALL]))->sy_call = afs3_syscall;
506 ((struct sysent *)(&sysent[AFS_SYSCALL]))->sy_info = 6;
508 ((struct sysent *)(&sysent[AFS_SYSCALL]))->sy_parallel = 0;
509 ((struct sysent *)(&sysent[AFS_SYSCALL]))->sy_narg = 6;
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;