+++ /dev/null
-#define P1003_1B 1
-#define _KPOSIX_PRIORITY_SCHEDULING 1
+++ /dev/null
-/*
- * 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
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-
-int afs_osicred_initialized = 0;
-afs_ucred_t afs_osi_cred;
-afs_lock_t afs_xosi; /* lock is for tvattr */
-extern struct osi_dev cacheDev;
-extern struct mount *afs_cacheVfsp;
-
-
-void *
-osi_UFSOpen(afs_dcache_id_t *ainode)
-{
- struct inode *ip;
- register struct osi_file *afile = NULL;
- extern int cacheDiskType;
- afs_int32 code = 0;
- int dummy;
- AFS_STATCNT(osi_UFSOpen);
- if (cacheDiskType != AFS_FCACHE_TYPE_UFS)
- osi_Panic("UFSOpen called for non-UFS cache\n");
- afile = (struct osi_file *)osi_AllocSmallSpace(sizeof(struct osi_file));
- AFS_GUNLOCK();
- code =
- igetinode(afs_cacheVfsp, (dev_t) cacheDev.dev, ainode->ufs, &ip,
- &dummy);
- AFS_GLOCK();
- if (code) {
- osi_FreeSmallSpace(afile);
- osi_Panic("UFSOpen: igetinode failed");
- }
- IN_UNLOCK(ip);
- afile->vnode = ITOV(ip);
- afile->size = VTOI(afile->vnode)->i_size;
- afile->offset = 0;
- afile->proc = (int (*)())0;
- return (void *)afile;
-}
-
-int
-afs_osi_Stat(register struct osi_file *afile, register struct osi_stat *astat)
-{
- register afs_int32 code;
- struct vattr tvattr;
- AFS_STATCNT(osi_Stat);
- ObtainWriteLock(&afs_xosi, 320);
- AFS_GUNLOCK();
- VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp, code);
- AFS_GLOCK();
- if (code == 0) {
- astat->size = tvattr.va_size;
- astat->mtime = tvattr.va_mtime.tv_sec;
- astat->atime = tvattr.va_atime.tv_sec;
- }
- ReleaseWriteLock(&afs_xosi);
- return code;
-}
-
-int
-osi_UFSClose(register struct osi_file *afile)
-{
- AFS_STATCNT(osi_Close);
- if (afile->vnode) {
- AFS_RELE(afile->vnode);
- }
-
- osi_FreeSmallSpace(afile);
- return 0;
-}
-
-int
-osi_UFSTruncate(register struct osi_file *afile, afs_int32 asize)
-{
- afs_ucred_t *oldCred;
- struct vattr tvattr;
- register afs_int32 code;
- struct osi_stat tstat;
- AFS_STATCNT(osi_Truncate);
-
- /* This routine only shrinks files, and most systems
- * have very slow truncates, even when the file is already
- * small enough. Check now and save some time.
- */
- code = afs_osi_Stat(afile, &tstat);
- if (code || tstat.size <= asize)
- return code;
- ObtainWriteLock(&afs_xosi, 321);
- VATTR_NULL(&tvattr);
- /* note that this credential swapping stuff is only necessary because
- * of ufs's references directly to cred instead of to
- * credentials parameter. Probably should fix ufs some day. */
- oldCred = curproc->p_cred->pc_ucred; /* remember old credentials pointer */
- curproc->p_cred->pc_ucred = afs_osi_credp;
- /* temporarily use superuser credentials */
- tvattr.va_size = asize;
- AFS_GUNLOCK();
- VOP_SETATTR(afile->vnode, &tvattr, afs_osi_credp, code);
- AFS_GLOCK();
- curproc->p_cred->pc_ucred = oldCred; /* restore */
- ReleaseWriteLock(&afs_xosi);
- return code;
-}
-
-void
-osi_DisableAtimes(struct vnode *avp)
-{
- struct inode *ip = VTOI(avp);
- ip->i_flag &= ~IACC;
-}
-
-
-/* Generic read interface */
-int
-afs_osi_Read(register struct osi_file *afile, int offset, void *aptr,
- afs_int32 asize)
-{
- afs_ucred_t *oldCred;
- unsigned int resid;
- register afs_int32 code;
- register afs_int32 cnt1 = 0;
- AFS_STATCNT(osi_Read);
-
- /**
- * If the osi_file passed in is NULL, panic only if AFS is not shutting
- * down. No point in crashing when we are already shutting down
- */
- if (!afile) {
- if (!afs_shuttingdown)
- osi_Panic("osi_Read called with null param");
- else
- return EIO;
- }
-
- if (offset != -1)
- afile->offset = offset;
- AFS_GUNLOCK();
- code =
- gop_rdwr(UIO_READ, afile->vnode, (caddr_t) aptr, asize, afile->offset,
- AFS_UIOSYS, IO_UNIT, afs_osi_credp, &resid);
- AFS_GLOCK();
- if (code == 0) {
- code = asize - resid;
- afile->offset += code;
- osi_DisableAtimes(afile->vnode);
- } else {
- afs_Trace2(afs_iclSetp, CM_TRACE_READFAILED, ICL_TYPE_INT32, resid,
- ICL_TYPE_INT32, code);
- code = -1;
- }
- return code;
-}
-
-/* Generic write interface */
-int
-afs_osi_Write(register struct osi_file *afile, afs_int32 offset, void *aptr,
- afs_int32 asize)
-{
- afs_ucred_t *oldCred;
- unsigned int resid;
- register afs_int32 code;
- AFS_STATCNT(osi_Write);
- if (!afile)
- osi_Panic("afs_osi_Write called with null param");
- if (offset != -1)
- afile->offset = offset;
- {
- struct ucred *tmpcred = curproc->p_cred->pc_ucred;
- curproc->p_cred->pc_ucred = afs_osi_credp;
- AFS_GUNLOCK();
- code =
- gop_rdwr(UIO_WRITE, afile->vnode, (caddr_t) aptr, asize,
- afile->offset, AFS_UIOSYS, IO_UNIT, afs_osi_credp,
- &resid);
- AFS_GLOCK();
- curproc->p_cred->pc_ucred = tmpcred;
- }
- if (code == 0) {
- code = asize - resid;
- afile->offset += code;
- } else {
- code = -1;
- }
- if (afile->proc) {
- (*afile->proc) (afile, code);
- }
- return code;
-}
-
-
-/* This work should be handled by physstrat in ca/machdep.c.
- This routine written from the RT NFS port strategy routine.
- It has been generalized a bit, but should still be pretty clear. */
-int
-afs_osi_MapStrategy(int (*aproc) (), register struct buf *bp)
-{
- afs_int32 returnCode;
-
- AFS_STATCNT(osi_MapStrategy);
- returnCode = (*aproc) (bp);
-
- return returnCode;
-}
-
-
-
-void
-shutdown_osifile(void)
-{
- AFS_STATCNT(shutdown_osifile);
- if (afs_cold_shutdown) {
- afs_osicred_initialized = 0;
- }
-}
+++ /dev/null
-/*
- * 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
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-#if AFS_GCPAGS
-
-/* return a pointer (sometimes a static copy ) to the cred for a
- * given afs_proc_t.
- * subsequent calls may overwrite the previously returned value.
- */
-
-
-const afs_ucred_t *
-afs_osi_proc2cred(afs_proc_t * pr)
-{
- afs_ucred_t *rv = NULL;
-
- if (pr == NULL) {
- return NULL;
- }
- rv = pr->p_cred;
-
- return rv;
-}
-
-#endif /* AFS_GCPAGS */
+++ /dev/null
-/*
- * 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_groups.c
- *
- * Implements:
- * Afs_xsetgroups (syscall)
- * setpag
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "afs/afs_stats.h" /* statistics */
-
-#define NOCRED ((struct ucred *) -1)
-#define NOUID ((uid_t) -1)
-#define NOGID ((gid_t) -1)
-
-
-static int
- afs_getgroups(struct ucred *cred, int ngroups, gid_t * gidset);
-
-static int
- afs_setgroups(struct proc *proc, struct ucred **cred, int ngroups,
- gid_t * gidset, int change_parent);
-
-int
-Afs_xsetgroups(p, args, retval)
- struct proc *p;
- void *args;
- int *retval;
-{
- int code = 0;
- struct vrequest treq;
-
- AFS_STATCNT(afs_xsetgroups);
- AFS_GLOCK();
-
- /* code = afs_InitReq(&treq, u.u_cred); */
- code = afs_InitReq(&treq, curproc->p_cred->pc_ucred);
- AFS_GUNLOCK();
- if (code)
- return code;
-
- code = setgroups(p, args, retval);
- /* Note that if there is a pag already in the new groups we don't
- * overwrite it with the old pag.
- */
- if (PagInCred(curproc->p_cred->pc_ucred) == NOPAG) {
- if (((treq.uid >> 24) & 0xff) == 'A') {
- AFS_GLOCK();
- /* we've already done a setpag, so now we redo it */
- AddPag(p, treq.uid, &p->p_rcred);
- AFS_GUNLOCK();
- }
- }
- return code;
-}
-
-
-int
-setpag(proc, cred, pagvalue, newpag, change_parent)
- struct proc *proc;
- struct ucred **cred;
- afs_uint32 pagvalue;
- afs_uint32 *newpag;
- afs_uint32 change_parent;
-{
- gid_t gidset[NGROUPS];
- int ngroups, code;
- int j;
-
- AFS_STATCNT(setpag);
- ngroups = afs_getgroups(*cred, NGROUPS, gidset);
- if (afs_get_pag_from_groups(gidset[0], gidset[1]) == NOPAG) {
- /* We will have to shift grouplist to make room for pag */
- if (ngroups + 2 > NGROUPS) {
- return (E2BIG);
- }
- for (j = ngroups - 1; j >= 0; j--) {
- gidset[j + 2] = gidset[j];
- }
- ngroups += 2;
- }
- *newpag = (pagvalue == -1 ? genpag() : pagvalue);
- afs_get_groups_from_pag(*newpag, &gidset[0], &gidset[1]);
- code = afs_setgroups(proc, cred, ngroups, gidset, change_parent);
- return code;
-}
-
-
-static int
-afs_getgroups(struct ucred *cred, int ngroups, gid_t * gidset)
-{
- int ngrps, savengrps;
- gid_t *gp;
-
- AFS_STATCNT(afs_getgroups);
- savengrps = ngrps = MIN(ngroups, cred->cr_ngroups);
- gp = cred->cr_groups;
- while (ngrps--)
- *gidset++ = *gp++;
- return savengrps;
-}
-
-
-
-static int
-afs_setgroups(struct proc *proc, struct ucred **cred, int ngroups,
- gid_t * gidset, int change_parent)
-{
- int ngrps;
- int i;
- gid_t *gp;
- struct ucred *newcr, *cr;
-
- AFS_STATCNT(afs_setgroups);
- /*
- * The real setgroups() call does this, so maybe we should too.
- *
- */
- if (ngroups > NGROUPS)
- return EINVAL;
- cr = *cred;
- if (!change_parent) {
- crhold(cr);
- newcr = crcopy(cr);
- } else
- newcr = cr;
- newcr->cr_ngroups = ngroups;
- gp = newcr->cr_groups;
- while (ngroups--)
- *gp++ = *gidset++;
- if (!change_parent) {
- substitute_real_creds(proc, NOUID, NOUID, NOGID, NOGID, newcr);
- }
- *cred = newcr;
- return (0);
-}
+++ /dev/null
-/*
- * 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
- */
-
-/*
- * FreeBSD inode operations
- *
- * Implements:
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/osi_inode.h"
-#include "afs/afs_stats.h" /* statistics stuff */
-#include <sys/queue.h>
-#include <sys/lock.h>
-#include <ufs/ufsmount.h>
-#include <ufs/ufs/dinode.h>
-
-getinode(fs, dev, inode, ipp, perror)
- struct mount *fs;
- struct inode **ipp;
- dev_t dev;
- ino_t inode;
- int *perror;
-{
- register struct vnode *vp;
- char fake_vnode[FAKE_INODE_SIZE];
- struct inode *ip;
- int code;
-
- *ipp = 0;
- *perror = 0;
- if (!fs) {
- register struct ufsmount *ump;
- register struct vnode *vp;
- register struct mount *mp;
-
- MOUNTLIST_LOCK();
- if (mp = TAILQ_FIRST(&mountlist))
- do {
- /*
- * XXX Also do the test for MFS
- */
-#undef m_data
-#undef m_next
- if (mp->mnt_stat.f_type == MOUNT_UFS) {
- MOUNTLIST_UNLOCK();
- ump = VFSTOUFS(mp);
- if (ump->um_fs == NULL)
- break;
- if (ump->um_dev == dev) {
- fs = ump->um_mountp;
- }
- MOUNTLIST_LOCK();
- }
- mp = TAILQ_NEXT(mp, mnt_list);
- } while (mp != TAILQ_FIRST(&mountlist));
- MOUNTLIST_UNLOCK();
- if (!fs)
- return (ENXIO);
- }
- vp = (struct vnode *)fake_vnode;
- fake_inode_init(vp, fs);
- code = iget(VTOI(vp), inode, &ip, 0);
- if (code != 0) {
- *perror = BAD_IGET;
- return code;
- } else {
- *ipp = ip;
- return (0);
- }
-}
-
-igetinode(vfsp, dev, inode, ipp, perror)
- struct inode **ipp;
- struct mount *vfsp;
- dev_t dev;
- ino_t inode;
- int *perror;
-{
- struct inode *pip, *ip;
- extern struct osi_dev cacheDev;
- register int code = 0;
-
- *perror = 0;
-
- AFS_STATCNT(igetinode);
-
- if ((code = getinode(vfsp, dev, inode, &ip, perror)) != 0) {
- return (code);
- }
-
- if (ip->i_mode == 0) {
- /* Not an allocated inode */
- iforget(ip);
- return (ENOENT);
- }
-
- if (ip->i_nlink == 0 || (ip->i_mode & IFMT) != IFREG) {
- iput(ip);
- return (ENOENT);
- }
-
- *ipp = ip;
- return (0);
-}
-
-iforget(ip)
- struct inode *ip;
-{
- struct vnode *vp = ITOV(ip);
-
- AFS_STATCNT(iforget);
-
- VN_LOCK(vp);
- /* this whole thing is too wierd. Why??? XXX */
- if (vp->v_usecount == 1) {
- VN_UNLOCK(vp);
- idrop(ip);
- } else {
- VN_UNLOCK(vp);
- }
-}
-
-/*
- * icreate system call -- create an inode
- */
-afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, retval)
- long *retval;
- long dev, near_inode, param1, param2, param3, param4;
-{
- int dummy, err = 0;
- struct inode *ip, *newip;
- register int code;
- struct vnode *vp;
-
- AFS_STATCNT(afs_syscall_icreate);
-
- if (!afs_suser(NULL))
- return (EPERM);
-
- code = getinode(0, (dev_t) dev, 2, &ip, &dummy);
- if (code) {
- return (ENOENT);
- }
- code = ialloc(ip, (ino_t) near_inode, 0, &newip);
- iput(ip);
- if (code) {
- return (code);
- }
- IN_LOCK(newip);
- newip->i_flag |= IACC | IUPD | ICHG;
-
- newip->i_nlink = 1;
-
- newip->i_mode = IFREG;
-
- IN_UNLOCK(newip);
- vp = ITOV(newip);
- VN_LOCK(vp);
- vp->v_type = VREG;
- VN_UNLOCK(vp);
-
- /*
- * if ( !vp->v_object)
- * {
- * extern struct vfs_ubcops ufs_ubcops;
- * extern struct vm_ubc_object* ubc_object_allocate();
- * struct vm_ubc_object* vop;
- * vop = ubc_object_allocate(&vp, &ufs_ubcops,
- * vp->v_mount->m_funnel);
- * VN_LOCK(vp);
- * vp->v_object = vop;
- * VN_UNLOCK(vp);
- * }
- */
-
- IN_LOCK(newip);
- /* newip->i_flags |= IC_XUID|IC_XGID; */
- /* newip->i_flags &= ~IC_PROPLIST; */
- newip->i_vicep1 = param1;
- if (param2 == 0x1fffffff /*INODESPECIAL*/) {
- newip->i_vicep2 = ((0x1fffffff << 3) + (param4 & 0x3));
- newip->i_vicep3a = (u_short) (param3 >> 16);
- newip->i_vicep3b = (u_short) param3;
- } else {
- newip->i_vicep2 =
- (((param2 >> 16) & 0x1f) << 27) +
- (((param4 >> 16) & 0x1f) << 22) + (param3 & 0x3fffff);
- newip->i_vicep3a = (u_short) param4;
- newip->i_vicep3b = (u_short) param2;
- }
- newip->i_vicemagic = VICEMAGIC;
-
- *retval = newip->i_number;
- IN_UNLOCK(newip);
- iput(newip);
- return (code);
-}
-
-
-afs_syscall_iopen(dev, inode, usrmod, retval)
- long *retval;
- int dev, inode, usrmod;
-{
- struct file *fp;
- struct inode *ip;
- struct vnode *vp = NULL;
- int dummy;
- int fd;
- extern struct fileops vnops;
- register int code;
-
- AFS_STATCNT(afs_syscall_iopen);
-
- if (!afs_suser(NULL))
- return (EPERM);
-
- code = igetinode(0, (dev_t) dev, (ino_t) inode, &ip, &dummy);
- if (code) {
- return (code);
- }
- if ((code = falloc(curproc, &fp, &fd)) != 0) {
- iput(ip);
- return (code);
- }
- IN_UNLOCK(ip);
-
- /* FreeBSD doesn't do much mp stuff yet :( */
- /* FP_LOCK(fp); */
- fp->f_flag = (usrmod) & FMASK;
- fp->f_type = DTYPE_VNODE;
- fp->f_ops = &vnops;
- fp->f_data = (caddr_t) ITOV(ip);
-
- /* FP_UNLOCK(fp); */
- return (0);
-}
-
-
-/*
- * Support for iinc() and idec() system calls--increment or decrement
- * count on inode.
- * Restricted to super user.
- * Only VICEMAGIC type inodes.
- */
-afs_syscall_iincdec(dev, inode, inode_p1, amount)
- int dev, inode, inode_p1, amount;
-{
- int dummy;
- struct inode *ip;
- register int code;
-
- if (!afs_suser(NULL))
- return (EPERM);
-
- code = igetinode(0, (dev_t) dev, (ino_t) inode, &ip, &dummy);
- if (code) {
- return (code);
- }
- if (!IS_VICEMAGIC(ip)) {
- return (EPERM);
- } else if (ip->i_vicep1 != inode_p1) {
- return (ENXIO);
- }
- ip->i_nlink += amount;
- if (ip->i_nlink == 0) {
- CLEAR_VICEMAGIC(ip);
- }
- ip->i_flag |= ICHG;
- iput(ip);
- return (0);
-}
+++ /dev/null
-/*
- * 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_inode.h
- *
- * Inode information required for NetBSD servers and salvager.
- */
-#ifndef _OSI_INODE_H_
-#define _OSI_INODE_H_
-
-#define BAD_IGET -1000
-
-#define VICEMAGIC 0xb61cfa84
-
-#define DI_VICEP3(p) \
- ( ((u_int)((p)->di_vicep3a)) << 16 | ((u_int)((p)->di_vicep3b)) )
-#define I_VICE3(p) \
- ( ((u_int)((p)->i_vicep3a)) << 16 | ((u_int)((p)->i_vicep3b)) )
-
-#define FAKE_INODE_SIZE (sizeof(struct vnode)+sizeof(struct inode))
-#define MOUNTLIST_UNLOCK() simple_lock_unlock(&mountlist_slock)
-#define MOUNTLIST_LOCK() simple_lock(&mountlist_slock)
-
-/* FreeBSD doesn't actually have a di_proplb, so we use di_spare[0] */
-#define di_proplb di_spare[0]
-/* For some reason, they're called "oldids" instead of "bc_{u,g}id" */
-#define di_bcuid di_u.oldids[0]
-#define di_bcgid di_u.oldids[1]
-
-#define i_vicemagic i_din.di_spare[0]
-#define i_vicep1 i_din.di_uid
-#define i_vicep2 i_din.di_gid
-#define i_vicep3a i_din.di_u.oldids[0]
-#define i_vicep3b i_din.di_u.oldids[1]
-#define i_vicep4 i_din.di_spare[1] /* not used */
-
-#define di_vicemagic di_spare[0]
-#define di_vicep1 di_uid
-#define di_vicep2 di_gid
-#define di_vicep3a di_u.oldids[0]
-#define di_vicep3b di_u.oldids[1]
-#define di_vicep4 di_spare[1] /* not used */
-
-/*
- * Macros for handling inode numbers:
- * inode number to file system block offset.
- * inode number to cylinder group number.
- * inode number to file system block address.
- */
-#define itoo(fs, x) ((x) % INOPB(fs))
-#define itog(fs, x) ((x) / (fs)->fs_ipg)
-#define itod(fs, x) \
- ((daddr_t)(cgimin(fs, itog(fs, x)) + \
- (blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs))))))
-
-
-#define IS_VICEMAGIC(ip) ((ip)->i_vicemagic == VICEMAGIC)
-#define IS_DVICEMAGIC(dp) ((dp)->di_vicemagic == VICEMAGIC)
-
-#define CLEAR_VICEMAGIC(ip) (ip)->i_vicemagic = 0
-#define CLEAR_DVICEMAGIC(dp) (dp)->di_vicemagic = 0
-
-#endif /* _OSI_INODE_H_ */
+++ /dev/null
-/*
- * 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
- */
-
-/*
- *
- * NetBSD OSI header file. Extends afs_osi.h.
- *
- * afs_osi.h includes this file, which is the only way this file should
- * be included in a source file. This file can redefine macros declared in
- * afs_osi.h.
- */
-
-#ifndef _OSI_MACHDEP_H_
-#define _OSI_MACHDEP_H_
-
-#include <sys/lock.h>
-/* #include <kern/sched_prim.h> */
-/* #include <sys/unix_defs.h> */
-
-#define getpid() curproc
-
-/*
- * Time related macros
- */
-extern struct timeval time;
-#define osi_Time() (time.tv_sec)
-#define afs_hz hz
-
-typedef struct ucred afs_ucred_t;
-typedef struct proc afs_proc_t;
-
-#define afs_bufferpages bufpages
-
-#undef gop_lookupname
-#define gop_lookupname(fnamep,segflg,followlink,compvpp) lookupname((fnamep),(segflg),(followlink),NULL,(compvpp))
-#undef gop_lookupname_user
-#define gop_lookupname_user(fnamep,segflg,followlink,compvpp) lookupname((fnamep),(segflg),(followlink),NULL,(compvpp))
-
-#define osi_vnhold(avc,r) do { \
- if ((avc)->vrefCount) { VN_HOLD((struct vnode *)(avc)); } \
- else osi_Panic("refcnt==0"); } while(0)
-
-#define gop_rdwr(rw,gp,base,len,offset,segflg,unit,cred,aresid) \
- vn_rdwr((rw),(gp),(base),(len),(offset),(segflg),(unit),(cred),(aresid), curproc)
-
-#undef afs_suser
-
-extern struct simplelock afs_global_lock;
-#if 0
-extern thread_t afs_global_owner;
-#define AFS_GLOCK() \
- do { \
- usimple_lock(&afs_global_lock); \
- osi_Assert(afs_global_owner == (thread_t)0); \
- afs_global_owner = current_thread(); \
- } while (0)
-#define AFS_GUNLOCK() \
- do { \
- osi_Assert(afs_global_owner == current_thread()); \
- afs_global_owner = (thread_t)0; \
- usimple_unlock(&afs_global_lock); \
- } while(0)
-#define ISAFS_GLOCK() (afs_global_owner == current_thread())
-#else
-#define AFS_GLOCK() \
- do { \
- simple_lock(&afs_global_lock); \
- } while (0)
-#define AFS_GUNLOCK() \
- do { \
- simple_unlock(&afs_global_lock); \
- } while(0)
-#define osi_InitGlock() \
- do { \
- lockinit(&afs_global_lock, PLOCK, "afs global lock", 0, 0); \
- afs_global_owner = 0; \
- } while (0)
-#endif /* 0 */
-
-#undef SPLVAR
-#define SPLVAR
-#undef NETPRI
-#define NETPRI
-#undef USERPRI
-#define USERPRI
-
-/* Vnode related macros */
-
-extern int (**afs_vnodeop_p) ();
-#define vType(vc) AFSTOV(vc)->v_type
-#define vSetVfsp(vc, vfsp) AFSTOV(vc)->v_mount = (vfsp)
-#define vSetType(vc, type) AFSTOV(vc)->v_type = (type)
-#define IsAfsVnode(v) ((v)->v_op == afs_vnodeop_p)
-#define SetAfsVnode(v) /* nothing; done in getnewvnode() */
-
-#define osi_procname(procname, size) strncpy(procname, curproc->p_comm, size)
-
-#endif /* _OSI_MACHDEP_H_ */
+++ /dev/null
-/*
- * 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_misc.c
- *
- * Implements:
- * afs_suser
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-
-/*
- * afs_suser() returns true if the caller is superuser, false otherwise.
- *
- * Note that it must NOT set errno.
- */
-
-afs_suser(void *credp)
-{
- int error;
-
- if (suser(curproc) == 0) {
- return (1);
- }
- return (0);
-}
+++ /dev/null
-/*
- * 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
- */
-
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-static char waitV;
-
-void
-afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle)
-{
- AFS_STATCNT(osi_InitWaitHandle);
- achandle->proc = (caddr_t) 0;
-}
-
-/* cancel osi_Wait */
-void
-afs_osi_CancelWait(struct afs_osi_WaitHandle *achandle)
-{
- caddr_t proc;
-
- AFS_STATCNT(osi_CancelWait);
- proc = achandle->proc;
- if (proc == 0)
- return;
- achandle->proc = (caddr_t) 0; /* so dude can figure out he was signalled */
- afs_osi_Wakeup(&waitV);
-}
-
-/* afs_osi_Wait
- * Waits for data on ahandle, or ams ms later. ahandle may be null.
- * Returns 0 if timeout and EINTR if signalled.
- */
-int
-afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok)
-{
- int code;
- afs_int32 endTime, tid;
-
- AFS_STATCNT(osi_Wait);
- endTime = osi_Time() + (ams / 1000);
- if (ahandle)
- ahandle->proc = (caddr_t) curproc;
- do {
- AFS_ASSERT_GLOCK();
- code = 0;
- code = afs_osi_TimedSleep(&waitV, ams, aintok);
-
- if (code)
- break; /* if something happened, quit now */
- /* if we we're cancelled, quit now */
- if (ahandle && (ahandle->proc == (caddr_t) 0)) {
- /* we've been signalled */
- break;
- }
- } while (osi_Time() < endTime);
- return code;
-}
-
-
-
-
-typedef struct afs_event {
- struct afs_event *next; /* next in hash chain */
- char *event; /* lwp event: an address */
- int refcount; /* Is it in use? */
- int seq; /* Sequence number: this is incremented
- * by wakeup calls; wait will not return until
- * it changes */
- int cond;
-} afs_event_t;
-
-#define HASHSIZE 128
-afs_event_t *afs_evhasht[HASHSIZE]; /* Hash table for events */
-#define afs_evhash(event) (afs_uint32) ((((long)event)>>2) & (HASHSIZE-1));
-int afs_evhashcnt = 0;
-
-/* Get and initialize event structure corresponding to lwp event (i.e. address)
- * */
-static afs_event_t *
-afs_getevent(char *event)
-{
- afs_event_t *evp, *newp = 0;
- int hashcode;
-
- AFS_ASSERT_GLOCK();
- hashcode = afs_evhash(event);
- evp = afs_evhasht[hashcode];
- while (evp) {
- if (evp->event == event) {
- evp->refcount++;
- return evp;
- }
- if (evp->refcount == 0)
- newp = evp;
- evp = evp->next;
- }
- if (!newp) {
- newp = (afs_event_t *) osi_AllocSmallSpace(sizeof(afs_event_t));
- afs_evhashcnt++;
- newp->next = afs_evhasht[hashcode];
- afs_evhasht[hashcode] = newp;
- newp->seq = 0;
- }
- newp->event = event;
- newp->refcount = 1;
- return newp;
-}
-
-/* Release the specified event */
-#define relevent(evp) ((evp)->refcount--)
-
-
-void
-afs_osi_Sleep(void *event)
-{
- struct afs_event *evp;
- int seq;
-
- evp = afs_getevent(event);
- seq = evp->seq;
- while (seq == evp->seq) {
- AFS_ASSERT_GLOCK();
- assert_wait((vm_offset_t) (&evp->cond), 0);
- AFS_GUNLOCK();
- thread_block();
- AFS_GLOCK();
- }
- relevent(evp);
-}
-
-int
-afs_osi_SleepSig(void *event)
-{
- afs_osi_Sleep(event);
- return 0;
-}
-
-/* afs_osi_TimedSleep
- *
- * Arguments:
- * event - event to sleep on
- * ams --- max sleep time in milliseconds
- * aintok - 1 if should sleep interruptibly
- *
- * Returns 0 if timeout and EINTR if signalled.
- */
-int
-afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok)
-{
- int code = 0;
- struct afs_event *evp;
- int ticks;
-
- ticks = (ams * afs_hz) / 1000;
-
-
- evp = afs_getevent(event);
-
- assert_wait((vm_offset_t) (&evp->cond), aintok);
- AFS_GUNLOCK();
- thread_set_timeout(ticks);
- thread_block();
- AFS_GLOCK();
- /* if (current_thread()->wait_result != THREAD_AWAKENED)
- * code = EINTR; */
-
- relevent(evp);
- return code;
-}
-
-
-int
-afs_osi_Wakeup(void *event)
-{
- int ret = 1;
- struct afs_event *evp;
-
- evp = afs_getevent(event);
- if (evp->refcount > 1) {
- evp->seq++;
- thread_wakeup((vm_offset_t) (&evp->cond));
- ret = 0;
- }
- relevent(evp);
- return ret;
-}
+++ /dev/null
-/*
- * 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 NetBSD
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics stuff */
-#include <sys/types.h>
-#include <kern/mach_param.h>
-#include <sys/sysconfig.h>
-#include <sys/systm.h>
-#include <sys/resource.h>
-#include <sys/errno.h>
-#include <sys/conf.h>
-#include <machine/machlimits.h>
-
-
-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");
-
- memset(afsp->m_stat.f_mntonname, 0, MNAMELEN);
- memset(afsp->m_stat.f_mntfromname, 0, MNAMELEN);
- AFS_COPYINSTR(path, (caddr_t) afsp->m_stat.f_mntonname, MNAMELEN, &size,
- code);
- memcpy(afsp->m_stat.f_mntfromname, "AFS", 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->f.states & CStatd)) {
- tvp = afs_globalVp;
- } else {
- if (afs_globalVp) {
- afs_PutVCache(afs_globalVp);
- afs_globalVp = NULL;
- }
-
- if (!(code = afs_InitReq(&treq, cred)) && !(code = afs_CheckInit())) {
- tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
- /* 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;
-}
-
-
-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, 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 = VTOAFS(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->f.fid.Cell, READ_LOCK);
- Sfid.Volume = avc->f.fid.Fid.Volume;
- fidp->fid_reserved = avc->f.fid.Fid.Vnode;
- Sfid.CellAndUnique =
- ((tcell->cellIndex << 24) + (avc->f.fid.Fid.Unique & 0xffffff));
- afs_PutCell(tcell, READ_LOCK);
- if (avc->f.fid.Fid.Vnode > 0xffff)
- afs_fid_vnodeoverflow++;
- if (avc->f.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) {
- memcpy(fidp->fid_data, (caddr_t) & Sfid, AFS_FIDDATASIZE);
- } else {
- memcpy(fidp->fid_data, (caddr_t) addr, AFS_FIDDATASIZE);
- }
- } else {
- memcpy(fidp->fid_data, (caddr_t) & Sfid, 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
-};
-
-
-/*
- * 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();
-
- AFS_GLOCK();
- sysent[AFS_SYSCALL].sy_call = afs3_syscall;
- sysent[AFS_SYSCALL].sy_parallel = 0;
- sysent[AFS_SYSCALL].sy_narg = 6;
- sysent[SYS_setgroups].sy_call = Afs_xsetgroups;
- afs_xioctl_func = afsxioctl;
- afs_xsetgroups_func = afsxsetgroups;
- afs_syscall_func = afssyscall;
- AFS_GUNLOCK();
-
- return 0;
-}
+++ /dev/null
-/*
- * 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_vm.c implements:
- *
- * osi_VM_FlushVCache(avc, slept)
- * osi_ubc_flush_dirty_and_wait(vp, flags)
- * osi_VM_StoreAllSegments(avc)
- * osi_VM_TryToSmush(avc, acred, sync)
- * osi_VM_FlushPages(avc, credp)
- * osi_VM_Truncate(avc, alen, acred)
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-/* #include <vm/vm_ubc.h> */
-#include <limits.h>
-#include <float.h>
-
-/* Try to discard pages, in order to recycle a vcache entry.
- *
- * We also make some sanity checks: ref count, open count, held locks.
- *
- * We also do some non-VM-related chores, such as releasing the cred pointer
- * (for AIX and Solaris) and releasing the gnode (for AIX).
- *
- * Locking: afs_xvcache lock is held. If it is dropped and re-acquired,
- * *slept should be set to warn the caller.
- *
- * Formerly, afs_xvcache was dropped and re-acquired for Solaris, but now it
- * is not dropped and re-acquired for any platform. It may be that *slept is
- * therefore obsolescent.
- *
- * OSF/1 Locking: VN_LOCK has been called.
- */
-int
-osi_VM_FlushVCache(struct vcache *avc, int *slept)
-{
-#ifdef SECRETLY_OSF1
- if (avc->vrefCount > 1)
- return EBUSY;
-
- if (avc->opens)
- return EBUSY;
-
- /* if a lock is held, give up */
- if (CheckLock(&avc->lock))
- return EBUSY;
-
- AFS_GUNLOCK();
- ubc_invalidate(((struct vnode *)avc)->v_object, 0, 0, B_INVAL);
- AFS_GLOCK();
-#endif /* SECRETLY_OSF1 */
-
- return 0;
-}
-
-/*
- * osi_ubc_flush_dirty_and_wait -- ensure all dirty pages cleaned
- *
- * Alpha OSF/1 doesn't make it easy to wait for all dirty pages to be cleaned.
- * NFS tries to do this by calling waitforio(), which waits for v_numoutput
- * to go to zero. But that isn't good enough, because afs_putpage() doesn't
- * increment v_numoutput until it has obtained the vcache entry lock. Suppose
- * that Process A, trying to flush a page, is waiting for that lock, and
- * Process B tries to close the file. Process B calls waitforio() which thinks
- * that everything is cool because v_numoutput is still zero. Process B then
- * proceeds to call afs_StoreAllSegments(). Finally when B is finished, A gets
- * to proceed and flush its page. But then it's too late because the file is
- * already closed.
- *
- * (I suspect that waitforio() is not adequate for NFS, just as it isn't
- * adequate for us. But that's not my problem.)
- *
- * The only way we can be sure that there are no more dirty pages is if there
- * are no more pages with pg_busy set. We look for them on the cleanpl.
- *
- * For some reason, ubc_flush_dirty() only looks at the dirtypl, not the
- * dirtywpl. I don't know why this is good enough, but I assume it is. By
- * the same token, I only look for busy pages on the cleanpl, not the cleanwpl.
- *
- * Called with the global lock NOT held.
- */
-static void
-osi_ubc_flush_dirty_and_wait(struct vnode *vp, int flags)
-{
- int retry;
- vm_page_t pp;
- int first;
-
-#ifdef SECRETLY_OSF1
- do {
- struct vm_ubc_object *vop;
- vop = (struct vm_ubc_object *)(vp->v_object);
- ubc_flush_dirty(vop, flags);
-
- vm_object_lock(vop);
- if (vop->vu_dirtypl)
- /* shouldn't happen, but who knows */
- retry = 1;
- else {
- retry = 0;
- if (vop->vu_cleanpl) {
- for (first = 1, pp = vop->vu_cleanpl;
- first || pp != vop->vu_cleanpl;
- first = 0, pp = pp->pg_onext) {
- if (pp->pg_busy) {
- retry = 1;
- pp->pg_wait = 1;
- assert_wait_mesg((vm_offset_t) pp, FALSE, "pg_wait");
- vm_object_unlock(vop);
- thread_block();
- break;
- }
- }
- }
- if (retry)
- continue;
- }
- vm_object_unlock(vop);
- } while (retry);
-#endif /* SECRETLY_OSF1 */
-}
-
-/* Try to store pages to cache, in order to store a file back to the server.
- *
- * Locking: the vcache entry's lock is held. It will usually be dropped and
- * re-obtained.
- */
-void
-osi_VM_StoreAllSegments(struct vcache *avc)
-{
-#ifdef SECRETLY_OSF1
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- osi_ubc_flush_dirty_and_wait((struct vnode *)avc, 0);
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 94);
-#endif /* SECRETLY_OSF1 */
-}
-
-/* Try to invalidate pages, for "fs flush" or "fs flushv"; or
- * try to free pages, when deleting a file.
- *
- * Locking: the vcache entry's lock is held. It may be dropped and
- * re-obtained.
- *
- * Since we drop and re-obtain the lock, we can't guarantee that there won't
- * be some pages around when we return, newly created by concurrent activity.
- */
-void
-osi_VM_TryToSmush(struct vcache *avc, afs_ucred_t *acred, int sync)
-{
-#ifdef SECRETLY_OSF1
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- osi_ubc_flush_dirty_and_wait((struct vnode *)avc, 0);
- ubc_invalidate(((struct vnode *)avc)->v_object, 0, 0, B_INVAL);
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 59);
-#endif /* SECRETLY_OSF1 */
-}
-
-/* Purge VM for a file when its callback is revoked.
- *
- * Locking: No lock is held, not even the global lock.
- */
-void
-osi_VM_FlushPages(struct vcache *avc, afs_ucred_t *credp)
-{
-#ifdef SECRETLY_OSF1
- ubc_flush_dirty(((struct vnode *)avc)->v_object, 0);
- ubc_invalidate(((struct vnode *)avc)->v_object, 0, 0, B_INVAL);
-#endif /* SECRETLY_OSF1 */
-}
-
-/* Purge pages beyond end-of-file, when truncating a file.
- *
- * Locking: no lock is held, not even the global lock.
- * activeV is raised. This is supposed to block pageins, but at present
- * it only works on Solaris.
- */
-void
-osi_VM_Truncate(struct vcache *avc, int alen, afs_ucred_t *acred)
-{
-#ifdef SECRETLY_OSF1
- ubc_invalidate(((struct vnode *)avc)->v_object, alen, MAXINT - alen,
- B_INVAL);
-#endif /* SECRETLY_OSF1 */
-}
+++ /dev/null
-/*
- * 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
- */
-
-/*
- * vnodeops structure and Digital Unix specific ops and support routines.
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include <vm/vm.h>
-#include <vm/vnode_pager.h>
-#include <vm/vm_map.h>
-/* #include <vm/vm_ubc.h> */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/afs_osidnlc.h"
-
-
-extern int afs_lookup(), afs_create(), afs_noop(), afs_open(), afs_close();
-extern int afs_access(), afs_getattr(), afs_setattr(), afs_badop();
-extern int afs_fsync(), afs_seek(), afs_remove(), afs_link(), afs_rename();
-extern int afs_mkdir(), afs_rmdir(), afs_symlink(), afs_readdir();
-extern int afs_readlink(), afs_lockctl();
-extern int vn_pathconf_default(), seltrue();
-
-int mp_afs_lookup(), mp_afs_create(), mp_afs_open();
-int mp_afs_access(), mp_afs_getattr(), mp_afs_setattr(), mp_afs_ubcrdwr();
-int mp_afs_ubcrdwr(), mp_afs_mmap();
-int mp_afs_fsync(), mp_afs_seek(), mp_afs_remove(), mp_afs_link();
-int mp_afs_rename(), mp_afs_mkdir(), mp_afs_rmdir(), mp_afs_symlink();
-int mp_afs_readdir(), mp_afs_readlink(), mp_afs_abortop(), mp_afs_inactive();
-int mp_afs_reclaim(), mp_afs_bmap(), mp_afs_strategy(), mp_afs_print();
-int mp_afs_page_read(), mp_afs_page_write(), mp_afs_swap(), mp_afs_bread();
-int mp_afs_brelse(), mp_afs_lockctl(), mp_afs_syncdata(), mp_afs_close();
-int mp_afs_closex();
-
-#if 0
-/* AFS vnodeops */
-struct vnodeops Afs_vnodeops = {
- mp_afs_lookup,
- mp_afs_create,
- afs_noop, /* vn_mknod */
- mp_afs_open,
- mp_afs_close,
- mp_afs_access,
- mp_afs_getattr,
- mp_afs_setattr,
- mp_afs_ubcrdwr,
- mp_afs_ubcrdwr,
- afs_badop, /* vn_ioctl */
- seltrue, /* vn_select */
- mp_afs_mmap,
- mp_afs_fsync,
- mp_afs_seek,
- mp_afs_remove,
- mp_afs_link,
- mp_afs_rename,
- mp_afs_mkdir,
- mp_afs_rmdir,
- mp_afs_symlink,
- mp_afs_readdir,
- mp_afs_readlink,
- mp_afs_abortop,
- mp_afs_inactive,
- mp_afs_reclaim,
- mp_afs_bmap,
- mp_afs_strategy,
- mp_afs_print,
- mp_afs_page_read,
- mp_afs_page_write,
- mp_afs_swap,
- mp_afs_bread,
- mp_afs_brelse,
- mp_afs_lockctl,
- mp_afs_syncdata,
- afs_noop, /* Lock */
- afs_noop, /* unLock */
- afs_noop, /* get ext attrs */
- afs_noop, /* set ext attrs */
- afs_noop, /* del ext attrs */
- vn_pathconf_default,
-};
-struct vnodeops *afs_ops = &Afs_vnodeops;
-#endif /* 0 */
-
-/* vnode file operations, and our own */
-extern int vn_read();
-extern int vn_write();
-extern int vn_ioctl();
-extern int vn_select();
-extern int afs_closex();
-
-struct fileops afs_fileops = {
- vn_read,
- vn_write,
- vn_ioctl,
- vn_select,
- mp_afs_closex,
-};
-
-#if 0
-mp_afs_lookup(adp, ndp)
- struct vcache *adp;
- struct nameidata *ndp;
-{
- int code;
- AFS_GLOCK();
- code = afs_lookup(adp, ndp);
- AFS_GUNLOCK();
- return code;
-}
-
-mp_afs_create(ndp, attrs)
- struct nameidata *ndp;
- struct vattr *attrs;
-{
- int code;
- AFS_GLOCK();
- code = afs_create(ndp, attrs);
- AFS_GUNLOCK();
- return code;
-}
-
-mp_afs_open(avcp, aflags, acred)
- struct vcache **avcp;
- afs_int32 aflags;
- afs_ucred_t *acred;
-{
- int code;
- AFS_GLOCK();
- code = afs_open(avcp, aflags, acred);
- AFS_GUNLOCK();
- return code;
-}
-
-mp_afs_access(avc, amode, acred)
- struct vcache *avc;
- afs_int32 amode;
- afs_ucred_t *acred;
-{
- int code;
- AFS_GLOCK();
- code = afs_access(avc, amode, acred);
- AFS_GUNLOCK();
- return code;
-}
-
-mp_afs_close(avc, flags, cred)
- struct vnode *avc;
- int flags;
- struct ucred *cred;
-{
- int code;
- AFS_GLOCK();
- code = afs_close(avc, flags, cred);
- AFS_GUNLOCK();
- return code;
-}
-
-mp_afs_getattr(avc, attrs, acred)
- struct vcache *avc;
- struct vattr *attrs;
- afs_ucred_t *acred;
-{
- int code;
- AFS_GLOCK();
- code = afs_getattr(avc, attrs, acred);
- AFS_GUNLOCK();
- return code;
-}
-
-mp_afs_setattr(avc, attrs, acred)
- struct vcache *avc;
- struct vattr *attrs;
- afs_ucred_t *acred;
-{
- int code;
- AFS_GLOCK();
- code = afs_setattr(avc, attrs, acred);
- AFS_GUNLOCK();
- return code;
-}
-
-mp_afs_fsync(avc, fflags, acred, waitfor)
- struct vcache *avc;
- int fflags;
- afs_ucred_t *acred;
- int waitfor;
-{
- int code;
- AFS_GLOCK();
- code = afs_fsync(avc, fflags, acred, waitfor);
- AFS_GUNLOCK();
- return code;
-}
-
-mp_afs_remove(ndp)
- struct nameidata *ndp;
-{
- int code;
- AFS_GLOCK();
- code = afs_remove(ndp);
- AFS_GUNLOCK();
- return code;
-}
-
-mp_afs_link(avc, ndp)
- struct vcache *avc;
- struct nameidata *ndp;
-{
- int code;
- AFS_GLOCK();
- code = afs_link(avc, ndp);
- AFS_GUNLOCK();
- return code;
-}
-
-mp_afs_rename(fndp, tndp)
- struct nameidata *fndp, *tndp;
-{
- int code;
- AFS_GLOCK();
- code = afs_rename(fndp, tndp);
- AFS_GUNLOCK();
- return code;
-}
-
-mp_afs_mkdir(ndp, attrs)
- struct nameidata *ndp;
- struct vattr *attrs;
-{
- int code;
- AFS_GLOCK();
- code = afs_mkdir(ndp, attrs);
- AFS_GUNLOCK();
- return code;
-}
-
-mp_afs_rmdir(ndp)
- struct nameidata *ndp;
-{
- int code;
- AFS_GLOCK();
- code = afs_rmdir(ndp);
- AFS_GUNLOCK();
- return code;
-}
-
-mp_afs_symlink(ndp, attrs, atargetName)
- struct nameidata *ndp;
- struct vattr *attrs;
- register char *atargetName;
-{
- int code;
- AFS_GLOCK();
- code = afs_symlink(ndp, attrs, atargetName);
- AFS_GUNLOCK();
- return code;
-}
-
-mp_afs_readdir(avc, auio, acred, eofp)
- struct vcache *avc;
- struct uio *auio;
- afs_ucred_t *acred;
- int *eofp;
-{
- int code;
- AFS_GLOCK();
- code = afs_readdir(avc, auio, acred, eofp);
- AFS_GUNLOCK();
- return code;
-}
-
-mp_afs_readlink(avc, auio, acred)
- struct vcache *avc;
- struct uio *auio;
- afs_ucred_t *acred;
-{
- int code;
- AFS_GLOCK();
- code = afs_readlink(avc, auio, acred);
- AFS_GUNLOCK();
- return code;
-}
-
-mp_afs_lockctl(avc, af, flag, acred, clid, offset)
- struct vcache *avc;
- struct eflock *af;
- afs_ucred_t *acred;
- int flag;
- pid_t clid;
- off_t offset;
-{
- int code;
- AFS_GLOCK();
- code = afs_lockctl(avc, af, flag, acred, clid, offset);
- AFS_GUNLOCK();
- return code;
-}
-
-mp_afs_closex(afd)
- struct file *afd;
-{
- int code;
- AFS_GLOCK();
- code = afs_closex(afd);
- AFS_GUNLOCK();
- return code;
-}
-
-mp_afs_seek(avc, oldoff, newoff, cred)
- struct vcache *avc;
- off_t oldoff, newoff;
- struct ucred *cred;
-{
- if ((int)newoff < 0)
- return (EINVAL);
- else
- return (0);
-}
-
-mp_afs_abortop(ndp)
- struct nameidata *ndp;
-{
- return (0);
-}
-
-mp_afs_inactive(avc, acred)
- register struct vcache *avc;
- afs_ucred_t *acred;
-{
- AFS_GLOCK();
- afs_InactiveVCache(avc, acred);
- AFS_GUNLOCK();
-}
-
-
-mp_afs_reclaim(avc)
- struct vcache *avc;
-{
- return (0);
-}
-
-mp_afs_print(avc)
- struct vcache *avc;
-{
- return (0);
-}
-
-mp_afs_page_read(avc, uio, acred)
- struct vcache *avc;
- struct uio *uio;
- struct ucred *acred;
-{
- int error;
- struct vrequest treq;
-
- AFS_GLOCK();
- error = afs_rdwr(avc, uio, UIO_READ, 0, acred);
- afs_Trace3(afs_iclSetp, CM_TRACE_PAGE_READ, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, error, ICL_TYPE_INT32, avc->f.states);
- if (error) {
- error = EIO;
- } else if ((avc->f.states) == 0) {
- afs_InitReq(&treq, acred);
- ObtainWriteLock(&avc->lock, 161);
- afs_Wire(avc, &treq);
- ReleaseWriteLock(&avc->lock);
- }
- AFS_GUNLOCK();
- return (error);
-}
-
-
-mp_afs_page_write(avc, uio, acred, pager, offset)
- struct vcache *avc;
- struct uio *uio;
- struct ucred *acred;
- memory_object_t pager;
- vm_offset_t offset;
-{
- int error;
-
- AFS_GLOCK();
- error = afs_rdwr(avc, uio, UIO_WRITE, 0, acred);
- afs_Trace3(afs_iclSetp, CM_TRACE_PAGE_WRITE, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, error, ICL_TYPE_INT32, avc->f.states);
- if (error) {
- error = EIO;
- }
- AFS_GUNLOCK();
- return (error);
-}
-
-
-int DO_FLUSH = 1;
-mp_afs_ubcrdwr(avc, uio, ioflag, cred)
- struct vcache *avc;
- struct uio *uio;
- int ioflag;
- struct ucred *cred;
-{
- register afs_int32 code;
- register char *data;
- afs_int32 fileBase, size, cnt = 0;
- afs_int32 pageBase;
- register afs_int32 tsize;
- register afs_int32 pageOffset;
- int eof;
- struct vrequest treq;
- int rw = uio->uio_rw;
- int rv, flags;
- int newpage = 0;
- vm_page_t page;
- afs_int32 save_resid;
- struct dcache *tdc;
- int didFakeOpen = 0;
- int counter = 0;
-
- AFS_GLOCK();
- afs_InitReq(&treq, cred);
- if (AFS_NFSXLATORREQ(cred) && rw == UIO_READ) {
- if (!afs_AccessOK
- (avc, PRSFS_READ, &treq,
- CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
- AFS_GUNLOCK();
- return EACCES;
- }
- }
- afs_Trace4(afs_iclSetp, CM_TRACE_VMRW, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, (rw == UIO_WRITE ? 1 : 0), ICL_TYPE_LONG,
- uio->uio_offset, ICL_TYPE_LONG, uio->uio_resid);
- code = afs_VerifyVCache(avc, &treq);
- if (code) {
- code = afs_CheckCode(code, &treq, 35);
- AFS_GUNLOCK();
- return code;
- }
- if (vType(avc) != VREG) {
- AFS_GUNLOCK();
- return EISDIR; /* can't read or write other things */
- }
- osi_FlushPages(avc); /* hold bozon lock, but not basic vnode lock */
- ObtainWriteLock(&avc->lock, 162);
- /* adjust parameters when appending files */
- if ((ioflag & IO_APPEND) && uio->uio_rw == UIO_WRITE)
- uio->uio_offset = avc->f.m.Length; /* write at EOF position */
- if (uio->uio_rw == UIO_WRITE) {
- avc->f.states |= CDirty;
- afs_FakeOpen(avc);
- didFakeOpen = 1;
- /*
- * before starting any I/O, we must ensure that the file is big enough
- * to hold the results (since afs_putpage will be called to force
- * the I/O.
- */
- size = uio->afsio_resid + uio->afsio_offset; /* new file size */
- if (size > avc->f.m.Length)
- avc->f.m.Length = size; /* file grew */
- avc->f.m.Date = osi_Time(); /* Set file date (for ranlib) */
- if (uio->afsio_resid > PAGE_SIZE)
- cnt = uio->afsio_resid / PAGE_SIZE;
- save_resid = uio->afsio_resid;
- }
-
- while (1) {
- /*
- * compute the amount of data to move into this block,
- * based on uio->afsio_resid.
- */
- size = uio->afsio_resid; /* transfer size */
- fileBase = uio->afsio_offset; /* start file position */
- pageBase = fileBase & ~(PAGE_SIZE - 1); /* file position of the page */
- pageOffset = fileBase & (PAGE_SIZE - 1); /* start offset within page */
- tsize = PAGE_SIZE - pageOffset; /* amount left in this page */
- /*
- * we'll read tsize bytes,
- * but first must make sure tsize isn't too big
- */
- if (tsize > size)
- tsize = size; /* don't read past end of request */
- eof = 0; /* flag telling us if we hit the EOF on the read */
- if (uio->uio_rw == UIO_READ) { /* we're doing a read operation */
- /* don't read past EOF */
- if (tsize + fileBase > avc->f.m.Length) {
- tsize = avc->f.m.Length - fileBase;
- eof = 1; /* we did hit the EOF */
- if (tsize < 0)
- tsize = 0; /* better safe than sorry */
- }
- }
- if (tsize <= 0)
- break; /* nothing to transfer, we're done */
-
- /* Purge dirty chunks of file if there are too many dirty chunks.
- * Inside the write loop, we only do this at a chunk boundary.
- * Clean up partial chunk if necessary at end of loop.
- */
- if (uio->uio_rw == UIO_WRITE && counter > 0
- && AFS_CHUNKOFFSET(fileBase) == 0) {
- code = afs_DoPartialWrite(avc, &treq);
- avc->f.states |= CDirty;
- }
-
- if (code) {
- break;
- }
-
- flags = 0;
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- code =
- ubc_lookup(((struct vnode *)avc)->v_object, pageBase, PAGE_SIZE,
- PAGE_SIZE, &page, &flags);
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 163);
-
- if (code) {
- break;
- }
- if (flags & B_NOCACHE) {
- /*
- * No page found. We should not read the page in if
- * 1. the write starts on a page edge (ie, pageoffset == 0)
- * and either
- * 1. we will fill the page (ie, size == PAGESIZE), or
- * 2. we are writing past eof
- */
- if ((uio->uio_rw == UIO_WRITE)
- &&
- ((pageOffset == 0
- && (size == PAGE_SIZE || fileBase >= avc->f.m.Length)))) {
- struct vnode *vp = (struct vnode *)avc;
- /* we're doing a write operation past eof; no need to read it */
- newpage = 1;
- AFS_GUNLOCK();
- ubc_page_zero(page, 0, PAGE_SIZE);
- ubc_page_release(page, B_DONE);
- AFS_GLOCK();
- } else {
- /* page wasn't cached, read it in. */
- struct buf *bp;
-
- AFS_GUNLOCK();
- bp = ubc_bufalloc(page, 1, PAGE_SIZE, 1, B_READ);
- AFS_GLOCK();
- bp->b_dev = 0;
- bp->b_vp = (struct vnode *)avc;
- bp->b_blkno = btodb(pageBase);
- ReleaseWriteLock(&avc->lock);
- code = afs_ustrategy(bp, cred); /* do the I/O */
- ObtainWriteLock(&avc->lock, 164);
- AFS_GUNLOCK();
- ubc_sync_iodone(bp);
- AFS_GLOCK();
- if (code) {
- AFS_GUNLOCK();
- ubc_page_release(page, 0);
- AFS_GLOCK();
- break;
- }
- }
- }
- AFS_GUNLOCK();
- ubc_page_wait(page);
- data = (char *)page->pg_addr; /* DUX 4.0D */
- if (data == 0)
- data = (char *)PHYS_TO_KSEG(page->pg_phys_addr); /* DUX 4.0E */
- AFS_GLOCK();
- ReleaseWriteLock(&avc->lock); /* uiomove may page fault */
- AFS_GUNLOCK();
- code = uiomove(data + pageOffset, tsize, uio);
- ubc_unload(page, pageOffset, page_size);
- if (uio->uio_rw == UIO_WRITE) {
- vm_offset_t toffset;
-
- /* Mark the page dirty and release it to avoid a deadlock
- * in ubc_dirty_kluster when more than one process writes
- * this page at the same time. */
- toffset = page->pg_offset;
- flags |= B_DIRTY;
- ubc_page_release(page, flags);
-
- if (cnt > 10) {
- vm_page_t pl;
- int kpcnt;
- struct buf *bp;
-
- /* We released the page, so we can get a null page
- * list if another thread calls the strategy routine.
- */
- pl = ubc_dirty_kluster(((struct vnode *)avc)->v_object, NULL,
- toffset, 0, B_WANTED, FALSE, &kpcnt);
- if (pl) {
- bp = ubc_bufalloc(pl, 1, PAGE_SIZE, 1, B_WRITE);
- bp->b_dev = 0;
- bp->b_vp = (struct vnode *)avc;
- bp->b_blkno = btodb(pageBase);
- AFS_GLOCK();
- code = afs_ustrategy(bp, cred); /* do the I/O */
- AFS_GUNLOCK();
- ubc_sync_iodone(bp);
- if (code) {
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 415);
- break;
- }
- }
- }
- } else {
- ubc_page_release(page, flags);
- }
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 165);
- /*
- * If reading at a chunk boundary, start prefetch of next chunk.
- */
- if (uio->uio_rw == UIO_READ
- && (counter == 0 || AFS_CHUNKOFFSET(fileBase) == 0)) {
- tdc = afs_FindDCache(avc, fileBase);
- if (tdc) {
- if (!(tdc->mflags & DFNextStarted))
- afs_PrefetchChunk(avc, tdc, cred, &treq);
- afs_PutDCache(tdc);
- }
- }
- counter++;
- if (code)
- break;
- }
- if (didFakeOpen)
- afs_FakeClose(avc, cred);
- if (uio->uio_rw == UIO_WRITE && code == 0 && (avc->f.states & CDirty)) {
- code = afs_DoPartialWrite(avc, &treq);
- }
- ReleaseWriteLock(&avc->lock);
- if (DO_FLUSH || (!newpage && (cnt < 10))) {
- AFS_GUNLOCK();
- ubc_flush_dirty(((struct vnode *)avc)->v_object, flags);
- AFS_GLOCK();
- }
-
- ObtainSharedLock(&avc->lock, 409);
- if (!code) {
- if (avc->vc_error) {
- code = avc->vc_error;
- }
- }
- /* This is required since we may still have dirty pages after the write.
- * I could just let close do the right thing, but stat's before the close
- * return the wrong length.
- */
- if (code == EDQUOT || code == ENOSPC) {
- uio->uio_resid = save_resid;
- UpgradeSToWLock(&avc->lock, 410);
- osi_ReleaseVM(avc, cred);
- ConvertWToSLock(&avc->lock);
- }
- ReleaseSharedLock(&avc->lock);
-
- if (!code && (ioflag & IO_SYNC) && (uio->uio_rw == UIO_WRITE)
- && !AFS_NFSXLATORREQ(cred)) {
- code = afs_fsync(avc, 0, cred, 0);
- }
- out:
- code = afs_CheckCode(code, &treq, 36);
- AFS_GUNLOCK();
- return code;
-}
-
-
-/*
- * Now for some bad news. Since we artificially hold on to vnodes by doing
- * and extra VNHOLD in afs_NewVCache(), there is no way for us to know
- * when we need to flush the pages when a program exits. Particularly
- * if it closes the file after mapping it R/W.
- *
- */
-
-mp_afs_mmap(avc, offset, map, addrp, len, prot, maxprot, flags, cred)
- register struct vcache *avc;
- vm_offset_t offset;
- vm_map_t map;
- vm_offset_t *addrp;
- vm_size_t len;
- vm_prot_t prot;
- vm_prot_t maxprot;
- int flags;
- struct ucred *cred;
-{
- struct vp_mmap_args args;
- register struct vp_mmap_args *ap = &args;
- struct vnode *vp = (struct vnode *)avc;
- int code;
- struct vrequest treq;
-#if !defined(DYNEL)
- extern kern_return_t u_vp_create();
-#endif
-
- AFS_GLOCK();
- afs_InitReq(&treq, cred);
- code = afs_VerifyVCache(avc, &treq);
- if (code) {
- code = afs_CheckCode(code, &treq, 37);
- AFS_GUNLOCK();
- return code;
- }
- osi_FlushPages(avc); /* ensure old pages are gone */
- ObtainWriteLock(&avc->lock, 166);
- avc->f.states |= CMAPPED;
- ReleaseWriteLock(&avc->lock);
- ap->a_offset = offset;
- ap->a_vaddr = addrp;
- ap->a_size = len;
- ap->a_prot = prot, ap->a_maxprot = maxprot;
- ap->a_flags = flags;
- AFS_GUNLOCK();
- code = u_vp_create(map, vp->v_object, (vm_offset_t) ap);
- AFS_GLOCK();
- code = afs_CheckCode(code, &treq, 38);
- AFS_GUNLOCK();
- return code;
-}
-
-
-int
-mp_afs_getpage(vop, offset, len, protp, pl, plsz, mape, addr, rw, cred)
- vm_ubc_object_t vop;
- vm_offset_t offset;
- vm_size_t len;
- vm_prot_t *protp;
- vm_page_t *pl;
- int plsz;
- vm_map_entry_t mape;
- vm_offset_t addr;
- int rw;
- struct ucred *cred;
-{
- register afs_int32 code;
- struct vrequest treq;
- int flags = 0;
- int i, pages = (len + PAGE_SIZE - 1) >> page_shift;
- vm_page_t *pagep;
- vm_offset_t off;
-
- struct vcache *avc = VTOAFS(vop->vu_vp);
-
- /* first, obtain the proper lock for the VM system */
-
- AFS_GLOCK();
- afs_InitReq(&treq, cred);
- code = afs_VerifyVCache(avc, &treq);
- if (code) {
- *pl = VM_PAGE_NULL;
- code = afs_CheckCode(code, &treq, 39); /* failed to get it */
- AFS_GUNLOCK();
- return code;
- }
-
- /* clean all dirty pages for this vnode */
- AFS_GUNLOCK();
- ubc_flush_dirty(vop, 0);
- AFS_GLOCK();
-
- ObtainWriteLock(&avc->lock, 167);
- afs_Trace4(afs_iclSetp, CM_TRACE_PAGEIN, ICL_TYPE_POINTER, avc,
- ICL_TYPE_LONG, offset, ICL_TYPE_LONG, len, ICL_TYPE_INT32,
- (int)rw);
- for (i = 0; i < pages; i++) {
- pagep = &pl[i];
- off = offset + PAGE_SIZE * i;
- if (protp)
- protp[i] = 0;
- flags = 0;
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- code =
- ubc_lookup(((struct vnode *)avc)->v_object, off, PAGE_SIZE,
- PAGE_SIZE, pagep, &flags);
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 168);
- if (code) {
- goto out;
- }
- if (flags & B_NOCACHE) { /* if (page) */
- if ((rw & B_WRITE) && (offset + len >= avc->f.m.Length)) {
- struct vnode *vp = (struct vnode *)avc;
- /* we're doing a write operation past eof; no need to read it */
- AFS_GUNLOCK();
- ubc_page_zero(*pagep, 0, PAGE_SIZE);
- ubc_page_release(*pagep, B_DONE);
- AFS_GLOCK();
- } else {
- /* page wasn't cached, read it in. */
- struct buf *bp;
-
- AFS_GUNLOCK();
- bp = ubc_bufalloc(*pagep, 1, PAGE_SIZE, 1, B_READ);
- AFS_GLOCK();
- bp->b_dev = 0;
- bp->b_vp = (struct vnode *)avc;
- bp->b_blkno = btodb(off);
- ReleaseWriteLock(&avc->lock);
- code = afs_ustrategy(bp, cred); /* do the I/O */
- ObtainWriteLock(&avc->lock, 169);
- AFS_GUNLOCK();
- ubc_sync_iodone(bp);
- AFS_GLOCK();
- if (code) {
- AFS_GUNLOCK();
- ubc_page_release(pl[i], 0);
- AFS_GLOCK();
- goto out;
- }
- }
- }
- if ((rw & B_READ) == 0) {
- AFS_GUNLOCK();
- ubc_page_dirty(pl[i]);
- AFS_GLOCK();
- } else {
- if (protp && (flags & B_DIRTY) == 0) {
- protp[i] = VM_PROT_WRITE;
- }
- }
- }
- out:
- pl[i] = VM_PAGE_NULL;
- ReleaseWriteLock(&avc->lock);
- afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_INT32, code,
- ICL_TYPE_POINTER, *pagep, ICL_TYPE_INT32, flags);
- code = afs_CheckCode(code, &treq, 40);
- AFS_GUNLOCK();
- return code;
-}
-
-
-int
-mp_afs_putpage(vop, pl, pcnt, flags, cred)
- vm_ubc_object_t vop;
- vm_page_t *pl;
- int pcnt;
- int flags;
- struct ucred *cred;
-{
- register afs_int32 code = 0;
- struct vcache *avc = VTOAFS(vop->vu_vp);
- struct vnode *vp = (struct vnode *)avc;
- int i;
-
- AFS_GLOCK();
- afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUT, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, pcnt, ICL_TYPE_INT32, vp->v_flag,
- ICL_TYPE_INT32, flags);
- if (flags & B_UBC) {
- AFS_GUNLOCK();
- VN_LOCK(vp);
- if (vp->v_flag & VXLOCK) {
- VN_UNLOCK(vp);
- for (i = 0; i < pcnt; i++) {
- ubc_page_release(pl[i], B_DONE | B_DIRTY);
- pl[i] = VM_PAGE_NULL;
- }
- return (0);
- } else {
- VN_UNLOCK(vp);
- }
- AFS_GLOCK();
- }
-
- /* first, obtain the proper lock for the VM system */
- ObtainWriteLock(&avc->lock, 170);
- for (i = 0; i < pcnt; i++) {
- vm_page_t page = pl[i];
- struct buf *bp;
-
- /* write it out */
- AFS_GUNLOCK();
- bp = ubc_bufalloc(page, 1, PAGE_SIZE, 1, B_WRITE);
- AFS_GLOCK();
- bp->b_dev = 0;
- bp->b_vp = (struct vnode *)avc;
- bp->b_blkno = btodb(page->pg_offset);
- ReleaseWriteLock(&avc->lock);
- code = afs_ustrategy(bp, cred); /* do the I/O */
- ObtainWriteLock(&avc->lock, 171);
- AFS_GUNLOCK();
- ubc_sync_iodone(bp);
- AFS_GLOCK();
- if (code) {
- goto done;
- } else {
- pl[i] = VM_PAGE_NULL;
- }
- }
- done:
- ReleaseWriteLock(&avc->lock);
- afs_Trace2(afs_iclSetp, CM_TRACE_PAGEOUTDONE, ICL_TYPE_INT32, code,
- ICL_TYPE_INT32, avc->f.m.Length);
- AFS_GUNLOCK();
- return code;
-}
-
-
-int
-mp_afs_swap(avc, swapop, argp)
- struct vcache *avc;
- vp_swap_op_t swapop;
- vm_offset_t argp;
-{
- return EIO;
-}
-
-int
-mp_afs_syncdata(avc, flag, offset, length, cred)
- struct vcache *avc;
- int flag;
- vm_offset_t offset;
- vm_size_t length;
- struct ucred *cred;
-{
- /* NFS V3 makes this call, ignore it. We'll sync the data in afs_fsync. */
- if (AFS_NFSXLATORREQ(cred))
- return 0;
- else
- return EINVAL;
-}
-
-/* a freelist of one */
-struct buf *afs_bread_freebp = 0;
-
-/*
- * Only rfs_read calls this, and it only looks at bp->b_un.b_addr.
- * Thus we can use fake bufs (ie not from the real buffer pool).
- */
-mp_afs_bread(vp, lbn, bpp, cred)
- struct ucred *cred;
- struct vnode *vp;
- daddr_t lbn;
- struct buf **bpp;
-{
- int offset, fsbsize, error;
- struct buf *bp;
- struct iovec iov;
- struct uio uio;
-
- AFS_GLOCK();
- AFS_STATCNT(afs_bread);
- fsbsize = vp->v_vfsp->vfs_bsize;
- offset = lbn * fsbsize;
- if (afs_bread_freebp) {
- bp = afs_bread_freebp;
- afs_bread_freebp = 0;
- } else {
- bp = (struct buf *)AFS_KALLOC(sizeof(*bp));
- bp->b_un.b_addr = (caddr_t) AFS_KALLOC(fsbsize);
- }
-
- iov.iov_base = bp->b_un.b_addr;
- iov.iov_len = fsbsize;
- uio.afsio_iov = &iov;
- uio.afsio_iovcnt = 1;
- uio.afsio_seg = AFS_UIOSYS;
- uio.afsio_offset = offset;
- uio.afsio_resid = fsbsize;
- *bpp = 0;
- error = afs_read(VTOAFS(vp), &uio, cred, lbn, bpp, 0);
- if (error) {
- afs_bread_freebp = bp;
- AFS_GUNLOCK();
- return error;
- }
- if (*bpp) {
- afs_bread_freebp = bp;
- } else {
- *(struct buf **)&bp->b_vp = bp; /* mark as fake */
- *bpp = bp;
- }
- AFS_GUNLOCK();
- return 0;
-}
-
-
-mp_afs_brelse(vp, bp)
- struct vnode *vp;
- struct buf *bp;
-{
- AFS_GLOCK();
- AFS_STATCNT(afs_brelse);
- if ((struct buf *)bp->b_vp != bp) { /* not fake */
- brelse(bp);
- } else if (afs_bread_freebp) {
- AFS_KFREE(bp->b_un.b_addr, vp->v_vfsp->vfs_bsize);
- AFS_KFREE(bp, sizeof(*bp));
- } else {
- afs_bread_freebp = bp;
- }
- AFS_GUNLOCK();
-}
-
-
-mp_afs_bmap(avc, abn, anvp, anbn)
- register struct vcache *avc;
- afs_int32 abn, *anbn;
- struct vcache **anvp;
-{
- AFS_GLOCK();
- AFS_STATCNT(afs_bmap);
- if (anvp)
- *anvp = avc;
- if (anbn)
- *anbn = abn * (8192 / DEV_BSIZE); /* in 512 byte units */
- AFS_GUNLOCK();
- return 0;
-}
-
-
-/* real strategy */
-mp_afs_strategy(abp)
- register struct buf *abp;
-{
- register afs_int32 code;
-
- AFS_GLOCK();
- AFS_STATCNT(afs_strategy);
- code = afs_osi_MapStrategy(afs_ustrategy, abp);
- AFS_GUNLOCK();
- return code;
-}
-
-
-mp_afs_refer(vm_ubc_object_t vop)
-{
- VREF(vop->vu_vp);
-}
-
-
-mp_afs_release(vm_ubc_object_t vop)
-{
- vrele(vop->vu_vp);
-}
-
-
-mp_afs_write_check(vm_ubc_object_t vop, vm_page_t pp)
-{
- return TRUE;
-}
-
-
-
-struct vfs_ubcops afs_ubcops = {
- mp_afs_refer, /* refer vnode */
- mp_afs_release, /* release vnode */
- mp_afs_getpage, /* get page */
- mp_afs_putpage, /* put page */
- mp_afs_write_check, /* check writablity */
-};
-#endif /* 0 */
-
-/*
- * Cover function for lookup name using OSF equivalent, namei()
- *
- * Note, the result vnode (ni_vp) in the namei data structure is remains
- * locked after return.
- */
-lookupname(namep, seg, follow, dvpp, cvpp)
- char *namep; /* path name */
- int seg; /* address space containing name */
- int follow; /* follow symbolic links */
- struct vnode **dvpp; /* result, containing parent vnode */
- struct vnode **cvpp; /* result, containing final component vnode */
-{
- /* Should I use free-bee in u-area? */
- struct nameidata *ndp = &u.u_nd;
- int error;
-
- ndp->ni_nameiop = ((follow) ? (LOOKUP | FOLLOW) : (LOOKUP));
- ndp->ni_segflg = seg;
- ndp->ni_dirp = namep;
- error = namei(ndp);
- if (dvpp != NULL)
- *dvpp = ndp->ni_dvp;
- if (cvpp != NULL)
- *cvpp = ndp->ni_vp;
- return (error);
-}