/* * Copyright 2000, International Business Machines Corporation and others. * All Rights Reserved. * * This software has been released under the terms of the IBM Public * License. For details, see the LICENSE file in the top-level source * directory or online at http://www.openafs.org/dl/license10.html */ /* * osi_vfsops.c for DUX */ #include "../afs/param.h" /* Should be always first */ #include "../afs/sysincludes.h" /* Standard vendor system headers */ #include "../afs/afsincludes.h" /* Afs-based standard headers */ #include "../afs/afs_stats.h" /* statistics stuff */ #include #include #include #include #include #include #include #include struct vcache *afs_globalVp = 0; struct mount *afs_globalVFS = 0; static u_char afs_mntid; int afs_vfsdev = 0; udecl_simple_lock_data(, afsmntid_lock) #define AFSMNTID_LOCK() usimple_lock(&afsmntid_lock) #define AFSMNTID_UNLOCK() usimple_unlock(&afsmntid_lock) #define AFSMNTID_LOCK_INIT() usimple_lock_init(&afsmntid_lock) int mp_afs_mount(struct mount *afsp,char * path, caddr_t data, struct nameidata *ndp) { u_int size; fsid_t tfsid; struct mount *xmp, *getvfs(); int code; AFS_GLOCK(); AFS_STATCNT(afs_mount); if (afs_globalVFS) { /* Don't allow remounts. */ AFS_GUNLOCK(); return (EBUSY); } afs_globalVFS = afsp; afsp->vfs_bsize = 8192; /* * Generate a unique afs mount i.d. ( see nfs_mount() ). */ afsp->m_stat.f_fsid.val[0] = makedev(130, 0); afsp->m_stat.f_fsid.val[1] = MOUNT_AFS; AFSMNTID_LOCK(); if (++afs_mntid == 0) ++afs_mntid; AFSMNTID_UNLOCK(); BM(AFSMNTID_LOCK()); tfsid.val[0] = makedev(130, afs_mntid); tfsid.val[1] = MOUNT_AFS; BM(AFSMNTID_UNLOCK()); while (xmp = getvfs(&tfsid)) { UNMOUNT_READ_UNLOCK(xmp); tfsid.val[0]++; AFSMNTID_LOCK(); afs_mntid++; AFSMNTID_UNLOCK(); } if (major(tfsid.val[0]) != 130) { AFS_GUNLOCK(); return (ENOENT); } afsp->m_stat.f_fsid.val[0] = tfsid.val[0]; afsp->m_stat.f_mntonname = AFS_KALLOC(MNAMELEN); afsp->m_stat.f_mntfromname = AFS_KALLOC(MNAMELEN); if ( !afsp->m_stat.f_mntonname || !afsp->m_stat.f_mntfromname) panic("malloc failure in afs_mount\n"); bzero(afsp->m_stat.f_mntonname, MNAMELEN); bzero(afsp->m_stat.f_mntfromname, MNAMELEN); AFS_COPYINSTR(path, (caddr_t)afsp->m_stat.f_mntonname, MNAMELEN, &size, code); bcopy("AFS", afsp->m_stat.f_mntfromname, 4); AFS_GUNLOCK(); (void) mp_afs_statfs(afsp); AFS_GLOCK(); afs_vfsdev = afsp->m_stat.f_fsid.val[0]; #ifndef AFS_NONFSTRANS /* Set up the xlator in case it wasn't done elsewhere */ afs_xlatorinit_v2(); afs_xlatorinit_v3(); #endif AFS_GUNLOCK(); return 0; } int mp_afs_unmount (struct mount *afsp, int flag) { AFS_GLOCK(); AFS_STATCNT(afs_unmount); afs_globalVFS = 0; afs_shutdown(); AFS_GUNLOCK(); return 0; } int mp_afs_start(struct mount *mp, int flags) { return(0); } int mp_afs_root (struct mount *afsp, struct vnode **avpp) { register afs_int32 code = 0; struct vrequest treq; register struct vcache *tvp=0; AFS_GLOCK(); AFS_STATCNT(afs_root); if (afs_globalVp && (afs_globalVp->states & CStatd)) { tvp = afs_globalVp; } else { if (!(code = afs_InitReq(&treq, u.u_cred)) && !(code = afs_CheckInit())) { tvp = afs_GetVCache(&afs_rootFid, &treq, (afs_int32 *)0, (struct vcache*)0, WRITE_LOCK); /* we really want this to stay around */ if (tvp) { afs_globalVp = tvp; } else code = ENOENT; } } if (tvp) { AFS_GUNLOCK(); VN_HOLD((struct vnode *)tvp); VN_LOCK((struct vnode *)tvp); tvp->v.v_flag |= VROOT; /* No-op on Ultrix 2.2 */ VN_UNLOCK((struct vnode *)tvp); AFS_GLOCK(); afs_globalVFS = afsp; *avpp = (struct vnode *) tvp; } afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *avpp, ICL_TYPE_INT32, code); AFS_GUNLOCK(); return code; } mp_afs_quotactl(struct mount *mp, int cmd, uid_t uid, caddr_t arg) { return EOPNOTSUPP; } int mp_afs_statfs(struct mount *afsp) { struct nstatfs *abp = &afsp->m_stat; AFS_GLOCK(); AFS_STATCNT(afs_statfs); abp->f_type = MOUNT_AFS; abp->f_bsize = afsp->vfs_bsize; /* Fake a high number below to satisfy programs that use the statfs call * to make sure that there's enough space in the device partition before * storing something there. */ abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files = abp->f_ffree = 2000000; abp->f_fsize = 1024; abp->f_fsid.val[0] = afsp->m_stat.f_fsid.val[0]; abp->f_fsid.val[1] = afsp->m_stat.f_fsid.val[1]; AFS_GUNLOCK(); return 0; } int mp_afs_sync(struct mount *mp, int flags) { AFS_STATCNT(afs_sync); return 0; } #ifdef AFS_DUX50_ENV int mp_afs_smoothsync(struct mount *mp, u_int age, u_int smsync_flag) { AFS_STATCNT(afs_sync); return 0; } #endif int mp_afs_fhtovp(struct mount *afsp, struct fid *fidp, struct vnode **avcp) { struct vrequest treq; register code = 0; AFS_GLOCK(); AFS_STATCNT(afs_vget); *avcp = NULL; if ((code = afs_InitReq(&treq, u.u_cred)) == 0) { code = afs_osi_vget((struct vcache**)avcp, fidp, &treq); } afs_Trace3(afs_iclSetp, CM_TRACE_VGET, ICL_TYPE_POINTER, *avcp, ICL_TYPE_INT32, treq.uid, ICL_TYPE_FID, fidp); code = afs_CheckCode(code, &treq, 42); AFS_GUNLOCK(); return code; } /* * afs_vptofh * * afs_vptofh can return two flavors of NFS fid, depending on if submounts are * allowed. The reason for this is that we can't guarantee that we found all * the entry points any OS might use to get the fid for the NFS mountd. * Hence we return a "magic" fid for all but /afs. If it goes through the * translator code, it will get transformed into a SmallFid that we recognize. * So, if submounts are disallowed, and an NFS client tries a submount, it will * get a fid which we don't recognize and the mount will either fail or we * will ignore subsequent requests for that mount. * * The Alpha fid is organized differently than for other platforms. Their * intention was to have the data portion of the fid aligned on a 4 byte * boundary. To do so, the fid is organized as: * u_short reserved * u_short len * char data[8] * The len field is the length of the entire fid, from reserved through data. * This length is used by fid_copy to include copying the reserved field. * Alpha's zero the reserved field before handing us the fid, but they use * it in fid_cmp. We use the reserved field to store the 16 bits of the Vnode. * * Note that the SmallFid only allows for 8 bits of the cell index and * 16 bits of the vnode. */ #define AFS_FIDDATASIZE 8 #define AFS_SIZEOFSMALLFID 12 /* full size of fid, including len field */ extern int afs_NFSRootOnly; /* 1 => only allow NFS mounts of /afs. */ int afs_fid_vnodeoverflow=0, afs_fid_uniqueoverflow=0; int mp_afs_vptofh(struct vnode *avn, struct fid *fidp) { struct SmallFid Sfid; long addr[2]; register struct cell *tcell; int rootvp = 0; struct vcache *avc = (struct vcache *)avn; AFS_GLOCK(); AFS_STATCNT(afs_fid); if (afs_shuttingdown) { AFS_GUNLOCK(); return EIO; } if (afs_NFSRootOnly && (avc == afs_globalVp)) rootvp = 1; if (!afs_NFSRootOnly || rootvp) { tcell = afs_GetCell(avc->fid.Cell, READ_LOCK); Sfid.Volume = avc->fid.Fid.Volume; fidp->fid_reserved = avc->fid.Fid.Vnode; Sfid.CellAndUnique = ((tcell->cellIndex << 24) + (avc->fid.Fid.Unique & 0xffffff)); afs_PutCell(tcell, READ_LOCK); if (avc->fid.Fid.Vnode > 0xffff) afs_fid_vnodeoverflow++; if (avc->fid.Fid.Unique > 0xffffff) afs_fid_uniqueoverflow++; } else { fidp->fid_reserved = AFS_XLATOR_MAGIC; addr[0] = (long)avc; AFS_GUNLOCK(); VN_HOLD((struct vnode *)avc); AFS_GLOCK(); } /* Use the fid pointer passed to us. */ fidp->fid_len = AFS_SIZEOFSMALLFID; if (afs_NFSRootOnly) { if (rootvp) { bcopy((caddr_t)&Sfid, fidp->fid_data, AFS_FIDDATASIZE); } else { bcopy((caddr_t)addr, fidp->fid_data, AFS_FIDDATASIZE); } } else { bcopy((caddr_t)&Sfid, fidp->fid_data, AFS_FIDDATASIZE); } AFS_GUNLOCK(); return 0; } int mp_Afs_init(void); /* vfs_init - defined below */ /* This is only called by vfs_mount when afs is going to be mounted as root. * Since we don't support diskless clients we shouldn't come here. */ int afsmountroot=0; int mp_afs_mountroot(struct mount *afsp, struct vnode **vp) { AFS_GLOCK(); AFS_STATCNT(afs_mountroot); afsmountroot++; AFS_GUNLOCK(); return EINVAL; } /* It's called to setup swapping over the net for diskless clients; again * not for us. */ int afsswapvp=0; int mp_afs_swapvp(void) { AFS_GLOCK(); AFS_STATCNT(afs_swapvp); afsswapvp++; AFS_GUNLOCK(); return EINVAL; } struct vfsops afs_vfsops = { mp_afs_mount, mp_afs_start, mp_afs_unmount, mp_afs_root, mp_afs_quotactl, mp_afs_statfs, mp_afs_sync, mp_afs_fhtovp, /* afs_vget */ mp_afs_vptofh, mp_Afs_init, mp_afs_mountroot, mp_afs_swapvp, #ifdef AFS_DUX50_ENV mp_afs_smoothsync #endif }; /* * System Call Entry Points */ #define NULL_FUNC (int (*)(int))0 int (*afs_syscall_func)() = NULL_FUNC; int (*afs_xsetgroups_func)() = NULL_FUNC; int (*afs_xioctl_func)() = NULL_FUNC; afssyscall(p, args, retval) struct proc *p; void *args; long *retval; { int (*func)(); int code; AFS_GLOCK(); func = afs_syscall_func; if (func == NULL_FUNC) { code = nosys(p, args, retval); } else { code = (*func)(p, args, retval); } AFS_GUNLOCK(); return code; } afsxsetgroups(p, args, retval) struct proc *p; void *args; long *retval; { int (*func)(); int code; AFS_GLOCK(); func = afs_xsetgroups_func; if (func == NULL_FUNC) { code = nosys(p, args, retval); } else { code = (*func)(p, args, retval); } AFS_GUNLOCK(); return code; } afsxioctl(p, args, retval) struct proc *p; void *args; long *retval; { int (*func)(); int code; AFS_GLOCK(); func = afs_xioctl_func; if (func == NULL_FUNC) { code = nosys(p, args, retval); } else { code = (*func)(p, args, retval); } AFS_GUNLOCK(); return code; } /* * VFS initialization and unload */ afs_unconfig() { return EBUSY; } cfg_subsys_attr_t afs_attributes[] = { {"", 0, 0, 0, 0, 0, 0} /* must be the last element */ }; afs_configure(cfg_op_t op, caddr_t indata, size_t indata_size, caddr_t outdata, size_t outdata_size) { cfg_attr_t *attributes; int ret = ESUCCESS; int i, j, size; caddr_t p; switch (op) { case CFG_OP_CONFIGURE: /* * The indata parameter is a list of attributes to be configured, and * indata_size is the count of attributes. */ if ((ret = vfssw_add_fsname(MOUNT_AFS, &afs_vfsops, "afs")) != 0) return(ret); break; case CFG_OP_UNCONFIGURE: if ((ret = afs_unconfig()) != 0) return(ret); break; default: ret = EINVAL; break; } return ret; } int mp_Afs_init(void) { extern int Afs_xsetgroups(), afs_xioctl(), afs3_syscall(); AFS_GLOCK(); sysent[AFS_SYSCALL].sy_call = afs3_syscall; #ifdef SY_NARG sysent[AFS_SYSCALL].sy_info = 6; #else sysent[AFS_SYSCALL].sy_parallel = 0; sysent[AFS_SYSCALL].sy_narg = 6; #endif sysent[SYS_setgroups].sy_call = Afs_xsetgroups; afs_xioctl_func = afsxioctl; afs_xsetgroups_func = afsxsetgroups; afs_syscall_func = afssyscall; AFS_GUNLOCK(); return 0; }